ad8d291076a7c3be6e8df5cda008a5dd6191b719.svn-base 4.7 MB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625326263262732628326293263032631326323263332634326353263632637326383263932640326413264232643326443264532646326473264832649326503265132652326533265432655326563265732658326593266032661326623266332664326653266632667326683266932670326713267232673326743267532676326773267832679326803268132682326833268432685326863268732688326893269032691326923269332694326953269632697326983269932700327013270232703327043270532706327073270832709327103271132712327133271432715327163271732718327193272032721327223272332724327253272632727327283272932730327313273232733327343273532736327373273832739327403274132742327433274432745327463274732748327493275032751327523275332754327553275632757327583275932760327613276232763327643276532766327673276832769327703277132772327733277432775327763277732778327793278032781327823278332784327853278632787327883278932790327913279232793327943279532796327973279832799328003280132802328033280432805328063280732808328093281032811328123281332814328153281632817328183281932820328213282232823328243282532826328273282832829328303283132832328333283432835328363283732838328393284032841328423284332844328453284632847328483284932850328513285232853328543285532856328573285832859328603286132862328633286432865328663286732868328693287032871328723287332874328753287632877328783287932880328813288232883328843288532886328873288832889328903289132892328933289432895328963289732898328993290032901329023290332904329053290632907329083290932910329113291232913329143291532916329173291832919329203292132922329233292432925329263292732928329293293032931329323293332934329353293632937329383293932940329413294232943329443294532946329473294832949329503295132952329533295432955329563295732958329593296032961329623296332964329653296632967329683296932970329713297232973329743297532976329773297832979329803298132982329833298432985329863298732988329893299032991329923299332994329953299632997329983299933000330013300233003330043300533006330073300833009330103301133012330133301433015330163301733018330193302033021330223302333024330253302633027330283302933030330313303233033330343303533036330373303833039330403304133042330433304433045330463304733048330493305033051330523305333054330553305633057330583305933060330613306233063330643306533066330673306833069330703307133072330733307433075330763307733078330793308033081330823308333084330853308633087330883308933090330913309233093330943309533096330973309833099331003310133102331033310433105331063310733108331093311033111331123311333114331153311633117331183311933120331213312233123331243312533126331273312833129331303313133132331333313433135331363313733138331393314033141331423314333144331453314633147331483314933150331513315233153331543315533156331573315833159331603316133162331633316433165331663316733168331693317033171331723317333174331753317633177331783317933180331813318233183331843318533186331873318833189331903319133192331933319433195331963319733198331993320033201332023320333204332053320633207332083320933210332113321233213332143321533216332173321833219332203322133222332233322433225332263322733228332293323033231332323323333234332353323633237332383323933240332413324233243332443324533246332473324833249332503325133252332533325433255332563325733258332593326033261332623326333264332653326633267332683326933270332713327233273332743327533276332773327833279332803328133282332833328433285332863328733288332893329033291332923329333294332953329633297332983329933300333013330233303333043330533306333073330833309333103331133312333133331433315333163331733318333193332033321333223332333324333253332633327333283332933330333313333233333333343333533336333373333833339333403334133342333433334433345333463334733348333493335033351333523335333354333553335633357333583335933360333613336233363333643336533366333673336833369333703337133372333733337433375333763337733378333793338033381333823338333384333853338633387333883338933390333913339233393333943339533396333973339833399334003340133402334033340433405334063340733408334093341033411334123341333414334153341633417334183341933420334213342233423334243342533426334273342833429334303343133432334333343433435334363343733438334393344033441334423344333444334453344633447334483344933450334513345233453334543345533456334573345833459334603346133462334633346433465334663346733468334693347033471334723347333474334753347633477334783347933480334813348233483334843348533486334873348833489334903349133492334933349433495334963349733498334993350033501335023350333504335053350633507335083350933510335113351233513335143351533516335173351833519335203352133522335233352433525335263352733528335293353033531335323353333534335353353633537335383353933540335413354233543335443354533546335473354833549335503355133552335533355433555335563355733558335593356033561335623356333564335653356633567335683356933570335713357233573335743357533576335773357833579335803358133582335833358433585335863358733588335893359033591335923359333594335953359633597335983359933600336013360233603336043360533606336073360833609336103361133612336133361433615336163361733618336193362033621336223362333624336253362633627336283362933630336313363233633336343363533636336373363833639336403364133642336433364433645336463364733648336493365033651336523365333654336553365633657336583365933660336613366233663336643366533666336673366833669336703367133672336733367433675336763367733678336793368033681336823368333684336853368633687336883368933690336913369233693336943369533696336973369833699337003370133702337033370433705337063370733708337093371033711337123371333714337153371633717337183371933720337213372233723337243372533726337273372833729337303373133732337333373433735337363373733738337393374033741337423374333744337453374633747337483374933750337513375233753337543375533756337573375833759337603376133762337633376433765337663376733768337693377033771337723377333774337753377633777337783377933780337813378233783337843378533786337873378833789337903379133792337933379433795337963379733798337993380033801338023380333804338053380633807338083380933810338113381233813338143381533816338173381833819338203382133822338233382433825338263382733828338293383033831338323383333834338353383633837338383383933840338413384233843338443384533846338473384833849338503385133852338533385433855338563385733858338593386033861338623386333864338653386633867338683386933870338713387233873338743387533876338773387833879338803388133882338833388433885338863388733888338893389033891338923389333894338953389633897338983389933900339013390233903339043390533906339073390833909339103391133912339133391433915339163391733918339193392033921339223392333924339253392633927339283392933930339313393233933339343393533936339373393833939339403394133942339433394433945339463394733948339493395033951339523395333954339553395633957339583395933960339613396233963339643396533966339673396833969339703397133972339733397433975339763397733978339793398033981339823398333984339853398633987339883398933990339913399233993339943399533996339973399833999340003400134002340033400434005340063400734008340093401034011340123401334014340153401634017340183401934020340213402234023340243402534026340273402834029340303403134032340333403434035340363403734038340393404034041340423404334044340453404634047340483404934050340513405234053340543405534056340573405834059340603406134062340633406434065340663406734068340693407034071340723407334074340753407634077340783407934080340813408234083340843408534086340873408834089340903409134092340933409434095340963409734098340993410034101341023410334104341053410634107341083410934110341113411234113341143411534116341173411834119341203412134122341233412434125341263412734128341293413034131341323413334134341353413634137341383413934140341413414234143341443414534146341473414834149341503415134152341533415434155341563415734158341593416034161341623416334164341653416634167341683416934170341713417234173341743417534176341773417834179341803418134182341833418434185341863418734188341893419034191341923419334194341953419634197341983419934200342013420234203342043420534206342073420834209342103421134212342133421434215342163421734218342193422034221342223422334224342253422634227342283422934230342313423234233342343423534236342373423834239342403424134242342433424434245342463424734248342493425034251342523425334254342553425634257342583425934260342613426234263342643426534266342673426834269342703427134272342733427434275342763427734278342793428034281342823428334284342853428634287342883428934290342913429234293342943429534296342973429834299343003430134302343033430434305343063430734308343093431034311343123431334314343153431634317343183431934320343213432234323343243432534326343273432834329343303433134332343333433434335343363433734338343393434034341343423434334344343453434634347343483434934350343513435234353343543435534356343573435834359343603436134362343633436434365343663436734368343693437034371343723437334374343753437634377343783437934380343813438234383343843438534386343873438834389343903439134392343933439434395343963439734398343993440034401344023440334404344053440634407344083440934410344113441234413344143441534416344173441834419344203442134422344233442434425344263442734428344293443034431344323443334434344353443634437344383443934440344413444234443344443444534446344473444834449344503445134452344533445434455344563445734458344593446034461344623446334464344653446634467344683446934470344713447234473344743447534476344773447834479344803448134482344833448434485344863448734488344893449034491344923449334494344953449634497344983449934500345013450234503345043450534506345073450834509345103451134512345133451434515345163451734518345193452034521345223452334524345253452634527345283452934530345313453234533345343453534536345373453834539345403454134542345433454434545345463454734548345493455034551345523455334554345553455634557345583455934560345613456234563345643456534566345673456834569345703457134572345733457434575345763457734578345793458034581345823458334584345853458634587345883458934590345913459234593345943459534596345973459834599346003460134602346033460434605346063460734608346093461034611346123461334614346153461634617346183461934620346213462234623346243462534626346273462834629346303463134632346333463434635346363463734638346393464034641346423464334644346453464634647346483464934650346513465234653346543465534656346573465834659346603466134662346633466434665346663466734668346693467034671346723467334674346753467634677346783467934680346813468234683346843468534686346873468834689346903469134692346933469434695346963469734698346993470034701347023470334704347053470634707347083470934710347113471234713347143471534716347173471834719347203472134722347233472434725347263472734728347293473034731347323473334734347353473634737347383473934740347413474234743347443474534746347473474834749347503475134752347533475434755347563475734758347593476034761347623476334764347653476634767347683476934770347713477234773347743477534776347773477834779347803478134782347833478434785347863478734788347893479034791347923479334794347953479634797347983479934800348013480234803348043480534806348073480834809348103481134812348133481434815348163481734818348193482034821348223482334824348253482634827348283482934830348313483234833348343483534836348373483834839348403484134842348433484434845348463484734848348493485034851348523485334854348553485634857348583485934860348613486234863348643486534866348673486834869348703487134872348733487434875348763487734878348793488034881348823488334884348853488634887348883488934890348913489234893348943489534896348973489834899349003490134902349033490434905349063490734908349093491034911349123491334914349153491634917349183491934920349213492234923349243492534926349273492834929349303493134932349333493434935349363493734938349393494034941349423494334944349453494634947349483494934950349513495234953349543495534956349573495834959349603496134962349633496434965349663496734968349693497034971349723497334974349753497634977349783497934980349813498234983349843498534986349873498834989349903499134992349933499434995349963499734998349993500035001350023500335004350053500635007350083500935010350113501235013350143501535016350173501835019350203502135022350233502435025350263502735028350293503035031350323503335034350353503635037350383503935040350413504235043350443504535046350473504835049350503505135052350533505435055350563505735058350593506035061350623506335064350653506635067350683506935070350713507235073350743507535076350773507835079350803508135082350833508435085350863508735088350893509035091350923509335094350953509635097350983509935100351013510235103351043510535106351073510835109351103511135112351133511435115351163511735118351193512035121351223512335124351253512635127351283512935130351313513235133351343513535136351373513835139351403514135142351433514435145351463514735148351493515035151351523515335154351553515635157351583515935160351613516235163351643516535166351673516835169351703517135172351733517435175351763517735178351793518035181351823518335184351853518635187351883518935190351913519235193351943519535196351973519835199352003520135202352033520435205352063520735208352093521035211352123521335214352153521635217352183521935220352213522235223352243522535226352273522835229352303523135232352333523435235352363523735238352393524035241352423524335244352453524635247352483524935250352513525235253352543525535256352573525835259352603526135262352633526435265352663526735268352693527035271352723527335274352753527635277352783527935280352813528235283352843528535286352873528835289352903529135292352933529435295352963529735298352993530035301353023530335304353053530635307353083530935310353113531235313353143531535316353173531835319353203532135322353233532435325353263532735328353293533035331353323533335334353353533635337353383533935340353413534235343353443534535346353473534835349353503535135352353533535435355353563535735358353593536035361353623536335364353653536635367353683536935370353713537235373353743537535376353773537835379353803538135382353833538435385353863538735388353893539035391353923539335394353953539635397353983539935400354013540235403354043540535406354073540835409354103541135412354133541435415354163541735418354193542035421354223542335424354253542635427354283542935430354313543235433354343543535436354373543835439354403544135442354433544435445354463544735448354493545035451354523545335454354553545635457354583545935460354613546235463354643546535466354673546835469354703547135472354733547435475354763547735478354793548035481354823548335484354853548635487354883548935490354913549235493354943549535496354973549835499355003550135502355033550435505355063550735508355093551035511355123551335514355153551635517355183551935520355213552235523355243552535526355273552835529355303553135532355333553435535355363553735538355393554035541355423554335544355453554635547355483554935550355513555235553355543555535556355573555835559355603556135562355633556435565355663556735568355693557035571355723557335574355753557635577355783557935580355813558235583355843558535586355873558835589355903559135592355933559435595355963559735598355993560035601356023560335604356053560635607356083560935610356113561235613356143561535616356173561835619356203562135622356233562435625356263562735628356293563035631356323563335634356353563635637356383563935640356413564235643356443564535646356473564835649356503565135652356533565435655356563565735658356593566035661356623566335664356653566635667356683566935670356713567235673356743567535676356773567835679356803568135682356833568435685356863568735688356893569035691356923569335694356953569635697356983569935700357013570235703357043570535706357073570835709357103571135712357133571435715357163571735718357193572035721357223572335724357253572635727357283572935730357313573235733357343573535736357373573835739357403574135742357433574435745357463574735748357493575035751357523575335754357553575635757357583575935760357613576235763357643576535766357673576835769357703577135772357733577435775357763577735778357793578035781357823578335784357853578635787357883578935790357913579235793357943579535796357973579835799358003580135802358033580435805358063580735808358093581035811358123581335814358153581635817358183581935820358213582235823358243582535826358273582835829358303583135832358333583435835358363583735838358393584035841358423584335844358453584635847358483584935850358513585235853358543585535856358573585835859358603586135862358633586435865358663586735868358693587035871358723587335874358753587635877358783587935880358813588235883358843588535886358873588835889358903589135892358933589435895358963589735898358993590035901359023590335904359053590635907359083590935910359113591235913359143591535916359173591835919359203592135922359233592435925359263592735928359293593035931359323593335934359353593635937359383593935940359413594235943359443594535946359473594835949359503595135952359533595435955359563595735958359593596035961359623596335964359653596635967359683596935970359713597235973359743597535976359773597835979359803598135982359833598435985359863598735988359893599035991359923599335994359953599635997359983599936000360013600236003360043600536006360073600836009360103601136012360133601436015360163601736018360193602036021360223602336024360253602636027360283602936030360313603236033360343603536036360373603836039360403604136042360433604436045360463604736048360493605036051360523605336054360553605636057360583605936060360613606236063360643606536066360673606836069360703607136072360733607436075360763607736078360793608036081360823608336084360853608636087360883608936090360913609236093360943609536096360973609836099361003610136102361033610436105361063610736108361093611036111361123611336114361153611636117361183611936120361213612236123361243612536126361273612836129361303613136132361333613436135361363613736138361393614036141361423614336144361453614636147361483614936150361513615236153361543615536156361573615836159361603616136162361633616436165361663616736168361693617036171361723617336174361753617636177361783617936180361813618236183361843618536186361873618836189361903619136192361933619436195361963619736198361993620036201362023620336204362053620636207362083620936210362113621236213362143621536216362173621836219362203622136222362233622436225362263622736228362293623036231362323623336234362353623636237362383623936240362413624236243362443624536246362473624836249362503625136252362533625436255362563625736258362593626036261362623626336264362653626636267362683626936270362713627236273362743627536276362773627836279362803628136282362833628436285362863628736288362893629036291362923629336294362953629636297362983629936300363013630236303363043630536306363073630836309363103631136312363133631436315363163631736318363193632036321363223632336324363253632636327363283632936330363313633236333363343633536336363373633836339363403634136342363433634436345363463634736348363493635036351363523635336354363553635636357363583635936360363613636236363363643636536366363673636836369363703637136372363733637436375363763637736378363793638036381363823638336384363853638636387363883638936390363913639236393363943639536396363973639836399364003640136402364033640436405364063640736408364093641036411364123641336414364153641636417364183641936420364213642236423364243642536426364273642836429364303643136432364333643436435364363643736438364393644036441364423644336444364453644636447364483644936450364513645236453364543645536456364573645836459364603646136462364633646436465364663646736468364693647036471364723647336474364753647636477364783647936480364813648236483364843648536486364873648836489364903649136492364933649436495364963649736498364993650036501365023650336504365053650636507365083650936510365113651236513365143651536516365173651836519365203652136522365233652436525365263652736528365293653036531365323653336534365353653636537365383653936540365413654236543365443654536546365473654836549365503655136552365533655436555365563655736558365593656036561365623656336564365653656636567365683656936570365713657236573365743657536576365773657836579365803658136582365833658436585365863658736588365893659036591365923659336594365953659636597365983659936600366013660236603366043660536606366073660836609366103661136612366133661436615366163661736618366193662036621366223662336624366253662636627366283662936630366313663236633366343663536636366373663836639366403664136642366433664436645366463664736648366493665036651366523665336654366553665636657366583665936660366613666236663366643666536666366673666836669366703667136672366733667436675366763667736678366793668036681366823668336684366853668636687366883668936690366913669236693366943669536696366973669836699367003670136702367033670436705367063670736708367093671036711367123671336714367153671636717367183671936720367213672236723367243672536726367273672836729367303673136732367333673436735367363673736738367393674036741367423674336744367453674636747367483674936750367513675236753367543675536756367573675836759367603676136762367633676436765367663676736768367693677036771367723677336774367753677636777367783677936780367813678236783367843678536786367873678836789367903679136792367933679436795367963679736798367993680036801368023680336804368053680636807368083680936810368113681236813368143681536816368173681836819368203682136822368233682436825368263682736828368293683036831368323683336834368353683636837368383683936840368413684236843368443684536846368473684836849368503685136852368533685436855368563685736858368593686036861368623686336864368653686636867368683686936870368713687236873368743687536876368773687836879368803688136882368833688436885368863688736888368893689036891368923689336894368953689636897368983689936900369013690236903369043690536906369073690836909369103691136912369133691436915369163691736918369193692036921369223692336924369253692636927369283692936930369313693236933369343693536936369373693836939369403694136942369433694436945369463694736948369493695036951369523695336954369553695636957369583695936960369613696236963369643696536966369673696836969369703697136972369733697436975369763697736978369793698036981369823698336984369853698636987369883698936990369913699236993369943699536996369973699836999370003700137002370033700437005370063700737008370093701037011370123701337014370153701637017370183701937020370213702237023370243702537026370273702837029370303703137032370333703437035370363703737038370393704037041370423704337044370453704637047370483704937050370513705237053370543705537056370573705837059370603706137062370633706437065370663706737068370693707037071370723707337074370753707637077370783707937080370813708237083370843708537086370873708837089370903709137092370933709437095370963709737098370993710037101371023710337104371053710637107371083710937110371113711237113371143711537116371173711837119371203712137122371233712437125371263712737128371293713037131371323713337134371353713637137371383713937140371413714237143371443714537146371473714837149371503715137152371533715437155371563715737158371593716037161371623716337164371653716637167371683716937170371713717237173371743717537176371773717837179371803718137182371833718437185371863718737188371893719037191371923719337194371953719637197371983719937200372013720237203372043720537206372073720837209372103721137212372133721437215372163721737218372193722037221372223722337224372253722637227372283722937230372313723237233372343723537236372373723837239372403724137242372433724437245372463724737248372493725037251372523725337254372553725637257372583725937260372613726237263372643726537266372673726837269372703727137272372733727437275372763727737278372793728037281372823728337284372853728637287372883728937290372913729237293372943729537296372973729837299373003730137302373033730437305373063730737308373093731037311373123731337314373153731637317373183731937320373213732237323373243732537326373273732837329373303733137332373333733437335373363733737338373393734037341373423734337344373453734637347373483734937350373513735237353373543735537356373573735837359373603736137362373633736437365373663736737368373693737037371373723737337374373753737637377373783737937380373813738237383373843738537386373873738837389373903739137392373933739437395373963739737398373993740037401374023740337404374053740637407374083740937410374113741237413374143741537416374173741837419374203742137422374233742437425374263742737428374293743037431374323743337434374353743637437374383743937440374413744237443374443744537446374473744837449374503745137452374533745437455374563745737458374593746037461374623746337464374653746637467374683746937470374713747237473374743747537476374773747837479374803748137482374833748437485374863748737488374893749037491374923749337494374953749637497374983749937500375013750237503375043750537506375073750837509375103751137512375133751437515375163751737518375193752037521375223752337524375253752637527375283752937530375313753237533375343753537536375373753837539375403754137542375433754437545375463754737548375493755037551375523755337554375553755637557375583755937560375613756237563375643756537566375673756837569375703757137572375733757437575375763757737578375793758037581375823758337584375853758637587375883758937590375913759237593375943759537596375973759837599376003760137602376033760437605376063760737608376093761037611376123761337614376153761637617376183761937620376213762237623376243762537626376273762837629376303763137632376333763437635376363763737638376393764037641376423764337644376453764637647376483764937650376513765237653376543765537656376573765837659376603766137662376633766437665376663766737668376693767037671376723767337674376753767637677376783767937680376813768237683376843768537686376873768837689376903769137692376933769437695376963769737698376993770037701377023770337704377053770637707377083770937710377113771237713377143771537716377173771837719377203772137722377233772437725377263772737728377293773037731377323773337734377353773637737377383773937740377413774237743377443774537746377473774837749377503775137752377533775437755377563775737758377593776037761377623776337764377653776637767377683776937770377713777237773377743777537776377773777837779377803778137782377833778437785377863778737788377893779037791377923779337794377953779637797377983779937800378013780237803378043780537806378073780837809378103781137812378133781437815378163781737818378193782037821378223782337824378253782637827378283782937830378313783237833378343783537836378373783837839378403784137842378433784437845378463784737848378493785037851378523785337854378553785637857378583785937860378613786237863378643786537866378673786837869378703787137872378733787437875378763787737878378793788037881378823788337884378853788637887378883788937890378913789237893378943789537896378973789837899379003790137902379033790437905379063790737908379093791037911379123791337914379153791637917379183791937920379213792237923379243792537926379273792837929379303793137932379333793437935379363793737938379393794037941379423794337944379453794637947379483794937950379513795237953379543795537956379573795837959379603796137962379633796437965379663796737968379693797037971379723797337974379753797637977379783797937980379813798237983379843798537986379873798837989379903799137992379933799437995379963799737998379993800038001380023800338004380053800638007380083800938010380113801238013380143801538016380173801838019380203802138022380233802438025380263802738028380293803038031380323803338034380353803638037380383803938040380413804238043380443804538046380473804838049380503805138052380533805438055380563805738058380593806038061380623806338064380653806638067380683806938070380713807238073380743807538076380773807838079380803808138082380833808438085380863808738088380893809038091380923809338094380953809638097380983809938100381013810238103381043810538106381073810838109381103811138112381133811438115381163811738118381193812038121381223812338124381253812638127381283812938130381313813238133381343813538136381373813838139381403814138142381433814438145381463814738148381493815038151381523815338154381553815638157381583815938160381613816238163381643816538166381673816838169381703817138172381733817438175381763817738178381793818038181381823818338184381853818638187381883818938190381913819238193381943819538196381973819838199382003820138202382033820438205382063820738208382093821038211382123821338214382153821638217382183821938220382213822238223382243822538226382273822838229382303823138232382333823438235382363823738238382393824038241382423824338244382453824638247382483824938250382513825238253382543825538256382573825838259382603826138262382633826438265382663826738268382693827038271382723827338274382753827638277382783827938280382813828238283382843828538286382873828838289382903829138292382933829438295382963829738298382993830038301383023830338304383053830638307383083830938310383113831238313383143831538316383173831838319383203832138322383233832438325383263832738328383293833038331383323833338334383353833638337383383833938340383413834238343383443834538346383473834838349383503835138352383533835438355383563835738358383593836038361383623836338364383653836638367383683836938370383713837238373383743837538376383773837838379383803838138382383833838438385383863838738388383893839038391383923839338394383953839638397383983839938400384013840238403384043840538406384073840838409384103841138412384133841438415384163841738418384193842038421384223842338424384253842638427384283842938430384313843238433384343843538436384373843838439384403844138442384433844438445384463844738448384493845038451384523845338454384553845638457384583845938460384613846238463384643846538466384673846838469384703847138472384733847438475384763847738478384793848038481384823848338484384853848638487384883848938490384913849238493384943849538496384973849838499385003850138502385033850438505385063850738508385093851038511385123851338514385153851638517385183851938520385213852238523385243852538526385273852838529385303853138532385333853438535385363853738538385393854038541385423854338544385453854638547385483854938550385513855238553385543855538556385573855838559385603856138562385633856438565385663856738568385693857038571385723857338574385753857638577385783857938580385813858238583385843858538586385873858838589385903859138592385933859438595385963859738598385993860038601386023860338604386053860638607386083860938610386113861238613386143861538616386173861838619386203862138622386233862438625386263862738628386293863038631386323863338634386353863638637386383863938640386413864238643386443864538646386473864838649386503865138652386533865438655386563865738658386593866038661386623866338664386653866638667386683866938670386713867238673386743867538676386773867838679386803868138682386833868438685386863868738688386893869038691386923869338694386953869638697386983869938700387013870238703387043870538706387073870838709387103871138712387133871438715387163871738718387193872038721387223872338724387253872638727387283872938730387313873238733387343873538736387373873838739387403874138742387433874438745387463874738748387493875038751387523875338754387553875638757387583875938760387613876238763387643876538766387673876838769387703877138772387733877438775387763877738778387793878038781387823878338784387853878638787387883878938790387913879238793387943879538796387973879838799388003880138802388033880438805388063880738808388093881038811388123881338814388153881638817388183881938820388213882238823388243882538826388273882838829388303883138832388333883438835388363883738838388393884038841388423884338844388453884638847388483884938850388513885238853388543885538856388573885838859388603886138862388633886438865388663886738868388693887038871388723887338874388753887638877388783887938880388813888238883388843888538886388873888838889388903889138892388933889438895388963889738898388993890038901389023890338904389053890638907389083890938910389113891238913389143891538916389173891838919389203892138922389233892438925389263892738928389293893038931389323893338934389353893638937389383893938940389413894238943389443894538946389473894838949389503895138952389533895438955389563895738958389593896038961389623896338964389653896638967389683896938970389713897238973389743897538976389773897838979389803898138982389833898438985389863898738988389893899038991389923899338994389953899638997389983899939000390013900239003390043900539006390073900839009390103901139012390133901439015390163901739018390193902039021390223902339024390253902639027390283902939030390313903239033390343903539036390373903839039390403904139042390433904439045390463904739048390493905039051390523905339054390553905639057390583905939060390613906239063390643906539066390673906839069390703907139072390733907439075390763907739078390793908039081390823908339084390853908639087390883908939090390913909239093390943909539096390973909839099391003910139102391033910439105391063910739108391093911039111391123911339114391153911639117391183911939120391213912239123391243912539126391273912839129391303913139132391333913439135391363913739138391393914039141391423914339144391453914639147391483914939150391513915239153391543915539156391573915839159391603916139162391633916439165391663916739168391693917039171391723917339174391753917639177391783917939180391813918239183391843918539186391873918839189391903919139192391933919439195391963919739198391993920039201392023920339204392053920639207392083920939210392113921239213392143921539216392173921839219392203922139222392233922439225392263922739228392293923039231392323923339234392353923639237392383923939240392413924239243392443924539246392473924839249392503925139252392533925439255392563925739258392593926039261392623926339264392653926639267392683926939270392713927239273392743927539276392773927839279392803928139282392833928439285392863928739288392893929039291392923929339294392953929639297392983929939300393013930239303393043930539306393073930839309393103931139312393133931439315393163931739318393193932039321393223932339324393253932639327393283932939330393313933239333393343933539336393373933839339393403934139342393433934439345393463934739348393493935039351393523935339354393553935639357393583935939360393613936239363393643936539366393673936839369393703937139372393733937439375393763937739378393793938039381393823938339384393853938639387393883938939390393913939239393393943939539396393973939839399394003940139402394033940439405394063940739408394093941039411394123941339414394153941639417394183941939420394213942239423394243942539426394273942839429394303943139432394333943439435394363943739438394393944039441394423944339444394453944639447394483944939450394513945239453394543945539456394573945839459394603946139462394633946439465394663946739468394693947039471394723947339474394753947639477394783947939480394813948239483394843948539486394873948839489394903949139492394933949439495394963949739498394993950039501395023950339504395053950639507395083950939510395113951239513395143951539516395173951839519395203952139522395233952439525395263952739528395293953039531395323953339534395353953639537395383953939540395413954239543395443954539546395473954839549395503955139552395533955439555395563955739558395593956039561395623956339564395653956639567395683956939570395713957239573395743957539576395773957839579395803958139582395833958439585395863958739588395893959039591395923959339594395953959639597395983959939600396013960239603396043960539606396073960839609396103961139612396133961439615396163961739618396193962039621396223962339624396253962639627396283962939630396313963239633396343963539636396373963839639396403964139642396433964439645396463964739648396493965039651396523965339654396553965639657396583965939660396613966239663396643966539666396673966839669396703967139672396733967439675396763967739678396793968039681396823968339684396853968639687396883968939690396913969239693396943969539696396973969839699397003970139702397033970439705397063970739708397093971039711397123971339714397153971639717397183971939720397213972239723397243972539726397273972839729397303973139732397333973439735397363973739738397393974039741397423974339744397453974639747397483974939750397513975239753397543975539756397573975839759397603976139762397633976439765397663976739768397693977039771397723977339774397753977639777397783977939780397813978239783397843978539786397873978839789397903979139792397933979439795397963979739798397993980039801398023980339804398053980639807398083980939810398113981239813398143981539816398173981839819398203982139822398233982439825398263982739828398293983039831398323983339834398353983639837398383983939840398413984239843398443984539846398473984839849398503985139852398533985439855398563985739858398593986039861398623986339864398653986639867398683986939870398713987239873398743987539876398773987839879398803988139882398833988439885398863988739888398893989039891398923989339894398953989639897398983989939900399013990239903399043990539906399073990839909399103991139912399133991439915399163991739918399193992039921399223992339924399253992639927399283992939930399313993239933399343993539936399373993839939399403994139942399433994439945399463994739948399493995039951399523995339954399553995639957399583995939960399613996239963399643996539966399673996839969399703997139972399733997439975399763997739978399793998039981399823998339984399853998639987399883998939990399913999239993399943999539996399973999839999400004000140002400034000440005400064000740008400094001040011400124001340014400154001640017400184001940020400214002240023400244002540026400274002840029400304003140032400334003440035400364003740038400394004040041400424004340044400454004640047400484004940050400514005240053400544005540056400574005840059400604006140062400634006440065400664006740068400694007040071400724007340074400754007640077400784007940080400814008240083400844008540086400874008840089400904009140092400934009440095400964009740098400994010040101401024010340104401054010640107401084010940110401114011240113401144011540116401174011840119401204012140122401234012440125401264012740128401294013040131401324013340134401354013640137401384013940140401414014240143401444014540146401474014840149401504015140152401534015440155401564015740158401594016040161401624016340164401654016640167401684016940170401714017240173401744017540176401774017840179401804018140182401834018440185401864018740188401894019040191401924019340194401954019640197401984019940200402014020240203402044020540206402074020840209402104021140212402134021440215402164021740218402194022040221402224022340224402254022640227402284022940230402314023240233402344023540236402374023840239402404024140242402434024440245402464024740248402494025040251402524025340254402554025640257402584025940260402614026240263402644026540266402674026840269402704027140272402734027440275402764027740278402794028040281402824028340284402854028640287402884028940290402914029240293402944029540296402974029840299403004030140302403034030440305403064030740308403094031040311403124031340314403154031640317403184031940320403214032240323403244032540326403274032840329403304033140332403334033440335403364033740338403394034040341403424034340344403454034640347403484034940350403514035240353403544035540356403574035840359403604036140362403634036440365403664036740368403694037040371403724037340374403754037640377403784037940380403814038240383403844038540386403874038840389403904039140392403934039440395403964039740398403994040040401404024040340404404054040640407404084040940410404114041240413404144041540416404174041840419404204042140422404234042440425404264042740428404294043040431404324043340434404354043640437404384043940440404414044240443404444044540446404474044840449404504045140452404534045440455404564045740458404594046040461404624046340464404654046640467404684046940470404714047240473404744047540476404774047840479404804048140482404834048440485404864048740488404894049040491404924049340494404954049640497404984049940500405014050240503405044050540506405074050840509405104051140512405134051440515405164051740518405194052040521405224052340524405254052640527405284052940530405314053240533405344053540536405374053840539405404054140542405434054440545405464054740548405494055040551405524055340554405554055640557405584055940560405614056240563405644056540566405674056840569405704057140572405734057440575405764057740578405794058040581405824058340584405854058640587405884058940590405914059240593405944059540596405974059840599406004060140602406034060440605406064060740608406094061040611406124061340614406154061640617406184061940620406214062240623406244062540626406274062840629406304063140632406334063440635406364063740638406394064040641406424064340644406454064640647406484064940650406514065240653406544065540656406574065840659406604066140662406634066440665406664066740668406694067040671406724067340674406754067640677406784067940680406814068240683406844068540686406874068840689406904069140692406934069440695406964069740698406994070040701407024070340704407054070640707407084070940710407114071240713407144071540716407174071840719407204072140722407234072440725407264072740728407294073040731407324073340734407354073640737407384073940740407414074240743407444074540746407474074840749407504075140752407534075440755407564075740758407594076040761407624076340764407654076640767407684076940770407714077240773407744077540776407774077840779407804078140782407834078440785407864078740788407894079040791407924079340794407954079640797407984079940800408014080240803408044080540806408074080840809408104081140812408134081440815408164081740818408194082040821408224082340824408254082640827408284082940830408314083240833408344083540836408374083840839408404084140842408434084440845408464084740848408494085040851408524085340854408554085640857408584085940860408614086240863408644086540866408674086840869408704087140872408734087440875408764087740878408794088040881408824088340884408854088640887408884088940890408914089240893408944089540896408974089840899409004090140902409034090440905409064090740908409094091040911409124091340914409154091640917409184091940920409214092240923409244092540926409274092840929409304093140932409334093440935409364093740938409394094040941409424094340944409454094640947409484094940950409514095240953409544095540956409574095840959409604096140962409634096440965409664096740968409694097040971409724097340974409754097640977409784097940980409814098240983409844098540986409874098840989409904099140992409934099440995409964099740998409994100041001410024100341004410054100641007410084100941010410114101241013410144101541016410174101841019410204102141022410234102441025410264102741028410294103041031410324103341034410354103641037410384103941040410414104241043410444104541046410474104841049410504105141052410534105441055410564105741058410594106041061410624106341064410654106641067410684106941070410714107241073410744107541076410774107841079410804108141082410834108441085410864108741088410894109041091410924109341094410954109641097410984109941100411014110241103411044110541106411074110841109411104111141112411134111441115411164111741118411194112041121411224112341124411254112641127411284112941130411314113241133411344113541136411374113841139411404114141142411434114441145411464114741148411494115041151411524115341154411554115641157411584115941160411614116241163411644116541166411674116841169411704117141172411734117441175411764117741178411794118041181411824118341184411854118641187411884118941190411914119241193411944119541196411974119841199412004120141202412034120441205412064120741208412094121041211412124121341214412154121641217412184121941220412214122241223412244122541226412274122841229412304123141232412334123441235412364123741238412394124041241412424124341244412454124641247412484124941250412514125241253412544125541256412574125841259412604126141262412634126441265412664126741268412694127041271412724127341274412754127641277412784127941280412814128241283412844128541286412874128841289412904129141292412934129441295412964129741298412994130041301413024130341304413054130641307413084130941310413114131241313413144131541316413174131841319413204132141322413234132441325413264132741328413294133041331413324133341334413354133641337413384133941340413414134241343413444134541346413474134841349413504135141352413534135441355413564135741358413594136041361413624136341364413654136641367413684136941370413714137241373413744137541376413774137841379413804138141382413834138441385413864138741388413894139041391413924139341394413954139641397413984139941400414014140241403414044140541406414074140841409414104141141412414134141441415414164141741418414194142041421414224142341424414254142641427414284142941430414314143241433414344143541436414374143841439414404144141442414434144441445414464144741448414494145041451414524145341454414554145641457414584145941460414614146241463414644146541466414674146841469414704147141472414734147441475414764147741478414794148041481414824148341484414854148641487414884148941490414914149241493414944149541496414974149841499415004150141502415034150441505415064150741508415094151041511415124151341514415154151641517415184151941520415214152241523415244152541526415274152841529415304153141532415334153441535415364153741538415394154041541415424154341544415454154641547415484154941550415514155241553415544155541556415574155841559415604156141562415634156441565415664156741568415694157041571415724157341574415754157641577415784157941580415814158241583415844158541586415874158841589415904159141592415934159441595415964159741598415994160041601416024160341604416054160641607416084160941610416114161241613416144161541616416174161841619416204162141622416234162441625416264162741628416294163041631416324163341634416354163641637416384163941640416414164241643416444164541646416474164841649416504165141652416534165441655416564165741658416594166041661416624166341664416654166641667416684166941670416714167241673416744167541676416774167841679416804168141682416834168441685416864168741688416894169041691416924169341694416954169641697416984169941700417014170241703417044170541706417074170841709417104171141712417134171441715417164171741718417194172041721417224172341724417254172641727417284172941730417314173241733417344173541736417374173841739417404174141742417434174441745417464174741748417494175041751417524175341754417554175641757417584175941760417614176241763417644176541766417674176841769417704177141772417734177441775417764177741778417794178041781417824178341784417854178641787417884178941790417914179241793417944179541796417974179841799418004180141802418034180441805418064180741808418094181041811418124181341814418154181641817418184181941820418214182241823418244182541826418274182841829418304183141832418334183441835418364183741838418394184041841418424184341844418454184641847418484184941850418514185241853418544185541856418574185841859418604186141862418634186441865418664186741868418694187041871418724187341874418754187641877418784187941880418814188241883418844188541886418874188841889418904189141892418934189441895418964189741898418994190041901419024190341904419054190641907419084190941910419114191241913419144191541916419174191841919419204192141922419234192441925419264192741928419294193041931419324193341934419354193641937419384193941940419414194241943419444194541946419474194841949419504195141952419534195441955419564195741958419594196041961419624196341964419654196641967419684196941970419714197241973419744197541976419774197841979419804198141982419834198441985419864198741988419894199041991419924199341994419954199641997419984199942000420014200242003420044200542006420074200842009420104201142012420134201442015420164201742018420194202042021420224202342024420254202642027420284202942030420314203242033420344203542036420374203842039420404204142042420434204442045420464204742048420494205042051420524205342054420554205642057420584205942060420614206242063420644206542066420674206842069420704207142072420734207442075420764207742078420794208042081420824208342084420854208642087420884208942090420914209242093420944209542096420974209842099421004210142102421034210442105421064210742108421094211042111421124211342114421154211642117421184211942120421214212242123421244212542126421274212842129421304213142132421334213442135421364213742138421394214042141421424214342144421454214642147421484214942150421514215242153421544215542156421574215842159421604216142162421634216442165421664216742168421694217042171421724217342174421754217642177421784217942180421814218242183421844218542186421874218842189421904219142192421934219442195421964219742198421994220042201422024220342204422054220642207422084220942210422114221242213422144221542216422174221842219422204222142222422234222442225422264222742228422294223042231422324223342234422354223642237422384223942240422414224242243422444224542246422474224842249422504225142252422534225442255422564225742258422594226042261422624226342264422654226642267422684226942270422714227242273422744227542276422774227842279422804228142282422834228442285422864228742288422894229042291422924229342294422954229642297422984229942300423014230242303423044230542306423074230842309423104231142312423134231442315423164231742318423194232042321423224232342324423254232642327423284232942330423314233242333423344233542336423374233842339423404234142342423434234442345423464234742348423494235042351423524235342354423554235642357423584235942360423614236242363423644236542366423674236842369423704237142372423734237442375423764237742378423794238042381423824238342384423854238642387423884238942390423914239242393423944239542396423974239842399424004240142402424034240442405424064240742408424094241042411424124241342414424154241642417424184241942420424214242242423424244242542426424274242842429424304243142432424334243442435424364243742438424394244042441424424244342444424454244642447424484244942450424514245242453424544245542456424574245842459424604246142462424634246442465424664246742468424694247042471424724247342474424754247642477424784247942480424814248242483424844248542486424874248842489424904249142492424934249442495424964249742498424994250042501425024250342504425054250642507425084250942510425114251242513425144251542516425174251842519425204252142522425234252442525425264252742528425294253042531425324253342534425354253642537425384253942540425414254242543425444254542546425474254842549425504255142552425534255442555425564255742558425594256042561425624256342564425654256642567425684256942570425714257242573425744257542576425774257842579425804258142582425834258442585425864258742588425894259042591425924259342594425954259642597425984259942600426014260242603426044260542606426074260842609426104261142612426134261442615426164261742618426194262042621426224262342624426254262642627426284262942630426314263242633426344263542636426374263842639426404264142642426434264442645426464264742648426494265042651426524265342654426554265642657426584265942660426614266242663426644266542666426674266842669426704267142672426734267442675426764267742678426794268042681426824268342684426854268642687426884268942690426914269242693426944269542696426974269842699427004270142702427034270442705427064270742708427094271042711427124271342714427154271642717427184271942720427214272242723427244272542726427274272842729427304273142732427334273442735427364273742738427394274042741427424274342744427454274642747427484274942750427514275242753427544275542756427574275842759427604276142762427634276442765427664276742768427694277042771427724277342774427754277642777427784277942780427814278242783427844278542786427874278842789427904279142792427934279442795427964279742798427994280042801428024280342804428054280642807428084280942810428114281242813428144281542816428174281842819428204282142822428234282442825428264282742828428294283042831428324283342834428354283642837428384283942840428414284242843428444284542846428474284842849428504285142852428534285442855428564285742858428594286042861428624286342864428654286642867428684286942870428714287242873428744287542876428774287842879428804288142882428834288442885428864288742888428894289042891428924289342894428954289642897428984289942900429014290242903429044290542906429074290842909429104291142912429134291442915429164291742918429194292042921429224292342924429254292642927429284292942930429314293242933429344293542936429374293842939429404294142942429434294442945429464294742948429494295042951429524295342954429554295642957429584295942960429614296242963429644296542966429674296842969429704297142972429734297442975429764297742978429794298042981429824298342984429854298642987429884298942990429914299242993429944299542996429974299842999430004300143002430034300443005430064300743008430094301043011430124301343014430154301643017430184301943020430214302243023430244302543026430274302843029430304303143032430334303443035430364303743038430394304043041430424304343044430454304643047430484304943050430514305243053430544305543056430574305843059430604306143062430634306443065430664306743068430694307043071430724307343074430754307643077430784307943080430814308243083430844308543086430874308843089430904309143092430934309443095430964309743098430994310043101431024310343104431054310643107431084310943110431114311243113431144311543116431174311843119431204312143122431234312443125431264312743128431294313043131431324313343134431354313643137431384313943140431414314243143431444314543146431474314843149431504315143152431534315443155431564315743158431594316043161431624316343164431654316643167431684316943170431714317243173431744317543176431774317843179431804318143182431834318443185431864318743188431894319043191431924319343194431954319643197431984319943200432014320243203432044320543206432074320843209432104321143212432134321443215432164321743218432194322043221432224322343224432254322643227432284322943230432314323243233432344323543236432374323843239432404324143242432434324443245432464324743248432494325043251432524325343254432554325643257432584325943260432614326243263432644326543266432674326843269432704327143272432734327443275432764327743278432794328043281432824328343284432854328643287432884328943290432914329243293432944329543296432974329843299433004330143302433034330443305433064330743308433094331043311433124331343314433154331643317433184331943320433214332243323433244332543326433274332843329433304333143332433334333443335433364333743338433394334043341433424334343344433454334643347433484334943350433514335243353433544335543356433574335843359433604336143362433634336443365433664336743368433694337043371433724337343374433754337643377433784337943380433814338243383433844338543386433874338843389433904339143392433934339443395433964339743398433994340043401434024340343404434054340643407434084340943410434114341243413434144341543416434174341843419434204342143422434234342443425434264342743428434294343043431434324343343434434354343643437434384343943440434414344243443434444344543446434474344843449434504345143452434534345443455434564345743458434594346043461434624346343464434654346643467434684346943470434714347243473434744347543476434774347843479434804348143482434834348443485434864348743488434894349043491434924349343494434954349643497434984349943500435014350243503435044350543506435074350843509435104351143512435134351443515435164351743518435194352043521435224352343524435254352643527435284352943530435314353243533435344353543536435374353843539435404354143542435434354443545435464354743548435494355043551435524355343554435554355643557435584355943560435614356243563435644356543566435674356843569435704357143572435734357443575435764357743578435794358043581435824358343584435854358643587435884358943590435914359243593435944359543596435974359843599436004360143602436034360443605436064360743608436094361043611436124361343614436154361643617436184361943620436214362243623436244362543626436274362843629436304363143632436334363443635436364363743638436394364043641436424364343644436454364643647436484364943650436514365243653436544365543656436574365843659436604366143662436634366443665436664366743668436694367043671436724367343674436754367643677436784367943680436814368243683436844368543686436874368843689436904369143692436934369443695436964369743698436994370043701437024370343704437054370643707437084370943710437114371243713437144371543716437174371843719437204372143722437234372443725437264372743728437294373043731437324373343734437354373643737437384373943740437414374243743437444374543746437474374843749437504375143752437534375443755437564375743758437594376043761437624376343764437654376643767437684376943770437714377243773437744377543776437774377843779437804378143782437834378443785437864378743788437894379043791437924379343794437954379643797437984379943800438014380243803438044380543806438074380843809438104381143812438134381443815438164381743818438194382043821438224382343824438254382643827438284382943830438314383243833438344383543836438374383843839438404384143842438434384443845438464384743848438494385043851438524385343854438554385643857438584385943860438614386243863438644386543866438674386843869438704387143872438734387443875438764387743878438794388043881438824388343884438854388643887438884388943890438914389243893438944389543896438974389843899439004390143902439034390443905439064390743908439094391043911439124391343914439154391643917439184391943920439214392243923439244392543926439274392843929439304393143932439334393443935439364393743938439394394043941439424394343944439454394643947439484394943950439514395243953439544395543956439574395843959439604396143962439634396443965439664396743968439694397043971439724397343974439754397643977439784397943980439814398243983439844398543986439874398843989439904399143992439934399443995439964399743998439994400044001440024400344004440054400644007440084400944010440114401244013440144401544016440174401844019440204402144022440234402444025440264402744028440294403044031440324403344034440354403644037440384403944040440414404244043440444404544046440474404844049440504405144052440534405444055440564405744058440594406044061440624406344064440654406644067440684406944070440714407244073440744407544076440774407844079440804408144082440834408444085440864408744088440894409044091440924409344094440954409644097440984409944100441014410244103441044410544106441074410844109441104411144112441134411444115441164411744118441194412044121441224412344124441254412644127441284412944130441314413244133441344413544136441374413844139441404414144142441434414444145441464414744148441494415044151441524415344154441554415644157441584415944160441614416244163441644416544166441674416844169441704417144172441734417444175441764417744178441794418044181441824418344184441854418644187441884418944190441914419244193441944419544196441974419844199442004420144202442034420444205442064420744208442094421044211442124421344214442154421644217442184421944220442214422244223442244422544226442274422844229442304423144232442334423444235442364423744238442394424044241442424424344244442454424644247442484424944250442514425244253442544425544256442574425844259442604426144262442634426444265442664426744268442694427044271442724427344274442754427644277442784427944280442814428244283442844428544286442874428844289442904429144292442934429444295442964429744298442994430044301443024430344304443054430644307443084430944310443114431244313443144431544316443174431844319443204432144322443234432444325443264432744328443294433044331443324433344334443354433644337443384433944340443414434244343443444434544346443474434844349443504435144352443534435444355443564435744358443594436044361443624436344364443654436644367443684436944370443714437244373443744437544376443774437844379443804438144382443834438444385443864438744388443894439044391443924439344394443954439644397443984439944400444014440244403444044440544406444074440844409444104441144412444134441444415444164441744418444194442044421444224442344424444254442644427444284442944430444314443244433444344443544436444374443844439444404444144442444434444444445444464444744448444494445044451444524445344454444554445644457444584445944460444614446244463444644446544466444674446844469444704447144472444734447444475444764447744478444794448044481444824448344484444854448644487444884448944490444914449244493444944449544496444974449844499445004450144502445034450444505445064450744508445094451044511445124451344514445154451644517445184451944520445214452244523445244452544526445274452844529445304453144532445334453444535445364453744538445394454044541445424454344544445454454644547445484454944550445514455244553445544455544556445574455844559445604456144562445634456444565445664456744568445694457044571445724457344574445754457644577445784457944580445814458244583445844458544586445874458844589445904459144592445934459444595445964459744598445994460044601446024460344604446054460644607446084460944610446114461244613446144461544616446174461844619446204462144622446234462444625446264462744628446294463044631446324463344634446354463644637446384463944640446414464244643446444464544646446474464844649446504465144652446534465444655446564465744658446594466044661446624466344664446654466644667446684466944670446714467244673446744467544676446774467844679446804468144682446834468444685446864468744688446894469044691446924469344694446954469644697446984469944700447014470244703447044470544706447074470844709447104471144712447134471444715447164471744718447194472044721447224472344724447254472644727447284472944730447314473244733447344473544736447374473844739447404474144742447434474444745447464474744748447494475044751447524475344754447554475644757447584475944760447614476244763447644476544766447674476844769447704477144772447734477444775447764477744778447794478044781447824478344784447854478644787447884478944790447914479244793447944479544796447974479844799448004480144802448034480444805448064480744808448094481044811448124481344814448154481644817448184481944820448214482244823448244482544826448274482844829448304483144832448334483444835448364483744838448394484044841448424484344844448454484644847448484484944850448514485244853448544485544856448574485844859448604486144862448634486444865448664486744868448694487044871448724487344874448754487644877448784487944880448814488244883448844488544886448874488844889448904489144892448934489444895448964489744898448994490044901449024490344904449054490644907449084490944910449114491244913449144491544916449174491844919449204492144922449234492444925449264492744928449294493044931449324493344934449354493644937449384493944940449414494244943449444494544946449474494844949449504495144952449534495444955449564495744958449594496044961449624496344964449654496644967449684496944970449714497244973449744497544976449774497844979449804498144982449834498444985449864498744988449894499044991449924499344994449954499644997449984499945000450014500245003450044500545006450074500845009450104501145012450134501445015450164501745018450194502045021450224502345024450254502645027450284502945030450314503245033450344503545036450374503845039450404504145042450434504445045450464504745048450494505045051450524505345054450554505645057450584505945060450614506245063450644506545066450674506845069450704507145072450734507445075450764507745078450794508045081450824508345084450854508645087450884508945090450914509245093450944509545096450974509845099451004510145102451034510445105451064510745108451094511045111451124511345114451154511645117451184511945120451214512245123451244512545126451274512845129451304513145132451334513445135451364513745138451394514045141451424514345144451454514645147451484514945150451514515245153451544515545156451574515845159451604516145162451634516445165451664516745168451694517045171451724517345174451754517645177451784517945180451814518245183451844518545186451874518845189451904519145192451934519445195451964519745198451994520045201452024520345204452054520645207452084520945210452114521245213452144521545216452174521845219452204522145222452234522445225452264522745228452294523045231452324523345234452354523645237452384523945240452414524245243452444524545246452474524845249452504525145252452534525445255452564525745258452594526045261452624526345264452654526645267452684526945270452714527245273452744527545276452774527845279452804528145282452834528445285452864528745288452894529045291452924529345294452954529645297452984529945300453014530245303453044530545306453074530845309453104531145312453134531445315453164531745318453194532045321453224532345324453254532645327453284532945330453314533245333453344533545336453374533845339453404534145342453434534445345453464534745348453494535045351453524535345354453554535645357453584535945360453614536245363453644536545366453674536845369453704537145372453734537445375453764537745378453794538045381453824538345384453854538645387453884538945390453914539245393453944539545396453974539845399454004540145402454034540445405454064540745408454094541045411454124541345414454154541645417454184541945420454214542245423454244542545426454274542845429454304543145432454334543445435454364543745438454394544045441454424544345444454454544645447454484544945450454514545245453454544545545456454574545845459454604546145462454634546445465454664546745468454694547045471454724547345474454754547645477454784547945480454814548245483454844548545486454874548845489454904549145492454934549445495454964549745498454994550045501455024550345504455054550645507455084550945510455114551245513455144551545516455174551845519455204552145522455234552445525455264552745528455294553045531455324553345534455354553645537455384553945540455414554245543455444554545546455474554845549455504555145552455534555445555455564555745558455594556045561455624556345564455654556645567455684556945570455714557245573455744557545576455774557845579455804558145582455834558445585455864558745588455894559045591455924559345594455954559645597455984559945600456014560245603456044560545606456074560845609456104561145612456134561445615456164561745618456194562045621456224562345624456254562645627456284562945630456314563245633456344563545636456374563845639456404564145642456434564445645456464564745648456494565045651456524565345654456554565645657456584565945660456614566245663456644566545666456674566845669456704567145672456734567445675456764567745678456794568045681456824568345684456854568645687456884568945690456914569245693456944569545696456974569845699457004570145702457034570445705457064570745708457094571045711457124571345714457154571645717457184571945720457214572245723457244572545726457274572845729457304573145732457334573445735457364573745738457394574045741457424574345744457454574645747457484574945750457514575245753457544575545756457574575845759457604576145762457634576445765457664576745768457694577045771457724577345774457754577645777457784577945780457814578245783457844578545786457874578845789457904579145792457934579445795457964579745798457994580045801458024580345804458054580645807458084580945810458114581245813458144581545816458174581845819458204582145822458234582445825458264582745828458294583045831458324583345834458354583645837458384583945840458414584245843458444584545846458474584845849458504585145852458534585445855458564585745858458594586045861458624586345864458654586645867458684586945870458714587245873458744587545876458774587845879458804588145882458834588445885458864588745888458894589045891458924589345894458954589645897458984589945900459014590245903459044590545906459074590845909459104591145912459134591445915459164591745918459194592045921459224592345924459254592645927459284592945930459314593245933459344593545936459374593845939459404594145942459434594445945459464594745948459494595045951459524595345954459554595645957459584595945960459614596245963459644596545966459674596845969459704597145972459734597445975459764597745978459794598045981459824598345984459854598645987459884598945990459914599245993459944599545996459974599845999460004600146002460034600446005460064600746008460094601046011460124601346014460154601646017460184601946020460214602246023460244602546026460274602846029460304603146032460334603446035460364603746038460394604046041460424604346044460454604646047460484604946050460514605246053460544605546056460574605846059460604606146062460634606446065460664606746068460694607046071460724607346074460754607646077460784607946080460814608246083460844608546086460874608846089460904609146092460934609446095460964609746098460994610046101461024610346104461054610646107461084610946110461114611246113461144611546116461174611846119461204612146122461234612446125461264612746128461294613046131461324613346134461354613646137461384613946140461414614246143461444614546146461474614846149461504615146152461534615446155461564615746158461594616046161461624616346164461654616646167461684616946170461714617246173461744617546176461774617846179461804618146182461834618446185461864618746188461894619046191461924619346194461954619646197461984619946200462014620246203462044620546206462074620846209462104621146212462134621446215462164621746218462194622046221462224622346224462254622646227462284622946230462314623246233462344623546236462374623846239462404624146242462434624446245462464624746248462494625046251462524625346254462554625646257462584625946260462614626246263462644626546266462674626846269462704627146272462734627446275462764627746278462794628046281462824628346284462854628646287462884628946290462914629246293462944629546296462974629846299463004630146302463034630446305463064630746308463094631046311463124631346314463154631646317463184631946320463214632246323463244632546326463274632846329463304633146332463334633446335463364633746338463394634046341463424634346344463454634646347463484634946350463514635246353463544635546356463574635846359463604636146362463634636446365463664636746368463694637046371463724637346374463754637646377463784637946380463814638246383463844638546386463874638846389463904639146392463934639446395463964639746398463994640046401464024640346404464054640646407464084640946410464114641246413464144641546416464174641846419464204642146422464234642446425464264642746428464294643046431464324643346434464354643646437464384643946440464414644246443464444644546446464474644846449464504645146452464534645446455464564645746458464594646046461464624646346464464654646646467464684646946470464714647246473464744647546476464774647846479464804648146482464834648446485464864648746488464894649046491464924649346494464954649646497464984649946500465014650246503465044650546506465074650846509465104651146512465134651446515465164651746518465194652046521465224652346524465254652646527465284652946530465314653246533465344653546536465374653846539465404654146542465434654446545465464654746548465494655046551465524655346554465554655646557465584655946560465614656246563465644656546566465674656846569465704657146572465734657446575465764657746578465794658046581465824658346584465854658646587465884658946590465914659246593465944659546596465974659846599466004660146602466034660446605466064660746608466094661046611466124661346614466154661646617466184661946620466214662246623466244662546626466274662846629466304663146632466334663446635466364663746638466394664046641466424664346644466454664646647466484664946650466514665246653466544665546656466574665846659466604666146662466634666446665466664666746668466694667046671466724667346674466754667646677466784667946680466814668246683466844668546686466874668846689466904669146692466934669446695466964669746698466994670046701467024670346704467054670646707467084670946710467114671246713467144671546716467174671846719467204672146722467234672446725467264672746728467294673046731467324673346734467354673646737467384673946740467414674246743467444674546746467474674846749467504675146752467534675446755467564675746758467594676046761467624676346764467654676646767467684676946770467714677246773467744677546776467774677846779467804678146782467834678446785467864678746788467894679046791467924679346794467954679646797467984679946800468014680246803468044680546806468074680846809468104681146812468134681446815468164681746818468194682046821468224682346824468254682646827468284682946830468314683246833468344683546836468374683846839468404684146842468434684446845468464684746848468494685046851468524685346854468554685646857468584685946860468614686246863468644686546866468674686846869468704687146872468734687446875468764687746878468794688046881468824688346884468854688646887468884688946890468914689246893468944689546896468974689846899469004690146902469034690446905469064690746908469094691046911469124691346914469154691646917469184691946920469214692246923469244692546926469274692846929469304693146932469334693446935469364693746938469394694046941469424694346944469454694646947469484694946950469514695246953469544695546956469574695846959469604696146962469634696446965469664696746968469694697046971469724697346974469754697646977469784697946980469814698246983469844698546986469874698846989469904699146992469934699446995469964699746998469994700047001470024700347004470054700647007470084700947010470114701247013470144701547016470174701847019470204702147022470234702447025470264702747028470294703047031470324703347034470354703647037470384703947040470414704247043470444704547046470474704847049470504705147052470534705447055470564705747058470594706047061470624706347064470654706647067470684706947070470714707247073470744707547076470774707847079470804708147082470834708447085470864708747088470894709047091470924709347094470954709647097470984709947100471014710247103471044710547106471074710847109471104711147112471134711447115471164711747118471194712047121471224712347124471254712647127471284712947130471314713247133471344713547136471374713847139471404714147142471434714447145471464714747148471494715047151471524715347154471554715647157471584715947160471614716247163471644716547166471674716847169471704717147172471734717447175471764717747178471794718047181471824718347184471854718647187471884718947190471914719247193471944719547196471974719847199472004720147202472034720447205472064720747208472094721047211472124721347214472154721647217472184721947220472214722247223472244722547226472274722847229472304723147232472334723447235472364723747238472394724047241472424724347244472454724647247472484724947250472514725247253472544725547256472574725847259472604726147262472634726447265472664726747268472694727047271472724727347274472754727647277472784727947280472814728247283472844728547286472874728847289472904729147292472934729447295472964729747298472994730047301473024730347304473054730647307473084730947310473114731247313473144731547316473174731847319473204732147322473234732447325473264732747328473294733047331473324733347334473354733647337473384733947340473414734247343473444734547346473474734847349473504735147352473534735447355473564735747358473594736047361473624736347364473654736647367473684736947370473714737247373473744737547376473774737847379473804738147382473834738447385473864738747388473894739047391473924739347394473954739647397473984739947400474014740247403474044740547406474074740847409474104741147412474134741447415474164741747418474194742047421474224742347424474254742647427474284742947430474314743247433474344743547436474374743847439474404744147442474434744447445474464744747448474494745047451474524745347454474554745647457474584745947460474614746247463474644746547466474674746847469474704747147472474734747447475474764747747478474794748047481474824748347484474854748647487474884748947490474914749247493474944749547496474974749847499475004750147502475034750447505475064750747508475094751047511475124751347514475154751647517475184751947520475214752247523475244752547526475274752847529475304753147532475334753447535475364753747538475394754047541475424754347544475454754647547475484754947550475514755247553475544755547556475574755847559475604756147562475634756447565475664756747568475694757047571475724757347574475754757647577475784757947580475814758247583475844758547586475874758847589475904759147592475934759447595475964759747598475994760047601476024760347604476054760647607476084760947610476114761247613476144761547616476174761847619476204762147622476234762447625476264762747628476294763047631476324763347634476354763647637476384763947640476414764247643476444764547646476474764847649476504765147652476534765447655476564765747658476594766047661476624766347664476654766647667476684766947670476714767247673476744767547676476774767847679476804768147682476834768447685476864768747688476894769047691476924769347694476954769647697476984769947700477014770247703477044770547706477074770847709477104771147712477134771447715477164771747718477194772047721477224772347724477254772647727477284772947730477314773247733477344773547736477374773847739477404774147742477434774447745477464774747748477494775047751477524775347754477554775647757477584775947760477614776247763477644776547766477674776847769477704777147772477734777447775477764777747778477794778047781477824778347784477854778647787477884778947790477914779247793477944779547796477974779847799478004780147802478034780447805478064780747808478094781047811478124781347814478154781647817478184781947820478214782247823478244782547826478274782847829478304783147832478334783447835478364783747838478394784047841478424784347844478454784647847478484784947850478514785247853478544785547856478574785847859478604786147862478634786447865478664786747868478694787047871478724787347874478754787647877478784787947880478814788247883478844788547886478874788847889478904789147892478934789447895478964789747898478994790047901479024790347904479054790647907479084790947910479114791247913479144791547916479174791847919479204792147922479234792447925479264792747928479294793047931479324793347934479354793647937479384793947940479414794247943479444794547946479474794847949479504795147952479534795447955479564795747958479594796047961479624796347964479654796647967479684796947970479714797247973479744797547976479774797847979479804798147982479834798447985479864798747988479894799047991479924799347994479954799647997479984799948000480014800248003480044800548006480074800848009480104801148012480134801448015480164801748018480194802048021480224802348024480254802648027480284802948030480314803248033480344803548036480374803848039480404804148042480434804448045480464804748048480494805048051480524805348054480554805648057480584805948060480614806248063480644806548066480674806848069480704807148072480734807448075480764807748078480794808048081480824808348084480854808648087480884808948090480914809248093480944809548096480974809848099481004810148102481034810448105481064810748108481094811048111481124811348114481154811648117481184811948120481214812248123481244812548126481274812848129481304813148132481334813448135481364813748138481394814048141481424814348144481454814648147481484814948150481514815248153481544815548156481574815848159481604816148162481634816448165481664816748168481694817048171481724817348174481754817648177481784817948180481814818248183481844818548186481874818848189481904819148192481934819448195481964819748198481994820048201482024820348204482054820648207482084820948210482114821248213482144821548216482174821848219482204822148222482234822448225482264822748228482294823048231482324823348234482354823648237482384823948240482414824248243482444824548246482474824848249482504825148252482534825448255482564825748258482594826048261482624826348264482654826648267482684826948270482714827248273482744827548276482774827848279482804828148282482834828448285482864828748288482894829048291482924829348294482954829648297482984829948300483014830248303483044830548306483074830848309483104831148312483134831448315483164831748318483194832048321483224832348324483254832648327483284832948330483314833248333483344833548336483374833848339483404834148342483434834448345483464834748348483494835048351483524835348354483554835648357483584835948360483614836248363483644836548366483674836848369483704837148372483734837448375483764837748378483794838048381483824838348384483854838648387483884838948390483914839248393483944839548396483974839848399484004840148402484034840448405484064840748408484094841048411484124841348414484154841648417484184841948420484214842248423484244842548426484274842848429484304843148432484334843448435484364843748438484394844048441484424844348444484454844648447484484844948450484514845248453484544845548456484574845848459484604846148462484634846448465484664846748468484694847048471484724847348474484754847648477484784847948480484814848248483484844848548486484874848848489484904849148492484934849448495484964849748498484994850048501485024850348504485054850648507485084850948510485114851248513485144851548516485174851848519485204852148522485234852448525485264852748528485294853048531485324853348534485354853648537485384853948540485414854248543485444854548546485474854848549485504855148552485534855448555485564855748558485594856048561485624856348564485654856648567485684856948570485714857248573485744857548576485774857848579485804858148582485834858448585485864858748588485894859048591485924859348594485954859648597485984859948600486014860248603486044860548606486074860848609486104861148612486134861448615486164861748618486194862048621486224862348624486254862648627486284862948630486314863248633486344863548636486374863848639486404864148642486434864448645486464864748648486494865048651486524865348654486554865648657486584865948660486614866248663486644866548666486674866848669486704867148672486734867448675486764867748678486794868048681486824868348684486854868648687486884868948690486914869248693486944869548696486974869848699487004870148702487034870448705487064870748708487094871048711487124871348714487154871648717487184871948720487214872248723487244872548726487274872848729487304873148732487334873448735487364873748738487394874048741487424874348744487454874648747487484874948750487514875248753487544875548756487574875848759487604876148762487634876448765487664876748768487694877048771487724877348774487754877648777487784877948780487814878248783487844878548786487874878848789487904879148792487934879448795487964879748798487994880048801488024880348804488054880648807488084880948810488114881248813488144881548816488174881848819488204882148822488234882448825488264882748828488294883048831488324883348834488354883648837488384883948840488414884248843488444884548846488474884848849488504885148852488534885448855488564885748858488594886048861488624886348864488654886648867488684886948870488714887248873488744887548876488774887848879488804888148882488834888448885488864888748888488894889048891488924889348894488954889648897488984889948900489014890248903489044890548906489074890848909489104891148912489134891448915489164891748918489194892048921489224892348924489254892648927489284892948930489314893248933489344893548936489374893848939489404894148942489434894448945489464894748948489494895048951489524895348954489554895648957489584895948960489614896248963489644896548966489674896848969489704897148972489734897448975489764897748978489794898048981489824898348984489854898648987489884898948990489914899248993489944899548996489974899848999490004900149002490034900449005490064900749008490094901049011490124901349014490154901649017490184901949020490214902249023490244902549026490274902849029490304903149032490334903449035490364903749038490394904049041490424904349044490454904649047490484904949050490514905249053490544905549056490574905849059490604906149062490634906449065490664906749068490694907049071490724907349074490754907649077490784907949080490814908249083490844908549086490874908849089490904909149092490934909449095490964909749098490994910049101491024910349104491054910649107491084910949110491114911249113491144911549116491174911849119491204912149122491234912449125491264912749128491294913049131491324913349134491354913649137491384913949140491414914249143491444914549146491474914849149491504915149152491534915449155491564915749158491594916049161491624916349164491654916649167491684916949170491714917249173491744917549176491774917849179491804918149182491834918449185491864918749188491894919049191491924919349194491954919649197491984919949200492014920249203492044920549206492074920849209492104921149212492134921449215492164921749218492194922049221492224922349224492254922649227492284922949230492314923249233492344923549236492374923849239492404924149242492434924449245492464924749248492494925049251492524925349254492554925649257492584925949260492614926249263492644926549266492674926849269492704927149272492734927449275492764927749278492794928049281492824928349284492854928649287492884928949290492914929249293492944929549296492974929849299493004930149302493034930449305493064930749308493094931049311493124931349314493154931649317493184931949320493214932249323493244932549326493274932849329493304933149332493334933449335493364933749338493394934049341493424934349344493454934649347493484934949350493514935249353493544935549356493574935849359493604936149362493634936449365493664936749368493694937049371493724937349374493754937649377493784937949380493814938249383493844938549386493874938849389493904939149392493934939449395493964939749398493994940049401494024940349404494054940649407494084940949410494114941249413494144941549416494174941849419494204942149422494234942449425494264942749428494294943049431494324943349434494354943649437494384943949440494414944249443494444944549446494474944849449494504945149452494534945449455494564945749458494594946049461494624946349464494654946649467494684946949470494714947249473494744947549476494774947849479494804948149482494834948449485494864948749488494894949049491494924949349494494954949649497494984949949500495014950249503495044950549506495074950849509495104951149512495134951449515495164951749518495194952049521495224952349524495254952649527495284952949530495314953249533495344953549536495374953849539495404954149542495434954449545495464954749548495494955049551495524955349554495554955649557495584955949560495614956249563495644956549566495674956849569495704957149572495734957449575495764957749578495794958049581495824958349584495854958649587495884958949590495914959249593495944959549596495974959849599496004960149602496034960449605496064960749608496094961049611496124961349614496154961649617496184961949620496214962249623496244962549626496274962849629496304963149632496334963449635496364963749638496394964049641496424964349644496454964649647496484964949650496514965249653496544965549656496574965849659496604966149662496634966449665496664966749668496694967049671496724967349674496754967649677496784967949680496814968249683496844968549686496874968849689496904969149692496934969449695496964969749698496994970049701497024970349704497054970649707497084970949710497114971249713497144971549716497174971849719497204972149722497234972449725497264972749728497294973049731497324973349734497354973649737497384973949740497414974249743497444974549746497474974849749497504975149752497534975449755497564975749758497594976049761497624976349764497654976649767497684976949770497714977249773497744977549776497774977849779497804978149782497834978449785497864978749788497894979049791497924979349794497954979649797497984979949800498014980249803498044980549806498074980849809498104981149812498134981449815498164981749818498194982049821498224982349824498254982649827498284982949830498314983249833498344983549836498374983849839498404984149842498434984449845498464984749848498494985049851498524985349854498554985649857498584985949860498614986249863498644986549866498674986849869498704987149872498734987449875498764987749878498794988049881498824988349884498854988649887498884988949890498914989249893498944989549896498974989849899499004990149902499034990449905499064990749908499094991049911499124991349914499154991649917499184991949920499214992249923499244992549926499274992849929499304993149932499334993449935499364993749938499394994049941499424994349944499454994649947499484994949950499514995249953499544995549956499574995849959499604996149962499634996449965499664996749968499694997049971499724997349974499754997649977499784997949980499814998249983499844998549986499874998849989499904999149992499934999449995499964999749998499995000050001500025000350004500055000650007500085000950010500115001250013500145001550016500175001850019500205002150022500235002450025500265002750028500295003050031500325003350034500355003650037500385003950040500415004250043500445004550046500475004850049500505005150052500535005450055500565005750058500595006050061500625006350064500655006650067500685006950070500715007250073500745007550076500775007850079500805008150082500835008450085500865008750088500895009050091500925009350094500955009650097500985009950100501015010250103501045010550106501075010850109501105011150112501135011450115501165011750118501195012050121501225012350124501255012650127501285012950130501315013250133501345013550136501375013850139501405014150142501435014450145501465014750148501495015050151501525015350154501555015650157501585015950160501615016250163501645016550166501675016850169501705017150172501735017450175501765017750178501795018050181501825018350184501855018650187501885018950190501915019250193501945019550196501975019850199502005020150202502035020450205502065020750208502095021050211502125021350214502155021650217502185021950220502215022250223502245022550226502275022850229502305023150232502335023450235502365023750238502395024050241502425024350244502455024650247502485024950250502515025250253502545025550256502575025850259502605026150262502635026450265502665026750268502695027050271502725027350274502755027650277502785027950280502815028250283502845028550286502875028850289502905029150292502935029450295502965029750298502995030050301503025030350304503055030650307503085030950310503115031250313503145031550316503175031850319503205032150322503235032450325503265032750328503295033050331503325033350334503355033650337503385033950340503415034250343503445034550346503475034850349503505035150352503535035450355503565035750358503595036050361503625036350364503655036650367503685036950370503715037250373503745037550376503775037850379503805038150382503835038450385503865038750388503895039050391503925039350394503955039650397503985039950400504015040250403504045040550406504075040850409504105041150412504135041450415504165041750418504195042050421504225042350424504255042650427504285042950430504315043250433504345043550436504375043850439504405044150442504435044450445504465044750448504495045050451504525045350454504555045650457504585045950460504615046250463504645046550466504675046850469504705047150472504735047450475504765047750478504795048050481504825048350484504855048650487504885048950490504915049250493504945049550496504975049850499505005050150502505035050450505505065050750508505095051050511505125051350514505155051650517505185051950520505215052250523505245052550526505275052850529505305053150532505335053450535505365053750538505395054050541505425054350544505455054650547505485054950550505515055250553505545055550556505575055850559505605056150562505635056450565505665056750568505695057050571505725057350574505755057650577505785057950580505815058250583505845058550586505875058850589505905059150592505935059450595505965059750598505995060050601506025060350604506055060650607506085060950610506115061250613506145061550616506175061850619506205062150622506235062450625506265062750628506295063050631506325063350634506355063650637506385063950640506415064250643506445064550646506475064850649506505065150652506535065450655506565065750658506595066050661506625066350664506655066650667506685066950670506715067250673506745067550676506775067850679506805068150682506835068450685506865068750688506895069050691506925069350694506955069650697506985069950700507015070250703507045070550706507075070850709507105071150712507135071450715507165071750718507195072050721507225072350724507255072650727507285072950730507315073250733507345073550736507375073850739507405074150742507435074450745507465074750748507495075050751507525075350754507555075650757507585075950760507615076250763507645076550766507675076850769507705077150772507735077450775507765077750778507795078050781507825078350784507855078650787507885078950790507915079250793507945079550796507975079850799508005080150802508035080450805508065080750808508095081050811508125081350814508155081650817508185081950820508215082250823508245082550826508275082850829508305083150832508335083450835508365083750838508395084050841508425084350844508455084650847508485084950850508515085250853508545085550856508575085850859508605086150862508635086450865508665086750868508695087050871508725087350874508755087650877508785087950880508815088250883508845088550886508875088850889508905089150892508935089450895508965089750898508995090050901509025090350904509055090650907509085090950910509115091250913509145091550916509175091850919509205092150922509235092450925509265092750928509295093050931509325093350934509355093650937509385093950940509415094250943509445094550946509475094850949509505095150952509535095450955509565095750958509595096050961509625096350964509655096650967509685096950970509715097250973509745097550976509775097850979509805098150982509835098450985509865098750988509895099050991509925099350994509955099650997509985099951000510015100251003510045100551006510075100851009510105101151012510135101451015510165101751018510195102051021510225102351024510255102651027510285102951030510315103251033510345103551036510375103851039510405104151042510435104451045510465104751048510495105051051510525105351054510555105651057510585105951060510615106251063510645106551066510675106851069510705107151072510735107451075510765107751078510795108051081510825108351084510855108651087510885108951090510915109251093510945109551096510975109851099511005110151102511035110451105511065110751108511095111051111511125111351114511155111651117511185111951120511215112251123511245112551126511275112851129511305113151132511335113451135511365113751138511395114051141511425114351144511455114651147511485114951150511515115251153511545115551156511575115851159511605116151162511635116451165511665116751168511695117051171511725117351174511755117651177511785117951180511815118251183511845118551186511875118851189511905119151192511935119451195511965119751198511995120051201512025120351204512055120651207512085120951210512115121251213512145121551216512175121851219512205122151222512235122451225512265122751228512295123051231512325123351234512355123651237512385123951240512415124251243512445124551246512475124851249512505125151252512535125451255512565125751258512595126051261512625126351264512655126651267512685126951270512715127251273512745127551276512775127851279512805128151282512835128451285512865128751288512895129051291512925129351294512955129651297512985129951300513015130251303513045130551306513075130851309513105131151312513135131451315513165131751318513195132051321513225132351324513255132651327513285132951330513315133251333513345133551336513375133851339513405134151342513435134451345513465134751348513495135051351513525135351354513555135651357513585135951360513615136251363513645136551366513675136851369513705137151372513735137451375513765137751378513795138051381513825138351384513855138651387513885138951390513915139251393513945139551396513975139851399514005140151402514035140451405514065140751408514095141051411514125141351414514155141651417514185141951420514215142251423514245142551426514275142851429514305143151432514335143451435514365143751438514395144051441514425144351444514455144651447514485144951450514515145251453514545145551456514575145851459514605146151462514635146451465514665146751468514695147051471514725147351474514755147651477514785147951480514815148251483514845148551486514875148851489514905149151492514935149451495514965149751498514995150051501515025150351504515055150651507515085150951510515115151251513515145151551516515175151851519515205152151522515235152451525515265152751528515295153051531515325153351534515355153651537515385153951540515415154251543515445154551546515475154851549515505155151552515535155451555515565155751558515595156051561515625156351564515655156651567515685156951570515715157251573515745157551576515775157851579515805158151582515835158451585515865158751588515895159051591515925159351594515955159651597515985159951600516015160251603516045160551606516075160851609516105161151612516135161451615516165161751618516195162051621516225162351624516255162651627516285162951630516315163251633516345163551636516375163851639516405164151642516435164451645516465164751648516495165051651516525165351654516555165651657516585165951660516615166251663516645166551666516675166851669516705167151672516735167451675516765167751678516795168051681516825168351684516855168651687516885168951690516915169251693516945169551696516975169851699517005170151702517035170451705517065170751708517095171051711517125171351714517155171651717517185171951720517215172251723517245172551726517275172851729517305173151732517335173451735517365173751738517395174051741517425174351744517455174651747517485174951750517515175251753517545175551756517575175851759517605176151762517635176451765517665176751768517695177051771517725177351774517755177651777517785177951780517815178251783517845178551786517875178851789517905179151792517935179451795517965179751798517995180051801518025180351804518055180651807518085180951810518115181251813518145181551816518175181851819518205182151822518235182451825518265182751828518295183051831518325183351834518355183651837518385183951840518415184251843518445184551846518475184851849518505185151852518535185451855518565185751858518595186051861518625186351864518655186651867518685186951870518715187251873518745187551876518775187851879518805188151882518835188451885518865188751888518895189051891518925189351894518955189651897518985189951900519015190251903519045190551906519075190851909519105191151912519135191451915519165191751918519195192051921519225192351924519255192651927519285192951930519315193251933519345193551936519375193851939519405194151942519435194451945519465194751948519495195051951519525195351954519555195651957519585195951960519615196251963519645196551966519675196851969519705197151972519735197451975519765197751978519795198051981519825198351984519855198651987519885198951990519915199251993519945199551996519975199851999520005200152002520035200452005520065200752008520095201052011520125201352014520155201652017520185201952020520215202252023520245202552026520275202852029520305203152032520335203452035520365203752038520395204052041520425204352044520455204652047520485204952050520515205252053520545205552056520575205852059520605206152062520635206452065520665206752068520695207052071520725207352074520755207652077520785207952080520815208252083520845208552086520875208852089520905209152092520935209452095520965209752098520995210052101521025210352104521055210652107521085210952110521115211252113521145211552116521175211852119521205212152122521235212452125521265212752128521295213052131521325213352134521355213652137521385213952140521415214252143521445214552146521475214852149521505215152152521535215452155521565215752158521595216052161521625216352164521655216652167521685216952170521715217252173521745217552176521775217852179521805218152182521835218452185521865218752188521895219052191521925219352194521955219652197521985219952200522015220252203522045220552206522075220852209522105221152212522135221452215522165221752218522195222052221522225222352224522255222652227522285222952230522315223252233522345223552236522375223852239522405224152242522435224452245522465224752248522495225052251522525225352254522555225652257522585225952260522615226252263522645226552266522675226852269522705227152272522735227452275522765227752278522795228052281522825228352284522855228652287522885228952290522915229252293522945229552296522975229852299523005230152302523035230452305523065230752308523095231052311523125231352314523155231652317523185231952320523215232252323523245232552326523275232852329523305233152332523335233452335523365233752338523395234052341523425234352344523455234652347523485234952350523515235252353523545235552356523575235852359523605236152362523635236452365523665236752368523695237052371523725237352374523755237652377523785237952380523815238252383523845238552386523875238852389523905239152392523935239452395523965239752398523995240052401524025240352404524055240652407524085240952410524115241252413524145241552416524175241852419524205242152422524235242452425524265242752428524295243052431524325243352434524355243652437524385243952440524415244252443524445244552446524475244852449524505245152452524535245452455524565245752458524595246052461524625246352464524655246652467524685246952470524715247252473524745247552476524775247852479524805248152482524835248452485524865248752488524895249052491524925249352494524955249652497524985249952500525015250252503525045250552506525075250852509525105251152512525135251452515525165251752518525195252052521525225252352524525255252652527525285252952530525315253252533525345253552536525375253852539525405254152542525435254452545525465254752548525495255052551525525255352554525555255652557525585255952560525615256252563525645256552566525675256852569525705257152572525735257452575525765257752578525795258052581525825258352584525855258652587525885258952590525915259252593525945259552596525975259852599526005260152602526035260452605526065260752608526095261052611526125261352614526155261652617526185261952620526215262252623526245262552626526275262852629526305263152632526335263452635526365263752638526395264052641526425264352644526455264652647526485264952650526515265252653526545265552656526575265852659526605266152662526635266452665526665266752668526695267052671526725267352674526755267652677526785267952680526815268252683526845268552686526875268852689526905269152692526935269452695526965269752698526995270052701527025270352704527055270652707527085270952710527115271252713527145271552716527175271852719527205272152722527235272452725527265272752728527295273052731527325273352734527355273652737527385273952740527415274252743527445274552746527475274852749527505275152752527535275452755527565275752758527595276052761527625276352764527655276652767527685276952770527715277252773527745277552776527775277852779527805278152782527835278452785527865278752788527895279052791527925279352794527955279652797527985279952800528015280252803528045280552806528075280852809528105281152812528135281452815528165281752818528195282052821528225282352824528255282652827528285282952830528315283252833528345283552836528375283852839528405284152842528435284452845528465284752848528495285052851528525285352854528555285652857528585285952860528615286252863528645286552866528675286852869528705287152872528735287452875528765287752878528795288052881528825288352884528855288652887528885288952890528915289252893528945289552896528975289852899529005290152902529035290452905529065290752908529095291052911529125291352914529155291652917529185291952920529215292252923529245292552926529275292852929529305293152932529335293452935529365293752938529395294052941529425294352944529455294652947529485294952950529515295252953529545295552956529575295852959529605296152962529635296452965529665296752968529695297052971529725297352974529755297652977529785297952980529815298252983529845298552986529875298852989529905299152992529935299452995529965299752998529995300053001530025300353004530055300653007530085300953010530115301253013530145301553016530175301853019530205302153022530235302453025530265302753028530295303053031530325303353034530355303653037530385303953040530415304253043530445304553046530475304853049530505305153052530535305453055530565305753058530595306053061530625306353064530655306653067530685306953070530715307253073530745307553076530775307853079530805308153082530835308453085530865308753088530895309053091530925309353094530955309653097530985309953100531015310253103531045310553106531075310853109531105311153112531135311453115531165311753118531195312053121531225312353124531255312653127531285312953130531315313253133531345313553136531375313853139531405314153142531435314453145531465314753148531495315053151531525315353154531555315653157531585315953160531615316253163531645316553166531675316853169531705317153172531735317453175531765317753178531795318053181531825318353184531855318653187531885318953190531915319253193531945319553196531975319853199532005320153202532035320453205532065320753208532095321053211532125321353214532155321653217532185321953220532215322253223532245322553226532275322853229532305323153232532335323453235532365323753238532395324053241532425324353244532455324653247532485324953250532515325253253532545325553256532575325853259532605326153262532635326453265532665326753268532695327053271532725327353274532755327653277532785327953280532815328253283532845328553286532875328853289532905329153292532935329453295532965329753298532995330053301533025330353304533055330653307533085330953310533115331253313533145331553316533175331853319533205332153322533235332453325533265332753328533295333053331533325333353334533355333653337533385333953340533415334253343533445334553346533475334853349533505335153352533535335453355533565335753358533595336053361533625336353364533655336653367533685336953370533715337253373533745337553376533775337853379533805338153382533835338453385533865338753388533895339053391533925339353394533955339653397533985339953400534015340253403534045340553406534075340853409534105341153412534135341453415534165341753418534195342053421534225342353424534255342653427534285342953430534315343253433534345343553436534375343853439534405344153442534435344453445534465344753448534495345053451534525345353454534555345653457534585345953460534615346253463534645346553466534675346853469534705347153472534735347453475534765347753478534795348053481534825348353484534855348653487534885348953490534915349253493534945349553496534975349853499535005350153502535035350453505535065350753508535095351053511535125351353514535155351653517535185351953520535215352253523535245352553526535275352853529535305353153532535335353453535535365353753538535395354053541535425354353544535455354653547535485354953550535515355253553535545355553556535575355853559535605356153562535635356453565535665356753568535695357053571535725357353574535755357653577535785357953580535815358253583535845358553586535875358853589535905359153592535935359453595535965359753598535995360053601536025360353604536055360653607536085360953610536115361253613536145361553616536175361853619536205362153622536235362453625536265362753628536295363053631536325363353634536355363653637536385363953640536415364253643536445364553646536475364853649536505365153652536535365453655536565365753658536595366053661536625366353664536655366653667536685366953670536715367253673536745367553676536775367853679536805368153682536835368453685536865368753688536895369053691536925369353694536955369653697536985369953700537015370253703537045370553706537075370853709537105371153712537135371453715537165371753718537195372053721537225372353724537255372653727537285372953730537315373253733537345373553736537375373853739537405374153742537435374453745537465374753748537495375053751537525375353754537555375653757537585375953760537615376253763537645376553766537675376853769537705377153772537735377453775537765377753778537795378053781537825378353784537855378653787537885378953790537915379253793537945379553796537975379853799538005380153802538035380453805538065380753808538095381053811538125381353814538155381653817538185381953820538215382253823538245382553826538275382853829538305383153832538335383453835538365383753838538395384053841538425384353844538455384653847538485384953850538515385253853538545385553856538575385853859538605386153862538635386453865538665386753868538695387053871538725387353874538755387653877538785387953880538815388253883538845388553886538875388853889538905389153892538935389453895538965389753898538995390053901539025390353904539055390653907539085390953910539115391253913539145391553916539175391853919539205392153922539235392453925539265392753928539295393053931539325393353934539355393653937539385393953940539415394253943539445394553946539475394853949539505395153952539535395453955539565395753958539595396053961539625396353964539655396653967539685396953970539715397253973539745397553976539775397853979539805398153982539835398453985539865398753988539895399053991539925399353994539955399653997539985399954000540015400254003540045400554006540075400854009540105401154012540135401454015540165401754018540195402054021540225402354024540255402654027540285402954030540315403254033540345403554036540375403854039540405404154042540435404454045540465404754048540495405054051540525405354054540555405654057540585405954060540615406254063540645406554066540675406854069540705407154072540735407454075540765407754078540795408054081540825408354084540855408654087540885408954090540915409254093540945409554096540975409854099541005410154102541035410454105541065410754108541095411054111541125411354114541155411654117541185411954120541215412254123541245412554126541275412854129541305413154132541335413454135541365413754138541395414054141541425414354144541455414654147541485414954150541515415254153541545415554156541575415854159541605416154162541635416454165541665416754168541695417054171541725417354174541755417654177541785417954180541815418254183541845418554186541875418854189541905419154192541935419454195541965419754198541995420054201542025420354204542055420654207542085420954210542115421254213542145421554216542175421854219542205422154222542235422454225542265422754228542295423054231542325423354234542355423654237542385423954240542415424254243542445424554246542475424854249542505425154252542535425454255542565425754258542595426054261542625426354264542655426654267542685426954270542715427254273542745427554276542775427854279542805428154282542835428454285542865428754288542895429054291542925429354294542955429654297542985429954300543015430254303543045430554306543075430854309543105431154312543135431454315543165431754318543195432054321543225432354324543255432654327543285432954330543315433254333543345433554336543375433854339543405434154342543435434454345543465434754348543495435054351543525435354354543555435654357543585435954360543615436254363543645436554366543675436854369543705437154372543735437454375543765437754378543795438054381543825438354384543855438654387543885438954390543915439254393543945439554396543975439854399544005440154402544035440454405544065440754408544095441054411544125441354414544155441654417544185441954420544215442254423544245442554426544275442854429544305443154432544335443454435544365443754438544395444054441544425444354444544455444654447544485444954450544515445254453544545445554456544575445854459544605446154462544635446454465544665446754468544695447054471544725447354474544755447654477544785447954480544815448254483544845448554486544875448854489544905449154492544935449454495544965449754498544995450054501545025450354504545055450654507545085450954510545115451254513545145451554516545175451854519545205452154522545235452454525545265452754528545295453054531545325453354534545355453654537545385453954540545415454254543545445454554546545475454854549545505455154552545535455454555545565455754558545595456054561545625456354564545655456654567545685456954570545715457254573545745457554576545775457854579545805458154582545835458454585545865458754588545895459054591545925459354594545955459654597545985459954600546015460254603546045460554606546075460854609546105461154612546135461454615546165461754618546195462054621546225462354624546255462654627546285462954630546315463254633546345463554636546375463854639546405464154642546435464454645546465464754648546495465054651546525465354654546555465654657546585465954660546615466254663546645466554666546675466854669546705467154672546735467454675546765467754678546795468054681546825468354684546855468654687546885468954690546915469254693546945469554696546975469854699547005470154702547035470454705547065470754708547095471054711547125471354714547155471654717547185471954720547215472254723547245472554726547275472854729547305473154732547335473454735547365473754738547395474054741547425474354744547455474654747547485474954750547515475254753547545475554756547575475854759547605476154762547635476454765547665476754768547695477054771547725477354774547755477654777547785477954780547815478254783547845478554786547875478854789547905479154792547935479454795547965479754798547995480054801548025480354804548055480654807548085480954810548115481254813548145481554816548175481854819548205482154822548235482454825548265482754828548295483054831548325483354834548355483654837548385483954840548415484254843548445484554846548475484854849548505485154852548535485454855548565485754858548595486054861548625486354864548655486654867548685486954870548715487254873548745487554876548775487854879548805488154882548835488454885548865488754888548895489054891548925489354894548955489654897548985489954900549015490254903549045490554906549075490854909549105491154912549135491454915549165491754918549195492054921549225492354924549255492654927549285492954930549315493254933549345493554936549375493854939549405494154942549435494454945549465494754948549495495054951549525495354954549555495654957549585495954960549615496254963549645496554966549675496854969549705497154972549735497454975549765497754978549795498054981549825498354984549855498654987549885498954990549915499254993549945499554996549975499854999550005500155002550035500455005550065500755008550095501055011550125501355014550155501655017550185501955020550215502255023550245502555026550275502855029550305503155032550335503455035550365503755038550395504055041550425504355044550455504655047550485504955050550515505255053550545505555056550575505855059550605506155062550635506455065550665506755068550695507055071550725507355074550755507655077550785507955080550815508255083550845508555086550875508855089550905509155092550935509455095550965509755098550995510055101551025510355104551055510655107551085510955110551115511255113551145511555116551175511855119551205512155122551235512455125551265512755128551295513055131551325513355134551355513655137551385513955140551415514255143551445514555146551475514855149551505515155152551535515455155551565515755158551595516055161551625516355164551655516655167551685516955170551715517255173551745517555176551775517855179551805518155182551835518455185551865518755188551895519055191551925519355194551955519655197551985519955200552015520255203552045520555206552075520855209552105521155212552135521455215552165521755218552195522055221552225522355224552255522655227552285522955230552315523255233552345523555236552375523855239552405524155242552435524455245552465524755248552495525055251552525525355254552555525655257552585525955260552615526255263552645526555266552675526855269552705527155272552735527455275552765527755278552795528055281552825528355284552855528655287552885528955290552915529255293552945529555296552975529855299553005530155302553035530455305553065530755308553095531055311553125531355314553155531655317553185531955320553215532255323553245532555326553275532855329553305533155332553335533455335553365533755338553395534055341553425534355344553455534655347553485534955350553515535255353553545535555356553575535855359553605536155362553635536455365553665536755368553695537055371553725537355374553755537655377553785537955380553815538255383553845538555386553875538855389553905539155392553935539455395553965539755398553995540055401554025540355404554055540655407554085540955410554115541255413554145541555416554175541855419554205542155422554235542455425554265542755428554295543055431554325543355434554355543655437554385543955440554415544255443554445544555446554475544855449554505545155452554535545455455554565545755458554595546055461554625546355464554655546655467554685546955470554715547255473554745547555476554775547855479554805548155482554835548455485554865548755488554895549055491554925549355494554955549655497554985549955500555015550255503555045550555506555075550855509555105551155512555135551455515555165551755518555195552055521555225552355524555255552655527555285552955530555315553255533555345553555536555375553855539555405554155542555435554455545555465554755548555495555055551555525555355554555555555655557555585555955560555615556255563555645556555566555675556855569555705557155572555735557455575555765557755578555795558055581555825558355584555855558655587555885558955590555915559255593555945559555596555975559855599556005560155602556035560455605556065560755608556095561055611556125561355614556155561655617556185561955620556215562255623556245562555626556275562855629556305563155632556335563455635556365563755638556395564055641556425564355644556455564655647556485564955650556515565255653556545565555656556575565855659556605566155662556635566455665556665566755668556695567055671556725567355674556755567655677556785567955680556815568255683556845568555686556875568855689556905569155692556935569455695556965569755698556995570055701557025570355704557055570655707557085570955710557115571255713557145571555716557175571855719557205572155722557235572455725557265572755728557295573055731557325573355734557355573655737557385573955740557415574255743557445574555746557475574855749557505575155752557535575455755557565575755758557595576055761557625576355764557655576655767557685576955770557715577255773557745577555776557775577855779557805578155782557835578455785557865578755788557895579055791557925579355794557955579655797557985579955800558015580255803558045580555806558075580855809558105581155812558135581455815558165581755818558195582055821558225582355824558255582655827558285582955830558315583255833558345583555836558375583855839558405584155842558435584455845558465584755848558495585055851558525585355854558555585655857558585585955860558615586255863558645586555866558675586855869558705587155872558735587455875558765587755878558795588055881558825588355884558855588655887558885588955890558915589255893558945589555896558975589855899559005590155902559035590455905559065590755908559095591055911559125591355914559155591655917559185591955920559215592255923559245592555926559275592855929559305593155932559335593455935559365593755938559395594055941559425594355944559455594655947559485594955950559515595255953559545595555956559575595855959559605596155962559635596455965559665596755968559695597055971559725597355974559755597655977559785597955980559815598255983559845598555986559875598855989559905599155992559935599455995559965599755998559995600056001560025600356004560055600656007560085600956010560115601256013560145601556016560175601856019560205602156022560235602456025560265602756028560295603056031560325603356034560355603656037560385603956040560415604256043560445604556046560475604856049560505605156052560535605456055560565605756058560595606056061560625606356064560655606656067560685606956070560715607256073560745607556076560775607856079560805608156082560835608456085560865608756088560895609056091560925609356094560955609656097560985609956100561015610256103561045610556106561075610856109561105611156112561135611456115561165611756118561195612056121561225612356124561255612656127561285612956130561315613256133561345613556136561375613856139561405614156142561435614456145561465614756148561495615056151561525615356154561555615656157561585615956160561615616256163561645616556166561675616856169561705617156172561735617456175561765617756178561795618056181561825618356184561855618656187561885618956190561915619256193561945619556196561975619856199562005620156202562035620456205562065620756208562095621056211562125621356214562155621656217562185621956220562215622256223562245622556226562275622856229562305623156232562335623456235562365623756238562395624056241562425624356244562455624656247562485624956250562515625256253562545625556256562575625856259562605626156262562635626456265562665626756268562695627056271562725627356274562755627656277562785627956280562815628256283562845628556286562875628856289562905629156292562935629456295562965629756298562995630056301563025630356304563055630656307563085630956310563115631256313563145631556316563175631856319563205632156322563235632456325563265632756328563295633056331563325633356334563355633656337563385633956340563415634256343563445634556346563475634856349563505635156352563535635456355563565635756358563595636056361563625636356364563655636656367563685636956370563715637256373563745637556376563775637856379563805638156382563835638456385563865638756388563895639056391563925639356394563955639656397563985639956400564015640256403564045640556406564075640856409564105641156412564135641456415564165641756418564195642056421564225642356424564255642656427564285642956430564315643256433564345643556436564375643856439564405644156442564435644456445564465644756448564495645056451564525645356454564555645656457564585645956460564615646256463564645646556466564675646856469564705647156472564735647456475564765647756478564795648056481564825648356484564855648656487564885648956490564915649256493564945649556496564975649856499565005650156502565035650456505565065650756508565095651056511565125651356514565155651656517565185651956520565215652256523565245652556526565275652856529565305653156532565335653456535565365653756538565395654056541565425654356544565455654656547565485654956550565515655256553565545655556556565575655856559565605656156562565635656456565565665656756568565695657056571565725657356574565755657656577565785657956580565815658256583565845658556586565875658856589565905659156592565935659456595565965659756598565995660056601566025660356604566055660656607566085660956610566115661256613566145661556616566175661856619566205662156622566235662456625566265662756628566295663056631566325663356634566355663656637566385663956640566415664256643566445664556646566475664856649566505665156652566535665456655566565665756658566595666056661566625666356664566655666656667566685666956670566715667256673566745667556676566775667856679566805668156682566835668456685566865668756688566895669056691566925669356694566955669656697566985669956700567015670256703567045670556706567075670856709567105671156712567135671456715567165671756718567195672056721567225672356724567255672656727567285672956730567315673256733567345673556736567375673856739567405674156742567435674456745567465674756748567495675056751567525675356754567555675656757567585675956760567615676256763567645676556766567675676856769567705677156772567735677456775567765677756778567795678056781567825678356784567855678656787567885678956790567915679256793567945679556796567975679856799568005680156802568035680456805568065680756808568095681056811568125681356814568155681656817568185681956820568215682256823568245682556826568275682856829568305683156832568335683456835568365683756838568395684056841568425684356844568455684656847568485684956850568515685256853568545685556856568575685856859568605686156862568635686456865568665686756868568695687056871568725687356874568755687656877568785687956880568815688256883568845688556886568875688856889568905689156892568935689456895568965689756898568995690056901569025690356904569055690656907569085690956910569115691256913569145691556916569175691856919569205692156922569235692456925569265692756928569295693056931569325693356934569355693656937569385693956940569415694256943569445694556946569475694856949569505695156952569535695456955569565695756958569595696056961569625696356964569655696656967569685696956970569715697256973569745697556976569775697856979569805698156982569835698456985569865698756988569895699056991569925699356994569955699656997569985699957000570015700257003570045700557006570075700857009570105701157012570135701457015570165701757018570195702057021570225702357024570255702657027570285702957030570315703257033570345703557036570375703857039570405704157042570435704457045570465704757048570495705057051570525705357054570555705657057570585705957060570615706257063570645706557066570675706857069570705707157072570735707457075570765707757078570795708057081570825708357084570855708657087570885708957090570915709257093570945709557096570975709857099571005710157102571035710457105571065710757108571095711057111571125711357114571155711657117571185711957120571215712257123571245712557126571275712857129571305713157132571335713457135571365713757138571395714057141571425714357144571455714657147571485714957150571515715257153571545715557156571575715857159571605716157162571635716457165571665716757168571695717057171571725717357174571755717657177571785717957180571815718257183571845718557186571875718857189571905719157192571935719457195571965719757198571995720057201572025720357204572055720657207572085720957210572115721257213572145721557216572175721857219572205722157222572235722457225572265722757228572295723057231572325723357234572355723657237572385723957240572415724257243572445724557246572475724857249572505725157252572535725457255572565725757258572595726057261572625726357264572655726657267572685726957270572715727257273572745727557276572775727857279572805728157282572835728457285572865728757288572895729057291572925729357294572955729657297572985729957300573015730257303573045730557306573075730857309573105731157312573135731457315573165731757318573195732057321573225732357324573255732657327573285732957330573315733257333573345733557336573375733857339573405734157342573435734457345573465734757348573495735057351573525735357354573555735657357573585735957360573615736257363573645736557366573675736857369573705737157372573735737457375573765737757378573795738057381573825738357384573855738657387573885738957390573915739257393573945739557396573975739857399574005740157402574035740457405574065740757408574095741057411574125741357414574155741657417574185741957420574215742257423574245742557426574275742857429574305743157432574335743457435574365743757438574395744057441574425744357444574455744657447574485744957450574515745257453574545745557456574575745857459574605746157462574635746457465574665746757468574695747057471574725747357474574755747657477574785747957480574815748257483574845748557486574875748857489574905749157492574935749457495574965749757498574995750057501575025750357504575055750657507575085750957510575115751257513575145751557516575175751857519575205752157522575235752457525575265752757528575295753057531575325753357534575355753657537575385753957540575415754257543575445754557546575475754857549575505755157552575535755457555575565755757558575595756057561575625756357564575655756657567575685756957570575715757257573575745757557576575775757857579575805758157582575835758457585575865758757588575895759057591575925759357594575955759657597575985759957600576015760257603576045760557606576075760857609576105761157612576135761457615576165761757618576195762057621576225762357624576255762657627576285762957630576315763257633576345763557636576375763857639576405764157642576435764457645576465764757648576495765057651576525765357654576555765657657576585765957660576615766257663576645766557666576675766857669576705767157672576735767457675576765767757678576795768057681576825768357684576855768657687576885768957690576915769257693576945769557696576975769857699577005770157702577035770457705577065770757708577095771057711577125771357714577155771657717577185771957720577215772257723577245772557726577275772857729577305773157732577335773457735577365773757738577395774057741577425774357744577455774657747577485774957750577515775257753577545775557756577575775857759577605776157762577635776457765577665776757768577695777057771577725777357774577755777657777577785777957780577815778257783577845778557786577875778857789577905779157792577935779457795577965779757798577995780057801578025780357804578055780657807578085780957810578115781257813578145781557816578175781857819578205782157822578235782457825578265782757828578295783057831578325783357834578355783657837578385783957840578415784257843578445784557846578475784857849578505785157852578535785457855578565785757858578595786057861578625786357864578655786657867578685786957870578715787257873578745787557876578775787857879578805788157882578835788457885578865788757888578895789057891578925789357894578955789657897578985789957900579015790257903579045790557906579075790857909579105791157912579135791457915579165791757918579195792057921579225792357924579255792657927579285792957930579315793257933579345793557936579375793857939579405794157942579435794457945579465794757948579495795057951579525795357954579555795657957579585795957960579615796257963579645796557966579675796857969579705797157972579735797457975579765797757978579795798057981579825798357984579855798657987579885798957990579915799257993579945799557996579975799857999580005800158002580035800458005580065800758008580095801058011580125801358014580155801658017580185801958020580215802258023580245802558026580275802858029580305803158032580335803458035580365803758038580395804058041580425804358044580455804658047580485804958050580515805258053580545805558056580575805858059580605806158062580635806458065580665806758068580695807058071580725807358074580755807658077580785807958080580815808258083580845808558086580875808858089580905809158092580935809458095580965809758098580995810058101581025810358104581055810658107581085810958110581115811258113581145811558116581175811858119581205812158122581235812458125581265812758128581295813058131581325813358134581355813658137581385813958140581415814258143581445814558146581475814858149581505815158152581535815458155581565815758158581595816058161581625816358164581655816658167581685816958170581715817258173581745817558176581775817858179581805818158182581835818458185581865818758188581895819058191581925819358194581955819658197581985819958200582015820258203582045820558206582075820858209582105821158212582135821458215582165821758218582195822058221582225822358224582255822658227582285822958230582315823258233582345823558236582375823858239582405824158242582435824458245582465824758248582495825058251582525825358254582555825658257582585825958260582615826258263582645826558266582675826858269582705827158272582735827458275582765827758278582795828058281582825828358284582855828658287582885828958290582915829258293582945829558296582975829858299583005830158302583035830458305583065830758308583095831058311583125831358314583155831658317583185831958320583215832258323583245832558326583275832858329583305833158332583335833458335583365833758338583395834058341583425834358344583455834658347583485834958350583515835258353583545835558356583575835858359583605836158362583635836458365583665836758368583695837058371583725837358374583755837658377583785837958380583815838258383583845838558386583875838858389583905839158392583935839458395583965839758398583995840058401584025840358404584055840658407584085840958410584115841258413584145841558416584175841858419584205842158422584235842458425584265842758428584295843058431584325843358434584355843658437584385843958440584415844258443584445844558446584475844858449584505845158452584535845458455584565845758458584595846058461584625846358464584655846658467584685846958470584715847258473584745847558476584775847858479584805848158482584835848458485584865848758488584895849058491584925849358494584955849658497584985849958500585015850258503585045850558506585075850858509585105851158512585135851458515585165851758518585195852058521585225852358524585255852658527585285852958530585315853258533585345853558536585375853858539585405854158542585435854458545585465854758548585495855058551585525855358554585555855658557585585855958560585615856258563585645856558566585675856858569585705857158572585735857458575585765857758578585795858058581585825858358584585855858658587585885858958590585915859258593585945859558596585975859858599586005860158602586035860458605586065860758608586095861058611586125861358614586155861658617586185861958620586215862258623586245862558626586275862858629586305863158632586335863458635586365863758638586395864058641586425864358644586455864658647586485864958650586515865258653586545865558656586575865858659586605866158662586635866458665586665866758668586695867058671586725867358674586755867658677586785867958680586815868258683586845868558686586875868858689586905869158692586935869458695586965869758698586995870058701587025870358704587055870658707587085870958710587115871258713587145871558716587175871858719587205872158722587235872458725587265872758728587295873058731587325873358734587355873658737587385873958740587415874258743587445874558746587475874858749587505875158752587535875458755587565875758758587595876058761587625876358764587655876658767587685876958770587715877258773587745877558776587775877858779587805878158782587835878458785587865878758788587895879058791587925879358794587955879658797587985879958800588015880258803588045880558806588075880858809588105881158812588135881458815588165881758818588195882058821588225882358824588255882658827588285882958830588315883258833588345883558836588375883858839588405884158842588435884458845588465884758848588495885058851588525885358854588555885658857588585885958860588615886258863588645886558866588675886858869588705887158872588735887458875588765887758878588795888058881588825888358884588855888658887588885888958890588915889258893588945889558896588975889858899589005890158902589035890458905589065890758908589095891058911589125891358914589155891658917589185891958920589215892258923589245892558926589275892858929589305893158932589335893458935589365893758938589395894058941589425894358944589455894658947589485894958950589515895258953589545895558956589575895858959589605896158962589635896458965589665896758968589695897058971589725897358974589755897658977589785897958980589815898258983589845898558986589875898858989589905899158992589935899458995589965899758998589995900059001590025900359004590055900659007590085900959010590115901259013590145901559016590175901859019590205902159022590235902459025590265902759028590295903059031590325903359034590355903659037590385903959040590415904259043590445904559046590475904859049590505905159052590535905459055590565905759058590595906059061590625906359064590655906659067590685906959070590715907259073590745907559076590775907859079590805908159082590835908459085590865908759088590895909059091590925909359094590955909659097590985909959100591015910259103591045910559106591075910859109591105911159112591135911459115591165911759118591195912059121591225912359124591255912659127591285912959130591315913259133591345913559136591375913859139591405914159142591435914459145591465914759148591495915059151591525915359154591555915659157591585915959160591615916259163591645916559166591675916859169591705917159172591735917459175591765917759178591795918059181591825918359184591855918659187591885918959190591915919259193591945919559196591975919859199592005920159202592035920459205592065920759208592095921059211592125921359214592155921659217592185921959220592215922259223592245922559226592275922859229592305923159232592335923459235592365923759238592395924059241592425924359244592455924659247592485924959250592515925259253592545925559256592575925859259592605926159262592635926459265592665926759268592695927059271592725927359274592755927659277592785927959280592815928259283592845928559286592875928859289592905929159292592935929459295592965929759298592995930059301593025930359304593055930659307593085930959310593115931259313593145931559316593175931859319593205932159322593235932459325593265932759328593295933059331593325933359334593355933659337593385933959340593415934259343593445934559346593475934859349593505935159352593535935459355593565935759358593595936059361593625936359364593655936659367593685936959370593715937259373593745937559376593775937859379593805938159382593835938459385593865938759388593895939059391593925939359394593955939659397593985939959400594015940259403594045940559406594075940859409594105941159412594135941459415594165941759418594195942059421594225942359424594255942659427594285942959430594315943259433594345943559436594375943859439594405944159442594435944459445594465944759448594495945059451594525945359454594555945659457594585945959460594615946259463594645946559466594675946859469594705947159472594735947459475594765947759478594795948059481594825948359484594855948659487594885948959490594915949259493594945949559496594975949859499595005950159502595035950459505595065950759508595095951059511595125951359514595155951659517595185951959520595215952259523595245952559526595275952859529595305953159532595335953459535595365953759538595395954059541595425954359544595455954659547595485954959550595515955259553595545955559556595575955859559595605956159562595635956459565595665956759568595695957059571595725957359574595755957659577595785957959580595815958259583595845958559586595875958859589595905959159592595935959459595595965959759598595995960059601596025960359604596055960659607596085960959610596115961259613596145961559616596175961859619596205962159622596235962459625596265962759628596295963059631596325963359634596355963659637596385963959640596415964259643596445964559646596475964859649596505965159652596535965459655596565965759658596595966059661596625966359664596655966659667596685966959670596715967259673596745967559676596775967859679596805968159682596835968459685596865968759688596895969059691596925969359694596955969659697596985969959700597015970259703597045970559706597075970859709597105971159712597135971459715597165971759718597195972059721597225972359724597255972659727597285972959730597315973259733597345973559736597375973859739597405974159742597435974459745597465974759748597495975059751597525975359754597555975659757597585975959760597615976259763597645976559766597675976859769597705977159772597735977459775597765977759778597795978059781597825978359784597855978659787597885978959790597915979259793597945979559796597975979859799598005980159802598035980459805598065980759808598095981059811598125981359814598155981659817598185981959820598215982259823598245982559826598275982859829598305983159832598335983459835598365983759838598395984059841598425984359844598455984659847598485984959850598515985259853598545985559856598575985859859598605986159862598635986459865598665986759868598695987059871598725987359874598755987659877598785987959880598815988259883598845988559886598875988859889598905989159892598935989459895598965989759898598995990059901599025990359904599055990659907599085990959910599115991259913599145991559916599175991859919599205992159922599235992459925599265992759928599295993059931599325993359934599355993659937599385993959940599415994259943599445994559946599475994859949599505995159952599535995459955599565995759958599595996059961599625996359964599655996659967599685996959970599715997259973599745997559976599775997859979599805998159982599835998459985599865998759988599895999059991599925999359994599955999659997599985999960000600016000260003600046000560006600076000860009600106001160012600136001460015600166001760018600196002060021600226002360024600256002660027600286002960030600316003260033600346003560036600376003860039600406004160042600436004460045600466004760048600496005060051600526005360054600556005660057600586005960060600616006260063600646006560066600676006860069600706007160072600736007460075600766007760078600796008060081600826008360084600856008660087600886008960090600916009260093600946009560096600976009860099601006010160102601036010460105601066010760108601096011060111601126011360114601156011660117601186011960120601216012260123601246012560126601276012860129601306013160132601336013460135601366013760138601396014060141601426014360144601456014660147601486014960150601516015260153601546015560156601576015860159601606016160162601636016460165601666016760168601696017060171601726017360174601756017660177601786017960180601816018260183601846018560186601876018860189601906019160192601936019460195601966019760198601996020060201602026020360204602056020660207602086020960210602116021260213602146021560216602176021860219602206022160222602236022460225602266022760228602296023060231602326023360234602356023660237602386023960240602416024260243602446024560246602476024860249602506025160252602536025460255602566025760258602596026060261602626026360264602656026660267602686026960270602716027260273602746027560276602776027860279602806028160282602836028460285602866028760288602896029060291602926029360294602956029660297602986029960300603016030260303603046030560306603076030860309603106031160312603136031460315603166031760318603196032060321603226032360324603256032660327603286032960330603316033260333603346033560336603376033860339603406034160342603436034460345603466034760348603496035060351603526035360354603556035660357603586035960360603616036260363603646036560366603676036860369603706037160372603736037460375603766037760378603796038060381603826038360384603856038660387603886038960390603916039260393603946039560396603976039860399604006040160402604036040460405604066040760408604096041060411604126041360414604156041660417604186041960420604216042260423604246042560426604276042860429604306043160432604336043460435604366043760438604396044060441604426044360444604456044660447604486044960450604516045260453604546045560456604576045860459604606046160462604636046460465604666046760468604696047060471604726047360474604756047660477604786047960480604816048260483604846048560486604876048860489604906049160492604936049460495604966049760498604996050060501605026050360504605056050660507605086050960510605116051260513605146051560516605176051860519605206052160522605236052460525605266052760528605296053060531605326053360534605356053660537605386053960540605416054260543605446054560546605476054860549605506055160552605536055460555605566055760558605596056060561605626056360564605656056660567605686056960570605716057260573605746057560576605776057860579605806058160582605836058460585605866058760588605896059060591605926059360594605956059660597605986059960600606016060260603606046060560606606076060860609606106061160612606136061460615606166061760618606196062060621606226062360624606256062660627606286062960630606316063260633606346063560636606376063860639606406064160642606436064460645606466064760648606496065060651606526065360654606556065660657606586065960660606616066260663606646066560666606676066860669606706067160672606736067460675606766067760678606796068060681606826068360684606856068660687606886068960690606916069260693606946069560696606976069860699607006070160702607036070460705607066070760708607096071060711607126071360714607156071660717607186071960720607216072260723607246072560726607276072860729607306073160732607336073460735607366073760738607396074060741607426074360744607456074660747607486074960750607516075260753607546075560756607576075860759607606076160762607636076460765607666076760768607696077060771607726077360774607756077660777607786077960780607816078260783607846078560786607876078860789607906079160792607936079460795607966079760798607996080060801608026080360804608056080660807608086080960810608116081260813608146081560816608176081860819608206082160822608236082460825608266082760828608296083060831608326083360834608356083660837608386083960840608416084260843608446084560846608476084860849608506085160852608536085460855608566085760858608596086060861608626086360864608656086660867608686086960870608716087260873608746087560876608776087860879608806088160882608836088460885608866088760888608896089060891608926089360894608956089660897608986089960900609016090260903609046090560906609076090860909609106091160912609136091460915609166091760918609196092060921609226092360924609256092660927609286092960930609316093260933609346093560936609376093860939609406094160942609436094460945609466094760948609496095060951609526095360954609556095660957609586095960960609616096260963609646096560966609676096860969609706097160972609736097460975609766097760978609796098060981609826098360984609856098660987609886098960990609916099260993609946099560996609976099860999610006100161002610036100461005610066100761008610096101061011610126101361014610156101661017610186101961020610216102261023610246102561026610276102861029610306103161032610336103461035610366103761038610396104061041610426104361044610456104661047610486104961050610516105261053610546105561056610576105861059610606106161062610636106461065610666106761068610696107061071610726107361074610756107661077610786107961080610816108261083610846108561086610876108861089610906109161092610936109461095610966109761098610996110061101611026110361104611056110661107611086110961110611116111261113611146111561116611176111861119611206112161122611236112461125611266112761128611296113061131611326113361134611356113661137611386113961140611416114261143611446114561146611476114861149611506115161152611536115461155611566115761158611596116061161611626116361164611656116661167611686116961170611716117261173611746117561176611776117861179611806118161182611836118461185611866118761188611896119061191611926119361194611956119661197611986119961200612016120261203612046120561206612076120861209612106121161212612136121461215612166121761218612196122061221612226122361224612256122661227612286122961230612316123261233612346123561236612376123861239612406124161242612436124461245612466124761248612496125061251612526125361254612556125661257612586125961260612616126261263612646126561266612676126861269612706127161272612736127461275612766127761278612796128061281612826128361284612856128661287612886128961290612916129261293612946129561296612976129861299613006130161302613036130461305613066130761308613096131061311613126131361314613156131661317613186131961320613216132261323613246132561326613276132861329613306133161332613336133461335613366133761338613396134061341613426134361344613456134661347613486134961350613516135261353613546135561356613576135861359613606136161362613636136461365613666136761368613696137061371613726137361374613756137661377613786137961380613816138261383613846138561386613876138861389613906139161392613936139461395613966139761398613996140061401614026140361404614056140661407614086140961410614116141261413614146141561416614176141861419614206142161422614236142461425614266142761428614296143061431614326143361434614356143661437614386143961440614416144261443614446144561446614476144861449614506145161452614536145461455614566145761458614596146061461614626146361464614656146661467614686146961470614716147261473614746147561476614776147861479614806148161482614836148461485614866148761488614896149061491614926149361494614956149661497614986149961500615016150261503615046150561506615076150861509615106151161512615136151461515615166151761518615196152061521615226152361524615256152661527615286152961530615316153261533615346153561536615376153861539615406154161542615436154461545615466154761548615496155061551615526155361554615556155661557615586155961560615616156261563615646156561566615676156861569615706157161572615736157461575615766157761578615796158061581615826158361584615856158661587615886158961590615916159261593615946159561596615976159861599616006160161602616036160461605616066160761608616096161061611616126161361614616156161661617616186161961620616216162261623616246162561626616276162861629616306163161632616336163461635616366163761638616396164061641616426164361644616456164661647616486164961650616516165261653616546165561656616576165861659616606166161662616636166461665616666166761668616696167061671616726167361674616756167661677616786167961680616816168261683616846168561686616876168861689616906169161692616936169461695616966169761698616996170061701617026170361704617056170661707617086170961710617116171261713617146171561716617176171861719617206172161722617236172461725617266172761728617296173061731617326173361734617356173661737617386173961740617416174261743617446174561746617476174861749617506175161752617536175461755617566175761758617596176061761617626176361764617656176661767617686176961770617716177261773617746177561776617776177861779617806178161782617836178461785617866178761788617896179061791617926179361794617956179661797617986179961800618016180261803618046180561806618076180861809618106181161812618136181461815618166181761818618196182061821618226182361824618256182661827618286182961830618316183261833618346183561836618376183861839618406184161842618436184461845618466184761848618496185061851618526185361854618556185661857618586185961860618616186261863618646186561866618676186861869618706187161872618736187461875618766187761878618796188061881618826188361884618856188661887618886188961890618916189261893618946189561896618976189861899619006190161902619036190461905619066190761908619096191061911619126191361914619156191661917619186191961920619216192261923619246192561926619276192861929619306193161932619336193461935619366193761938619396194061941619426194361944619456194661947619486194961950619516195261953619546195561956619576195861959619606196161962619636196461965619666196761968619696197061971619726197361974619756197661977619786197961980619816198261983619846198561986619876198861989619906199161992619936199461995619966199761998619996200062001620026200362004620056200662007620086200962010620116201262013620146201562016620176201862019620206202162022620236202462025620266202762028620296203062031620326203362034620356203662037620386203962040620416204262043620446204562046620476204862049620506205162052620536205462055620566205762058620596206062061620626206362064620656206662067620686206962070620716207262073620746207562076620776207862079620806208162082620836208462085620866208762088620896209062091620926209362094620956209662097620986209962100621016210262103621046210562106621076210862109621106211162112621136211462115621166211762118621196212062121621226212362124621256212662127621286212962130621316213262133621346213562136621376213862139621406214162142621436214462145621466214762148621496215062151621526215362154621556215662157621586215962160621616216262163621646216562166621676216862169621706217162172621736217462175621766217762178621796218062181621826218362184621856218662187621886218962190621916219262193621946219562196621976219862199622006220162202622036220462205622066220762208622096221062211622126221362214622156221662217622186221962220622216222262223622246222562226622276222862229622306223162232622336223462235622366223762238622396224062241622426224362244622456224662247622486224962250622516225262253622546225562256622576225862259622606226162262622636226462265622666226762268622696227062271622726227362274622756227662277622786227962280622816228262283622846228562286622876228862289622906229162292622936229462295622966229762298622996230062301623026230362304623056230662307623086230962310623116231262313623146231562316623176231862319623206232162322623236232462325623266232762328623296233062331623326233362334623356233662337623386233962340623416234262343623446234562346623476234862349623506235162352623536235462355623566235762358623596236062361623626236362364623656236662367623686236962370623716237262373623746237562376623776237862379623806238162382623836238462385623866238762388623896239062391623926239362394623956239662397623986239962400624016240262403624046240562406624076240862409624106241162412624136241462415624166241762418624196242062421624226242362424624256242662427624286242962430624316243262433624346243562436624376243862439624406244162442624436244462445624466244762448624496245062451624526245362454624556245662457624586245962460624616246262463624646246562466624676246862469624706247162472624736247462475624766247762478624796248062481624826248362484624856248662487624886248962490624916249262493624946249562496624976249862499625006250162502625036250462505625066250762508625096251062511625126251362514625156251662517625186251962520625216252262523625246252562526625276252862529625306253162532625336253462535625366253762538625396254062541625426254362544625456254662547625486254962550625516255262553625546255562556625576255862559625606256162562625636256462565625666256762568625696257062571625726257362574625756257662577625786257962580625816258262583625846258562586625876258862589625906259162592625936259462595625966259762598625996260062601626026260362604626056260662607626086260962610626116261262613626146261562616626176261862619626206262162622626236262462625626266262762628626296263062631626326263362634626356263662637626386263962640626416264262643626446264562646626476264862649626506265162652626536265462655626566265762658626596266062661626626266362664626656266662667626686266962670626716267262673626746267562676626776267862679626806268162682626836268462685626866268762688626896269062691626926269362694626956269662697626986269962700627016270262703627046270562706627076270862709627106271162712627136271462715627166271762718627196272062721627226272362724627256272662727627286272962730627316273262733627346273562736627376273862739627406274162742627436274462745627466274762748627496275062751627526275362754627556275662757627586275962760627616276262763627646276562766627676276862769627706277162772627736277462775627766277762778627796278062781627826278362784627856278662787627886278962790627916279262793627946279562796627976279862799628006280162802628036280462805628066280762808628096281062811628126281362814628156281662817628186281962820628216282262823628246282562826628276282862829628306283162832628336283462835628366283762838628396284062841628426284362844628456284662847628486284962850628516285262853628546285562856628576285862859628606286162862628636286462865628666286762868628696287062871628726287362874628756287662877628786287962880628816288262883628846288562886628876288862889628906289162892628936289462895628966289762898628996290062901629026290362904629056290662907629086290962910629116291262913629146291562916629176291862919629206292162922629236292462925629266292762928629296293062931629326293362934629356293662937629386293962940629416294262943629446294562946629476294862949629506295162952629536295462955629566295762958629596296062961629626296362964629656296662967629686296962970629716297262973629746297562976629776297862979629806298162982629836298462985629866298762988629896299062991629926299362994629956299662997629986299963000630016300263003630046300563006630076300863009630106301163012630136301463015630166301763018630196302063021630226302363024630256302663027630286302963030630316303263033630346303563036630376303863039630406304163042630436304463045630466304763048630496305063051630526305363054630556305663057630586305963060630616306263063630646306563066630676306863069630706307163072630736307463075630766307763078630796308063081630826308363084630856308663087630886308963090630916309263093630946309563096630976309863099631006310163102631036310463105631066310763108631096311063111631126311363114631156311663117631186311963120631216312263123631246312563126631276312863129631306313163132631336313463135631366313763138631396314063141631426314363144631456314663147631486314963150631516315263153631546315563156631576315863159631606316163162631636316463165631666316763168631696317063171631726317363174631756317663177631786317963180631816318263183631846318563186631876318863189631906319163192631936319463195631966319763198631996320063201632026320363204632056320663207632086320963210632116321263213632146321563216632176321863219632206322163222632236322463225632266322763228632296323063231632326323363234632356323663237632386323963240632416324263243632446324563246632476324863249632506325163252632536325463255632566325763258632596326063261632626326363264632656326663267632686326963270632716327263273632746327563276632776327863279632806328163282632836328463285632866328763288632896329063291632926329363294632956329663297632986329963300633016330263303633046330563306633076330863309633106331163312633136331463315633166331763318633196332063321633226332363324633256332663327633286332963330633316333263333633346333563336633376333863339633406334163342633436334463345633466334763348633496335063351633526335363354633556335663357633586335963360633616336263363633646336563366633676336863369633706337163372633736337463375633766337763378633796338063381633826338363384633856338663387633886338963390633916339263393633946339563396633976339863399634006340163402634036340463405634066340763408634096341063411634126341363414634156341663417634186341963420634216342263423634246342563426634276342863429634306343163432634336343463435634366343763438634396344063441634426344363444634456344663447634486344963450634516345263453634546345563456634576345863459634606346163462634636346463465634666346763468634696347063471634726347363474634756347663477634786347963480634816348263483634846348563486634876348863489634906349163492634936349463495634966349763498634996350063501635026350363504635056350663507635086350963510635116351263513635146351563516635176351863519635206352163522635236352463525635266352763528635296353063531635326353363534635356353663537635386353963540635416354263543635446354563546635476354863549635506355163552635536355463555635566355763558635596356063561635626356363564635656356663567635686356963570635716357263573635746357563576635776357863579635806358163582635836358463585635866358763588635896359063591635926359363594635956359663597635986359963600636016360263603636046360563606636076360863609636106361163612636136361463615636166361763618636196362063621636226362363624636256362663627636286362963630636316363263633636346363563636636376363863639636406364163642636436364463645636466364763648636496365063651636526365363654636556365663657636586365963660636616366263663636646366563666636676366863669636706367163672636736367463675636766367763678636796368063681636826368363684636856368663687636886368963690636916369263693636946369563696636976369863699637006370163702637036370463705637066370763708637096371063711637126371363714637156371663717637186371963720637216372263723637246372563726637276372863729637306373163732637336373463735637366373763738637396374063741637426374363744637456374663747637486374963750637516375263753637546375563756637576375863759637606376163762637636376463765637666376763768637696377063771637726377363774637756377663777637786377963780637816378263783637846378563786637876378863789637906379163792637936379463795637966379763798637996380063801638026380363804638056380663807638086380963810638116381263813638146381563816638176381863819638206382163822638236382463825638266382763828638296383063831638326383363834638356383663837638386383963840638416384263843638446384563846638476384863849638506385163852638536385463855638566385763858638596386063861638626386363864638656386663867638686386963870638716387263873638746387563876638776387863879638806388163882638836388463885638866388763888638896389063891638926389363894638956389663897638986389963900639016390263903639046390563906639076390863909639106391163912639136391463915639166391763918639196392063921639226392363924639256392663927639286392963930639316393263933639346393563936639376393863939639406394163942639436394463945639466394763948639496395063951639526395363954639556395663957639586395963960639616396263963639646396563966639676396863969639706397163972639736397463975639766397763978639796398063981639826398363984639856398663987639886398963990639916399263993639946399563996639976399863999640006400164002640036400464005640066400764008640096401064011640126401364014640156401664017640186401964020640216402264023640246402564026640276402864029640306403164032640336403464035640366403764038640396404064041640426404364044640456404664047640486404964050640516405264053640546405564056640576405864059640606406164062640636406464065640666406764068640696407064071640726407364074640756407664077640786407964080640816408264083640846408564086640876408864089640906409164092640936409464095640966409764098640996410064101641026410364104641056410664107641086410964110641116411264113641146411564116641176411864119641206412164122641236412464125641266412764128641296413064131641326413364134641356413664137641386413964140641416414264143641446414564146641476414864149641506415164152641536415464155641566415764158641596416064161641626416364164641656416664167641686416964170641716417264173641746417564176641776417864179641806418164182641836418464185641866418764188641896419064191641926419364194641956419664197641986419964200642016420264203642046420564206642076420864209642106421164212642136421464215642166421764218642196422064221642226422364224642256422664227642286422964230642316423264233642346423564236642376423864239642406424164242642436424464245642466424764248642496425064251642526425364254642556425664257642586425964260642616426264263642646426564266642676426864269642706427164272642736427464275642766427764278642796428064281642826428364284642856428664287642886428964290642916429264293642946429564296642976429864299643006430164302643036430464305643066430764308643096431064311643126431364314643156431664317643186431964320643216432264323643246432564326643276432864329643306433164332643336433464335643366433764338643396434064341643426434364344643456434664347643486434964350643516435264353643546435564356643576435864359643606436164362643636436464365643666436764368643696437064371643726437364374643756437664377643786437964380643816438264383643846438564386643876438864389643906439164392643936439464395643966439764398643996440064401644026440364404644056440664407644086440964410644116441264413644146441564416644176441864419644206442164422644236442464425644266442764428644296443064431644326443364434644356443664437644386443964440644416444264443644446444564446644476444864449644506445164452644536445464455644566445764458644596446064461644626446364464644656446664467644686446964470644716447264473644746447564476644776447864479644806448164482644836448464485644866448764488644896449064491644926449364494644956449664497644986449964500645016450264503645046450564506645076450864509645106451164512645136451464515645166451764518645196452064521645226452364524645256452664527645286452964530645316453264533645346453564536645376453864539645406454164542645436454464545645466454764548645496455064551645526455364554645556455664557645586455964560645616456264563645646456564566645676456864569645706457164572645736457464575645766457764578645796458064581645826458364584645856458664587645886458964590645916459264593645946459564596645976459864599646006460164602646036460464605646066460764608646096461064611646126461364614646156461664617646186461964620646216462264623646246462564626646276462864629646306463164632646336463464635646366463764638646396464064641646426464364644646456464664647646486464964650646516465264653646546465564656646576465864659646606466164662646636466464665646666466764668646696467064671646726467364674646756467664677646786467964680646816468264683646846468564686646876468864689646906469164692646936469464695646966469764698646996470064701647026470364704647056470664707647086470964710647116471264713647146471564716647176471864719647206472164722647236472464725647266472764728647296473064731647326473364734647356473664737647386473964740647416474264743647446474564746647476474864749647506475164752647536475464755647566475764758647596476064761647626476364764647656476664767647686476964770647716477264773647746477564776647776477864779647806478164782647836478464785647866478764788647896479064791647926479364794647956479664797647986479964800648016480264803648046480564806648076480864809648106481164812648136481464815648166481764818648196482064821648226482364824648256482664827648286482964830648316483264833648346483564836648376483864839648406484164842648436484464845648466484764848648496485064851648526485364854648556485664857648586485964860648616486264863648646486564866648676486864869648706487164872648736487464875648766487764878648796488064881648826488364884648856488664887648886488964890648916489264893648946489564896648976489864899649006490164902649036490464905649066490764908649096491064911649126491364914649156491664917649186491964920649216492264923649246492564926649276492864929649306493164932649336493464935649366493764938649396494064941649426494364944649456494664947649486494964950649516495264953649546495564956649576495864959649606496164962649636496464965649666496764968649696497064971649726497364974649756497664977649786497964980649816498264983649846498564986649876498864989649906499164992649936499464995649966499764998649996500065001650026500365004650056500665007650086500965010650116501265013650146501565016650176501865019650206502165022650236502465025650266502765028650296503065031650326503365034650356503665037650386503965040650416504265043650446504565046650476504865049650506505165052650536505465055650566505765058650596506065061650626506365064650656506665067650686506965070650716507265073650746507565076650776507865079650806508165082650836508465085650866508765088650896509065091650926509365094650956509665097650986509965100651016510265103651046510565106651076510865109651106511165112651136511465115651166511765118651196512065121651226512365124651256512665127651286512965130651316513265133651346513565136651376513865139651406514165142651436514465145651466514765148651496515065151651526515365154651556515665157651586515965160651616516265163651646516565166651676516865169651706517165172651736517465175651766517765178651796518065181651826518365184651856518665187651886518965190651916519265193651946519565196651976519865199652006520165202652036520465205652066520765208652096521065211652126521365214652156521665217652186521965220652216522265223652246522565226652276522865229652306523165232652336523465235652366523765238652396524065241652426524365244652456524665247652486524965250652516525265253652546525565256652576525865259652606526165262652636526465265652666526765268652696527065271652726527365274652756527665277652786527965280652816528265283652846528565286652876528865289652906529165292652936529465295652966529765298652996530065301653026530365304653056530665307653086530965310653116531265313653146531565316653176531865319653206532165322653236532465325653266532765328653296533065331653326533365334653356533665337653386533965340653416534265343653446534565346653476534865349653506535165352653536535465355653566535765358653596536065361653626536365364653656536665367653686536965370653716537265373653746537565376653776537865379653806538165382653836538465385653866538765388653896539065391653926539365394653956539665397653986539965400654016540265403654046540565406654076540865409654106541165412654136541465415654166541765418654196542065421654226542365424654256542665427654286542965430654316543265433654346543565436654376543865439654406544165442654436544465445654466544765448654496545065451654526545365454654556545665457654586545965460654616546265463654646546565466654676546865469654706547165472654736547465475654766547765478654796548065481654826548365484654856548665487654886548965490654916549265493654946549565496654976549865499655006550165502655036550465505655066550765508655096551065511655126551365514655156551665517655186551965520655216552265523655246552565526655276552865529655306553165532655336553465535655366553765538655396554065541655426554365544655456554665547655486554965550655516555265553655546555565556655576555865559655606556165562655636556465565655666556765568655696557065571655726557365574655756557665577655786557965580655816558265583655846558565586655876558865589655906559165592655936559465595655966559765598655996560065601656026560365604656056560665607656086560965610656116561265613656146561565616656176561865619656206562165622656236562465625656266562765628656296563065631656326563365634656356563665637656386563965640656416564265643656446564565646656476564865649656506565165652656536565465655656566565765658656596566065661656626566365664656656566665667656686566965670656716567265673656746567565676656776567865679656806568165682656836568465685656866568765688656896569065691656926569365694656956569665697656986569965700657016570265703657046570565706657076570865709657106571165712657136571465715657166571765718657196572065721657226572365724657256572665727657286572965730657316573265733657346573565736657376573865739657406574165742657436574465745657466574765748657496575065751657526575365754657556575665757657586575965760657616576265763657646576565766657676576865769657706577165772657736577465775657766577765778657796578065781657826578365784657856578665787657886578965790657916579265793657946579565796657976579865799658006580165802658036580465805658066580765808658096581065811658126581365814658156581665817658186581965820658216582265823658246582565826658276582865829658306583165832658336583465835658366583765838658396584065841658426584365844658456584665847658486584965850658516585265853658546585565856658576585865859658606586165862658636586465865658666586765868658696587065871658726587365874658756587665877658786587965880658816588265883658846588565886658876588865889658906589165892658936589465895658966589765898658996590065901659026590365904659056590665907659086590965910659116591265913659146591565916659176591865919659206592165922659236592465925659266592765928659296593065931659326593365934659356593665937659386593965940659416594265943659446594565946659476594865949659506595165952659536595465955659566595765958659596596065961659626596365964659656596665967659686596965970659716597265973659746597565976659776597865979659806598165982659836598465985659866598765988659896599065991659926599365994659956599665997659986599966000660016600266003660046600566006660076600866009660106601166012660136601466015660166601766018660196602066021660226602366024660256602666027660286602966030660316603266033660346603566036660376603866039660406604166042660436604466045660466604766048660496605066051660526605366054660556605666057660586605966060660616606266063660646606566066660676606866069660706607166072660736607466075660766607766078660796608066081660826608366084660856608666087660886608966090660916609266093660946609566096660976609866099661006610166102661036610466105661066610766108661096611066111661126611366114661156611666117661186611966120661216612266123661246612566126661276612866129661306613166132661336613466135661366613766138661396614066141661426614366144661456614666147661486614966150661516615266153661546615566156661576615866159661606616166162661636616466165661666616766168661696617066171661726617366174661756617666177661786617966180661816618266183661846618566186661876618866189661906619166192661936619466195661966619766198661996620066201662026620366204662056620666207662086620966210662116621266213662146621566216662176621866219662206622166222662236622466225662266622766228662296623066231662326623366234662356623666237662386623966240662416624266243662446624566246662476624866249662506625166252662536625466255662566625766258662596626066261662626626366264662656626666267662686626966270662716627266273662746627566276662776627866279662806628166282662836628466285662866628766288662896629066291662926629366294662956629666297662986629966300663016630266303663046630566306663076630866309663106631166312663136631466315663166631766318663196632066321663226632366324663256632666327663286632966330663316633266333663346633566336663376633866339663406634166342663436634466345663466634766348663496635066351663526635366354663556635666357663586635966360663616636266363663646636566366663676636866369663706637166372663736637466375663766637766378663796638066381663826638366384663856638666387663886638966390663916639266393663946639566396663976639866399664006640166402664036640466405664066640766408664096641066411664126641366414664156641666417664186641966420664216642266423664246642566426664276642866429664306643166432664336643466435664366643766438664396644066441664426644366444664456644666447664486644966450664516645266453664546645566456664576645866459664606646166462664636646466465664666646766468664696647066471664726647366474664756647666477664786647966480664816648266483664846648566486664876648866489664906649166492664936649466495664966649766498664996650066501665026650366504665056650666507665086650966510665116651266513665146651566516665176651866519665206652166522665236652466525665266652766528665296653066531665326653366534665356653666537665386653966540665416654266543665446654566546665476654866549665506655166552665536655466555665566655766558665596656066561665626656366564665656656666567665686656966570665716657266573665746657566576665776657866579665806658166582665836658466585665866658766588665896659066591665926659366594665956659666597665986659966600666016660266603666046660566606666076660866609666106661166612666136661466615666166661766618666196662066621666226662366624666256662666627666286662966630666316663266633666346663566636666376663866639666406664166642666436664466645666466664766648666496665066651666526665366654666556665666657666586665966660666616666266663666646666566666666676666866669666706667166672666736667466675666766667766678666796668066681666826668366684666856668666687666886668966690666916669266693666946669566696666976669866699667006670166702667036670466705667066670766708667096671066711667126671366714667156671666717667186671966720667216672266723667246672566726667276672866729667306673166732667336673466735667366673766738667396674066741667426674366744667456674666747667486674966750667516675266753667546675566756667576675866759667606676166762667636676466765667666676766768667696677066771667726677366774667756677666777667786677966780667816678266783667846678566786667876678866789667906679166792667936679466795667966679766798667996680066801668026680366804668056680666807668086680966810668116681266813668146681566816668176681866819668206682166822668236682466825668266682766828668296683066831668326683366834668356683666837668386683966840668416684266843668446684566846668476684866849668506685166852668536685466855668566685766858668596686066861668626686366864668656686666867668686686966870668716687266873668746687566876668776687866879668806688166882668836688466885668866688766888668896689066891668926689366894668956689666897668986689966900669016690266903669046690566906669076690866909669106691166912669136691466915669166691766918669196692066921669226692366924669256692666927669286692966930669316693266933669346693566936669376693866939669406694166942669436694466945669466694766948669496695066951669526695366954669556695666957669586695966960669616696266963669646696566966669676696866969669706697166972669736697466975669766697766978669796698066981669826698366984669856698666987669886698966990669916699266993669946699566996669976699866999670006700167002670036700467005670066700767008670096701067011670126701367014670156701667017670186701967020670216702267023670246702567026670276702867029670306703167032670336703467035670366703767038670396704067041670426704367044670456704667047670486704967050670516705267053670546705567056670576705867059670606706167062670636706467065670666706767068670696707067071670726707367074670756707667077670786707967080670816708267083670846708567086670876708867089670906709167092670936709467095670966709767098670996710067101671026710367104671056710667107671086710967110671116711267113671146711567116671176711867119671206712167122671236712467125671266712767128671296713067131671326713367134671356713667137671386713967140671416714267143671446714567146671476714867149671506715167152671536715467155671566715767158671596716067161671626716367164671656716667167671686716967170671716717267173671746717567176671776717867179671806718167182671836718467185671866718767188671896719067191671926719367194671956719667197671986719967200672016720267203672046720567206672076720867209672106721167212672136721467215672166721767218672196722067221672226722367224672256722667227672286722967230672316723267233672346723567236672376723867239672406724167242672436724467245672466724767248672496725067251672526725367254672556725667257672586725967260672616726267263672646726567266672676726867269672706727167272672736727467275672766727767278672796728067281672826728367284672856728667287672886728967290672916729267293672946729567296672976729867299673006730167302673036730467305673066730767308673096731067311673126731367314673156731667317673186731967320673216732267323673246732567326673276732867329673306733167332673336733467335673366733767338673396734067341673426734367344673456734667347673486734967350673516735267353673546735567356673576735867359673606736167362673636736467365673666736767368673696737067371673726737367374673756737667377673786737967380673816738267383673846738567386673876738867389673906739167392673936739467395673966739767398673996740067401674026740367404674056740667407674086740967410674116741267413674146741567416674176741867419674206742167422674236742467425674266742767428674296743067431674326743367434674356743667437674386743967440674416744267443674446744567446674476744867449674506745167452674536745467455674566745767458674596746067461674626746367464674656746667467674686746967470674716747267473674746747567476674776747867479674806748167482674836748467485674866748767488674896749067491674926749367494674956749667497674986749967500675016750267503675046750567506675076750867509675106751167512675136751467515675166751767518675196752067521675226752367524675256752667527675286752967530675316753267533675346753567536675376753867539675406754167542675436754467545675466754767548675496755067551675526755367554675556755667557675586755967560675616756267563675646756567566675676756867569675706757167572675736757467575675766757767578675796758067581675826758367584675856758667587675886758967590675916759267593675946759567596675976759867599676006760167602676036760467605676066760767608676096761067611676126761367614676156761667617676186761967620676216762267623676246762567626676276762867629676306763167632676336763467635676366763767638676396764067641676426764367644676456764667647676486764967650676516765267653676546765567656676576765867659676606766167662676636766467665676666766767668676696767067671676726767367674676756767667677676786767967680676816768267683676846768567686676876768867689676906769167692676936769467695676966769767698676996770067701677026770367704677056770667707677086770967710677116771267713677146771567716677176771867719677206772167722677236772467725677266772767728677296773067731677326773367734677356773667737677386773967740677416774267743677446774567746677476774867749677506775167752677536775467755677566775767758677596776067761677626776367764677656776667767677686776967770677716777267773677746777567776677776777867779677806778167782677836778467785677866778767788677896779067791677926779367794677956779667797677986779967800678016780267803678046780567806678076780867809678106781167812678136781467815678166781767818678196782067821678226782367824678256782667827678286782967830678316783267833678346783567836678376783867839678406784167842678436784467845678466784767848678496785067851678526785367854678556785667857678586785967860678616786267863678646786567866678676786867869678706787167872678736787467875678766787767878678796788067881678826788367884678856788667887678886788967890678916789267893678946789567896678976789867899679006790167902679036790467905679066790767908679096791067911679126791367914679156791667917679186791967920679216792267923679246792567926679276792867929679306793167932679336793467935679366793767938679396794067941679426794367944679456794667947679486794967950679516795267953679546795567956679576795867959679606796167962679636796467965679666796767968679696797067971679726797367974679756797667977679786797967980679816798267983679846798567986679876798867989679906799167992679936799467995679966799767998679996800068001680026800368004680056800668007680086800968010680116801268013680146801568016680176801868019680206802168022680236802468025680266802768028680296803068031680326803368034680356803668037680386803968040680416804268043680446804568046680476804868049680506805168052680536805468055680566805768058680596806068061680626806368064680656806668067680686806968070680716807268073680746807568076680776807868079680806808168082680836808468085680866808768088680896809068091680926809368094680956809668097680986809968100681016810268103681046810568106681076810868109681106811168112681136811468115681166811768118681196812068121681226812368124681256812668127681286812968130681316813268133681346813568136681376813868139681406814168142681436814468145681466814768148681496815068151681526815368154681556815668157681586815968160681616816268163681646816568166681676816868169681706817168172681736817468175681766817768178681796818068181681826818368184681856818668187681886818968190681916819268193681946819568196681976819868199682006820168202682036820468205682066820768208682096821068211682126821368214682156821668217682186821968220682216822268223682246822568226682276822868229682306823168232682336823468235682366823768238682396824068241682426824368244682456824668247682486824968250682516825268253682546825568256682576825868259682606826168262682636826468265682666826768268682696827068271682726827368274682756827668277682786827968280682816828268283682846828568286682876828868289682906829168292682936829468295682966829768298682996830068301683026830368304683056830668307683086830968310683116831268313683146831568316683176831868319683206832168322683236832468325683266832768328683296833068331683326833368334683356833668337683386833968340683416834268343683446834568346683476834868349683506835168352683536835468355683566835768358683596836068361683626836368364683656836668367683686836968370683716837268373683746837568376683776837868379683806838168382683836838468385683866838768388683896839068391683926839368394683956839668397683986839968400684016840268403684046840568406684076840868409684106841168412684136841468415684166841768418684196842068421684226842368424684256842668427684286842968430684316843268433684346843568436684376843868439684406844168442684436844468445684466844768448684496845068451684526845368454684556845668457684586845968460684616846268463684646846568466684676846868469684706847168472684736847468475684766847768478684796848068481684826848368484684856848668487684886848968490684916849268493684946849568496684976849868499685006850168502685036850468505685066850768508685096851068511685126851368514685156851668517685186851968520685216852268523685246852568526685276852868529685306853168532685336853468535685366853768538685396854068541685426854368544685456854668547685486854968550685516855268553685546855568556685576855868559685606856168562685636856468565685666856768568685696857068571685726857368574685756857668577685786857968580685816858268583685846858568586685876858868589685906859168592685936859468595685966859768598685996860068601686026860368604686056860668607686086860968610686116861268613686146861568616686176861868619686206862168622686236862468625686266862768628686296863068631686326863368634686356863668637686386863968640686416864268643686446864568646686476864868649686506865168652686536865468655686566865768658686596866068661686626866368664686656866668667686686866968670686716867268673686746867568676686776867868679686806868168682686836868468685686866868768688686896869068691686926869368694686956869668697686986869968700687016870268703687046870568706687076870868709687106871168712687136871468715687166871768718687196872068721687226872368724687256872668727687286872968730687316873268733687346873568736687376873868739687406874168742687436874468745687466874768748687496875068751687526875368754687556875668757687586875968760687616876268763687646876568766687676876868769687706877168772687736877468775687766877768778687796878068781687826878368784687856878668787687886878968790687916879268793687946879568796687976879868799688006880168802688036880468805688066880768808688096881068811688126881368814688156881668817688186881968820688216882268823688246882568826688276882868829688306883168832688336883468835688366883768838688396884068841688426884368844688456884668847688486884968850688516885268853688546885568856688576885868859688606886168862688636886468865688666886768868688696887068871688726887368874688756887668877688786887968880688816888268883688846888568886688876888868889688906889168892688936889468895688966889768898688996890068901689026890368904689056890668907689086890968910689116891268913689146891568916689176891868919689206892168922689236892468925689266892768928689296893068931689326893368934689356893668937689386893968940689416894268943689446894568946689476894868949689506895168952689536895468955689566895768958689596896068961689626896368964689656896668967689686896968970689716897268973689746897568976689776897868979689806898168982689836898468985689866898768988689896899068991689926899368994689956899668997689986899969000690016900269003690046900569006690076900869009690106901169012690136901469015690166901769018690196902069021690226902369024690256902669027690286902969030690316903269033690346903569036690376903869039690406904169042690436904469045690466904769048690496905069051690526905369054690556905669057690586905969060690616906269063690646906569066690676906869069690706907169072690736907469075690766907769078690796908069081690826908369084690856908669087690886908969090690916909269093690946909569096690976909869099691006910169102691036910469105691066910769108691096911069111691126911369114691156911669117691186911969120691216912269123691246912569126691276912869129691306913169132691336913469135691366913769138691396914069141691426914369144691456914669147691486914969150691516915269153691546915569156691576915869159691606916169162691636916469165691666916769168691696917069171691726917369174691756917669177691786917969180691816918269183691846918569186691876918869189691906919169192691936919469195691966919769198691996920069201692026920369204692056920669207692086920969210692116921269213692146921569216692176921869219692206922169222692236922469225692266922769228692296923069231692326923369234692356923669237692386923969240692416924269243692446924569246692476924869249692506925169252692536925469255692566925769258692596926069261692626926369264692656926669267692686926969270692716927269273692746927569276692776927869279692806928169282692836928469285692866928769288692896929069291692926929369294692956929669297692986929969300693016930269303693046930569306693076930869309693106931169312693136931469315693166931769318693196932069321693226932369324693256932669327693286932969330693316933269333693346933569336693376933869339693406934169342693436934469345693466934769348693496935069351693526935369354693556935669357693586935969360693616936269363693646936569366693676936869369693706937169372693736937469375693766937769378693796938069381693826938369384693856938669387693886938969390693916939269393693946939569396693976939869399694006940169402694036940469405694066940769408694096941069411694126941369414694156941669417694186941969420694216942269423694246942569426694276942869429694306943169432694336943469435694366943769438694396944069441694426944369444694456944669447694486944969450694516945269453694546945569456694576945869459694606946169462694636946469465694666946769468694696947069471694726947369474694756947669477694786947969480694816948269483694846948569486694876948869489694906949169492694936949469495694966949769498694996950069501695026950369504695056950669507695086950969510695116951269513695146951569516695176951869519695206952169522695236952469525695266952769528695296953069531695326953369534695356953669537695386953969540695416954269543695446954569546695476954869549695506955169552695536955469555695566955769558695596956069561695626956369564695656956669567695686956969570695716957269573695746957569576695776957869579695806958169582695836958469585695866958769588695896959069591695926959369594695956959669597695986959969600696016960269603696046960569606696076960869609696106961169612696136961469615696166961769618696196962069621696226962369624696256962669627696286962969630696316963269633696346963569636696376963869639696406964169642696436964469645696466964769648696496965069651696526965369654696556965669657696586965969660696616966269663696646966569666696676966869669696706967169672696736967469675696766967769678696796968069681696826968369684696856968669687696886968969690696916969269693696946969569696696976969869699697006970169702697036970469705697066970769708697096971069711697126971369714697156971669717697186971969720697216972269723697246972569726697276972869729697306973169732697336973469735697366973769738697396974069741697426974369744697456974669747697486974969750697516975269753697546975569756697576975869759697606976169762697636976469765697666976769768697696977069771697726977369774697756977669777697786977969780697816978269783697846978569786697876978869789697906979169792697936979469795697966979769798697996980069801698026980369804698056980669807698086980969810698116981269813698146981569816698176981869819698206982169822698236982469825698266982769828698296983069831698326983369834698356983669837698386983969840698416984269843698446984569846698476984869849698506985169852698536985469855698566985769858698596986069861698626986369864698656986669867698686986969870698716987269873698746987569876698776987869879698806988169882698836988469885698866988769888698896989069891698926989369894698956989669897698986989969900699016990269903699046990569906699076990869909699106991169912699136991469915699166991769918699196992069921699226992369924699256992669927699286992969930699316993269933699346993569936699376993869939699406994169942699436994469945699466994769948699496995069951699526995369954699556995669957699586995969960699616996269963699646996569966699676996869969699706997169972699736997469975699766997769978699796998069981699826998369984699856998669987699886998969990699916999269993699946999569996699976999869999700007000170002700037000470005700067000770008700097001070011700127001370014700157001670017700187001970020700217002270023700247002570026700277002870029700307003170032700337003470035700367003770038700397004070041700427004370044700457004670047700487004970050700517005270053700547005570056700577005870059700607006170062700637006470065700667006770068700697007070071700727007370074700757007670077700787007970080700817008270083700847008570086700877008870089700907009170092700937009470095700967009770098700997010070101701027010370104701057010670107701087010970110701117011270113701147011570116701177011870119701207012170122701237012470125701267012770128701297013070131701327013370134701357013670137701387013970140701417014270143701447014570146701477014870149701507015170152701537015470155701567015770158701597016070161701627016370164701657016670167701687016970170701717017270173701747017570176701777017870179701807018170182701837018470185701867018770188701897019070191701927019370194701957019670197701987019970200702017020270203702047020570206702077020870209702107021170212702137021470215702167021770218702197022070221702227022370224702257022670227702287022970230702317023270233702347023570236702377023870239702407024170242702437024470245702467024770248702497025070251702527025370254702557025670257702587025970260702617026270263702647026570266702677026870269702707027170272702737027470275702767027770278702797028070281702827028370284702857028670287702887028970290702917029270293702947029570296702977029870299703007030170302703037030470305703067030770308703097031070311703127031370314703157031670317703187031970320703217032270323703247032570326703277032870329703307033170332703337033470335703367033770338703397034070341703427034370344703457034670347703487034970350703517035270353703547035570356703577035870359703607036170362703637036470365703667036770368703697037070371703727037370374703757037670377703787037970380703817038270383703847038570386703877038870389703907039170392703937039470395703967039770398703997040070401704027040370404704057040670407704087040970410704117041270413704147041570416704177041870419704207042170422704237042470425704267042770428704297043070431704327043370434704357043670437704387043970440704417044270443704447044570446704477044870449704507045170452704537045470455704567045770458704597046070461704627046370464704657046670467704687046970470704717047270473704747047570476704777047870479704807048170482704837048470485704867048770488704897049070491704927049370494704957049670497704987049970500705017050270503705047050570506705077050870509705107051170512705137051470515705167051770518705197052070521705227052370524705257052670527705287052970530705317053270533705347053570536705377053870539705407054170542705437054470545705467054770548705497055070551705527055370554705557055670557705587055970560705617056270563705647056570566705677056870569705707057170572705737057470575705767057770578705797058070581705827058370584705857058670587705887058970590705917059270593705947059570596705977059870599706007060170602706037060470605706067060770608706097061070611706127061370614706157061670617706187061970620706217062270623706247062570626706277062870629706307063170632706337063470635706367063770638706397064070641706427064370644706457064670647706487064970650706517065270653706547065570656706577065870659706607066170662706637066470665706667066770668706697067070671706727067370674706757067670677706787067970680706817068270683706847068570686706877068870689706907069170692706937069470695706967069770698706997070070701707027070370704707057070670707707087070970710707117071270713707147071570716707177071870719707207072170722707237072470725707267072770728707297073070731707327073370734707357073670737707387073970740707417074270743707447074570746707477074870749707507075170752707537075470755707567075770758707597076070761707627076370764707657076670767707687076970770707717077270773707747077570776707777077870779707807078170782707837078470785707867078770788707897079070791707927079370794707957079670797707987079970800708017080270803708047080570806708077080870809708107081170812708137081470815708167081770818708197082070821708227082370824708257082670827708287082970830708317083270833708347083570836708377083870839708407084170842708437084470845708467084770848708497085070851708527085370854708557085670857708587085970860708617086270863708647086570866708677086870869708707087170872708737087470875708767087770878708797088070881708827088370884708857088670887708887088970890708917089270893708947089570896708977089870899709007090170902709037090470905709067090770908709097091070911709127091370914709157091670917709187091970920709217092270923709247092570926709277092870929709307093170932709337093470935709367093770938709397094070941709427094370944709457094670947709487094970950709517095270953709547095570956709577095870959709607096170962709637096470965709667096770968709697097070971709727097370974709757097670977709787097970980709817098270983709847098570986709877098870989709907099170992709937099470995709967099770998709997100071001710027100371004710057100671007710087100971010710117101271013710147101571016710177101871019710207102171022710237102471025710267102771028710297103071031710327103371034710357103671037710387103971040710417104271043710447104571046710477104871049710507105171052710537105471055710567105771058710597106071061710627106371064710657106671067710687106971070710717107271073710747107571076710777107871079710807108171082710837108471085710867108771088710897109071091710927109371094710957109671097710987109971100711017110271103711047110571106711077110871109711107111171112711137111471115711167111771118711197112071121711227112371124711257112671127711287112971130711317113271133711347113571136711377113871139711407114171142711437114471145711467114771148711497115071151711527115371154711557115671157711587115971160711617116271163711647116571166711677116871169711707117171172711737117471175711767117771178711797118071181711827118371184711857118671187711887118971190711917119271193711947119571196711977119871199712007120171202712037120471205712067120771208712097121071211712127121371214712157121671217712187121971220712217122271223712247122571226712277122871229712307123171232712337123471235712367123771238712397124071241712427124371244712457124671247712487124971250712517125271253712547125571256712577125871259712607126171262712637126471265712667126771268712697127071271712727127371274712757127671277712787127971280712817128271283712847128571286712877128871289712907129171292712937129471295712967129771298712997130071301713027130371304713057130671307713087130971310713117131271313713147131571316713177131871319713207132171322713237132471325713267132771328713297133071331713327133371334713357133671337713387133971340713417134271343713447134571346713477134871349713507135171352713537135471355713567135771358713597136071361713627136371364713657136671367713687136971370713717137271373713747137571376713777137871379713807138171382713837138471385713867138771388713897139071391713927139371394713957139671397713987139971400714017140271403714047140571406714077140871409714107141171412714137141471415714167141771418714197142071421714227142371424714257142671427714287142971430714317143271433714347143571436714377143871439714407144171442714437144471445714467144771448714497145071451714527145371454714557145671457714587145971460714617146271463714647146571466714677146871469714707147171472714737147471475714767147771478714797148071481714827148371484714857148671487714887148971490714917149271493714947149571496714977149871499715007150171502715037150471505715067150771508715097151071511715127151371514715157151671517715187151971520715217152271523715247152571526715277152871529715307153171532715337153471535715367153771538715397154071541715427154371544715457154671547715487154971550715517155271553715547155571556715577155871559715607156171562715637156471565715667156771568715697157071571715727157371574715757157671577715787157971580715817158271583715847158571586715877158871589715907159171592715937159471595715967159771598715997160071601716027160371604716057160671607716087160971610716117161271613716147161571616716177161871619716207162171622716237162471625716267162771628716297163071631716327163371634716357163671637716387163971640716417164271643716447164571646716477164871649716507165171652716537165471655716567165771658716597166071661716627166371664716657166671667716687166971670716717167271673716747167571676716777167871679716807168171682716837168471685716867168771688716897169071691716927169371694716957169671697716987169971700717017170271703717047170571706717077170871709717107171171712717137171471715717167171771718717197172071721717227172371724717257172671727717287172971730717317173271733717347173571736717377173871739717407174171742717437174471745717467174771748717497175071751717527175371754717557175671757717587175971760717617176271763717647176571766717677176871769717707177171772717737177471775717767177771778717797178071781717827178371784717857178671787717887178971790717917179271793717947179571796717977179871799718007180171802718037180471805718067180771808718097181071811718127181371814718157181671817718187181971820718217182271823718247182571826718277182871829718307183171832718337183471835718367183771838718397184071841718427184371844718457184671847718487184971850718517185271853718547185571856718577185871859718607186171862718637186471865718667186771868718697187071871718727187371874718757187671877718787187971880718817188271883718847188571886718877188871889718907189171892718937189471895718967189771898718997190071901719027190371904719057190671907719087190971910719117191271913719147191571916719177191871919719207192171922719237192471925719267192771928719297193071931719327193371934719357193671937719387193971940719417194271943719447194571946719477194871949719507195171952719537195471955719567195771958719597196071961719627196371964719657196671967719687196971970719717197271973719747197571976719777197871979719807198171982719837198471985719867198771988719897199071991719927199371994719957199671997719987199972000720017200272003720047200572006720077200872009720107201172012720137201472015720167201772018720197202072021720227202372024720257202672027720287202972030720317203272033720347203572036720377203872039720407204172042720437204472045720467204772048720497205072051720527205372054720557205672057720587205972060720617206272063720647206572066720677206872069720707207172072720737207472075720767207772078720797208072081720827208372084720857208672087720887208972090720917209272093720947209572096720977209872099721007210172102721037210472105721067210772108721097211072111721127211372114721157211672117721187211972120721217212272123721247212572126721277212872129721307213172132721337213472135721367213772138721397214072141721427214372144721457214672147721487214972150721517215272153721547215572156721577215872159721607216172162721637216472165721667216772168721697217072171721727217372174721757217672177721787217972180721817218272183721847218572186721877218872189721907219172192721937219472195721967219772198721997220072201722027220372204722057220672207722087220972210722117221272213722147221572216722177221872219722207222172222722237222472225722267222772228722297223072231722327223372234722357223672237722387223972240722417224272243722447224572246722477224872249722507225172252722537225472255722567225772258722597226072261722627226372264722657226672267722687226972270722717227272273722747227572276722777227872279722807228172282722837228472285722867228772288722897229072291722927229372294722957229672297722987229972300723017230272303723047230572306723077230872309723107231172312723137231472315723167231772318723197232072321723227232372324723257232672327723287232972330723317233272333723347233572336723377233872339723407234172342723437234472345723467234772348723497235072351723527235372354723557235672357723587235972360723617236272363723647236572366723677236872369723707237172372723737237472375723767237772378723797238072381723827238372384723857238672387723887238972390723917239272393723947239572396723977239872399724007240172402724037240472405724067240772408724097241072411724127241372414724157241672417724187241972420724217242272423724247242572426724277242872429724307243172432724337243472435724367243772438724397244072441724427244372444724457244672447724487244972450724517245272453724547245572456724577245872459724607246172462724637246472465724667246772468724697247072471724727247372474724757247672477724787247972480724817248272483724847248572486724877248872489724907249172492724937249472495724967249772498724997250072501725027250372504725057250672507725087250972510725117251272513725147251572516725177251872519725207252172522725237252472525725267252772528725297253072531725327253372534725357253672537725387253972540725417254272543725447254572546725477254872549725507255172552725537255472555725567255772558725597256072561725627256372564725657256672567725687256972570725717257272573725747257572576725777257872579725807258172582725837258472585725867258772588725897259072591725927259372594725957259672597725987259972600726017260272603726047260572606726077260872609726107261172612726137261472615726167261772618726197262072621726227262372624726257262672627726287262972630726317263272633726347263572636726377263872639726407264172642726437264472645726467264772648726497265072651726527265372654726557265672657726587265972660726617266272663726647266572666726677266872669726707267172672726737267472675726767267772678726797268072681726827268372684726857268672687726887268972690726917269272693726947269572696726977269872699727007270172702727037270472705727067270772708727097271072711727127271372714727157271672717727187271972720727217272272723727247272572726727277272872729727307273172732727337273472735727367273772738727397274072741727427274372744727457274672747727487274972750727517275272753727547275572756727577275872759727607276172762727637276472765727667276772768727697277072771727727277372774727757277672777727787277972780727817278272783727847278572786727877278872789727907279172792727937279472795727967279772798727997280072801728027280372804728057280672807728087280972810728117281272813728147281572816728177281872819728207282172822728237282472825728267282772828728297283072831728327283372834728357283672837728387283972840728417284272843728447284572846728477284872849728507285172852728537285472855728567285772858728597286072861728627286372864728657286672867728687286972870728717287272873728747287572876728777287872879728807288172882728837288472885728867288772888728897289072891728927289372894728957289672897728987289972900729017290272903729047290572906729077290872909729107291172912729137291472915729167291772918729197292072921729227292372924729257292672927729287292972930729317293272933729347293572936729377293872939729407294172942729437294472945729467294772948729497295072951729527295372954729557295672957729587295972960729617296272963729647296572966729677296872969729707297172972729737297472975729767297772978729797298072981729827298372984729857298672987729887298972990729917299272993729947299572996729977299872999730007300173002730037300473005730067300773008730097301073011730127301373014730157301673017730187301973020730217302273023730247302573026730277302873029730307303173032730337303473035730367303773038730397304073041730427304373044730457304673047730487304973050730517305273053730547305573056730577305873059730607306173062730637306473065730667306773068730697307073071730727307373074730757307673077730787307973080730817308273083730847308573086730877308873089730907309173092730937309473095730967309773098730997310073101731027310373104731057310673107731087310973110731117311273113731147311573116731177311873119731207312173122731237312473125731267312773128731297313073131731327313373134731357313673137731387313973140731417314273143731447314573146731477314873149731507315173152731537315473155731567315773158731597316073161731627316373164731657316673167731687316973170731717317273173731747317573176731777317873179731807318173182731837318473185731867318773188731897319073191731927319373194731957319673197731987319973200732017320273203732047320573206732077320873209732107321173212732137321473215732167321773218732197322073221732227322373224732257322673227732287322973230732317323273233732347323573236732377323873239732407324173242732437324473245732467324773248732497325073251732527325373254732557325673257732587325973260732617326273263732647326573266732677326873269732707327173272732737327473275732767327773278732797328073281732827328373284732857328673287732887328973290732917329273293732947329573296732977329873299733007330173302733037330473305733067330773308733097331073311733127331373314733157331673317733187331973320733217332273323733247332573326733277332873329733307333173332733337333473335733367333773338733397334073341733427334373344733457334673347733487334973350733517335273353733547335573356733577335873359733607336173362733637336473365733667336773368733697337073371733727337373374733757337673377733787337973380733817338273383733847338573386733877338873389733907339173392733937339473395733967339773398733997340073401734027340373404734057340673407734087340973410734117341273413734147341573416734177341873419734207342173422734237342473425734267342773428734297343073431734327343373434734357343673437734387343973440734417344273443734447344573446734477344873449734507345173452734537345473455734567345773458734597346073461734627346373464734657346673467734687346973470734717347273473734747347573476734777347873479734807348173482734837348473485734867348773488734897349073491734927349373494734957349673497734987349973500735017350273503735047350573506735077350873509735107351173512735137351473515735167351773518735197352073521735227352373524735257352673527735287352973530735317353273533735347353573536735377353873539735407354173542735437354473545735467354773548735497355073551735527355373554735557355673557735587355973560735617356273563735647356573566735677356873569735707357173572735737357473575735767357773578735797358073581735827358373584735857358673587735887358973590735917359273593735947359573596735977359873599736007360173602736037360473605736067360773608736097361073611736127361373614736157361673617736187361973620736217362273623736247362573626736277362873629736307363173632736337363473635736367363773638736397364073641736427364373644736457364673647736487364973650736517365273653736547365573656736577365873659736607366173662736637366473665736667366773668736697367073671736727367373674736757367673677736787367973680736817368273683736847368573686736877368873689736907369173692736937369473695736967369773698736997370073701737027370373704737057370673707737087370973710737117371273713737147371573716737177371873719737207372173722737237372473725737267372773728737297373073731737327373373734737357373673737737387373973740737417374273743737447374573746737477374873749737507375173752737537375473755737567375773758737597376073761737627376373764737657376673767737687376973770737717377273773737747377573776737777377873779737807378173782737837378473785737867378773788737897379073791737927379373794737957379673797737987379973800738017380273803738047380573806738077380873809738107381173812738137381473815738167381773818738197382073821738227382373824738257382673827738287382973830738317383273833738347383573836738377383873839738407384173842738437384473845738467384773848738497385073851738527385373854738557385673857738587385973860738617386273863738647386573866738677386873869738707387173872738737387473875738767387773878738797388073881738827388373884738857388673887738887388973890738917389273893738947389573896738977389873899739007390173902739037390473905739067390773908739097391073911739127391373914739157391673917739187391973920739217392273923739247392573926739277392873929739307393173932739337393473935739367393773938739397394073941739427394373944739457394673947739487394973950739517395273953739547395573956739577395873959739607396173962739637396473965739667396773968739697397073971739727397373974739757397673977739787397973980739817398273983739847398573986739877398873989739907399173992739937399473995739967399773998739997400074001740027400374004740057400674007740087400974010740117401274013740147401574016740177401874019740207402174022740237402474025740267402774028740297403074031740327403374034740357403674037740387403974040740417404274043740447404574046740477404874049740507405174052740537405474055740567405774058740597406074061740627406374064740657406674067740687406974070740717407274073740747407574076740777407874079740807408174082740837408474085740867408774088740897409074091740927409374094740957409674097740987409974100741017410274103741047410574106741077410874109741107411174112741137411474115741167411774118741197412074121741227412374124741257412674127741287412974130741317413274133741347413574136741377413874139741407414174142741437414474145741467414774148741497415074151741527415374154741557415674157741587415974160741617416274163741647416574166741677416874169741707417174172741737417474175741767417774178741797418074181741827418374184741857418674187741887418974190741917419274193741947419574196741977419874199742007420174202742037420474205742067420774208742097421074211742127421374214742157421674217742187421974220742217422274223742247422574226742277422874229742307423174232742337423474235742367423774238742397424074241742427424374244742457424674247742487424974250742517425274253742547425574256742577425874259742607426174262742637426474265742667426774268742697427074271742727427374274742757427674277742787427974280742817428274283742847428574286742877428874289742907429174292742937429474295742967429774298742997430074301743027430374304743057430674307743087430974310743117431274313743147431574316743177431874319743207432174322743237432474325743267432774328743297433074331743327433374334743357433674337743387433974340743417434274343743447434574346743477434874349743507435174352743537435474355743567435774358743597436074361743627436374364743657436674367743687436974370743717437274373743747437574376743777437874379743807438174382743837438474385743867438774388743897439074391743927439374394743957439674397743987439974400744017440274403744047440574406744077440874409744107441174412744137441474415744167441774418744197442074421744227442374424744257442674427744287442974430744317443274433744347443574436744377443874439744407444174442744437444474445744467444774448744497445074451744527445374454744557445674457744587445974460744617446274463744647446574466744677446874469744707447174472744737447474475744767447774478744797448074481744827448374484744857448674487744887448974490744917449274493744947449574496744977449874499745007450174502745037450474505745067450774508745097451074511745127451374514745157451674517745187451974520745217452274523745247452574526745277452874529745307453174532745337453474535745367453774538745397454074541745427454374544745457454674547745487454974550745517455274553745547455574556745577455874559745607456174562745637456474565745667456774568745697457074571745727457374574745757457674577745787457974580745817458274583745847458574586745877458874589745907459174592745937459474595745967459774598745997460074601746027460374604746057460674607746087460974610746117461274613746147461574616746177461874619746207462174622746237462474625746267462774628746297463074631746327463374634746357463674637746387463974640746417464274643746447464574646746477464874649746507465174652746537465474655746567465774658746597466074661746627466374664746657466674667746687466974670746717467274673746747467574676746777467874679746807468174682746837468474685746867468774688746897469074691746927469374694746957469674697746987469974700747017470274703747047470574706747077470874709747107471174712747137471474715747167471774718747197472074721747227472374724747257472674727747287472974730747317473274733747347473574736747377473874739747407474174742747437474474745747467474774748747497475074751747527475374754747557475674757747587475974760747617476274763747647476574766747677476874769747707477174772747737477474775747767477774778747797478074781747827478374784747857478674787747887478974790747917479274793747947479574796747977479874799748007480174802748037480474805748067480774808748097481074811748127481374814748157481674817748187481974820748217482274823748247482574826748277482874829748307483174832748337483474835748367483774838748397484074841748427484374844748457484674847748487484974850748517485274853748547485574856748577485874859748607486174862748637486474865748667486774868748697487074871748727487374874748757487674877748787487974880748817488274883748847488574886748877488874889748907489174892748937489474895748967489774898748997490074901749027490374904749057490674907749087490974910749117491274913749147491574916749177491874919749207492174922749237492474925749267492774928749297493074931749327493374934749357493674937749387493974940749417494274943749447494574946749477494874949749507495174952749537495474955749567495774958749597496074961749627496374964749657496674967749687496974970749717497274973749747497574976749777497874979749807498174982749837498474985749867498774988749897499074991749927499374994749957499674997749987499975000750017500275003750047500575006750077500875009750107501175012750137501475015750167501775018750197502075021750227502375024750257502675027750287502975030750317503275033750347503575036750377503875039750407504175042750437504475045750467504775048750497505075051750527505375054750557505675057750587505975060750617506275063750647506575066750677506875069750707507175072750737507475075750767507775078750797508075081750827508375084750857508675087750887508975090750917509275093750947509575096750977509875099751007510175102751037510475105751067510775108751097511075111751127511375114751157511675117751187511975120751217512275123751247512575126751277512875129751307513175132751337513475135751367513775138751397514075141751427514375144751457514675147751487514975150751517515275153751547515575156751577515875159751607516175162751637516475165751667516775168751697517075171751727517375174751757517675177751787517975180751817518275183751847518575186751877518875189751907519175192751937519475195751967519775198751997520075201752027520375204752057520675207752087520975210752117521275213752147521575216752177521875219752207522175222752237522475225752267522775228752297523075231752327523375234752357523675237752387523975240752417524275243752447524575246752477524875249752507525175252752537525475255752567525775258752597526075261752627526375264752657526675267752687526975270752717527275273752747527575276752777527875279752807528175282752837528475285752867528775288752897529075291752927529375294752957529675297752987529975300753017530275303753047530575306753077530875309753107531175312753137531475315753167531775318753197532075321753227532375324753257532675327753287532975330753317533275333753347533575336753377533875339753407534175342753437534475345753467534775348753497535075351753527535375354753557535675357753587535975360753617536275363753647536575366753677536875369753707537175372753737537475375753767537775378753797538075381753827538375384753857538675387753887538975390753917539275393753947539575396753977539875399754007540175402754037540475405754067540775408754097541075411754127541375414754157541675417754187541975420754217542275423754247542575426754277542875429754307543175432754337543475435754367543775438754397544075441754427544375444754457544675447754487544975450754517545275453754547545575456754577545875459754607546175462754637546475465754667546775468754697547075471754727547375474754757547675477754787547975480754817548275483754847548575486754877548875489754907549175492754937549475495754967549775498754997550075501755027550375504755057550675507755087550975510755117551275513755147551575516755177551875519755207552175522755237552475525755267552775528755297553075531755327553375534755357553675537755387553975540755417554275543755447554575546755477554875549755507555175552755537555475555755567555775558755597556075561755627556375564755657556675567755687556975570755717557275573755747557575576755777557875579755807558175582755837558475585755867558775588755897559075591755927559375594755957559675597755987559975600756017560275603756047560575606756077560875609756107561175612756137561475615756167561775618756197562075621756227562375624756257562675627756287562975630756317563275633756347563575636756377563875639756407564175642756437564475645756467564775648756497565075651756527565375654756557565675657756587565975660756617566275663756647566575666756677566875669756707567175672756737567475675756767567775678756797568075681756827568375684756857568675687756887568975690756917569275693756947569575696756977569875699757007570175702757037570475705757067570775708757097571075711757127571375714757157571675717757187571975720757217572275723757247572575726757277572875729757307573175732757337573475735757367573775738757397574075741757427574375744757457574675747757487574975750757517575275753757547575575756757577575875759757607576175762757637576475765757667576775768757697577075771757727577375774757757577675777757787577975780757817578275783757847578575786757877578875789757907579175792757937579475795757967579775798757997580075801758027580375804758057580675807758087580975810758117581275813758147581575816758177581875819758207582175822758237582475825758267582775828758297583075831758327583375834758357583675837758387583975840758417584275843758447584575846758477584875849758507585175852758537585475855758567585775858758597586075861758627586375864758657586675867758687586975870758717587275873758747587575876758777587875879758807588175882758837588475885758867588775888758897589075891758927589375894758957589675897758987589975900759017590275903759047590575906759077590875909759107591175912759137591475915759167591775918759197592075921759227592375924759257592675927759287592975930759317593275933759347593575936759377593875939759407594175942759437594475945759467594775948759497595075951759527595375954759557595675957759587595975960759617596275963759647596575966759677596875969759707597175972759737597475975759767597775978759797598075981759827598375984759857598675987759887598975990759917599275993759947599575996759977599875999760007600176002760037600476005760067600776008760097601076011760127601376014760157601676017760187601976020760217602276023760247602576026760277602876029760307603176032760337603476035760367603776038760397604076041760427604376044760457604676047760487604976050760517605276053760547605576056760577605876059760607606176062760637606476065760667606776068760697607076071760727607376074760757607676077760787607976080760817608276083760847608576086760877608876089760907609176092760937609476095760967609776098760997610076101761027610376104761057610676107761087610976110761117611276113761147611576116761177611876119761207612176122761237612476125761267612776128761297613076131761327613376134761357613676137761387613976140761417614276143761447614576146761477614876149761507615176152761537615476155761567615776158761597616076161761627616376164761657616676167761687616976170761717617276173761747617576176761777617876179761807618176182761837618476185761867618776188761897619076191761927619376194761957619676197761987619976200762017620276203762047620576206762077620876209762107621176212762137621476215762167621776218762197622076221762227622376224762257622676227762287622976230762317623276233762347623576236762377623876239762407624176242762437624476245762467624776248762497625076251762527625376254762557625676257762587625976260762617626276263762647626576266762677626876269762707627176272762737627476275762767627776278762797628076281762827628376284762857628676287762887628976290762917629276293762947629576296762977629876299763007630176302763037630476305763067630776308763097631076311763127631376314763157631676317763187631976320763217632276323763247632576326763277632876329763307633176332763337633476335763367633776338763397634076341763427634376344763457634676347763487634976350763517635276353763547635576356763577635876359763607636176362763637636476365763667636776368763697637076371763727637376374763757637676377763787637976380763817638276383763847638576386763877638876389763907639176392763937639476395763967639776398763997640076401764027640376404764057640676407764087640976410764117641276413764147641576416764177641876419764207642176422764237642476425764267642776428764297643076431764327643376434764357643676437764387643976440764417644276443764447644576446764477644876449764507645176452764537645476455764567645776458764597646076461764627646376464764657646676467764687646976470764717647276473764747647576476764777647876479764807648176482764837648476485764867648776488764897649076491764927649376494764957649676497764987649976500765017650276503765047650576506765077650876509765107651176512765137651476515765167651776518765197652076521765227652376524765257652676527765287652976530765317653276533765347653576536765377653876539765407654176542765437654476545765467654776548765497655076551765527655376554765557655676557765587655976560765617656276563765647656576566765677656876569765707657176572765737657476575765767657776578765797658076581765827658376584765857658676587765887658976590765917659276593765947659576596765977659876599766007660176602766037660476605766067660776608766097661076611766127661376614766157661676617766187661976620766217662276623766247662576626766277662876629766307663176632766337663476635766367663776638766397664076641766427664376644766457664676647766487664976650766517665276653766547665576656766577665876659766607666176662766637666476665766667666776668766697667076671766727667376674766757667676677766787667976680766817668276683766847668576686766877668876689766907669176692766937669476695766967669776698766997670076701767027670376704767057670676707767087670976710767117671276713767147671576716767177671876719767207672176722767237672476725767267672776728767297673076731767327673376734767357673676737767387673976740767417674276743767447674576746767477674876749767507675176752767537675476755767567675776758767597676076761767627676376764767657676676767767687676976770767717677276773767747677576776767777677876779767807678176782767837678476785767867678776788767897679076791767927679376794767957679676797767987679976800768017680276803768047680576806768077680876809768107681176812768137681476815768167681776818768197682076821768227682376824768257682676827768287682976830768317683276833768347683576836768377683876839768407684176842768437684476845768467684776848768497685076851768527685376854768557685676857768587685976860768617686276863768647686576866768677686876869768707687176872768737687476875768767687776878768797688076881768827688376884768857688676887768887688976890768917689276893768947689576896768977689876899769007690176902769037690476905769067690776908769097691076911769127691376914769157691676917769187691976920769217692276923769247692576926769277692876929769307693176932769337693476935769367693776938769397694076941769427694376944769457694676947769487694976950769517695276953769547695576956769577695876959769607696176962769637696476965769667696776968769697697076971769727697376974769757697676977769787697976980769817698276983769847698576986769877698876989769907699176992769937699476995769967699776998769997700077001770027700377004770057700677007770087700977010770117701277013770147701577016770177701877019770207702177022770237702477025770267702777028770297703077031770327703377034770357703677037770387703977040770417704277043770447704577046770477704877049770507705177052770537705477055770567705777058770597706077061770627706377064770657706677067770687706977070770717707277073770747707577076770777707877079770807708177082770837708477085770867708777088770897709077091770927709377094770957709677097770987709977100771017710277103771047710577106771077710877109771107711177112771137711477115771167711777118771197712077121771227712377124771257712677127771287712977130771317713277133771347713577136771377713877139771407714177142771437714477145771467714777148771497715077151771527715377154771557715677157771587715977160771617716277163771647716577166771677716877169771707717177172771737717477175771767717777178771797718077181771827718377184771857718677187771887718977190771917719277193771947719577196771977719877199772007720177202772037720477205772067720777208772097721077211772127721377214772157721677217772187721977220772217722277223772247722577226772277722877229772307723177232772337723477235772367723777238772397724077241772427724377244772457724677247772487724977250772517725277253772547725577256772577725877259772607726177262772637726477265772667726777268772697727077271772727727377274772757727677277772787727977280772817728277283772847728577286772877728877289772907729177292772937729477295772967729777298772997730077301773027730377304773057730677307773087730977310773117731277313773147731577316773177731877319773207732177322773237732477325773267732777328773297733077331773327733377334773357733677337773387733977340773417734277343773447734577346773477734877349773507735177352773537735477355773567735777358773597736077361773627736377364773657736677367773687736977370773717737277373773747737577376773777737877379773807738177382773837738477385773867738777388773897739077391773927739377394773957739677397773987739977400774017740277403774047740577406774077740877409774107741177412774137741477415774167741777418774197742077421774227742377424774257742677427774287742977430774317743277433774347743577436774377743877439774407744177442774437744477445774467744777448774497745077451774527745377454774557745677457774587745977460774617746277463774647746577466774677746877469774707747177472774737747477475774767747777478774797748077481774827748377484774857748677487774887748977490774917749277493774947749577496774977749877499775007750177502775037750477505775067750777508775097751077511775127751377514775157751677517775187751977520775217752277523775247752577526775277752877529775307753177532775337753477535775367753777538775397754077541775427754377544775457754677547775487754977550775517755277553775547755577556775577755877559775607756177562775637756477565775667756777568775697757077571775727757377574775757757677577775787757977580775817758277583775847758577586775877758877589775907759177592775937759477595775967759777598775997760077601776027760377604776057760677607776087760977610776117761277613776147761577616776177761877619776207762177622776237762477625776267762777628776297763077631776327763377634776357763677637776387763977640776417764277643776447764577646776477764877649776507765177652776537765477655776567765777658776597766077661776627766377664776657766677667776687766977670776717767277673776747767577676776777767877679776807768177682776837768477685776867768777688776897769077691776927769377694776957769677697776987769977700777017770277703777047770577706777077770877709777107771177712777137771477715777167771777718777197772077721777227772377724777257772677727777287772977730777317773277733777347773577736777377773877739777407774177742777437774477745777467774777748777497775077751777527775377754777557775677757777587775977760777617776277763777647776577766777677776877769777707777177772777737777477775777767777777778777797778077781777827778377784777857778677787777887778977790777917779277793777947779577796777977779877799778007780177802778037780477805778067780777808778097781077811778127781377814778157781677817778187781977820778217782277823778247782577826778277782877829778307783177832778337783477835778367783777838778397784077841778427784377844778457784677847778487784977850778517785277853778547785577856778577785877859778607786177862778637786477865778667786777868778697787077871778727787377874778757787677877778787787977880778817788277883778847788577886778877788877889778907789177892778937789477895778967789777898778997790077901779027790377904779057790677907779087790977910779117791277913779147791577916779177791877919779207792177922779237792477925779267792777928779297793077931779327793377934779357793677937779387793977940779417794277943779447794577946779477794877949779507795177952779537795477955779567795777958779597796077961779627796377964779657796677967779687796977970779717797277973779747797577976779777797877979779807798177982779837798477985779867798777988779897799077991779927799377994779957799677997779987799978000780017800278003780047800578006780077800878009780107801178012780137801478015780167801778018780197802078021780227802378024780257802678027780287802978030780317803278033780347803578036780377803878039780407804178042780437804478045780467804778048780497805078051780527805378054780557805678057780587805978060780617806278063780647806578066780677806878069780707807178072780737807478075780767807778078780797808078081780827808378084780857808678087780887808978090780917809278093780947809578096780977809878099781007810178102781037810478105781067810778108781097811078111781127811378114781157811678117781187811978120781217812278123781247812578126781277812878129781307813178132781337813478135781367813778138781397814078141781427814378144781457814678147781487814978150781517815278153781547815578156781577815878159781607816178162781637816478165781667816778168781697817078171781727817378174781757817678177781787817978180781817818278183781847818578186781877818878189781907819178192781937819478195781967819778198781997820078201782027820378204782057820678207782087820978210782117821278213782147821578216782177821878219782207822178222782237822478225782267822778228782297823078231782327823378234782357823678237782387823978240782417824278243782447824578246782477824878249782507825178252782537825478255782567825778258782597826078261782627826378264782657826678267782687826978270782717827278273782747827578276782777827878279782807828178282782837828478285782867828778288782897829078291782927829378294782957829678297782987829978300783017830278303783047830578306783077830878309783107831178312783137831478315783167831778318783197832078321783227832378324783257832678327783287832978330783317833278333783347833578336783377833878339783407834178342783437834478345783467834778348783497835078351783527835378354783557835678357783587835978360783617836278363783647836578366783677836878369783707837178372783737837478375783767837778378783797838078381783827838378384783857838678387783887838978390783917839278393783947839578396783977839878399784007840178402784037840478405784067840778408784097841078411784127841378414784157841678417784187841978420784217842278423784247842578426784277842878429784307843178432784337843478435784367843778438784397844078441784427844378444784457844678447784487844978450784517845278453784547845578456784577845878459784607846178462784637846478465784667846778468784697847078471784727847378474784757847678477784787847978480784817848278483784847848578486784877848878489784907849178492784937849478495784967849778498784997850078501785027850378504785057850678507785087850978510785117851278513785147851578516785177851878519785207852178522785237852478525785267852778528785297853078531785327853378534785357853678537785387853978540785417854278543785447854578546785477854878549785507855178552785537855478555785567855778558785597856078561785627856378564785657856678567785687856978570785717857278573785747857578576785777857878579785807858178582785837858478585785867858778588785897859078591785927859378594785957859678597785987859978600786017860278603786047860578606786077860878609786107861178612786137861478615786167861778618786197862078621786227862378624786257862678627786287862978630786317863278633786347863578636786377863878639786407864178642786437864478645786467864778648786497865078651786527865378654786557865678657786587865978660786617866278663786647866578666786677866878669786707867178672786737867478675786767867778678786797868078681786827868378684786857868678687786887868978690786917869278693786947869578696786977869878699787007870178702787037870478705787067870778708787097871078711787127871378714787157871678717787187871978720787217872278723787247872578726787277872878729787307873178732787337873478735787367873778738787397874078741787427874378744787457874678747787487874978750787517875278753787547875578756787577875878759787607876178762787637876478765787667876778768787697877078771787727877378774787757877678777787787877978780787817878278783787847878578786787877878878789787907879178792787937879478795787967879778798787997880078801788027880378804788057880678807788087880978810788117881278813788147881578816788177881878819788207882178822788237882478825788267882778828788297883078831788327883378834788357883678837788387883978840788417884278843788447884578846788477884878849788507885178852788537885478855788567885778858788597886078861788627886378864788657886678867788687886978870788717887278873788747887578876788777887878879788807888178882788837888478885788867888778888788897889078891788927889378894788957889678897788987889978900789017890278903789047890578906789077890878909789107891178912789137891478915789167891778918789197892078921789227892378924789257892678927789287892978930789317893278933789347893578936789377893878939789407894178942789437894478945789467894778948789497895078951789527895378954789557895678957789587895978960789617896278963789647896578966789677896878969789707897178972789737897478975789767897778978789797898078981789827898378984789857898678987789887898978990789917899278993789947899578996789977899878999790007900179002790037900479005790067900779008790097901079011790127901379014790157901679017790187901979020790217902279023790247902579026790277902879029790307903179032790337903479035790367903779038790397904079041790427904379044790457904679047790487904979050790517905279053790547905579056790577905879059790607906179062790637906479065790667906779068790697907079071790727907379074790757907679077790787907979080790817908279083790847908579086790877908879089790907909179092790937909479095790967909779098790997910079101791027910379104791057910679107791087910979110791117911279113791147911579116791177911879119791207912179122791237912479125791267912779128791297913079131791327913379134791357913679137791387913979140791417914279143791447914579146791477914879149791507915179152791537915479155791567915779158791597916079161791627916379164791657916679167791687916979170791717917279173791747917579176791777917879179791807918179182791837918479185791867918779188791897919079191791927919379194791957919679197791987919979200792017920279203792047920579206792077920879209792107921179212792137921479215792167921779218792197922079221792227922379224792257922679227792287922979230792317923279233792347923579236792377923879239792407924179242792437924479245792467924779248792497925079251792527925379254792557925679257792587925979260792617926279263792647926579266792677926879269792707927179272792737927479275792767927779278792797928079281792827928379284792857928679287792887928979290792917929279293792947929579296792977929879299793007930179302793037930479305793067930779308793097931079311793127931379314793157931679317793187931979320793217932279323793247932579326793277932879329793307933179332793337933479335793367933779338793397934079341793427934379344793457934679347793487934979350793517935279353793547935579356793577935879359793607936179362793637936479365793667936779368793697937079371793727937379374793757937679377793787937979380793817938279383793847938579386793877938879389793907939179392793937939479395793967939779398793997940079401794027940379404794057940679407794087940979410794117941279413794147941579416794177941879419794207942179422794237942479425794267942779428794297943079431794327943379434794357943679437794387943979440794417944279443794447944579446794477944879449794507945179452794537945479455794567945779458794597946079461794627946379464794657946679467794687946979470794717947279473794747947579476794777947879479794807948179482794837948479485794867948779488794897949079491794927949379494794957949679497794987949979500795017950279503795047950579506795077950879509795107951179512795137951479515795167951779518795197952079521795227952379524795257952679527795287952979530795317953279533795347953579536795377953879539795407954179542795437954479545795467954779548795497955079551795527955379554795557955679557795587955979560795617956279563795647956579566795677956879569795707957179572795737957479575795767957779578795797958079581795827958379584795857958679587795887958979590795917959279593795947959579596795977959879599796007960179602796037960479605796067960779608796097961079611796127961379614796157961679617796187961979620796217962279623796247962579626796277962879629796307963179632796337963479635796367963779638796397964079641796427964379644796457964679647796487964979650796517965279653796547965579656796577965879659796607966179662796637966479665796667966779668796697967079671796727967379674796757967679677796787967979680796817968279683796847968579686796877968879689796907969179692796937969479695796967969779698796997970079701797027970379704797057970679707797087970979710797117971279713797147971579716797177971879719797207972179722797237972479725797267972779728797297973079731797327973379734797357973679737797387973979740797417974279743797447974579746797477974879749797507975179752797537975479755797567975779758797597976079761797627976379764797657976679767797687976979770797717977279773797747977579776797777977879779797807978179782797837978479785797867978779788797897979079791797927979379794797957979679797797987979979800798017980279803798047980579806798077980879809798107981179812798137981479815798167981779818798197982079821798227982379824798257982679827798287982979830798317983279833798347983579836798377983879839798407984179842798437984479845798467984779848798497985079851798527985379854798557985679857798587985979860798617986279863798647986579866798677986879869798707987179872798737987479875798767987779878798797988079881798827988379884798857988679887798887988979890798917989279893798947989579896798977989879899799007990179902799037990479905799067990779908799097991079911799127991379914799157991679917799187991979920799217992279923799247992579926799277992879929799307993179932799337993479935799367993779938799397994079941799427994379944799457994679947799487994979950799517995279953799547995579956799577995879959799607996179962799637996479965799667996779968799697997079971799727997379974799757997679977799787997979980799817998279983799847998579986799877998879989799907999179992799937999479995799967999779998799998000080001800028000380004800058000680007800088000980010800118001280013800148001580016800178001880019800208002180022800238002480025800268002780028800298003080031800328003380034800358003680037800388003980040800418004280043800448004580046800478004880049800508005180052800538005480055800568005780058800598006080061800628006380064800658006680067800688006980070800718007280073800748007580076800778007880079800808008180082800838008480085800868008780088800898009080091800928009380094800958009680097800988009980100801018010280103801048010580106801078010880109801108011180112801138011480115801168011780118801198012080121801228012380124801258012680127801288012980130801318013280133801348013580136801378013880139801408014180142801438014480145801468014780148801498015080151801528015380154801558015680157801588015980160801618016280163801648016580166801678016880169801708017180172801738017480175801768017780178801798018080181801828018380184801858018680187801888018980190801918019280193801948019580196801978019880199802008020180202802038020480205802068020780208802098021080211802128021380214802158021680217802188021980220802218022280223802248022580226802278022880229802308023180232802338023480235802368023780238802398024080241802428024380244802458024680247802488024980250802518025280253802548025580256802578025880259802608026180262802638026480265802668026780268802698027080271802728027380274802758027680277802788027980280802818028280283802848028580286802878028880289802908029180292802938029480295802968029780298802998030080301803028030380304803058030680307803088030980310803118031280313803148031580316803178031880319803208032180322803238032480325803268032780328803298033080331803328033380334803358033680337803388033980340803418034280343803448034580346803478034880349803508035180352803538035480355803568035780358803598036080361803628036380364803658036680367803688036980370803718037280373803748037580376803778037880379803808038180382803838038480385803868038780388803898039080391803928039380394803958039680397803988039980400804018040280403804048040580406804078040880409804108041180412804138041480415804168041780418804198042080421804228042380424804258042680427804288042980430804318043280433804348043580436804378043880439804408044180442804438044480445804468044780448804498045080451804528045380454804558045680457804588045980460804618046280463804648046580466804678046880469804708047180472804738047480475804768047780478804798048080481804828048380484804858048680487804888048980490804918049280493804948049580496804978049880499805008050180502805038050480505805068050780508805098051080511805128051380514805158051680517805188051980520805218052280523805248052580526805278052880529805308053180532805338053480535805368053780538805398054080541805428054380544805458054680547805488054980550805518055280553805548055580556805578055880559805608056180562805638056480565805668056780568805698057080571805728057380574805758057680577805788057980580805818058280583805848058580586805878058880589805908059180592805938059480595805968059780598805998060080601806028060380604806058060680607806088060980610806118061280613806148061580616806178061880619806208062180622806238062480625806268062780628806298063080631806328063380634806358063680637806388063980640806418064280643806448064580646806478064880649806508065180652806538065480655806568065780658806598066080661806628066380664806658066680667806688066980670806718067280673806748067580676806778067880679806808068180682806838068480685806868068780688806898069080691806928069380694806958069680697806988069980700807018070280703807048070580706807078070880709807108071180712807138071480715807168071780718807198072080721807228072380724807258072680727807288072980730807318073280733807348073580736807378073880739807408074180742807438074480745807468074780748807498075080751807528075380754807558075680757807588075980760807618076280763807648076580766807678076880769807708077180772807738077480775807768077780778807798078080781807828078380784807858078680787807888078980790807918079280793807948079580796807978079880799808008080180802808038080480805808068080780808808098081080811808128081380814808158081680817808188081980820808218082280823808248082580826808278082880829808308083180832808338083480835808368083780838808398084080841808428084380844808458084680847808488084980850808518085280853808548085580856808578085880859808608086180862808638086480865808668086780868808698087080871808728087380874808758087680877808788087980880808818088280883808848088580886808878088880889808908089180892808938089480895808968089780898808998090080901809028090380904809058090680907809088090980910809118091280913809148091580916809178091880919809208092180922809238092480925809268092780928809298093080931809328093380934809358093680937809388093980940809418094280943809448094580946809478094880949809508095180952809538095480955809568095780958809598096080961809628096380964809658096680967809688096980970809718097280973809748097580976809778097880979809808098180982809838098480985809868098780988809898099080991809928099380994809958099680997809988099981000810018100281003810048100581006810078100881009810108101181012810138101481015810168101781018810198102081021810228102381024810258102681027810288102981030810318103281033810348103581036810378103881039810408104181042810438104481045810468104781048810498105081051810528105381054810558105681057810588105981060810618106281063810648106581066810678106881069810708107181072810738107481075810768107781078810798108081081810828108381084810858108681087810888108981090810918109281093810948109581096810978109881099811008110181102811038110481105811068110781108811098111081111811128111381114811158111681117811188111981120811218112281123811248112581126811278112881129811308113181132811338113481135811368113781138811398114081141811428114381144811458114681147811488114981150811518115281153811548115581156811578115881159811608116181162811638116481165811668116781168811698117081171811728117381174811758117681177811788117981180811818118281183811848118581186811878118881189811908119181192811938119481195811968119781198811998120081201812028120381204812058120681207812088120981210812118121281213812148121581216812178121881219812208122181222812238122481225812268122781228812298123081231812328123381234812358123681237812388123981240812418124281243812448124581246812478124881249812508125181252812538125481255812568125781258812598126081261812628126381264812658126681267812688126981270812718127281273812748127581276812778127881279812808128181282812838128481285812868128781288812898129081291812928129381294812958129681297812988129981300813018130281303813048130581306813078130881309813108131181312813138131481315813168131781318813198132081321813228132381324813258132681327813288132981330813318133281333813348133581336813378133881339813408134181342813438134481345813468134781348813498135081351813528135381354813558135681357813588135981360813618136281363813648136581366813678136881369813708137181372813738137481375813768137781378813798138081381813828138381384813858138681387813888138981390813918139281393813948139581396813978139881399814008140181402814038140481405814068140781408814098141081411814128141381414814158141681417814188141981420814218142281423814248142581426814278142881429814308143181432814338143481435814368143781438814398144081441814428144381444814458144681447814488144981450814518145281453814548145581456814578145881459814608146181462814638146481465814668146781468814698147081471814728147381474814758147681477814788147981480814818148281483814848148581486814878148881489814908149181492814938149481495814968149781498814998150081501815028150381504815058150681507815088150981510815118151281513815148151581516815178151881519815208152181522815238152481525815268152781528815298153081531815328153381534815358153681537815388153981540815418154281543815448154581546815478154881549815508155181552815538155481555815568155781558815598156081561815628156381564815658156681567815688156981570815718157281573815748157581576815778157881579815808158181582815838158481585815868158781588815898159081591815928159381594815958159681597815988159981600816018160281603816048160581606816078160881609816108161181612816138161481615816168161781618816198162081621816228162381624816258162681627816288162981630816318163281633816348163581636816378163881639816408164181642816438164481645816468164781648816498165081651816528165381654816558165681657816588165981660816618166281663816648166581666816678166881669816708167181672816738167481675816768167781678816798168081681816828168381684816858168681687816888168981690816918169281693816948169581696816978169881699817008170181702817038170481705817068170781708817098171081711817128171381714817158171681717817188171981720817218172281723817248172581726817278172881729817308173181732817338173481735817368173781738817398174081741817428174381744817458174681747817488174981750817518175281753817548175581756817578175881759817608176181762817638176481765817668176781768817698177081771817728177381774817758177681777817788177981780817818178281783817848178581786817878178881789817908179181792817938179481795817968179781798817998180081801818028180381804818058180681807818088180981810818118181281813818148181581816818178181881819818208182181822818238182481825818268182781828818298183081831818328183381834818358183681837818388183981840818418184281843818448184581846818478184881849818508185181852818538185481855818568185781858818598186081861818628186381864818658186681867818688186981870818718187281873818748187581876818778187881879818808188181882818838188481885818868188781888818898189081891818928189381894818958189681897818988189981900819018190281903819048190581906819078190881909819108191181912819138191481915819168191781918819198192081921819228192381924819258192681927819288192981930819318193281933819348193581936819378193881939819408194181942819438194481945819468194781948819498195081951819528195381954819558195681957819588195981960819618196281963819648196581966819678196881969819708197181972819738197481975819768197781978819798198081981819828198381984819858198681987819888198981990819918199281993819948199581996819978199881999820008200182002820038200482005820068200782008820098201082011820128201382014820158201682017820188201982020820218202282023820248202582026820278202882029820308203182032820338203482035820368203782038820398204082041820428204382044820458204682047820488204982050820518205282053820548205582056820578205882059820608206182062820638206482065820668206782068820698207082071820728207382074820758207682077820788207982080820818208282083820848208582086820878208882089820908209182092820938209482095820968209782098820998210082101821028210382104821058210682107821088210982110821118211282113821148211582116821178211882119821208212182122821238212482125821268212782128821298213082131821328213382134821358213682137821388213982140821418214282143821448214582146821478214882149821508215182152821538215482155821568215782158821598216082161821628216382164821658216682167821688216982170821718217282173821748217582176821778217882179821808218182182821838218482185821868218782188821898219082191821928219382194821958219682197821988219982200822018220282203822048220582206822078220882209822108221182212822138221482215822168221782218822198222082221822228222382224822258222682227822288222982230822318223282233822348223582236822378223882239822408224182242822438224482245822468224782248822498225082251822528225382254822558225682257822588225982260822618226282263822648226582266822678226882269822708227182272822738227482275822768227782278822798228082281822828228382284822858228682287822888228982290822918229282293822948229582296822978229882299823008230182302823038230482305823068230782308823098231082311823128231382314823158231682317823188231982320823218232282323823248232582326823278232882329823308233182332823338233482335823368233782338823398234082341823428234382344823458234682347823488234982350823518235282353823548235582356823578235882359823608236182362823638236482365823668236782368823698237082371823728237382374823758237682377823788237982380823818238282383823848238582386823878238882389823908239182392823938239482395823968239782398823998240082401824028240382404824058240682407824088240982410824118241282413824148241582416824178241882419824208242182422824238242482425824268242782428824298243082431824328243382434824358243682437824388243982440824418244282443824448244582446824478244882449824508245182452824538245482455824568245782458824598246082461824628246382464824658246682467824688246982470824718247282473824748247582476824778247882479824808248182482824838248482485824868248782488824898249082491824928249382494824958249682497824988249982500825018250282503825048250582506825078250882509825108251182512825138251482515825168251782518825198252082521825228252382524825258252682527825288252982530825318253282533825348253582536825378253882539825408254182542825438254482545825468254782548825498255082551825528255382554825558255682557825588255982560825618256282563825648256582566825678256882569825708257182572825738257482575825768257782578825798258082581825828258382584825858258682587825888258982590825918259282593825948259582596825978259882599826008260182602826038260482605826068260782608826098261082611826128261382614826158261682617826188261982620826218262282623826248262582626826278262882629826308263182632826338263482635826368263782638826398264082641826428264382644826458264682647826488264982650826518265282653826548265582656826578265882659826608266182662826638266482665826668266782668826698267082671826728267382674826758267682677826788267982680826818268282683826848268582686826878268882689826908269182692826938269482695826968269782698826998270082701827028270382704827058270682707827088270982710827118271282713827148271582716827178271882719827208272182722827238272482725827268272782728827298273082731827328273382734827358273682737827388273982740827418274282743827448274582746827478274882749827508275182752827538275482755827568275782758827598276082761827628276382764827658276682767827688276982770827718277282773827748277582776827778277882779827808278182782827838278482785827868278782788827898279082791827928279382794827958279682797827988279982800828018280282803828048280582806828078280882809828108281182812828138281482815828168281782818828198282082821828228282382824828258282682827828288282982830828318283282833828348283582836828378283882839828408284182842828438284482845828468284782848828498285082851828528285382854828558285682857828588285982860828618286282863828648286582866828678286882869828708287182872828738287482875828768287782878828798288082881828828288382884828858288682887828888288982890828918289282893828948289582896828978289882899829008290182902829038290482905829068290782908829098291082911829128291382914829158291682917829188291982920829218292282923829248292582926829278292882929829308293182932829338293482935829368293782938829398294082941829428294382944829458294682947829488294982950829518295282953829548295582956829578295882959829608296182962829638296482965829668296782968829698297082971829728297382974829758297682977829788297982980829818298282983829848298582986829878298882989829908299182992829938299482995829968299782998829998300083001830028300383004830058300683007830088300983010830118301283013830148301583016830178301883019830208302183022830238302483025830268302783028830298303083031830328303383034830358303683037830388303983040830418304283043830448304583046830478304883049830508305183052830538305483055830568305783058830598306083061830628306383064830658306683067830688306983070830718307283073830748307583076830778307883079830808308183082830838308483085830868308783088830898309083091830928309383094830958309683097830988309983100831018310283103831048310583106831078310883109831108311183112831138311483115831168311783118831198312083121831228312383124831258312683127831288312983130831318313283133831348313583136831378313883139831408314183142831438314483145831468314783148831498315083151831528315383154831558315683157831588315983160831618316283163831648316583166831678316883169831708317183172831738317483175831768317783178831798318083181831828318383184831858318683187831888318983190831918319283193831948319583196831978319883199832008320183202832038320483205832068320783208832098321083211832128321383214832158321683217832188321983220832218322283223832248322583226832278322883229832308323183232832338323483235832368323783238832398324083241832428324383244832458324683247832488324983250832518325283253832548325583256832578325883259832608326183262832638326483265832668326783268832698327083271832728327383274832758327683277832788327983280832818328283283832848328583286832878328883289832908329183292832938329483295832968329783298832998330083301833028330383304833058330683307833088330983310833118331283313833148331583316833178331883319833208332183322833238332483325833268332783328833298333083331833328333383334833358333683337833388333983340833418334283343833448334583346833478334883349833508335183352833538335483355833568335783358833598336083361833628336383364833658336683367833688336983370833718337283373833748337583376833778337883379833808338183382833838338483385833868338783388833898339083391833928339383394833958339683397833988339983400834018340283403834048340583406834078340883409834108341183412834138341483415834168341783418834198342083421834228342383424834258342683427834288342983430834318343283433834348343583436834378343883439834408344183442834438344483445834468344783448834498345083451834528345383454834558345683457834588345983460834618346283463834648346583466834678346883469834708347183472834738347483475834768347783478834798348083481834828348383484834858348683487834888348983490834918349283493834948349583496834978349883499835008350183502835038350483505835068350783508835098351083511835128351383514835158351683517835188351983520835218352283523835248352583526835278352883529835308353183532835338353483535835368353783538835398354083541835428354383544835458354683547835488354983550835518355283553835548355583556835578355883559835608356183562835638356483565835668356783568835698357083571835728357383574835758357683577835788357983580835818358283583835848358583586835878358883589835908359183592835938359483595835968359783598835998360083601836028360383604836058360683607836088360983610836118361283613836148361583616836178361883619836208362183622836238362483625836268362783628836298363083631836328363383634836358363683637836388363983640836418364283643836448364583646836478364883649836508365183652836538365483655836568365783658836598366083661836628366383664836658366683667836688366983670836718367283673836748367583676836778367883679836808368183682836838368483685836868368783688836898369083691836928369383694836958369683697836988369983700837018370283703837048370583706837078370883709837108371183712837138371483715837168371783718837198372083721837228372383724837258372683727837288372983730837318373283733837348373583736837378373883739837408374183742837438374483745837468374783748837498375083751837528375383754837558375683757837588375983760837618376283763837648376583766837678376883769837708377183772837738377483775837768377783778837798378083781837828378383784837858378683787837888378983790837918379283793837948379583796837978379883799838008380183802838038380483805838068380783808838098381083811838128381383814838158381683817838188381983820838218382283823838248382583826838278382883829838308383183832838338383483835838368383783838838398384083841838428384383844838458384683847838488384983850838518385283853838548385583856838578385883859838608386183862838638386483865838668386783868838698387083871838728387383874838758387683877838788387983880838818388283883838848388583886838878388883889838908389183892838938389483895838968389783898838998390083901839028390383904839058390683907839088390983910839118391283913839148391583916839178391883919839208392183922839238392483925839268392783928839298393083931839328393383934839358393683937839388393983940839418394283943839448394583946839478394883949839508395183952839538395483955839568395783958839598396083961839628396383964839658396683967839688396983970839718397283973839748397583976839778397883979839808398183982839838398483985839868398783988839898399083991839928399383994839958399683997839988399984000840018400284003840048400584006840078400884009840108401184012840138401484015840168401784018840198402084021840228402384024840258402684027840288402984030840318403284033840348403584036840378403884039840408404184042840438404484045840468404784048840498405084051840528405384054840558405684057840588405984060840618406284063840648406584066840678406884069840708407184072840738407484075840768407784078840798408084081840828408384084840858408684087840888408984090840918409284093840948409584096840978409884099841008410184102841038410484105841068410784108841098411084111841128411384114841158411684117841188411984120841218412284123841248412584126841278412884129841308413184132841338413484135841368413784138841398414084141841428414384144841458414684147841488414984150841518415284153841548415584156841578415884159841608416184162841638416484165841668416784168841698417084171841728417384174841758417684177841788417984180841818418284183841848418584186841878418884189841908419184192841938419484195841968419784198841998420084201842028420384204842058420684207842088420984210842118421284213842148421584216842178421884219842208422184222842238422484225842268422784228842298423084231842328423384234842358423684237842388423984240842418424284243842448424584246842478424884249842508425184252842538425484255842568425784258842598426084261842628426384264842658426684267842688426984270842718427284273842748427584276842778427884279842808428184282842838428484285842868428784288842898429084291842928429384294842958429684297842988429984300843018430284303843048430584306843078430884309843108431184312843138431484315843168431784318843198432084321843228432384324843258432684327843288432984330843318433284333843348433584336843378433884339843408434184342843438434484345843468434784348843498435084351843528435384354843558435684357843588435984360843618436284363843648436584366843678436884369843708437184372843738437484375843768437784378843798438084381843828438384384843858438684387843888438984390843918439284393843948439584396843978439884399844008440184402844038440484405844068440784408844098441084411844128441384414844158441684417844188441984420844218442284423844248442584426844278442884429844308443184432844338443484435844368443784438844398444084441844428444384444844458444684447844488444984450844518445284453844548445584456844578445884459844608446184462844638446484465844668446784468844698447084471844728447384474844758447684477844788447984480844818448284483844848448584486844878448884489844908449184492844938449484495844968449784498844998450084501845028450384504845058450684507845088450984510845118451284513845148451584516845178451884519845208452184522845238452484525845268452784528845298453084531845328453384534845358453684537845388453984540845418454284543845448454584546845478454884549845508455184552845538455484555845568455784558845598456084561845628456384564845658456684567845688456984570845718457284573845748457584576845778457884579845808458184582845838458484585845868458784588845898459084591845928459384594845958459684597845988459984600846018460284603846048460584606846078460884609846108461184612846138461484615846168461784618846198462084621846228462384624846258462684627846288462984630846318463284633846348463584636846378463884639846408464184642846438464484645846468464784648846498465084651846528465384654846558465684657846588465984660846618466284663846648466584666846678466884669846708467184672846738467484675846768467784678846798468084681846828468384684846858468684687846888468984690846918469284693846948469584696846978469884699847008470184702847038470484705847068470784708847098471084711847128471384714847158471684717847188471984720847218472284723847248472584726847278472884729847308473184732847338473484735847368473784738847398474084741847428474384744847458474684747847488474984750847518475284753847548475584756847578475884759847608476184762847638476484765847668476784768847698477084771847728477384774847758477684777847788477984780847818478284783847848478584786847878478884789847908479184792847938479484795847968479784798847998480084801848028480384804848058480684807848088480984810848118481284813848148481584816848178481884819848208482184822848238482484825848268482784828848298483084831848328483384834848358483684837848388483984840848418484284843848448484584846848478484884849848508485184852848538485484855848568485784858848598486084861848628486384864848658486684867848688486984870848718487284873848748487584876848778487884879848808488184882848838488484885848868488784888848898489084891848928489384894848958489684897848988489984900849018490284903849048490584906849078490884909849108491184912849138491484915849168491784918849198492084921849228492384924849258492684927849288492984930849318493284933849348493584936849378493884939849408494184942849438494484945849468494784948849498495084951849528495384954849558495684957849588495984960849618496284963849648496584966849678496884969849708497184972849738497484975849768497784978849798498084981849828498384984849858498684987849888498984990849918499284993849948499584996849978499884999850008500185002850038500485005850068500785008850098501085011850128501385014850158501685017850188501985020850218502285023850248502585026850278502885029850308503185032850338503485035850368503785038850398504085041850428504385044850458504685047850488504985050850518505285053850548505585056850578505885059850608506185062850638506485065850668506785068850698507085071850728507385074850758507685077850788507985080850818508285083850848508585086850878508885089850908509185092850938509485095850968509785098850998510085101851028510385104851058510685107851088510985110851118511285113851148511585116851178511885119851208512185122851238512485125851268512785128851298513085131851328513385134851358513685137851388513985140851418514285143851448514585146851478514885149851508515185152851538515485155851568515785158851598516085161851628516385164851658516685167851688516985170851718517285173851748517585176851778517885179851808518185182851838518485185851868518785188851898519085191851928519385194851958519685197851988519985200852018520285203852048520585206852078520885209852108521185212852138521485215852168521785218852198522085221852228522385224852258522685227852288522985230852318523285233852348523585236852378523885239852408524185242852438524485245852468524785248852498525085251852528525385254852558525685257852588525985260852618526285263852648526585266852678526885269852708527185272852738527485275852768527785278852798528085281852828528385284852858528685287852888528985290852918529285293852948529585296852978529885299853008530185302853038530485305853068530785308853098531085311853128531385314853158531685317853188531985320853218532285323853248532585326853278532885329853308533185332853338533485335853368533785338853398534085341853428534385344853458534685347853488534985350853518535285353853548535585356853578535885359853608536185362853638536485365853668536785368853698537085371853728537385374853758537685377853788537985380853818538285383853848538585386853878538885389853908539185392853938539485395853968539785398853998540085401854028540385404854058540685407854088540985410854118541285413854148541585416854178541885419854208542185422854238542485425854268542785428854298543085431854328543385434854358543685437854388543985440854418544285443854448544585446854478544885449854508545185452854538545485455854568545785458854598546085461854628546385464854658546685467854688546985470854718547285473854748547585476854778547885479854808548185482854838548485485854868548785488854898549085491854928549385494854958549685497854988549985500855018550285503855048550585506855078550885509855108551185512855138551485515855168551785518855198552085521855228552385524855258552685527855288552985530855318553285533855348553585536855378553885539855408554185542855438554485545855468554785548855498555085551855528555385554855558555685557855588555985560855618556285563855648556585566855678556885569855708557185572855738557485575855768557785578855798558085581855828558385584855858558685587855888558985590855918559285593855948559585596855978559885599856008560185602856038560485605856068560785608856098561085611856128561385614856158561685617856188561985620856218562285623856248562585626856278562885629856308563185632856338563485635856368563785638856398564085641856428564385644856458564685647856488564985650856518565285653856548565585656856578565885659856608566185662856638566485665856668566785668856698567085671856728567385674856758567685677856788567985680856818568285683856848568585686856878568885689856908569185692856938569485695856968569785698856998570085701857028570385704857058570685707857088570985710857118571285713857148571585716857178571885719857208572185722857238572485725857268572785728857298573085731857328573385734857358573685737857388573985740857418574285743857448574585746857478574885749857508575185752857538575485755857568575785758857598576085761857628576385764857658576685767857688576985770857718577285773857748577585776857778577885779857808578185782857838578485785857868578785788857898579085791857928579385794857958579685797857988579985800858018580285803858048580585806858078580885809858108581185812858138581485815858168581785818858198582085821858228582385824858258582685827858288582985830858318583285833858348583585836858378583885839858408584185842858438584485845858468584785848858498585085851858528585385854858558585685857858588585985860858618586285863858648586585866858678586885869858708587185872858738587485875858768587785878858798588085881858828588385884858858588685887858888588985890858918589285893858948589585896858978589885899859008590185902859038590485905859068590785908859098591085911859128591385914859158591685917859188591985920859218592285923859248592585926859278592885929859308593185932859338593485935859368593785938859398594085941859428594385944859458594685947859488594985950859518595285953859548595585956859578595885959859608596185962859638596485965859668596785968859698597085971859728597385974859758597685977859788597985980859818598285983859848598585986859878598885989859908599185992859938599485995859968599785998859998600086001860028600386004860058600686007860088600986010860118601286013860148601586016860178601886019860208602186022860238602486025860268602786028860298603086031860328603386034860358603686037860388603986040860418604286043860448604586046860478604886049860508605186052860538605486055860568605786058860598606086061860628606386064860658606686067860688606986070860718607286073860748607586076860778607886079860808608186082860838608486085860868608786088860898609086091860928609386094860958609686097860988609986100861018610286103861048610586106861078610886109861108611186112861138611486115861168611786118861198612086121861228612386124861258612686127861288612986130861318613286133861348613586136861378613886139861408614186142861438614486145861468614786148861498615086151861528615386154861558615686157861588615986160861618616286163861648616586166861678616886169861708617186172861738617486175861768617786178861798618086181861828618386184861858618686187861888618986190861918619286193861948619586196861978619886199862008620186202862038620486205862068620786208862098621086211862128621386214862158621686217862188621986220862218622286223862248622586226862278622886229862308623186232862338623486235862368623786238862398624086241862428624386244862458624686247862488624986250862518625286253862548625586256862578625886259862608626186262862638626486265862668626786268862698627086271862728627386274862758627686277862788627986280862818628286283862848628586286862878628886289862908629186292862938629486295862968629786298862998630086301863028630386304863058630686307863088630986310863118631286313863148631586316863178631886319863208632186322863238632486325863268632786328863298633086331863328633386334863358633686337863388633986340863418634286343863448634586346863478634886349863508635186352863538635486355863568635786358863598636086361863628636386364863658636686367863688636986370863718637286373863748637586376863778637886379863808638186382863838638486385863868638786388863898639086391863928639386394863958639686397863988639986400864018640286403864048640586406864078640886409864108641186412864138641486415864168641786418864198642086421864228642386424864258642686427864288642986430864318643286433864348643586436864378643886439864408644186442864438644486445864468644786448864498645086451864528645386454864558645686457864588645986460864618646286463864648646586466864678646886469864708647186472864738647486475864768647786478864798648086481864828648386484864858648686487864888648986490864918649286493864948649586496864978649886499865008650186502865038650486505865068650786508865098651086511865128651386514865158651686517865188651986520865218652286523865248652586526865278652886529865308653186532865338653486535865368653786538865398654086541865428654386544865458654686547865488654986550865518655286553865548655586556865578655886559865608656186562865638656486565865668656786568865698657086571865728657386574865758657686577865788657986580865818658286583865848658586586865878658886589865908659186592865938659486595865968659786598865998660086601866028660386604866058660686607866088660986610866118661286613866148661586616866178661886619866208662186622866238662486625866268662786628866298663086631866328663386634866358663686637866388663986640866418664286643866448664586646866478664886649866508665186652866538665486655866568665786658866598666086661866628666386664866658666686667866688666986670866718667286673866748667586676866778667886679866808668186682866838668486685866868668786688866898669086691866928669386694866958669686697866988669986700867018670286703867048670586706867078670886709867108671186712867138671486715867168671786718867198672086721867228672386724867258672686727867288672986730867318673286733867348673586736867378673886739867408674186742867438674486745867468674786748867498675086751867528675386754867558675686757867588675986760867618676286763867648676586766867678676886769867708677186772867738677486775867768677786778867798678086781867828678386784867858678686787867888678986790867918679286793867948679586796867978679886799868008680186802868038680486805868068680786808868098681086811868128681386814868158681686817868188681986820868218682286823868248682586826868278682886829868308683186832868338683486835868368683786838868398684086841868428684386844868458684686847868488684986850868518685286853868548685586856868578685886859868608686186862868638686486865868668686786868868698687086871868728687386874868758687686877868788687986880868818688286883868848688586886868878688886889868908689186892868938689486895868968689786898868998690086901869028690386904869058690686907869088690986910869118691286913869148691586916869178691886919869208692186922869238692486925869268692786928869298693086931869328693386934869358693686937869388693986940869418694286943869448694586946869478694886949869508695186952869538695486955869568695786958869598696086961869628696386964869658696686967869688696986970869718697286973869748697586976869778697886979869808698186982869838698486985869868698786988869898699086991869928699386994869958699686997869988699987000870018700287003870048700587006870078700887009870108701187012870138701487015870168701787018870198702087021870228702387024870258702687027870288702987030870318703287033870348703587036870378703887039870408704187042870438704487045870468704787048870498705087051870528705387054870558705687057870588705987060870618706287063870648706587066870678706887069870708707187072870738707487075870768707787078870798708087081870828708387084870858708687087870888708987090870918709287093870948709587096870978709887099871008710187102871038710487105871068710787108871098711087111871128711387114871158711687117871188711987120871218712287123871248712587126871278712887129871308713187132871338713487135871368713787138871398714087141871428714387144871458714687147871488714987150871518715287153871548715587156871578715887159871608716187162871638716487165871668716787168871698717087171871728717387174871758717687177871788717987180871818718287183871848718587186871878718887189871908719187192871938719487195871968719787198871998720087201872028720387204872058720687207872088720987210872118721287213872148721587216872178721887219872208722187222872238722487225872268722787228872298723087231872328723387234872358723687237872388723987240872418724287243872448724587246872478724887249872508725187252872538725487255872568725787258872598726087261872628726387264872658726687267872688726987270872718727287273872748727587276872778727887279872808728187282872838728487285872868728787288872898729087291872928729387294872958729687297872988729987300873018730287303873048730587306873078730887309873108731187312873138731487315873168731787318873198732087321873228732387324873258732687327873288732987330873318733287333873348733587336873378733887339873408734187342873438734487345873468734787348873498735087351873528735387354873558735687357873588735987360873618736287363873648736587366873678736887369873708737187372873738737487375873768737787378873798738087381873828738387384873858738687387873888738987390873918739287393873948739587396873978739887399874008740187402874038740487405874068740787408874098741087411874128741387414874158741687417874188741987420874218742287423874248742587426874278742887429874308743187432874338743487435874368743787438874398744087441874428744387444874458744687447874488744987450874518745287453874548745587456874578745887459874608746187462874638746487465874668746787468874698747087471874728747387474874758747687477874788747987480874818748287483874848748587486874878748887489874908749187492874938749487495874968749787498874998750087501875028750387504875058750687507875088750987510875118751287513875148751587516875178751887519875208752187522875238752487525875268752787528875298753087531875328753387534875358753687537875388753987540875418754287543875448754587546875478754887549875508755187552875538755487555875568755787558875598756087561875628756387564875658756687567875688756987570875718757287573875748757587576875778757887579875808758187582875838758487585875868758787588875898759087591875928759387594875958759687597875988759987600876018760287603876048760587606876078760887609876108761187612876138761487615876168761787618876198762087621876228762387624876258762687627876288762987630876318763287633876348763587636876378763887639876408764187642876438764487645876468764787648876498765087651876528765387654876558765687657876588765987660876618766287663876648766587666876678766887669876708767187672876738767487675876768767787678876798768087681876828768387684876858768687687876888768987690876918769287693876948769587696876978769887699877008770187702877038770487705877068770787708877098771087711877128771387714877158771687717877188771987720877218772287723877248772587726877278772887729877308773187732877338773487735877368773787738877398774087741877428774387744877458774687747877488774987750877518775287753877548775587756877578775887759877608776187762877638776487765877668776787768877698777087771877728777387774877758777687777877788777987780877818778287783877848778587786877878778887789877908779187792877938779487795877968779787798877998780087801878028780387804878058780687807878088780987810878118781287813878148781587816878178781887819878208782187822878238782487825878268782787828878298783087831878328783387834878358783687837878388783987840878418784287843878448784587846878478784887849878508785187852878538785487855878568785787858878598786087861878628786387864878658786687867878688786987870878718787287873878748787587876878778787887879878808788187882878838788487885878868788787888878898789087891878928789387894878958789687897878988789987900879018790287903879048790587906879078790887909879108791187912879138791487915879168791787918879198792087921879228792387924879258792687927879288792987930879318793287933879348793587936879378793887939879408794187942879438794487945879468794787948879498795087951879528795387954879558795687957879588795987960879618796287963879648796587966879678796887969879708797187972879738797487975879768797787978879798798087981879828798387984879858798687987879888798987990879918799287993879948799587996879978799887999880008800188002880038800488005880068800788008880098801088011880128801388014880158801688017880188801988020880218802288023880248802588026880278802888029880308803188032880338803488035880368803788038880398804088041880428804388044880458804688047880488804988050880518805288053880548805588056880578805888059880608806188062880638806488065880668806788068880698807088071880728807388074880758807688077880788807988080880818808288083880848808588086880878808888089880908809188092880938809488095880968809788098880998810088101881028810388104881058810688107881088810988110881118811288113881148811588116881178811888119881208812188122881238812488125881268812788128881298813088131881328813388134881358813688137881388813988140881418814288143881448814588146881478814888149881508815188152881538815488155881568815788158881598816088161881628816388164881658816688167881688816988170881718817288173881748817588176881778817888179881808818188182881838818488185881868818788188881898819088191881928819388194881958819688197881988819988200882018820288203882048820588206882078820888209882108821188212882138821488215882168821788218882198822088221882228822388224882258822688227882288822988230882318823288233882348823588236882378823888239882408824188242882438824488245882468824788248882498825088251882528825388254882558825688257882588825988260882618826288263882648826588266882678826888269882708827188272882738827488275882768827788278882798828088281882828828388284882858828688287882888828988290882918829288293882948829588296882978829888299883008830188302883038830488305883068830788308883098831088311883128831388314883158831688317883188831988320883218832288323883248832588326883278832888329883308833188332883338833488335883368833788338883398834088341883428834388344883458834688347883488834988350883518835288353883548835588356883578835888359883608836188362883638836488365883668836788368883698837088371883728837388374883758837688377883788837988380883818838288383883848838588386883878838888389883908839188392883938839488395883968839788398883998840088401884028840388404884058840688407884088840988410884118841288413884148841588416884178841888419884208842188422884238842488425884268842788428884298843088431884328843388434884358843688437884388843988440884418844288443884448844588446884478844888449884508845188452884538845488455884568845788458884598846088461884628846388464884658846688467884688846988470884718847288473884748847588476884778847888479884808848188482884838848488485884868848788488884898849088491884928849388494884958849688497884988849988500885018850288503885048850588506885078850888509885108851188512885138851488515885168851788518885198852088521885228852388524885258852688527885288852988530885318853288533885348853588536885378853888539885408854188542885438854488545885468854788548885498855088551885528855388554885558855688557885588855988560885618856288563885648856588566885678856888569885708857188572885738857488575885768857788578885798858088581885828858388584885858858688587885888858988590885918859288593885948859588596885978859888599886008860188602886038860488605886068860788608886098861088611886128861388614886158861688617886188861988620886218862288623886248862588626886278862888629886308863188632886338863488635886368863788638886398864088641886428864388644886458864688647886488864988650886518865288653886548865588656886578865888659886608866188662886638866488665886668866788668886698867088671886728867388674886758867688677886788867988680886818868288683886848868588686886878868888689886908869188692886938869488695886968869788698886998870088701887028870388704887058870688707887088870988710887118871288713887148871588716887178871888719887208872188722887238872488725887268872788728887298873088731887328873388734887358873688737887388873988740887418874288743887448874588746887478874888749887508875188752887538875488755887568875788758887598876088761887628876388764887658876688767887688876988770887718877288773887748877588776887778877888779887808878188782887838878488785887868878788788887898879088791887928879388794887958879688797887988879988800888018880288803888048880588806888078880888809888108881188812888138881488815888168881788818888198882088821888228882388824888258882688827888288882988830888318883288833888348883588836888378883888839888408884188842888438884488845888468884788848888498885088851888528885388854888558885688857888588885988860888618886288863888648886588866888678886888869888708887188872888738887488875888768887788878888798888088881888828888388884888858888688887888888888988890888918889288893888948889588896888978889888899889008890188902889038890488905889068890788908889098891088911889128891388914889158891688917889188891988920889218892288923889248892588926889278892888929889308893188932889338893488935889368893788938889398894088941889428894388944889458894688947889488894988950889518895288953889548895588956889578895888959889608896188962889638896488965889668896788968889698897088971889728897388974889758897688977889788897988980889818898288983889848898588986889878898888989889908899188992889938899488995889968899788998889998900089001890028900389004890058900689007890088900989010890118901289013890148901589016890178901889019890208902189022890238902489025890268902789028890298903089031890328903389034890358903689037890388903989040890418904289043890448904589046890478904889049890508905189052890538905489055890568905789058890598906089061890628906389064890658906689067890688906989070890718907289073890748907589076890778907889079890808908189082890838908489085890868908789088890898909089091890928909389094890958909689097890988909989100891018910289103891048910589106891078910889109891108911189112891138911489115891168911789118891198912089121891228912389124891258912689127891288912989130891318913289133891348913589136891378913889139891408914189142891438914489145891468914789148891498915089151891528915389154891558915689157891588915989160891618916289163891648916589166891678916889169891708917189172891738917489175891768917789178891798918089181891828918389184891858918689187891888918989190891918919289193891948919589196891978919889199892008920189202892038920489205892068920789208892098921089211892128921389214892158921689217892188921989220892218922289223892248922589226892278922889229892308923189232892338923489235892368923789238892398924089241892428924389244892458924689247892488924989250892518925289253892548925589256892578925889259892608926189262892638926489265892668926789268892698927089271892728927389274892758927689277892788927989280892818928289283892848928589286892878928889289892908929189292892938929489295892968929789298892998930089301893028930389304893058930689307893088930989310893118931289313893148931589316893178931889319893208932189322893238932489325893268932789328893298933089331893328933389334893358933689337893388933989340893418934289343893448934589346893478934889349893508935189352893538935489355893568935789358893598936089361893628936389364893658936689367893688936989370893718937289373893748937589376893778937889379893808938189382893838938489385893868938789388893898939089391893928939389394893958939689397893988939989400894018940289403894048940589406894078940889409894108941189412894138941489415894168941789418894198942089421894228942389424894258942689427894288942989430894318943289433894348943589436894378943889439894408944189442894438944489445894468944789448894498945089451894528945389454894558945689457894588945989460894618946289463894648946589466894678946889469894708947189472894738947489475894768947789478894798948089481894828948389484894858948689487894888948989490894918949289493894948949589496894978949889499895008950189502895038950489505895068950789508895098951089511895128951389514895158951689517895188951989520895218952289523895248952589526895278952889529895308953189532895338953489535895368953789538895398954089541895428954389544895458954689547895488954989550895518955289553895548955589556895578955889559895608956189562895638956489565895668956789568895698957089571895728957389574895758957689577895788957989580895818958289583895848958589586895878958889589895908959189592895938959489595895968959789598895998960089601896028960389604896058960689607896088960989610896118961289613896148961589616896178961889619896208962189622896238962489625896268962789628896298963089631896328963389634896358963689637896388963989640896418964289643896448964589646896478964889649896508965189652896538965489655896568965789658896598966089661896628966389664896658966689667896688966989670896718967289673896748967589676896778967889679896808968189682896838968489685896868968789688896898969089691896928969389694896958969689697896988969989700897018970289703897048970589706897078970889709897108971189712897138971489715897168971789718897198972089721897228972389724897258972689727897288972989730897318973289733897348973589736897378973889739897408974189742897438974489745897468974789748897498975089751897528975389754897558975689757897588975989760897618976289763897648976589766897678976889769897708977189772897738977489775897768977789778897798978089781897828978389784897858978689787897888978989790897918979289793897948979589796897978979889799898008980189802898038980489805898068980789808898098981089811898128981389814898158981689817898188981989820898218982289823898248982589826898278982889829898308983189832898338983489835898368983789838898398984089841898428984389844898458984689847898488984989850898518985289853898548985589856898578985889859898608986189862898638986489865898668986789868898698987089871898728987389874898758987689877898788987989880898818988289883898848988589886898878988889889898908989189892898938989489895898968989789898898998990089901899028990389904899058990689907899088990989910899118991289913899148991589916899178991889919899208992189922899238992489925899268992789928899298993089931899328993389934899358993689937899388993989940899418994289943899448994589946899478994889949899508995189952899538995489955899568995789958899598996089961899628996389964899658996689967899688996989970899718997289973899748997589976899778997889979899808998189982899838998489985899868998789988899898999089991899928999389994899958999689997899988999990000900019000290003900049000590006900079000890009900109001190012900139001490015900169001790018900199002090021900229002390024900259002690027900289002990030900319003290033900349003590036900379003890039900409004190042900439004490045900469004790048900499005090051900529005390054900559005690057900589005990060900619006290063900649006590066900679006890069900709007190072900739007490075900769007790078900799008090081900829008390084900859008690087900889008990090900919009290093900949009590096900979009890099901009010190102901039010490105901069010790108901099011090111901129011390114901159011690117901189011990120901219012290123901249012590126901279012890129901309013190132901339013490135901369013790138901399014090141901429014390144901459014690147901489014990150901519015290153901549015590156901579015890159901609016190162901639016490165901669016790168901699017090171901729017390174901759017690177901789017990180901819018290183901849018590186901879018890189901909019190192901939019490195901969019790198901999020090201902029020390204902059020690207902089020990210902119021290213902149021590216902179021890219902209022190222902239022490225902269022790228902299023090231902329023390234902359023690237902389023990240902419024290243902449024590246902479024890249902509025190252902539025490255902569025790258902599026090261902629026390264902659026690267902689026990270902719027290273902749027590276902779027890279902809028190282902839028490285902869028790288902899029090291902929029390294902959029690297902989029990300903019030290303903049030590306903079030890309903109031190312903139031490315903169031790318903199032090321903229032390324903259032690327903289032990330903319033290333903349033590336903379033890339903409034190342903439034490345903469034790348903499035090351903529035390354903559035690357903589035990360903619036290363903649036590366903679036890369903709037190372903739037490375903769037790378903799038090381903829038390384903859038690387903889038990390903919039290393903949039590396903979039890399904009040190402904039040490405904069040790408904099041090411904129041390414904159041690417904189041990420904219042290423904249042590426904279042890429904309043190432904339043490435904369043790438904399044090441904429044390444904459044690447904489044990450904519045290453904549045590456904579045890459904609046190462904639046490465904669046790468904699047090471904729047390474904759047690477904789047990480904819048290483904849048590486904879048890489904909049190492904939049490495904969049790498904999050090501905029050390504905059050690507905089050990510905119051290513905149051590516905179051890519905209052190522905239052490525905269052790528905299053090531905329053390534905359053690537905389053990540905419054290543905449054590546905479054890549905509055190552905539055490555905569055790558905599056090561905629056390564905659056690567905689056990570905719057290573905749057590576905779057890579905809058190582905839058490585905869058790588905899059090591905929059390594905959059690597905989059990600906019060290603906049060590606906079060890609906109061190612906139061490615906169061790618906199062090621906229062390624906259062690627906289062990630906319063290633906349063590636906379063890639906409064190642906439064490645906469064790648906499065090651906529065390654906559065690657906589065990660906619066290663906649066590666906679066890669906709067190672906739067490675906769067790678906799068090681906829068390684906859068690687906889068990690906919069290693906949069590696906979069890699907009070190702907039070490705907069070790708907099071090711907129071390714907159071690717907189071990720907219072290723907249072590726907279072890729907309073190732907339073490735907369073790738907399074090741907429074390744907459074690747907489074990750907519075290753907549075590756907579075890759907609076190762907639076490765907669076790768907699077090771907729077390774907759077690777907789077990780907819078290783907849078590786907879078890789907909079190792907939079490795907969079790798907999080090801908029080390804908059080690807908089080990810908119081290813908149081590816908179081890819908209082190822908239082490825908269082790828908299083090831908329083390834908359083690837908389083990840908419084290843908449084590846908479084890849908509085190852908539085490855908569085790858908599086090861908629086390864908659086690867908689086990870908719087290873908749087590876908779087890879908809088190882908839088490885908869088790888908899089090891908929089390894908959089690897908989089990900909019090290903909049090590906909079090890909909109091190912909139091490915909169091790918909199092090921909229092390924909259092690927909289092990930909319093290933909349093590936909379093890939909409094190942909439094490945909469094790948909499095090951909529095390954909559095690957909589095990960909619096290963909649096590966909679096890969909709097190972909739097490975909769097790978909799098090981909829098390984909859098690987909889098990990909919099290993909949099590996909979099890999910009100191002910039100491005910069100791008910099101091011910129101391014910159101691017910189101991020910219102291023910249102591026910279102891029910309103191032910339103491035910369103791038910399104091041910429104391044910459104691047910489104991050910519105291053910549105591056910579105891059910609106191062910639106491065910669106791068910699107091071910729107391074910759107691077910789107991080910819108291083910849108591086910879108891089910909109191092910939109491095910969109791098910999110091101911029110391104911059110691107911089110991110911119111291113911149111591116911179111891119911209112191122911239112491125911269112791128911299113091131911329113391134911359113691137911389113991140911419114291143911449114591146911479114891149911509115191152911539115491155911569115791158911599116091161911629116391164911659116691167911689116991170911719117291173911749117591176911779117891179911809118191182911839118491185911869118791188911899119091191911929119391194911959119691197911989119991200912019120291203912049120591206912079120891209912109121191212912139121491215912169121791218912199122091221912229122391224912259122691227912289122991230912319123291233912349123591236912379123891239912409124191242912439124491245912469124791248912499125091251912529125391254912559125691257912589125991260912619126291263912649126591266912679126891269912709127191272912739127491275912769127791278912799128091281912829128391284912859128691287912889128991290912919129291293912949129591296912979129891299913009130191302913039130491305913069130791308913099131091311913129131391314913159131691317913189131991320913219132291323913249132591326913279132891329913309133191332913339133491335913369133791338913399134091341913429134391344913459134691347913489134991350913519135291353913549135591356913579135891359913609136191362913639136491365913669136791368913699137091371913729137391374913759137691377913789137991380913819138291383913849138591386913879138891389913909139191392913939139491395913969139791398913999140091401914029140391404914059140691407914089140991410914119141291413914149141591416914179141891419914209142191422914239142491425914269142791428914299143091431914329143391434914359143691437914389143991440914419144291443914449144591446914479144891449914509145191452914539145491455914569145791458914599146091461914629146391464914659146691467914689146991470914719147291473914749147591476914779147891479914809148191482914839148491485914869148791488914899149091491914929149391494914959149691497914989149991500915019150291503915049150591506915079150891509915109151191512915139151491515915169151791518915199152091521915229152391524915259152691527915289152991530915319153291533915349153591536915379153891539915409154191542915439154491545915469154791548915499155091551915529155391554915559155691557915589155991560915619156291563915649156591566915679156891569915709157191572915739157491575915769157791578915799158091581915829158391584915859158691587915889158991590915919159291593915949159591596915979159891599916009160191602916039160491605916069160791608916099161091611916129161391614916159161691617916189161991620916219162291623916249162591626916279162891629916309163191632916339163491635916369163791638916399164091641916429164391644916459164691647916489164991650916519165291653916549165591656916579165891659916609166191662916639166491665916669166791668916699167091671916729167391674916759167691677916789167991680916819168291683916849168591686916879168891689916909169191692916939169491695916969169791698916999170091701917029170391704917059170691707917089170991710917119171291713917149171591716917179171891719917209172191722917239172491725917269172791728917299173091731917329173391734917359173691737917389173991740917419174291743917449174591746917479174891749917509175191752917539175491755917569175791758917599176091761917629176391764917659176691767917689176991770917719177291773917749177591776917779177891779917809178191782917839178491785917869178791788917899179091791917929179391794917959179691797917989179991800918019180291803918049180591806918079180891809918109181191812918139181491815918169181791818918199182091821918229182391824918259182691827918289182991830918319183291833918349183591836918379183891839918409184191842918439184491845918469184791848918499185091851918529185391854918559185691857918589185991860918619186291863918649186591866918679186891869918709187191872918739187491875918769187791878918799188091881918829188391884918859188691887918889188991890918919189291893918949189591896918979189891899919009190191902919039190491905919069190791908919099191091911919129191391914919159191691917919189191991920919219192291923919249192591926919279192891929919309193191932919339193491935919369193791938919399194091941919429194391944919459194691947919489194991950919519195291953919549195591956919579195891959919609196191962919639196491965919669196791968919699197091971919729197391974919759197691977919789197991980919819198291983919849198591986919879198891989919909199191992919939199491995919969199791998919999200092001920029200392004920059200692007920089200992010920119201292013920149201592016920179201892019920209202192022920239202492025920269202792028920299203092031920329203392034920359203692037920389203992040920419204292043920449204592046920479204892049920509205192052920539205492055920569205792058920599206092061920629206392064920659206692067920689206992070920719207292073920749207592076920779207892079920809208192082920839208492085920869208792088920899209092091920929209392094920959209692097920989209992100921019210292103921049210592106921079210892109921109211192112921139211492115921169211792118921199212092121921229212392124921259212692127921289212992130921319213292133921349213592136921379213892139921409214192142921439214492145921469214792148921499215092151921529215392154921559215692157921589215992160921619216292163921649216592166921679216892169921709217192172921739217492175921769217792178921799218092181921829218392184921859218692187921889218992190921919219292193921949219592196921979219892199922009220192202922039220492205922069220792208922099221092211922129221392214922159221692217922189221992220922219222292223922249222592226922279222892229922309223192232922339223492235922369223792238922399224092241922429224392244922459224692247922489224992250922519225292253922549225592256922579225892259922609226192262922639226492265922669226792268922699227092271922729227392274922759227692277922789227992280922819228292283922849228592286922879228892289922909229192292922939229492295922969229792298922999230092301923029230392304923059230692307923089230992310923119231292313923149231592316923179231892319923209232192322923239232492325923269232792328923299233092331923329233392334923359233692337923389233992340923419234292343923449234592346923479234892349923509235192352923539235492355923569235792358923599236092361923629236392364923659236692367923689236992370923719237292373923749237592376923779237892379923809238192382923839238492385923869238792388923899239092391923929239392394923959239692397923989239992400924019240292403924049240592406924079240892409924109241192412924139241492415924169241792418924199242092421924229242392424924259242692427924289242992430924319243292433924349243592436924379243892439924409244192442924439244492445924469244792448924499245092451924529245392454924559245692457924589245992460924619246292463924649246592466924679246892469924709247192472924739247492475924769247792478924799248092481924829248392484924859248692487924889248992490924919249292493924949249592496924979249892499925009250192502925039250492505925069250792508925099251092511925129251392514925159251692517925189251992520925219252292523925249252592526925279252892529925309253192532925339253492535925369253792538925399254092541925429254392544925459254692547925489254992550925519255292553925549255592556925579255892559925609256192562925639256492565925669256792568925699257092571925729257392574925759257692577925789257992580925819258292583925849258592586925879258892589925909259192592925939259492595925969259792598925999260092601926029260392604926059260692607926089260992610926119261292613926149261592616926179261892619926209262192622926239262492625926269262792628926299263092631926329263392634926359263692637926389263992640926419264292643926449264592646926479264892649926509265192652926539265492655926569265792658926599266092661926629266392664926659266692667926689266992670926719267292673926749267592676926779267892679926809268192682926839268492685926869268792688926899269092691926929269392694926959269692697926989269992700927019270292703927049270592706927079270892709927109271192712927139271492715927169271792718927199272092721927229272392724927259272692727927289272992730927319273292733927349273592736927379273892739927409274192742927439274492745927469274792748927499275092751927529275392754927559275692757927589275992760927619276292763927649276592766927679276892769927709277192772927739277492775927769277792778927799278092781927829278392784927859278692787927889278992790927919279292793927949279592796927979279892799928009280192802928039280492805928069280792808928099281092811928129281392814928159281692817928189281992820928219282292823928249282592826928279282892829928309283192832928339283492835928369283792838928399284092841928429284392844928459284692847928489284992850928519285292853928549285592856928579285892859928609286192862928639286492865928669286792868928699287092871928729287392874928759287692877928789287992880928819288292883928849288592886928879288892889928909289192892928939289492895928969289792898928999290092901929029290392904929059290692907929089290992910929119291292913929149291592916929179291892919929209292192922929239292492925929269292792928929299293092931929329293392934929359293692937929389293992940929419294292943929449294592946929479294892949929509295192952929539295492955929569295792958929599296092961929629296392964929659296692967929689296992970929719297292973929749297592976929779297892979929809298192982929839298492985929869298792988929899299092991929929299392994929959299692997929989299993000930019300293003930049300593006930079300893009930109301193012930139301493015930169301793018930199302093021930229302393024930259302693027930289302993030930319303293033930349303593036930379303893039930409304193042930439304493045930469304793048930499305093051930529305393054930559305693057930589305993060930619306293063930649306593066930679306893069930709307193072930739307493075930769307793078930799308093081930829308393084930859308693087930889308993090930919309293093930949309593096930979309893099931009310193102931039310493105931069310793108931099311093111931129311393114931159311693117931189311993120931219312293123931249312593126931279312893129931309313193132931339313493135931369313793138931399314093141931429314393144931459314693147931489314993150931519315293153931549315593156931579315893159931609316193162931639316493165931669316793168931699317093171931729317393174931759317693177931789317993180931819318293183931849318593186931879318893189931909319193192931939319493195931969319793198931999320093201932029320393204932059320693207932089320993210932119321293213932149321593216932179321893219932209322193222932239322493225932269322793228932299323093231932329323393234932359323693237932389323993240932419324293243932449324593246932479324893249932509325193252932539325493255932569325793258932599326093261932629326393264932659326693267932689326993270932719327293273932749327593276932779327893279932809328193282932839328493285932869328793288932899329093291932929329393294932959329693297932989329993300933019330293303933049330593306933079330893309933109331193312933139331493315933169331793318933199332093321933229332393324933259332693327933289332993330933319333293333933349333593336933379333893339933409334193342933439334493345933469334793348933499335093351933529335393354933559335693357933589335993360933619336293363933649336593366933679336893369933709337193372933739337493375933769337793378933799338093381933829338393384933859338693387933889338993390933919339293393933949339593396933979339893399934009340193402934039340493405934069340793408934099341093411934129341393414934159341693417934189341993420934219342293423934249342593426934279342893429934309343193432934339343493435934369343793438934399344093441934429344393444934459344693447934489344993450934519345293453934549345593456934579345893459934609346193462934639346493465934669346793468934699347093471934729347393474934759347693477934789347993480934819348293483934849348593486934879348893489934909349193492934939349493495934969349793498934999350093501935029350393504935059350693507935089350993510935119351293513935149351593516935179351893519935209352193522935239352493525935269352793528935299353093531935329353393534935359353693537935389353993540935419354293543935449354593546935479354893549935509355193552935539355493555935569355793558935599356093561935629356393564935659356693567935689356993570935719357293573935749357593576935779357893579935809358193582935839358493585935869358793588935899359093591935929359393594935959359693597935989359993600936019360293603936049360593606936079360893609936109361193612936139361493615936169361793618936199362093621936229362393624936259362693627936289362993630936319363293633936349363593636936379363893639936409364193642936439364493645936469364793648936499365093651936529365393654936559365693657936589365993660936619366293663936649366593666936679366893669936709367193672936739367493675936769367793678936799368093681936829368393684936859368693687936889368993690936919369293693936949369593696936979369893699937009370193702937039370493705937069370793708937099371093711937129371393714937159371693717937189371993720937219372293723937249372593726937279372893729937309373193732937339373493735937369373793738937399374093741937429374393744937459374693747937489374993750937519375293753937549375593756937579375893759937609376193762937639376493765937669376793768937699377093771937729377393774937759377693777937789377993780937819378293783937849378593786937879378893789937909379193792937939379493795937969379793798937999380093801938029380393804938059380693807938089380993810938119381293813938149381593816938179381893819938209382193822938239382493825938269382793828938299383093831938329383393834938359383693837938389383993840938419384293843938449384593846938479384893849938509385193852938539385493855938569385793858938599386093861938629386393864938659386693867938689386993870938719387293873938749387593876938779387893879938809388193882938839388493885938869388793888938899389093891938929389393894938959389693897938989389993900939019390293903939049390593906939079390893909939109391193912939139391493915939169391793918939199392093921939229392393924939259392693927939289392993930939319393293933939349393593936939379393893939939409394193942939439394493945939469394793948939499395093951939529395393954939559395693957939589395993960939619396293963939649396593966939679396893969939709397193972939739397493975939769397793978939799398093981939829398393984939859398693987939889398993990939919399293993939949399593996939979399893999940009400194002940039400494005940069400794008940099401094011940129401394014940159401694017940189401994020940219402294023940249402594026940279402894029940309403194032940339403494035940369403794038940399404094041940429404394044940459404694047940489404994050940519405294053940549405594056940579405894059940609406194062940639406494065940669406794068940699407094071940729407394074940759407694077940789407994080940819408294083940849408594086940879408894089940909409194092940939409494095940969409794098940999410094101941029410394104941059410694107941089410994110941119411294113941149411594116941179411894119941209412194122941239412494125941269412794128941299413094131941329413394134941359413694137941389413994140941419414294143941449414594146941479414894149941509415194152941539415494155941569415794158941599416094161941629416394164941659416694167941689416994170941719417294173941749417594176941779417894179941809418194182941839418494185941869418794188941899419094191941929419394194941959419694197941989419994200942019420294203942049420594206942079420894209942109421194212942139421494215942169421794218942199422094221942229422394224942259422694227942289422994230942319423294233942349423594236942379423894239942409424194242942439424494245942469424794248942499425094251942529425394254942559425694257942589425994260942619426294263942649426594266942679426894269942709427194272942739427494275942769427794278942799428094281942829428394284942859428694287942889428994290942919429294293942949429594296942979429894299943009430194302943039430494305943069430794308943099431094311943129431394314943159431694317943189431994320943219432294323943249432594326943279432894329943309433194332943339433494335943369433794338943399434094341943429434394344943459434694347943489434994350943519435294353943549435594356943579435894359943609436194362943639436494365943669436794368943699437094371943729437394374943759437694377943789437994380943819438294383943849438594386943879438894389943909439194392943939439494395943969439794398943999440094401944029440394404944059440694407944089440994410944119441294413944149441594416944179441894419944209442194422944239442494425944269442794428944299443094431944329443394434944359443694437944389443994440944419444294443944449444594446944479444894449944509445194452944539445494455944569445794458944599446094461944629446394464944659446694467944689446994470944719447294473944749447594476944779447894479944809448194482944839448494485944869448794488944899449094491944929449394494944959449694497944989449994500945019450294503945049450594506945079450894509945109451194512945139451494515945169451794518945199452094521945229452394524945259452694527945289452994530945319453294533945349453594536945379453894539945409454194542945439454494545945469454794548945499455094551945529455394554945559455694557945589455994560945619456294563945649456594566945679456894569945709457194572945739457494575945769457794578945799458094581945829458394584945859458694587945889458994590945919459294593945949459594596945979459894599946009460194602946039460494605946069460794608946099461094611946129461394614946159461694617946189461994620946219462294623946249462594626946279462894629946309463194632946339463494635946369463794638946399464094641946429464394644946459464694647946489464994650946519465294653946549465594656946579465894659946609466194662946639466494665946669466794668946699467094671946729467394674946759467694677946789467994680946819468294683946849468594686946879468894689946909469194692946939469494695946969469794698946999470094701947029470394704947059470694707947089470994710947119471294713947149471594716947179471894719947209472194722947239472494725947269472794728947299473094731947329473394734947359473694737947389473994740947419474294743947449474594746947479474894749947509475194752947539475494755947569475794758947599476094761947629476394764947659476694767947689476994770947719477294773947749477594776947779477894779947809478194782947839478494785947869478794788947899479094791947929479394794947959479694797947989479994800948019480294803948049480594806948079480894809948109481194812948139481494815948169481794818948199482094821948229482394824948259482694827948289482994830948319483294833948349483594836948379483894839948409484194842948439484494845948469484794848948499485094851948529485394854948559485694857948589485994860948619486294863948649486594866948679486894869948709487194872948739487494875948769487794878948799488094881948829488394884948859488694887948889488994890948919489294893948949489594896948979489894899949009490194902949039490494905949069490794908949099491094911949129491394914949159491694917949189491994920949219492294923949249492594926949279492894929949309493194932949339493494935949369493794938949399494094941949429494394944949459494694947949489494994950949519495294953949549495594956949579495894959949609496194962949639496494965949669496794968949699497094971949729497394974949759497694977949789497994980949819498294983949849498594986949879498894989949909499194992949939499494995949969499794998949999500095001950029500395004950059500695007950089500995010950119501295013950149501595016950179501895019950209502195022950239502495025950269502795028950299503095031950329503395034950359503695037950389503995040950419504295043950449504595046950479504895049950509505195052950539505495055950569505795058950599506095061950629506395064950659506695067950689506995070950719507295073950749507595076950779507895079950809508195082950839508495085950869508795088950899509095091950929509395094950959509695097950989509995100951019510295103951049510595106951079510895109951109511195112951139511495115951169511795118951199512095121951229512395124951259512695127951289512995130951319513295133951349513595136951379513895139951409514195142951439514495145951469514795148951499515095151951529515395154951559515695157951589515995160951619516295163951649516595166951679516895169951709517195172951739517495175951769517795178951799518095181951829518395184951859518695187951889518995190951919519295193951949519595196951979519895199952009520195202952039520495205952069520795208952099521095211952129521395214952159521695217952189521995220952219522295223952249522595226952279522895229952309523195232952339523495235952369523795238952399524095241952429524395244952459524695247952489524995250952519525295253952549525595256952579525895259952609526195262952639526495265952669526795268952699527095271952729527395274952759527695277952789527995280952819528295283952849528595286952879528895289952909529195292952939529495295952969529795298952999530095301953029530395304953059530695307953089530995310953119531295313953149531595316953179531895319953209532195322953239532495325953269532795328953299533095331953329533395334953359533695337953389533995340953419534295343953449534595346953479534895349953509535195352953539535495355953569535795358953599536095361953629536395364953659536695367953689536995370953719537295373953749537595376953779537895379953809538195382953839538495385953869538795388953899539095391953929539395394953959539695397953989539995400954019540295403954049540595406954079540895409954109541195412954139541495415954169541795418954199542095421954229542395424954259542695427954289542995430954319543295433954349543595436954379543895439954409544195442954439544495445954469544795448954499545095451954529545395454954559545695457954589545995460954619546295463954649546595466954679546895469954709547195472954739547495475954769547795478954799548095481954829548395484954859548695487954889548995490954919549295493954949549595496954979549895499955009550195502955039550495505955069550795508955099551095511955129551395514955159551695517955189551995520955219552295523955249552595526955279552895529955309553195532955339553495535955369553795538955399554095541955429554395544955459554695547955489554995550955519555295553955549555595556955579555895559955609556195562955639556495565955669556795568955699557095571955729557395574955759557695577955789557995580955819558295583955849558595586955879558895589955909559195592955939559495595955969559795598955999560095601956029560395604956059560695607956089560995610956119561295613956149561595616956179561895619956209562195622956239562495625956269562795628956299563095631956329563395634956359563695637956389563995640956419564295643956449564595646956479564895649956509565195652956539565495655956569565795658956599566095661956629566395664956659566695667956689566995670956719567295673956749567595676956779567895679956809568195682956839568495685956869568795688956899569095691956929569395694956959569695697956989569995700957019570295703957049570595706957079570895709957109571195712957139571495715957169571795718957199572095721957229572395724957259572695727957289572995730957319573295733957349573595736957379573895739957409574195742957439574495745957469574795748957499575095751957529575395754957559575695757957589575995760957619576295763957649576595766957679576895769957709577195772957739577495775957769577795778957799578095781957829578395784957859578695787957889578995790957919579295793957949579595796957979579895799958009580195802958039580495805958069580795808958099581095811958129581395814958159581695817958189581995820958219582295823958249582595826958279582895829958309583195832958339583495835958369583795838958399584095841958429584395844958459584695847958489584995850958519585295853958549585595856958579585895859958609586195862958639586495865958669586795868958699587095871958729587395874958759587695877958789587995880958819588295883958849588595886958879588895889958909589195892958939589495895958969589795898958999590095901959029590395904959059590695907959089590995910959119591295913959149591595916959179591895919959209592195922959239592495925959269592795928959299593095931959329593395934959359593695937959389593995940959419594295943959449594595946959479594895949959509595195952959539595495955959569595795958959599596095961959629596395964959659596695967959689596995970959719597295973959749597595976959779597895979959809598195982959839598495985959869598795988959899599095991959929599395994959959599695997959989599996000960019600296003960049600596006960079600896009960109601196012960139601496015960169601796018960199602096021960229602396024960259602696027960289602996030960319603296033960349603596036960379603896039960409604196042960439604496045960469604796048960499605096051960529605396054960559605696057960589605996060960619606296063960649606596066960679606896069960709607196072960739607496075960769607796078960799608096081960829608396084960859608696087960889608996090960919609296093960949609596096960979609896099961009610196102961039610496105961069610796108961099611096111961129611396114961159611696117961189611996120961219612296123961249612596126961279612896129961309613196132961339613496135961369613796138961399614096141961429614396144961459614696147961489614996150961519615296153961549615596156961579615896159961609616196162961639616496165961669616796168961699617096171961729617396174961759617696177961789617996180961819618296183961849618596186961879618896189961909619196192961939619496195961969619796198961999620096201962029620396204962059620696207962089620996210962119621296213962149621596216962179621896219962209622196222962239622496225962269622796228962299623096231962329623396234962359623696237962389623996240962419624296243962449624596246962479624896249962509625196252962539625496255962569625796258962599626096261962629626396264962659626696267962689626996270962719627296273962749627596276962779627896279962809628196282962839628496285962869628796288962899629096291962929629396294962959629696297962989629996300963019630296303963049630596306963079630896309963109631196312963139631496315963169631796318963199632096321963229632396324963259632696327963289632996330963319633296333963349633596336963379633896339963409634196342963439634496345963469634796348963499635096351963529635396354963559635696357963589635996360963619636296363963649636596366963679636896369963709637196372963739637496375963769637796378963799638096381963829638396384963859638696387963889638996390963919639296393963949639596396963979639896399964009640196402964039640496405964069640796408964099641096411964129641396414964159641696417964189641996420964219642296423964249642596426964279642896429964309643196432964339643496435964369643796438964399644096441964429644396444964459644696447964489644996450964519645296453964549645596456964579645896459964609646196462964639646496465964669646796468964699647096471964729647396474964759647696477964789647996480964819648296483964849648596486964879648896489964909649196492964939649496495964969649796498964999650096501965029650396504965059650696507965089650996510965119651296513965149651596516965179651896519965209652196522965239652496525965269652796528965299653096531965329653396534965359653696537965389653996540965419654296543965449654596546965479654896549965509655196552965539655496555965569655796558965599656096561965629656396564965659656696567965689656996570965719657296573965749657596576965779657896579965809658196582965839658496585965869658796588965899659096591965929659396594965959659696597965989659996600966019660296603966049660596606966079660896609966109661196612966139661496615966169661796618966199662096621966229662396624966259662696627966289662996630966319663296633966349663596636966379663896639966409664196642966439664496645966469664796648966499665096651966529665396654966559665696657966589665996660966619666296663966649666596666966679666896669966709667196672966739667496675966769667796678966799668096681966829668396684966859668696687966889668996690966919669296693966949669596696966979669896699967009670196702967039670496705967069670796708967099671096711967129671396714967159671696717967189671996720967219672296723967249672596726967279672896729967309673196732967339673496735967369673796738967399674096741967429674396744967459674696747967489674996750967519675296753967549675596756967579675896759967609676196762967639676496765967669676796768967699677096771967729677396774967759677696777967789677996780967819678296783967849678596786967879678896789967909679196792967939679496795967969679796798967999680096801968029680396804968059680696807968089680996810968119681296813968149681596816968179681896819968209682196822968239682496825968269682796828968299683096831968329683396834968359683696837968389683996840968419684296843968449684596846968479684896849968509685196852968539685496855968569685796858968599686096861968629686396864968659686696867968689686996870968719687296873968749687596876968779687896879968809688196882968839688496885968869688796888968899689096891968929689396894968959689696897968989689996900969019690296903969049690596906969079690896909969109691196912969139691496915969169691796918969199692096921969229692396924969259692696927969289692996930969319693296933969349693596936969379693896939969409694196942969439694496945969469694796948969499695096951969529695396954969559695696957969589695996960969619696296963969649696596966969679696896969969709697196972969739697496975969769697796978969799698096981969829698396984969859698696987969889698996990969919699296993969949699596996969979699896999970009700197002970039700497005970069700797008970099701097011970129701397014970159701697017970189701997020970219702297023970249702597026970279702897029970309703197032970339703497035970369703797038970399704097041970429704397044970459704697047970489704997050970519705297053970549705597056970579705897059970609706197062970639706497065970669706797068970699707097071970729707397074970759707697077970789707997080970819708297083970849708597086970879708897089970909709197092970939709497095970969709797098970999710097101971029710397104971059710697107971089710997110971119711297113971149711597116971179711897119971209712197122971239712497125971269712797128971299713097131971329713397134971359713697137971389713997140971419714297143971449714597146971479714897149971509715197152971539715497155971569715797158971599716097161971629716397164971659716697167971689716997170971719717297173971749717597176971779717897179971809718197182971839718497185971869718797188971899719097191971929719397194971959719697197971989719997200972019720297203972049720597206972079720897209972109721197212972139721497215972169721797218972199722097221972229722397224972259722697227972289722997230972319723297233972349723597236972379723897239972409724197242972439724497245972469724797248972499725097251972529725397254972559725697257972589725997260972619726297263972649726597266972679726897269972709727197272972739727497275972769727797278972799728097281972829728397284972859728697287972889728997290972919729297293972949729597296972979729897299973009730197302973039730497305973069730797308973099731097311973129731397314973159731697317973189731997320973219732297323973249732597326973279732897329973309733197332973339733497335973369733797338973399734097341973429734397344973459734697347973489734997350973519735297353973549735597356973579735897359973609736197362973639736497365973669736797368973699737097371973729737397374973759737697377973789737997380973819738297383973849738597386973879738897389973909739197392973939739497395973969739797398973999740097401974029740397404974059740697407974089740997410974119741297413974149741597416974179741897419974209742197422974239742497425974269742797428974299743097431974329743397434974359743697437974389743997440974419744297443974449744597446974479744897449974509745197452974539745497455974569745797458974599746097461974629746397464974659746697467974689746997470974719747297473974749747597476974779747897479974809748197482974839748497485974869748797488974899749097491974929749397494974959749697497974989749997500975019750297503975049750597506975079750897509975109751197512975139751497515975169751797518975199752097521975229752397524975259752697527975289752997530975319753297533975349753597536975379753897539975409754197542975439754497545975469754797548975499755097551975529755397554975559755697557975589755997560975619756297563975649756597566975679756897569975709757197572975739757497575975769757797578975799758097581975829758397584975859758697587975889758997590975919759297593975949759597596975979759897599976009760197602976039760497605976069760797608976099761097611976129761397614976159761697617976189761997620976219762297623976249762597626976279762897629976309763197632976339763497635976369763797638976399764097641976429764397644976459764697647976489764997650976519765297653976549765597656976579765897659976609766197662976639766497665976669766797668976699767097671976729767397674976759767697677976789767997680976819768297683976849768597686976879768897689976909769197692976939769497695976969769797698976999770097701977029770397704977059770697707977089770997710977119771297713977149771597716977179771897719977209772197722977239772497725977269772797728977299773097731977329773397734977359773697737977389773997740977419774297743977449774597746977479774897749977509775197752977539775497755977569775797758977599776097761977629776397764977659776697767977689776997770977719777297773977749777597776977779777897779977809778197782977839778497785977869778797788977899779097791977929779397794977959779697797977989779997800978019780297803978049780597806978079780897809978109781197812978139781497815978169781797818978199782097821978229782397824978259782697827978289782997830978319783297833978349783597836978379783897839978409784197842978439784497845978469784797848978499785097851978529785397854978559785697857978589785997860978619786297863978649786597866978679786897869978709787197872978739787497875978769787797878978799788097881978829788397884978859788697887978889788997890978919789297893978949789597896978979789897899979009790197902979039790497905979069790797908979099791097911979129791397914979159791697917979189791997920979219792297923979249792597926979279792897929979309793197932979339793497935979369793797938979399794097941979429794397944979459794697947979489794997950979519795297953979549795597956979579795897959979609796197962979639796497965979669796797968979699797097971979729797397974979759797697977979789797997980979819798297983979849798597986979879798897989979909799197992979939799497995979969799797998979999800098001980029800398004980059800698007980089800998010980119801298013980149801598016980179801898019980209802198022980239802498025980269802798028980299803098031980329803398034980359803698037980389803998040980419804298043980449804598046980479804898049980509805198052980539805498055980569805798058980599806098061980629806398064980659806698067980689806998070980719807298073980749807598076980779807898079980809808198082980839808498085980869808798088980899809098091980929809398094980959809698097980989809998100981019810298103981049810598106981079810898109981109811198112981139811498115981169811798118981199812098121981229812398124981259812698127981289812998130981319813298133981349813598136981379813898139981409814198142981439814498145981469814798148981499815098151981529815398154981559815698157981589815998160981619816298163981649816598166981679816898169981709817198172981739817498175981769817798178981799818098181981829818398184981859818698187981889818998190981919819298193981949819598196981979819898199982009820198202982039820498205982069820798208982099821098211982129821398214982159821698217982189821998220982219822298223982249822598226982279822898229982309823198232982339823498235982369823798238982399824098241982429824398244982459824698247982489824998250982519825298253982549825598256982579825898259982609826198262982639826498265982669826798268982699827098271982729827398274982759827698277982789827998280982819828298283982849828598286982879828898289982909829198292982939829498295982969829798298982999830098301983029830398304983059830698307983089830998310983119831298313983149831598316983179831898319983209832198322983239832498325983269832798328983299833098331983329833398334983359833698337983389833998340983419834298343983449834598346983479834898349983509835198352983539835498355983569835798358983599836098361983629836398364983659836698367983689836998370983719837298373983749837598376983779837898379983809838198382983839838498385983869838798388983899839098391983929839398394983959839698397983989839998400984019840298403984049840598406984079840898409984109841198412984139841498415984169841798418984199842098421984229842398424984259842698427984289842998430984319843298433984349843598436984379843898439984409844198442984439844498445984469844798448984499845098451984529845398454984559845698457984589845998460984619846298463984649846598466984679846898469984709847198472984739847498475984769847798478984799848098481984829848398484984859848698487984889848998490984919849298493984949849598496984979849898499985009850198502985039850498505985069850798508985099851098511985129851398514985159851698517985189851998520985219852298523985249852598526985279852898529985309853198532985339853498535985369853798538985399854098541985429854398544985459854698547985489854998550985519855298553985549855598556985579855898559985609856198562985639856498565985669856798568985699857098571985729857398574985759857698577985789857998580985819858298583985849858598586985879858898589985909859198592985939859498595985969859798598985999860098601986029860398604986059860698607986089860998610986119861298613986149861598616986179861898619986209862198622986239862498625986269862798628986299863098631986329863398634986359863698637986389863998640986419864298643986449864598646986479864898649986509865198652986539865498655986569865798658986599866098661986629866398664986659866698667986689866998670986719867298673986749867598676986779867898679986809868198682986839868498685986869868798688986899869098691986929869398694986959869698697986989869998700987019870298703987049870598706987079870898709987109871198712987139871498715987169871798718987199872098721987229872398724987259872698727987289872998730987319873298733987349873598736987379873898739987409874198742987439874498745987469874798748987499875098751987529875398754987559875698757987589875998760987619876298763987649876598766987679876898769987709877198772987739877498775987769877798778987799878098781987829878398784987859878698787987889878998790987919879298793987949879598796987979879898799988009880198802988039880498805988069880798808988099881098811988129881398814988159881698817988189881998820988219882298823988249882598826988279882898829988309883198832988339883498835988369883798838988399884098841988429884398844988459884698847988489884998850988519885298853988549885598856988579885898859988609886198862988639886498865988669886798868988699887098871988729887398874988759887698877988789887998880988819888298883988849888598886988879888898889988909889198892988939889498895988969889798898988999890098901989029890398904989059890698907989089890998910989119891298913989149891598916989179891898919989209892198922989239892498925989269892798928989299893098931989329893398934989359893698937989389893998940989419894298943989449894598946989479894898949989509895198952989539895498955989569895798958989599896098961989629896398964989659896698967989689896998970989719897298973989749897598976989779897898979989809898198982989839898498985989869898798988989899899098991989929899398994989959899698997989989899999000990019900299003990049900599006990079900899009990109901199012990139901499015990169901799018990199902099021990229902399024990259902699027990289902999030990319903299033990349903599036990379903899039990409904199042990439904499045990469904799048990499905099051990529905399054990559905699057990589905999060990619906299063990649906599066990679906899069990709907199072990739907499075990769907799078990799908099081990829908399084990859908699087990889908999090990919909299093990949909599096990979909899099991009910199102991039910499105991069910799108991099911099111991129911399114991159911699117991189911999120991219912299123991249912599126991279912899129991309913199132991339913499135991369913799138991399914099141991429914399144991459914699147991489914999150991519915299153991549915599156991579915899159991609916199162991639916499165991669916799168991699917099171991729917399174991759917699177991789917999180991819918299183991849918599186991879918899189991909919199192991939919499195991969919799198991999920099201992029920399204992059920699207992089920999210992119921299213992149921599216992179921899219992209922199222992239922499225992269922799228992299923099231992329923399234992359923699237992389923999240992419924299243992449924599246992479924899249992509925199252992539925499255992569925799258992599926099261992629926399264992659926699267992689926999270992719927299273992749927599276992779927899279992809928199282992839928499285992869928799288992899929099291992929929399294992959929699297992989929999300993019930299303993049930599306993079930899309993109931199312993139931499315993169931799318993199932099321993229932399324993259932699327993289932999330993319933299333993349933599336993379933899339993409934199342993439934499345993469934799348993499935099351993529935399354993559935699357993589935999360993619936299363993649936599366993679936899369993709937199372993739937499375993769937799378993799938099381993829938399384993859938699387993889938999390993919939299393993949939599396993979939899399994009940199402994039940499405994069940799408994099941099411994129941399414994159941699417994189941999420994219942299423994249942599426994279942899429994309943199432994339943499435994369943799438994399944099441994429944399444994459944699447994489944999450994519945299453994549945599456994579945899459994609946199462994639946499465994669946799468994699947099471994729947399474994759947699477994789947999480994819948299483994849948599486994879948899489994909949199492994939949499495994969949799498994999950099501995029950399504995059950699507995089950999510995119951299513995149951599516995179951899519995209952199522995239952499525995269952799528995299953099531995329953399534995359953699537995389953999540995419954299543995449954599546995479954899549995509955199552995539955499555995569955799558995599956099561995629956399564995659956699567995689956999570995719957299573995749957599576995779957899579995809958199582995839958499585995869958799588995899959099591995929959399594995959959699597995989959999600996019960299603996049960599606996079960899609996109961199612996139961499615996169961799618996199962099621996229962399624996259962699627996289962999630996319963299633996349963599636996379963899639996409964199642996439964499645996469964799648996499965099651996529965399654996559965699657996589965999660996619966299663996649966599666996679966899669996709967199672996739967499675996769967799678996799968099681996829968399684996859968699687996889968999690996919969299693996949969599696996979969899699997009970199702997039970499705997069970799708997099971099711997129971399714997159971699717997189971999720997219972299723997249972599726997279972899729997309973199732997339973499735997369973799738997399974099741997429974399744997459974699747997489974999750997519975299753997549975599756997579975899759997609976199762997639976499765997669976799768997699977099771997729977399774997759977699777997789977999780997819978299783997849978599786997879978899789997909979199792997939979499795997969979799798997999980099801998029980399804998059980699807998089980999810998119981299813998149981599816998179981899819998209982199822998239982499825998269982799828998299983099831998329983399834998359983699837998389983999840998419984299843998449984599846998479984899849998509985199852998539985499855998569985799858998599986099861998629986399864998659986699867998689986999870998719987299873998749987599876998779987899879998809988199882998839988499885998869988799888998899989099891998929989399894998959989699897998989989999900999019990299903999049990599906999079990899909999109991199912999139991499915999169991799918999199992099921999229992399924999259992699927999289992999930999319993299933999349993599936999379993899939999409994199942999439994499945999469994799948999499995099951999529995399954999559995699957999589995999960999619996299963999649996599966999679996899969999709997199972999739997499975999769997799978999799998099981999829998399984999859998699987999889998999990999919999299993999949999599996999979999899999100000100001100002100003100004100005100006100007100008100009100010100011100012100013100014100015100016100017100018100019100020100021100022100023100024100025100026100027100028100029100030100031100032100033100034100035100036100037100038100039100040100041100042100043100044100045100046100047100048100049100050100051100052100053100054100055100056100057100058100059100060100061100062100063100064100065100066100067100068100069100070100071100072100073100074100075100076100077100078100079100080100081100082100083100084100085100086100087100088100089100090100091100092100093100094100095100096100097100098100099100100100101100102100103100104100105100106100107100108100109100110100111100112100113100114100115100116100117100118100119100120100121100122100123100124100125100126100127100128100129100130100131100132100133100134100135100136100137100138100139100140100141100142100143100144100145100146100147100148100149100150100151100152100153100154100155100156100157100158100159100160100161100162100163100164100165100166100167100168100169100170100171100172100173100174100175100176100177100178100179100180100181100182100183100184100185100186100187100188100189100190100191100192100193100194100195100196100197100198100199100200100201100202100203100204100205100206100207100208100209100210100211100212100213100214100215100216100217100218100219100220100221100222100223100224100225100226100227100228100229100230100231100232100233100234100235100236100237100238100239100240100241100242100243100244100245100246100247100248100249100250100251100252100253100254100255100256100257100258100259100260100261100262100263100264100265100266100267100268100269100270100271100272100273100274100275100276100277100278100279100280100281100282100283100284100285100286100287100288100289100290100291100292100293100294100295100296100297100298100299100300100301100302100303100304100305100306100307100308100309100310100311100312100313100314100315100316100317100318100319100320100321100322100323100324100325100326100327100328100329100330100331100332100333100334100335100336100337100338100339100340100341100342100343100344100345100346100347100348100349100350100351100352100353100354100355100356100357100358100359100360100361100362100363100364100365100366100367100368100369100370100371100372100373100374100375100376100377100378100379100380100381100382100383100384100385100386100387100388100389100390100391100392100393100394100395100396100397100398100399100400100401100402100403100404100405100406100407100408100409100410100411100412100413100414100415100416100417100418100419100420100421100422100423100424100425100426100427100428100429100430100431100432100433100434100435100436100437100438100439100440100441100442100443100444100445100446100447100448100449100450100451100452100453100454100455100456100457100458100459100460100461100462100463100464100465100466100467100468100469100470100471100472100473100474100475100476100477100478100479100480100481100482100483100484100485100486100487100488100489100490100491100492100493100494100495100496100497100498100499100500100501100502100503100504100505100506100507100508100509100510100511100512100513100514100515100516100517100518100519100520100521100522100523100524100525100526100527100528100529100530100531100532100533100534100535100536100537100538100539100540100541100542100543100544100545100546100547100548100549100550100551100552100553100554100555100556100557100558100559100560100561100562100563100564100565100566100567100568100569100570100571100572100573100574100575100576100577100578100579100580100581100582100583100584100585100586100587100588100589100590100591100592100593100594100595100596100597100598100599100600100601100602100603100604100605100606100607100608100609100610100611100612100613100614100615100616100617100618100619100620100621100622100623100624100625100626100627100628100629100630100631100632100633100634100635100636100637100638100639100640100641100642100643100644100645100646100647100648100649100650100651100652100653100654100655100656100657100658100659100660100661100662100663100664100665100666100667100668100669100670100671100672100673100674100675100676100677100678100679100680100681100682100683100684100685100686100687100688100689100690100691100692100693100694100695100696100697100698100699100700100701100702100703100704100705100706100707100708100709100710100711100712100713100714100715100716100717100718100719100720100721100722100723100724100725100726100727100728100729100730100731100732100733100734100735100736100737100738100739100740100741100742100743100744100745100746100747100748100749100750100751100752100753100754100755100756100757100758100759100760100761100762100763100764100765100766100767100768100769100770100771100772100773100774100775100776100777100778100779100780100781100782100783100784100785100786100787100788100789100790100791100792100793100794100795100796100797100798100799100800100801100802100803100804100805100806100807100808100809100810100811100812100813100814100815100816100817100818100819100820100821100822100823100824100825100826100827100828100829100830100831100832100833100834100835100836100837100838100839100840100841100842100843100844100845100846100847100848100849100850100851100852100853100854100855100856100857100858100859100860100861100862100863100864100865100866100867100868100869100870100871100872100873100874100875100876100877100878100879100880100881100882100883100884100885100886100887100888100889100890100891100892100893100894100895100896100897100898100899100900100901100902100903100904100905100906100907100908100909100910100911100912100913100914100915100916100917100918100919100920100921100922100923100924100925100926100927100928100929100930100931100932100933100934100935100936100937100938100939100940100941100942100943100944100945100946100947100948100949100950100951100952100953100954100955100956100957100958100959100960100961100962100963100964100965100966100967100968100969100970100971100972100973100974100975100976100977100978100979100980100981100982100983100984100985100986100987100988100989100990100991100992100993100994100995100996100997100998100999101000101001101002101003101004101005101006101007101008101009101010101011101012101013101014101015101016101017101018101019101020101021101022101023101024101025101026101027101028101029101030101031101032101033101034101035101036101037101038101039101040101041101042101043101044101045101046101047101048101049101050101051101052101053101054101055101056101057101058101059101060101061101062101063101064101065101066101067101068101069101070101071101072101073101074101075101076101077101078101079101080101081101082101083101084101085101086101087101088101089101090101091101092101093101094101095101096101097101098101099101100101101101102101103101104101105101106101107101108101109101110101111101112101113101114101115101116101117101118101119101120101121101122101123101124101125101126101127101128101129101130101131101132101133101134101135101136101137101138101139101140101141101142101143101144101145101146101147101148101149101150101151101152101153101154101155101156101157101158101159101160101161101162101163101164101165101166101167101168101169101170101171101172101173101174101175101176101177101178101179101180101181101182101183101184101185101186101187101188101189101190101191101192101193101194101195101196101197101198101199101200101201101202101203101204101205101206101207101208101209101210101211101212101213101214101215101216101217101218101219101220101221101222101223101224101225101226101227101228101229101230101231101232101233101234101235101236101237101238101239101240101241101242101243101244101245101246101247101248101249101250101251101252101253101254101255101256101257101258101259101260101261101262101263101264101265101266101267101268101269101270101271101272101273101274101275101276101277101278101279101280101281101282101283101284101285101286101287101288101289101290101291101292101293101294101295101296101297101298101299101300101301101302101303101304101305101306101307101308101309101310101311101312101313101314101315101316101317101318101319101320101321101322101323101324101325101326101327101328101329101330101331101332101333101334101335101336101337101338101339101340101341101342101343101344101345101346101347101348101349101350101351101352101353101354101355101356101357101358101359101360101361101362101363101364101365101366101367101368101369101370101371101372101373101374101375101376101377101378101379101380101381101382101383101384101385101386101387101388101389101390101391101392101393101394101395101396101397101398101399101400101401101402101403101404101405101406101407101408101409101410101411101412101413101414101415101416101417101418101419101420101421101422101423101424101425101426101427101428101429101430101431101432101433101434101435101436101437101438101439101440101441101442101443101444101445101446101447101448101449101450101451101452101453101454101455101456101457101458101459101460101461101462101463101464101465101466101467101468101469101470101471101472101473101474101475101476101477101478101479101480101481101482101483101484101485101486101487101488101489101490101491101492101493101494101495101496101497101498101499101500101501101502101503101504101505101506
  1. /*!
  2. * DevExtreme
  3. * Version: 15.1.4
  4. * Build date: Jun 22, 2015
  5. *
  6. * Copyright (c) 2012 - 2015 Developer Express Inc. ALL RIGHTS RESERVED
  7. * EULA: https://www.devexpress.com/Support/EULAs/DevExtreme.xml
  8. */
  9. "use strict";
  10. if (!window.DevExpress) {
  11. /*! Module core, file devexpress.js */
  12. (function($, global, undefined) {
  13. global.DevExpress = global.DevExpress || {};
  14. $.extend(global.DevExpress, {
  15. VERSION: "15.1.4",
  16. abstract: function() {
  17. throw global.DevExpress.Error("E0001");
  18. },
  19. stringFormat: function() {
  20. var s = arguments[0],
  21. replaceDollarCount,
  22. reg,
  23. argument;
  24. for (var i = 0; i < arguments.length - 1; i++) {
  25. reg = new RegExp("\\{" + i + "\\}", "gm");
  26. argument = arguments[i + 1];
  27. if ($.type(argument) === "string" && argument.indexOf("$") >= 0) {
  28. replaceDollarCount = "$".replace("$", "$$").length;
  29. argument = argument.replace("$", replaceDollarCount === 1 ? "$$$$" : "$$")
  30. }
  31. s = s.replace(reg, argument)
  32. }
  33. return s
  34. },
  35. parseUrl: function() {
  36. var a = document.createElement("a"),
  37. props = ["protocol", "hostname", "port", "pathname", "search", "hash"];
  38. var normalizePath = function(value) {
  39. if (value.charAt(0) !== "/")
  40. value = "/" + value;
  41. return value
  42. };
  43. return function(url) {
  44. a.href = url;
  45. var result = {};
  46. $.each(props, function() {
  47. result[this] = a[this]
  48. });
  49. result.pathname = normalizePath(result.pathname);
  50. return result
  51. }
  52. }(),
  53. processHardwareBackButton: function() {
  54. this.hardwareBackButton.fire()
  55. },
  56. hardwareBackButton: $.Callbacks(),
  57. viewPort: function() {
  58. var $current;
  59. return function(element) {
  60. if (!arguments.length)
  61. return $current;
  62. var $element = $(element);
  63. var isNewViewportFound = !!$element.length;
  64. var prevViewPort = this.viewPort();
  65. $current = isNewViewportFound ? $element : $("body");
  66. this.viewPortChanged.fire(isNewViewportFound ? this.viewPort() : $(), prevViewPort)
  67. }
  68. }(),
  69. viewPortChanged: $.Callbacks(),
  70. hideTopOverlayCallback: function() {
  71. var callbacks = [];
  72. return {
  73. add: function(callback) {
  74. var indexOfCallback = $.inArray(callback, callbacks);
  75. if (indexOfCallback === -1)
  76. callbacks.push(callback)
  77. },
  78. remove: function(callback) {
  79. var indexOfCallback = $.inArray(callback, callbacks);
  80. if (indexOfCallback !== -1)
  81. callbacks.splice(indexOfCallback, 1)
  82. },
  83. fire: function() {
  84. var callback = callbacks.pop(),
  85. result = !!callback;
  86. if (result)
  87. callback();
  88. return result
  89. },
  90. hasCallback: function() {
  91. return callbacks.length > 0
  92. },
  93. reset: function() {
  94. callbacks = []
  95. }
  96. }
  97. }(),
  98. compareVersions: function(x, y, maxLevel) {
  99. function normalizeArg(value) {
  100. if (typeof value === "string")
  101. return value.split(".");
  102. if (typeof value === "number")
  103. return [value];
  104. return value
  105. }
  106. x = normalizeArg(x);
  107. y = normalizeArg(y);
  108. var length = Math.max(x.length, y.length);
  109. if (isFinite(maxLevel))
  110. length = Math.min(length, maxLevel);
  111. for (var i = 0; i < length; i++) {
  112. var xItem = parseInt(x[i] || 0, 10),
  113. yItem = parseInt(y[i] || 0, 10);
  114. if (xItem < yItem)
  115. return -1;
  116. if (xItem > yItem)
  117. return 1
  118. }
  119. return 0
  120. },
  121. rtlEnabled: false
  122. });
  123. $(function() {
  124. DevExpress.viewPort(".dx-viewport")
  125. })
  126. })(jQuery, this);
  127. /*! Module core, file errors.js */
  128. (function($, DX) {
  129. var ERROR_MESSAGES = {
  130. E0001: "Method is not implemented",
  131. E0002: "Member name collision: {0}",
  132. E0003: "A class must be instantiated using the 'new' keyword",
  133. E0004: "The NAME property of the component is not specified",
  134. E0005: "Unknown device",
  135. E0006: "Unknown endpoint key is requested",
  136. E0007: "'Invalidate' method is called outside the update transaction",
  137. E0008: "Type of the option name is not appropriate to create an action",
  138. E0009: "Component '{0}' has not been initialized for an element",
  139. E0010: "Animation configuration with the '{0}' type requires '{1}' configuration as {2}",
  140. E0011: "Unknown animation type '{0}'",
  141. E0012: "jQuery version is too old. Please upgrade jQuery to 1.10.0 or later",
  142. E0013: "KnockoutJS version is too old. Please upgrade KnockoutJS to 2.3.0 or later",
  143. E0014: "The 'release' method shouldn't be called for an unlocked Lock object",
  144. E0015: "Queued task returned an unexpected result",
  145. E0017: "Event namespace is not defined",
  146. E0018: "DevExpress.ui.dxPopup widget is required",
  147. E0020: "Template engine '{0}' is not supported",
  148. E0021: "Unknown theme is set: {0}",
  149. E0022: "LINK[rel=dx-theme] tags must go before DevExpress included scripts",
  150. E0023: "Template name is not specified",
  151. E0100: "Unknown validation type is detected",
  152. E0101: "Misconfigured range validation rule is detected",
  153. E0102: "Misconfigured comparison validation rule is detected",
  154. E0110: "Unknown validation group is detected",
  155. E0120: "Adapter for a dxValidator component cannot be configured",
  156. W0000: "'{0}' is deprecated in {1}. {2}",
  157. W0001: "{0} - '{1}' option is deprecated in {2}. {3}",
  158. W0002: "{0} - '{1}' method is deprecated in {2}. {3}",
  159. W0003: "{0} - '{1}' property is deprecated in {2}. {3}",
  160. W0004: "Timeout for theme loading is over: {0}",
  161. W0005: "'{0}' event is deprecated in {1}. {2}"
  162. };
  163. var ERROR_URL = "http://js.devexpress.com/error/" + DX.VERSION.split(".").slice(0, 2).join("_") + "/";
  164. var combineMessage = function(args) {
  165. var id = args[0];
  166. args = args.slice(1);
  167. return formatMessage(id, formatDetails(id, args))
  168. };
  169. var formatDetails = function(id, args) {
  170. args = [DX.ERROR_MESSAGES[id]].concat(args);
  171. return DX.stringFormat.apply(this, args).replace(/\.*\s*?$/, '')
  172. };
  173. var formatMessage = function(id, details) {
  174. return DX.stringFormat.apply(this, ["{0} - {1}. See:\n{2}", id, details, ERROR_URL + id])
  175. };
  176. var makeError = function(args) {
  177. var id,
  178. details,
  179. message;
  180. id = args[0];
  181. args = args.slice(1);
  182. details = formatDetails(id, args);
  183. message = formatMessage(id, details);
  184. return $.extend(new Error(message), {
  185. __id: id,
  186. __details: details
  187. })
  188. };
  189. $.extend(DX, {
  190. Error: function() {
  191. return makeError($.makeArray(arguments))
  192. },
  193. log: function(id) {
  194. var method = "log",
  195. logger = DX.utils.logger;
  196. if (/^E\d+$/.test(id))
  197. method = "error";
  198. else if (/^W\d+$/.test(id))
  199. method = "warn";
  200. logger[method](method === "log" ? id : combineMessage($.makeArray(arguments)))
  201. },
  202. ERROR_MESSAGES: ERROR_MESSAGES
  203. })
  204. })(jQuery, DevExpress);
  205. /*! Module core, file class.js */
  206. (function($, global, DX, undefined) {
  207. DX.Class = function() {
  208. var wrapOverridden = function(baseProto, methodName, method) {
  209. return function() {
  210. var prevCallBase = this.callBase;
  211. this.callBase = baseProto[methodName];
  212. try {
  213. return method.apply(this, arguments)
  214. }
  215. finally {
  216. this.callBase = prevCallBase
  217. }
  218. }
  219. };
  220. var clonePrototype = function(obj) {
  221. var func = function(){};
  222. func.prototype = obj.prototype;
  223. return new func
  224. };
  225. var classImpl = function(){};
  226. var redefine = function(members) {
  227. var that = this;
  228. if (!members)
  229. return that;
  230. var memberNames = $.map(members, function(_, k) {
  231. return k
  232. });
  233. $.each(["toString", "toLocaleString", "valueOf"], function() {
  234. if (members[this])
  235. memberNames.push(this)
  236. });
  237. $.each(memberNames, function() {
  238. var overridden = $.isFunction(that.prototype[this]) && $.isFunction(members[this]);
  239. that.prototype[this] = overridden ? wrapOverridden(that.parent.prototype, this, members[this]) : members[this]
  240. });
  241. return that
  242. };
  243. var include = function() {
  244. var classObj = this;
  245. $.each(arguments, function() {
  246. if (this.ctor)
  247. classObj._includedCtors.push(this.ctor);
  248. if (this.postCtor)
  249. classObj._includedPostCtors.push(this.postCtor);
  250. for (var name in this) {
  251. if (name === "ctor" || name === "postCtor")
  252. continue;
  253. if (name in classObj.prototype)
  254. throw DX.Error("E0002", name);
  255. classObj.prototype[name] = this[name]
  256. }
  257. });
  258. return classObj
  259. };
  260. var subclassOf = function(parentClass) {
  261. if (this.parent === parentClass)
  262. return true;
  263. if (!this.parent || !this.parent.subclassOf)
  264. return false;
  265. return this.parent.subclassOf(parentClass)
  266. };
  267. classImpl.inherit = function(members) {
  268. var inheritor = function() {
  269. if (!this || this === global || typeof this.constructor !== "function")
  270. throw DX.Error("E0003");
  271. var instance = this,
  272. ctor = instance.ctor;
  273. $.each(instance.constructor._includedCtors, function() {
  274. this.call(instance)
  275. });
  276. if (ctor)
  277. ctor.apply(instance, arguments);
  278. $.each(instance.constructor._includedPostCtors, function() {
  279. this.call(instance)
  280. })
  281. };
  282. inheritor.prototype = clonePrototype(this);
  283. inheritor.inherit = this.inherit;
  284. inheritor.redefine = redefine;
  285. inheritor.include = include;
  286. inheritor.subclassOf = subclassOf;
  287. inheritor.parent = this;
  288. inheritor._includedCtors = this._includedCtors ? this._includedCtors.slice(0) : [];
  289. inheritor._includedPostCtors = this._includedPostCtors ? this._includedPostCtors.slice(0) : [];
  290. inheritor.prototype.constructor = inheritor;
  291. inheritor.redefine(members);
  292. return inheritor
  293. };
  294. return classImpl
  295. }()
  296. })(jQuery, this, DevExpress);
  297. /*! Module core, file queue.js */
  298. (function($, global, undefined) {
  299. var DX = global.DevExpress;
  300. function createQueue(discardPendingTasks) {
  301. var _tasks = [],
  302. _busy = false;
  303. function exec() {
  304. while (_tasks.length) {
  305. _busy = true;
  306. var task = _tasks.shift(),
  307. result = task();
  308. if (result === undefined)
  309. continue;
  310. if (result.then) {
  311. $.when(result).always(exec);
  312. return
  313. }
  314. throw DX.Error("E0015");
  315. }
  316. _busy = false
  317. }
  318. function add(task, removeTaskCallback) {
  319. if (!discardPendingTasks)
  320. _tasks.push(task);
  321. else {
  322. if (_tasks[0] && removeTaskCallback)
  323. removeTaskCallback(_tasks[0]);
  324. _tasks = [task]
  325. }
  326. if (!_busy)
  327. exec()
  328. }
  329. function busy() {
  330. return _busy
  331. }
  332. return {
  333. add: add,
  334. busy: busy
  335. }
  336. }
  337. $.extend(global.DevExpress, {
  338. createQueue: createQueue,
  339. enqueue: createQueue().add
  340. })
  341. })(jQuery, this);
  342. /*! Module core, file inflector.js */
  343. (function($, DX, undefined) {
  344. var _normalize = function(text) {
  345. if (text === undefined || text === null)
  346. return "";
  347. return String(text)
  348. };
  349. var _ucfirst = function(text) {
  350. return _normalize(text).charAt(0).toUpperCase() + text.substr(1)
  351. };
  352. var _chop = function(text) {
  353. return _normalize(text).replace(/([a-z\d])([A-Z])/g, "$1 $2").split(/[\s_-]+/)
  354. };
  355. var dasherize = function(text) {
  356. return $.map(_chop(text), function(p) {
  357. return p.toLowerCase()
  358. }).join("-")
  359. };
  360. var underscore = function(text) {
  361. return dasherize(text).replace(/-/g, "_")
  362. };
  363. var camelize = function(text, upperFirst) {
  364. return $.map(_chop(text), function(p, i) {
  365. p = p.toLowerCase();
  366. if (upperFirst || i > 0)
  367. p = _ucfirst(p);
  368. return p
  369. }).join("")
  370. };
  371. var humanize = function(text) {
  372. return _ucfirst(dasherize(text).replace(/-/g, " "))
  373. };
  374. var titleize = function(text) {
  375. return $.map(_chop(text), function(p) {
  376. return _ucfirst(p.toLowerCase())
  377. }).join(" ")
  378. };
  379. DX.inflector = {
  380. dasherize: dasherize,
  381. camelize: camelize,
  382. humanize: humanize,
  383. titleize: titleize,
  384. underscore: underscore
  385. }
  386. })(jQuery, DevExpress);
  387. /*! Module core, file eventsMixin.js */
  388. (function($, DX, undefined) {
  389. var EventsMixin = {
  390. ctor: function() {
  391. this._events = {}
  392. },
  393. fireEvent: function(eventName, eventArgs) {
  394. var callbacks = this._events[eventName];
  395. if (callbacks)
  396. callbacks.fireWith(this, eventArgs);
  397. return this
  398. },
  399. on: function(eventName, eventHandler) {
  400. if ($.isPlainObject(eventName))
  401. $.each(eventName, $.proxy(function(e, h) {
  402. this.on(e, h)
  403. }, this));
  404. else {
  405. var callbacks = this._events[eventName],
  406. addFn;
  407. if (!callbacks) {
  408. callbacks = $.Callbacks();
  409. this._events[eventName] = callbacks
  410. }
  411. addFn = callbacks.originalAdd || callbacks.add;
  412. addFn.call(callbacks, eventHandler)
  413. }
  414. return this
  415. },
  416. off: function(eventName, eventHandler) {
  417. var callbacks = this._events[eventName];
  418. if (callbacks)
  419. if ($.isFunction(eventHandler))
  420. callbacks.remove(eventHandler);
  421. else
  422. callbacks.empty();
  423. return this
  424. },
  425. _disposeEvents: function() {
  426. $.each(this._events, function() {
  427. this.empty()
  428. })
  429. },
  430. _callbacksToEvents: function(className, eventNames) {
  431. var that = this;
  432. $.each(eventNames, function(_, eventName) {
  433. var callbacksProperty = that[eventName],
  434. originalAdd;
  435. if (callbacksProperty !== undefined) {
  436. originalAdd = callbacksProperty.add;
  437. callbacksProperty.originalAdd = originalAdd;
  438. callbacksProperty.add = function() {
  439. DX.log("W0003", className, eventName, "14.2", "Use the '" + eventName + "' event instead");
  440. return originalAdd.apply(that, arguments)
  441. };
  442. that._events[eventName] = callbacksProperty
  443. }
  444. })
  445. }
  446. };
  447. $.extend(DX, {EventsMixin: EventsMixin})
  448. })(jQuery, DevExpress);
  449. /*! Module core, file jquery.js */
  450. (function($, DX) {
  451. if (DX.compareVersions($.fn.jquery, [1, 10]) < 0)
  452. throw DX.Error("E0012");
  453. })(jQuery, DevExpress);
  454. /*! Module core, file jquery.selectors.js */
  455. (function($) {
  456. var focusable = function(element, tabIndex) {
  457. var nodeName = element.nodeName.toLowerCase(),
  458. isTabIndexNotNaN = !isNaN(tabIndex),
  459. isVisible = visible(element),
  460. isDisabled = element.disabled,
  461. isDefaultFocus = /^(input|select|textarea|button|object)$/.test(nodeName),
  462. isHyperlink = nodeName === "a",
  463. isFocusable = true;
  464. if (isDefaultFocus)
  465. isFocusable = !isDisabled;
  466. else if (isHyperlink)
  467. isFocusable = element.href || isTabIndexNotNaN;
  468. else
  469. isFocusable = isTabIndexNotNaN;
  470. return isVisible ? isFocusable : false
  471. };
  472. var visible = function(element) {
  473. var $element = $(element);
  474. return $element.is(":visible") && $element.css("visibility") !== "hidden" && $element.parents().css("visibility") !== "hidden"
  475. };
  476. $.extend(jQuery.expr[':'], {
  477. "dx-focusable": function(element) {
  478. return focusable(element, $.attr(element, "tabindex"))
  479. },
  480. "dx-tabbable": function(element) {
  481. var tabIndex = $.attr(element, "tabindex");
  482. return (isNaN(tabIndex) || tabIndex >= 0) && focusable(element, tabIndex)
  483. }
  484. })
  485. })(jQuery);
  486. /*! Module core, file utils.common.js */
  487. (function($, DX, undefined) {
  488. var isDefined = function(object) {
  489. return object !== null && object !== undefined
  490. };
  491. var isString = function(object) {
  492. return $.type(object) === 'string'
  493. };
  494. var isNumber = function(object) {
  495. return typeof object === "number" && isFinite(object) || $.isNumeric(object)
  496. };
  497. var isObject = function(object) {
  498. return $.type(object) === 'object'
  499. };
  500. var isArray = function(object) {
  501. return $.type(object) === 'array'
  502. };
  503. var isDate = function(object) {
  504. return $.type(object) === 'date'
  505. };
  506. var isFunction = function(object) {
  507. return $.type(object) === 'function'
  508. };
  509. var isExponential = function(value) {
  510. return isNumber(value) && value.toString().indexOf('e') !== -1
  511. };
  512. var ensureDefined = function(value, defaultValue) {
  513. return isDefined(value) ? value : defaultValue
  514. };
  515. var getImageSourceType = function(source) {
  516. if (!isDefined(source))
  517. return false;
  518. if (/^fa fa-|^fa-.* fa/.test(source))
  519. return "faIcon";
  520. else if (/^ion-.*|ion.*ion-.*/.test(source))
  521. return "ionIcon";
  522. else if (/^glyphicon glyphicon-|^glyphicon-.* glyphicon/.test(source))
  523. return "glyphIcon";
  524. else if (/data:.*base64|\.|\//.test(source))
  525. return "image";
  526. else if (/^[\w-_]+$/.test(source))
  527. return "dxIcon";
  528. else
  529. return false
  530. };
  531. var getImageContainer = function(source) {
  532. var imageType = getImageSourceType(source),
  533. ICON_CLASS = "dx-icon";
  534. switch (imageType) {
  535. case"image":
  536. return $("<img>", {src: source}).addClass(ICON_CLASS);
  537. case"faIcon":
  538. case"glyphIcon":
  539. return $("<i>", {"class": ICON_CLASS + " " + source});
  540. case"ionIcon":
  541. var result = $("<i>", {"class": ICON_CLASS + " " + source});
  542. if (!result.hasClass("ion") && !result.hasClass("ionicons"))
  543. result.addClass("ion");
  544. return result;
  545. case"dxIcon":
  546. return $("<i>", {"class": ICON_CLASS + " " + ICON_CLASS + "-" + source});
  547. default:
  548. return null
  549. }
  550. };
  551. var extendFromObject = function(target, source, overrideExistingValues) {
  552. target = target || {};
  553. for (var prop in source)
  554. if (source.hasOwnProperty(prop)) {
  555. var value = source[prop];
  556. if (!(prop in target) || overrideExistingValues)
  557. target[prop] = value
  558. }
  559. return target
  560. };
  561. var clone = function() {
  562. function Clone(){}
  563. return function(obj) {
  564. Clone.prototype = obj;
  565. return new Clone
  566. }
  567. }();
  568. var executeAsync = function(action, context) {
  569. var deferred = $.Deferred(),
  570. normalizedContext = context || this,
  571. timerId,
  572. task = {
  573. promise: deferred.promise(),
  574. abort: function() {
  575. clearTimeout(timerId);
  576. deferred.rejectWith(normalizedContext)
  577. }
  578. },
  579. callback = function() {
  580. var result = action.call(normalizedContext);
  581. if (result && result.done && $.isFunction(result.done))
  582. result.done(function() {
  583. deferred.resolveWith(normalizedContext)
  584. });
  585. else
  586. deferred.resolveWith(normalizedContext)
  587. };
  588. timerId = (arguments[2] || setTimeout)(callback, 0);
  589. return task
  590. };
  591. var findBestMatches = function(targetFilter, items, mapFn) {
  592. var bestMatches = [],
  593. maxMatchCount = 0;
  594. $.each(items, function(index, itemSrc) {
  595. var matchCount = 0,
  596. item = mapFn ? mapFn(itemSrc) : itemSrc;
  597. $.each(targetFilter, function(paramName) {
  598. var value = item[paramName];
  599. if (value === undefined)
  600. return;
  601. if (value === targetFilter[paramName]) {
  602. matchCount++;
  603. return
  604. }
  605. matchCount = -1;
  606. return false
  607. });
  608. if (matchCount < maxMatchCount)
  609. return;
  610. if (matchCount > maxMatchCount) {
  611. bestMatches.length = 0;
  612. maxMatchCount = matchCount
  613. }
  614. bestMatches.push(itemSrc)
  615. });
  616. return bestMatches
  617. };
  618. var preg_quote = function(str) {
  619. return (str + "").replace(/([\+\*\?\\\.\[\^\]\$\(\)\{\}\><\|\=\!\:])/g, "\\$1")
  620. };
  621. var replaceAll = function(text, searchToken, replacementToken) {
  622. return text.replace(new RegExp("(" + preg_quote(searchToken) + ")", "gi"), replacementToken)
  623. };
  624. var splitPair = function(raw) {
  625. switch (typeof raw) {
  626. case"string":
  627. return raw.split(/\s+/, 2);
  628. case"object":
  629. return [raw.x || raw.h, raw.y || raw.v];
  630. case"number":
  631. return [raw];
  632. default:
  633. return raw
  634. }
  635. };
  636. var stringPairToObject = function(raw) {
  637. var pair = splitPair(raw),
  638. h = parseInt(pair && pair[0], 10),
  639. v = parseInt(pair && pair[1], 10);
  640. if (!isFinite(h))
  641. h = 0;
  642. if (!isFinite(v))
  643. v = h;
  644. return {
  645. h: h,
  646. v: v
  647. }
  648. };
  649. var orderEach = function(map, func) {
  650. var keys = [],
  651. key,
  652. i;
  653. for (key in map)
  654. keys.push(key);
  655. keys.sort(function(x, y) {
  656. var isNumberX = DX.utils.isNumber(x),
  657. isNumberY = DX.utils.isNumber(y);
  658. if (isNumberX && isNumberY)
  659. return x - y;
  660. if (isNumberX && !isNumberY)
  661. return -1;
  662. if (!isNumberX && isNumberY)
  663. return 1;
  664. if (x < y)
  665. return -1;
  666. if (x > y)
  667. return 1;
  668. return 0
  669. });
  670. for (i = 0; i < keys.length; i++) {
  671. key = keys[i];
  672. func(key, map[key])
  673. }
  674. };
  675. function icontains(elem, text) {
  676. var result = false;
  677. $.each($(elem).contents(), function(index, content) {
  678. if (content.nodeType === 3 && (content.textContent || content.nodeValue || "").toLowerCase().indexOf((text || "").toLowerCase()) > -1) {
  679. result = true;
  680. return false
  681. }
  682. });
  683. return result
  684. }
  685. $.expr[":"].dxicontains = $.expr.createPseudo(function(text) {
  686. return function(elem) {
  687. return icontains(elem, text)
  688. }
  689. });
  690. function deepExtendArraySafe(target, changes) {
  691. var prevValue,
  692. newValue;
  693. for (var name in changes) {
  694. prevValue = target[name];
  695. newValue = changes[name];
  696. if (target === newValue)
  697. continue;
  698. if ($.isPlainObject(newValue) && !(newValue instanceof $.Event))
  699. target[name] = deepExtendArraySafe($.isPlainObject(prevValue) ? prevValue : {}, newValue);
  700. else if (newValue !== undefined)
  701. target[name] = newValue
  702. }
  703. return target
  704. }
  705. function unwrapObservable(value) {
  706. if (DX.support.hasKo)
  707. return ko.utils.unwrapObservable(value);
  708. return value
  709. }
  710. function normalizeIndexes(items, indexParameterName, currentItem, needIndexCallback) {
  711. var indexedItems = {},
  712. parameterIndex = 0;
  713. $.each(items, function(index, item) {
  714. index = item[indexParameterName];
  715. if (isDefined(index)) {
  716. indexedItems[index] = indexedItems[index] || [];
  717. if (item === currentItem)
  718. indexedItems[index].unshift(item);
  719. else
  720. indexedItems[index].push(item);
  721. delete item[indexParameterName]
  722. }
  723. });
  724. orderEach(indexedItems, function(index, items) {
  725. $.each(items, function() {
  726. if (index >= 0)
  727. this[indexParameterName] = parameterIndex++
  728. })
  729. });
  730. $.each(items, function() {
  731. if (!isDefined(this[indexParameterName]) && (!needIndexCallback || needIndexCallback(this)))
  732. this[indexParameterName] = parameterIndex++
  733. });
  734. return parameterIndex
  735. }
  736. DX.utils = {
  737. isDefined: isDefined,
  738. isString: isString,
  739. isNumber: isNumber,
  740. isObject: isObject,
  741. isArray: isArray,
  742. isDate: isDate,
  743. isFunction: isFunction,
  744. isExponential: isExponential,
  745. ensureDefined: ensureDefined,
  746. extendFromObject: extendFromObject,
  747. clone: clone,
  748. executeAsync: executeAsync,
  749. stringFormat: DX.stringFormat,
  750. findBestMatches: findBestMatches,
  751. replaceAll: replaceAll,
  752. deepExtendArraySafe: deepExtendArraySafe,
  753. splitPair: splitPair,
  754. stringPairToObject: stringPairToObject,
  755. normalizeIndexes: normalizeIndexes,
  756. orderEach: orderEach,
  757. unwrapObservable: unwrapObservable,
  758. getImageSourceType: getImageSourceType,
  759. getImageContainer: getImageContainer
  760. }
  761. })(jQuery, DevExpress);
  762. /*! Module core, file utils.console.js */
  763. (function($, DX, undefined) {
  764. var logger = function() {
  765. var console = window.console;
  766. function info(text) {
  767. if (!console || !$.isFunction(console.info))
  768. return;
  769. console.info(text)
  770. }
  771. function warn(text) {
  772. if (!console || !$.isFunction(console.warn))
  773. return;
  774. console.warn(text)
  775. }
  776. function error(text) {
  777. if (!console || !$.isFunction(console.error))
  778. return;
  779. console.error(text)
  780. }
  781. return {
  782. info: info,
  783. warn: warn,
  784. error: error
  785. }
  786. }();
  787. var debug = function() {
  788. function assert(condition, message) {
  789. if (!condition)
  790. throw new Error(message);
  791. }
  792. function assertParam(parameter, message) {
  793. assert(parameter !== null && parameter !== undefined, message)
  794. }
  795. return {
  796. assert: assert,
  797. assertParam: assertParam
  798. }
  799. }();
  800. $.extend(DX.utils, {
  801. logger: logger,
  802. debug: debug
  803. })
  804. })(jQuery, DevExpress);
  805. /*! Module core, file utils.math.js */
  806. (function($, DX, undefined) {
  807. var PI = Math.PI,
  808. LN10 = Math.LN10;
  809. var cos = Math.cos,
  810. sin = Math.sin,
  811. abs = Math.abs,
  812. log = Math.log,
  813. floor = Math.floor,
  814. ceil = Math.ceil,
  815. max = Math.max,
  816. isNaN = window.isNaN,
  817. Number = window.Number,
  818. NaN = window.NaN;
  819. var isNumber = DX.utils.isNumber,
  820. isExponential = DX.utils.isExponential;
  821. var getPrecision = function(value) {
  822. var stringFraction,
  823. stringValue = value.toString(),
  824. pointIndex = stringValue.indexOf('.'),
  825. startIndex,
  826. precision;
  827. if (isExponential(value)) {
  828. precision = getDecimalOrder(value);
  829. if (precision < 0)
  830. return Math.abs(precision);
  831. else
  832. return 0
  833. }
  834. if (pointIndex !== -1) {
  835. startIndex = pointIndex + 1;
  836. stringFraction = stringValue.substring(startIndex, startIndex + 20);
  837. return stringFraction.length
  838. }
  839. return 0
  840. };
  841. var getLog = function(value, base) {
  842. if (!value)
  843. return NaN;
  844. return Math.log(value) / Math.log(base)
  845. };
  846. var raiseTo = function(power, base) {
  847. return Math.pow(base, power)
  848. };
  849. var sign = function(value) {
  850. if (value === 0)
  851. return 0;
  852. return value / abs(value)
  853. };
  854. var normalizeAngle = function(angle) {
  855. return (angle % 360 + 360) % 360
  856. };
  857. var convertAngleToRendererSpace = function(angle) {
  858. return 90 - angle
  859. };
  860. var degreesToRadians = function(value) {
  861. return PI * value / 180
  862. };
  863. var getCosAndSin = function(angle) {
  864. var angleInRadians = degreesToRadians(angle);
  865. return {
  866. cos: cos(angleInRadians),
  867. sin: sin(angleInRadians)
  868. }
  869. };
  870. var DECIMAL_ORDER_THRESHOLD = 1E-14;
  871. var getDistance = function(x1, y1, x2, y2) {
  872. var diffX = x2 - x1,
  873. diffY = y2 - y1;
  874. return Math.sqrt(diffY * diffY + diffX * diffX)
  875. };
  876. var getDecimalOrder = function(number) {
  877. var n = abs(number),
  878. cn;
  879. if (!isNaN(n)) {
  880. if (n > 0) {
  881. n = log(n) / LN10;
  882. cn = ceil(n);
  883. return cn - n < DECIMAL_ORDER_THRESHOLD ? cn : floor(n)
  884. }
  885. return 0
  886. }
  887. return NaN
  888. };
  889. var getAppropriateFormat = function(start, end, count) {
  890. var order = max(getDecimalOrder(start), getDecimalOrder(end)),
  891. precision = -getDecimalOrder(abs(end - start) / count),
  892. format;
  893. if (!isNaN(order) && !isNaN(precision)) {
  894. if (abs(order) <= 4) {
  895. format = 'fixedPoint';
  896. precision < 0 && (precision = 0);
  897. precision > 4 && (precision = 4)
  898. }
  899. else {
  900. format = 'exponential';
  901. precision += order - 1;
  902. precision > 3 && (precision = 3)
  903. }
  904. return {
  905. format: format,
  906. precision: precision
  907. }
  908. }
  909. return null
  910. };
  911. var getFraction = function(value) {
  912. var valueString,
  913. dotIndex;
  914. if (isNumber(value)) {
  915. valueString = value.toString();
  916. dotIndex = valueString.indexOf('.');
  917. if (dotIndex >= 0)
  918. if (isExponential(value))
  919. return valueString.substr(dotIndex + 1, valueString.indexOf('e') - dotIndex - 1);
  920. else {
  921. valueString = value.toFixed(20);
  922. return valueString.substr(dotIndex + 1, valueString.length - dotIndex + 1)
  923. }
  924. }
  925. return ''
  926. };
  927. var getSignificantDigitPosition = function(value) {
  928. var fraction = getFraction(value),
  929. i;
  930. if (fraction)
  931. for (i = 0; i < fraction.length; i++)
  932. if (fraction.charAt(i) !== '0')
  933. return i + 1;
  934. return 0
  935. };
  936. var adjustValue = function(value) {
  937. var fraction = getFraction(value),
  938. nextValue,
  939. i;
  940. if (fraction)
  941. for (i = 1; i <= fraction.length; i++) {
  942. nextValue = roundValue(value, i);
  943. if (nextValue !== 0 && fraction[i - 2] && fraction[i - 1] && fraction[i - 2] === fraction[i - 1])
  944. return nextValue
  945. }
  946. return value
  947. };
  948. var roundValue = function(value, precision) {
  949. if (precision > 20)
  950. precision = 20;
  951. if (isNumber(value))
  952. if (isExponential(value))
  953. return Number(value.toExponential(precision));
  954. else
  955. return Number(value.toFixed(precision))
  956. };
  957. var applyPrecisionByMinDelta = function(min, delta, value) {
  958. var minPrecision = getPrecision(min),
  959. deltaPrecision = getPrecision(delta);
  960. return roundValue(value, minPrecision < deltaPrecision ? deltaPrecision : minPrecision)
  961. };
  962. var fitIntoRange = function(value, minValue, maxValue) {
  963. return Math.min(Math.max(value, minValue), maxValue)
  964. };
  965. var getPower = function(value) {
  966. return value.toExponential().split("e")[1]
  967. };
  968. $.extend(DX.utils, {
  969. getLog: getLog,
  970. raiseTo: raiseTo,
  971. sign: sign,
  972. normalizeAngle: normalizeAngle,
  973. convertAngleToRendererSpace: convertAngleToRendererSpace,
  974. degreesToRadians: degreesToRadians,
  975. getCosAndSin: getCosAndSin,
  976. getDecimalOrder: getDecimalOrder,
  977. getAppropriateFormat: getAppropriateFormat,
  978. getDistance: getDistance,
  979. getFraction: getFraction,
  980. adjustValue: adjustValue,
  981. roundValue: roundValue,
  982. applyPrecisionByMinDelta: applyPrecisionByMinDelta,
  983. getSignificantDigitPosition: getSignificantDigitPosition,
  984. getPower: getPower,
  985. fitIntoRange: fitIntoRange
  986. });
  987. DX.utils.getPrecision = getPrecision
  988. })(jQuery, DevExpress);
  989. /*! Module core, file utils.date.js */
  990. (function($, DX, undefined) {
  991. var isObject = DX.utils.isObject,
  992. isString = DX.utils.isString,
  993. isDate = DX.utils.isDate,
  994. isDefined = DX.utils.isDefined;
  995. var dateUnitIntervals = ['millisecond', 'second', 'minute', 'hour', 'day', 'week', 'month', 'quarter', 'year'];
  996. var addSubValues = function(value1, value2, isSub) {
  997. return value1 + (isSub ? -1 : 1) * value2
  998. };
  999. var toMilliseconds = function(value) {
  1000. switch (value) {
  1001. case'millisecond':
  1002. return 1;
  1003. case'second':
  1004. return toMilliseconds('millisecond') * 1000;
  1005. case'minute':
  1006. return toMilliseconds('second') * 60;
  1007. case'hour':
  1008. return toMilliseconds('minute') * 60;
  1009. case'day':
  1010. return toMilliseconds('hour') * 24;
  1011. case'week':
  1012. return toMilliseconds('day') * 7;
  1013. case'month':
  1014. return toMilliseconds('day') * 30;
  1015. case'quarter':
  1016. return toMilliseconds('month') * 3;
  1017. case'year':
  1018. return toMilliseconds('day') * 365;
  1019. default:
  1020. return 0
  1021. }
  1022. };
  1023. var convertMillisecondsToDateUnits = function(value) {
  1024. var i,
  1025. dateUnitCount,
  1026. dateUnitInterval,
  1027. dateUnitIntervals = ['millisecond', 'second', 'minute', 'hour', 'day', 'month', 'year'],
  1028. result = {};
  1029. for (i = dateUnitIntervals.length - 1; i >= 0; i--) {
  1030. dateUnitInterval = dateUnitIntervals[i];
  1031. dateUnitCount = Math.floor(value / toMilliseconds(dateUnitInterval));
  1032. if (dateUnitCount > 0) {
  1033. result[dateUnitInterval + 's'] = dateUnitCount;
  1034. value -= convertDateUnitToMilliseconds(dateUnitInterval, dateUnitCount)
  1035. }
  1036. }
  1037. return result
  1038. };
  1039. var dateToMilliseconds = function(tickInterval) {
  1040. var milliseconds = 0;
  1041. if (isObject(tickInterval))
  1042. $.each(tickInterval, function(key, value) {
  1043. milliseconds += convertDateUnitToMilliseconds(key.substr(0, key.length - 1), value)
  1044. });
  1045. if (isString(tickInterval))
  1046. milliseconds = convertDateUnitToMilliseconds(tickInterval, 1);
  1047. return milliseconds
  1048. };
  1049. var convertDateUnitToMilliseconds = function(dateUnit, count) {
  1050. return toMilliseconds(dateUnit) * count
  1051. };
  1052. var getDateUnitInterval = function(tickInterval) {
  1053. var maxInterval = -1,
  1054. i;
  1055. if (isString(tickInterval))
  1056. return tickInterval;
  1057. if (isObject(tickInterval)) {
  1058. $.each(tickInterval, function(key, value) {
  1059. for (i = 0; i < dateUnitIntervals.length; i++)
  1060. if (value && (key === dateUnitIntervals[i] + 's' || key === dateUnitIntervals[i]) && maxInterval < i)
  1061. maxInterval = i
  1062. });
  1063. return dateUnitIntervals[maxInterval]
  1064. }
  1065. return ''
  1066. };
  1067. var correctDateWithUnitBeginning = function(date, dateInterval, withCorrection) {
  1068. var oldDate = new Date(date.getTime()),
  1069. dayMonth,
  1070. firstQuarterMonth,
  1071. dateUnitInterval = getDateUnitInterval(dateInterval);
  1072. switch (dateUnitInterval) {
  1073. case'second':
  1074. date.setMilliseconds(0);
  1075. break;
  1076. case'minute':
  1077. date.setSeconds(0, 0);
  1078. break;
  1079. case'hour':
  1080. date.setMinutes(0, 0, 0);
  1081. break;
  1082. case'year':
  1083. date.setMonth(0);
  1084. case'month':
  1085. date.setDate(1);
  1086. case'day':
  1087. date.setHours(0, 0, 0, 0);
  1088. break;
  1089. case'week':
  1090. dayMonth = date.getDate();
  1091. if (date.getDay() !== 0)
  1092. dayMonth += 7 - date.getDay();
  1093. date.setDate(dayMonth);
  1094. date.setHours(0, 0, 0, 0);
  1095. break;
  1096. case'quarter':
  1097. firstQuarterMonth = DX.formatHelper.getFirstQuarterMonth(date.getMonth());
  1098. if (date.getMonth() !== firstQuarterMonth)
  1099. date.setMonth(firstQuarterMonth);
  1100. date.setDate(1);
  1101. date.setHours(0, 0, 0, 0);
  1102. break
  1103. }
  1104. if (withCorrection && dateUnitInterval !== "hour" && dateUnitInterval !== "minute" && dateUnitInterval !== "second")
  1105. fixTimezoneGap(oldDate, date)
  1106. };
  1107. var getDatesDifferences = function(date1, date2) {
  1108. var differences,
  1109. counter = 0;
  1110. differences = {
  1111. year: date1.getFullYear() !== date2.getFullYear(),
  1112. month: date1.getMonth() !== date2.getMonth(),
  1113. day: date1.getDate() !== date2.getDate(),
  1114. hour: date1.getHours() !== date2.getHours(),
  1115. minute: date1.getMinutes() !== date2.getMinutes(),
  1116. second: date1.getSeconds() !== date2.getSeconds()
  1117. };
  1118. $.each(differences, function(key, value) {
  1119. if (value)
  1120. counter++
  1121. });
  1122. differences.count = counter;
  1123. return differences
  1124. };
  1125. var addInterval = function(value, interval, isNegative) {
  1126. var result = null,
  1127. intervalObject;
  1128. if (isDate(value)) {
  1129. intervalObject = isString(interval) ? getDateIntervalByString(interval.toLowerCase()) : interval;
  1130. result = new Date(value.getTime());
  1131. if (intervalObject.years)
  1132. result.setFullYear(addSubValues(result.getFullYear(), intervalObject.years, isNegative));
  1133. if (intervalObject.quarters)
  1134. result.setMonth(addSubValues(result.getMonth(), 3 * intervalObject.quarters, isNegative));
  1135. if (intervalObject.months)
  1136. result.setMonth(addSubValues(result.getMonth(), intervalObject.months, isNegative));
  1137. if (intervalObject.weeks)
  1138. result.setDate(addSubValues(result.getDate(), 7 * intervalObject.weeks, isNegative));
  1139. if (intervalObject.days)
  1140. result.setDate(addSubValues(result.getDate(), intervalObject.days, isNegative));
  1141. if (intervalObject.hours)
  1142. result.setHours(addSubValues(result.getHours(), intervalObject.hours, isNegative));
  1143. if (intervalObject.minutes)
  1144. result.setMinutes(addSubValues(result.getMinutes(), intervalObject.minutes, isNegative));
  1145. if (intervalObject.seconds)
  1146. result.setSeconds(addSubValues(result.getSeconds(), intervalObject.seconds, isNegative));
  1147. if (intervalObject.milliseconds)
  1148. result.setMilliseconds(addSubValues(value.getMilliseconds(), intervalObject.milliseconds, isNegative))
  1149. }
  1150. else
  1151. result = addSubValues(value, interval, isNegative);
  1152. return result
  1153. };
  1154. var getFirstDateView = function(typeView, date) {
  1155. if (!isDefined(date))
  1156. return;
  1157. if (typeView === "month")
  1158. return getFirstMonthDate(date);
  1159. if (typeView === "year")
  1160. return new Date(date.getFullYear(), 0, 1);
  1161. if (typeView === "decade")
  1162. return new Date(getFirstYearInDecade(date), 0, 1);
  1163. if (typeView === "century")
  1164. return new Date(getFirstDecadeInCentury(date), 0, 1)
  1165. };
  1166. var getLastDateView = function(typeView, date) {
  1167. if (typeView === "month")
  1168. return new Date(date.getFullYear(), date.getMonth(), getLastDayOfMonth(date));
  1169. if (typeView === "year")
  1170. return new Date(date.getFullYear(), 11, 1);
  1171. if (typeView === "decade")
  1172. return new Date(getFirstYearInDecade(date) + 9, 0, 1);
  1173. if (typeView === "century")
  1174. return new Date(getFirstDecadeInCentury(date) + 90, 0, 1)
  1175. };
  1176. var sameView = function(view, date1, date2) {
  1177. return DX.utils[DX.inflector.camelize("same " + view)](date1, date2)
  1178. };
  1179. var getViewUp = function(typeView) {
  1180. switch (typeView) {
  1181. case"month":
  1182. return "year";
  1183. case"year":
  1184. return "decade";
  1185. case"decade":
  1186. return "century";
  1187. default:
  1188. break
  1189. }
  1190. };
  1191. var getViewDown = function(typeView) {
  1192. switch (typeView) {
  1193. case"century":
  1194. return "decade";
  1195. case"decade":
  1196. return "year";
  1197. case"year":
  1198. return "month";
  1199. default:
  1200. break
  1201. }
  1202. };
  1203. var getDifferenceInMonth = function(typeView) {
  1204. var difference = 1;
  1205. if (typeView === "year")
  1206. difference = 12;
  1207. if (typeView === "decade")
  1208. difference = 12 * 10;
  1209. if (typeView === "century")
  1210. difference = 12 * 100;
  1211. return difference
  1212. };
  1213. var getDifferenceInMonthForCells = function(typeView) {
  1214. var difference = 1;
  1215. if (typeView === "decade")
  1216. difference = 12;
  1217. if (typeView === "century")
  1218. difference = 12 * 10;
  1219. return difference
  1220. };
  1221. var getDateIntervalByString = function(intervalString) {
  1222. var result = {};
  1223. switch (intervalString) {
  1224. case'year':
  1225. result.years = 1;
  1226. break;
  1227. case'month':
  1228. result.months = 1;
  1229. break;
  1230. case'quarter':
  1231. result.months = 3;
  1232. break;
  1233. case'week':
  1234. result.days = 7;
  1235. break;
  1236. case'day':
  1237. result.days = 1;
  1238. break;
  1239. case'hour':
  1240. result.hours = 1;
  1241. break;
  1242. case'minute':
  1243. result.minutes = 1;
  1244. break;
  1245. case'second':
  1246. result.seconds = 1;
  1247. break;
  1248. case'millisecond':
  1249. result.milliseconds = 1;
  1250. break
  1251. }
  1252. return result
  1253. };
  1254. var sameMonthAndYear = function(date1, date2) {
  1255. return date1 && date2 && date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth()
  1256. };
  1257. var sameYear = function(date1, date2) {
  1258. return date1 && date2 && date1.getFullYear() === date2.getFullYear()
  1259. };
  1260. var sameDecade = function(date1, date2) {
  1261. if (!isDefined(date1) || !isDefined(date2))
  1262. return;
  1263. var startDecadeDate1 = date1.getFullYear() - date1.getFullYear() % 10,
  1264. startDecadeDate2 = date2.getFullYear() - date2.getFullYear() % 10;
  1265. return date1 && date2 && startDecadeDate1 === startDecadeDate2
  1266. };
  1267. var sameCentury = function(date1, date2) {
  1268. if (!isDefined(date1) || !isDefined(date2))
  1269. return;
  1270. var startCenturyDate1 = date1.getFullYear() - date1.getFullYear() % 100,
  1271. startCenturyDate2 = date2.getFullYear() - date2.getFullYear() % 100;
  1272. return date1 && date2 && startCenturyDate1 === startCenturyDate2
  1273. };
  1274. var getFirstDecadeInCentury = function(date) {
  1275. return date && date.getFullYear() - date.getFullYear() % 100
  1276. };
  1277. var getFirstYearInDecade = function(date) {
  1278. return date && date.getFullYear() - date.getFullYear() % 10
  1279. };
  1280. var getShortDate = function(date) {
  1281. return Globalize.format(date, "yyyy/M/d")
  1282. };
  1283. var getLastDayOfMonth = function(date) {
  1284. date = new Date(date.getFullYear(), date.getMonth() + 1, 0);
  1285. return date.getDate()
  1286. };
  1287. var getFirstMonthDate = function(date) {
  1288. if (!isDefined(date))
  1289. return;
  1290. var newDate = new Date(date.getFullYear(), date.getMonth(), 1);
  1291. return newDate
  1292. };
  1293. var getLastMonthDate = function(date) {
  1294. if (!isDefined(date))
  1295. return;
  1296. var newDate = new Date(date.getFullYear(), date.getMonth() + 1, 0);
  1297. return newDate
  1298. };
  1299. var getFirstWeekDate = function(date, firstDayOfWeek) {
  1300. firstDayOfWeek = firstDayOfWeek || Globalize.culture().calendar.firstDay;
  1301. var delta = (date.getDay() - firstDayOfWeek + 7) % 7;
  1302. var result = new Date(date);
  1303. result.setDate(date.getDate() - delta);
  1304. return result
  1305. };
  1306. var dateInRange = function(date, min, max) {
  1307. return normalizeDate(date, min, max) === date
  1308. };
  1309. var normalizeDate = function(date, min, max) {
  1310. var normalizedDate = date;
  1311. if (isDefined(min) && date < min)
  1312. normalizedDate = min;
  1313. if (isDefined(max) && date > max)
  1314. normalizedDate = max;
  1315. return normalizedDate
  1316. };
  1317. var fixTimezoneGap = function(oldDate, newDate) {
  1318. if (!DX.utils.isDefined(oldDate))
  1319. return;
  1320. var diff = newDate.getHours() - oldDate.getHours(),
  1321. sign,
  1322. trial;
  1323. if (diff === 0)
  1324. return;
  1325. sign = diff === 1 || diff === -23 ? -1 : 1,
  1326. trial = new Date(newDate.getTime() + sign * 3600000);
  1327. if (sign > 0 || trial.getDate() === newDate.getDate())
  1328. newDate.setTime(trial.getTime())
  1329. };
  1330. var makeDate = function(date) {
  1331. if (!(date instanceof Date))
  1332. date = new Date(date);
  1333. return date
  1334. };
  1335. $.extend(DX.utils, {
  1336. dateUnitIntervals: dateUnitIntervals,
  1337. convertMillisecondsToDateUnits: convertMillisecondsToDateUnits,
  1338. dateToMilliseconds: dateToMilliseconds,
  1339. convertDateUnitToMilliseconds: convertDateUnitToMilliseconds,
  1340. getDateUnitInterval: getDateUnitInterval,
  1341. getDatesDifferences: getDatesDifferences,
  1342. correctDateWithUnitBeginning: correctDateWithUnitBeginning,
  1343. addInterval: addInterval,
  1344. getDateIntervalByString: getDateIntervalByString,
  1345. sameMonthAndYear: sameMonthAndYear,
  1346. sameMonth: sameMonthAndYear,
  1347. sameYear: sameYear,
  1348. sameDecade: sameDecade,
  1349. sameCentury: sameCentury,
  1350. sameView: sameView,
  1351. getDifferenceInMonth: getDifferenceInMonth,
  1352. getDifferenceInMonthForCells: getDifferenceInMonthForCells,
  1353. getFirstYearInDecade: getFirstYearInDecade,
  1354. getFirstDecadeInCentury: getFirstDecadeInCentury,
  1355. getShortDate: getShortDate,
  1356. getFirstDateView: getFirstDateView,
  1357. getLastDateView: getLastDateView,
  1358. getViewDown: getViewDown,
  1359. getViewUp: getViewUp,
  1360. getLastMonthDate: getLastMonthDate,
  1361. getFirstMonthDate: getFirstMonthDate,
  1362. getFirstWeekDate: getFirstWeekDate,
  1363. getLastDayOfMonth: getLastDayOfMonth,
  1364. dateInRange: dateInRange,
  1365. normalizeDate: normalizeDate,
  1366. fixTimezoneGap: fixTimezoneGap,
  1367. makeDate: makeDate
  1368. })
  1369. })(jQuery, DevExpress);
  1370. /*! Module core, file utils.recurrence.js */
  1371. (function($, DX, undefined) {
  1372. var utils = DX.utils;
  1373. var intervalMap = {
  1374. secondly: "seconds",
  1375. minutely: "minutes",
  1376. hourly: "hours",
  1377. daily: "days",
  1378. weekly: "weeks",
  1379. monthly: "months",
  1380. yearly: "years"
  1381. };
  1382. var dateSetterMap = {
  1383. bysecond: function(date, value) {
  1384. date.setSeconds(value)
  1385. },
  1386. byminute: function(date, value) {
  1387. date.setMinutes(value)
  1388. },
  1389. byhour: function(date, value) {
  1390. date.setHours(value)
  1391. },
  1392. bymonth: function(date, value) {
  1393. date.setMonth(value)
  1394. },
  1395. bymonthday: function(date, value) {
  1396. date.setDate(value)
  1397. },
  1398. byday: function(date, dayOfWeek) {
  1399. date.setDate(date.getDate() - date.getDay() + dayOfWeek)
  1400. }
  1401. };
  1402. var dateGetterMap = {
  1403. bysecond: "getSeconds",
  1404. byminute: "getMinutes",
  1405. byhour: "getHours",
  1406. bymonth: "getMonth",
  1407. bymonthday: "getDate",
  1408. byday: "getDay"
  1409. };
  1410. var dateInRecurrenceRange = function(recurrenceString, currentDate, viewStartDate, viewEndDate) {
  1411. var result = [];
  1412. if (recurrenceString)
  1413. result = getDatesByRecurrence(recurrenceString, currentDate, viewStartDate, viewEndDate);
  1414. return !!result.length
  1415. };
  1416. var normalizeInterval = function(freq, interval) {
  1417. var intervalObject = {},
  1418. intervalField = intervalMap[freq.toLowerCase()];
  1419. intervalObject[intervalField] = interval;
  1420. return intervalObject
  1421. };
  1422. var getDatesByRecurrence = function(recurrenceString, recurrenceStartDate, viewStartDate, viewEndDate) {
  1423. if (!recurrenceString)
  1424. return [];
  1425. var result = [],
  1426. recurrenceRule = getRecurrenceRule(recurrenceString);
  1427. if (!recurrenceRule.freq)
  1428. return result;
  1429. recurrenceRule.interval = normalizeInterval(recurrenceRule.freq, recurrenceRule.interval);
  1430. viewEndDate = utils.normalizeDate(viewEndDate, viewStartDate, recurrenceRule.until);
  1431. var recurrenceCounter = 0,
  1432. dateCounter = 0,
  1433. dateRules = splitDateRules(recurrenceRule),
  1434. ruleDates = getDatesByRules(dateRules, recurrenceStartDate),
  1435. currentDate = ruleDates[0],
  1436. firstDate = new Date(recurrenceStartDate);
  1437. utils.correctDateWithUnitBeginning(firstDate, recurrenceRule.interval);
  1438. var firstDateInterval = getDatePartDiffs(recurrenceStartDate, firstDate);
  1439. while (currentDate <= viewEndDate && recurrenceRule.count !== recurrenceCounter) {
  1440. if (checkDateByRule(currentDate, dateRules)) {
  1441. if (currentDate >= viewStartDate) {
  1442. viewStartDate = new Date(currentDate);
  1443. viewStartDate.setMilliseconds(viewStartDate.getMilliseconds() + 1);
  1444. result.push(new Date(currentDate))
  1445. }
  1446. recurrenceCounter++
  1447. }
  1448. dateCounter++;
  1449. currentDate = ruleDates[dateCounter % ruleDates.length];
  1450. if (dateCounter / ruleDates.length >= 1) {
  1451. dateCounter = 0;
  1452. firstDate = utils.addInterval(firstDate, recurrenceRule.interval);
  1453. ruleDates = getDatesByRules(dateRules, utils.addInterval(firstDate, firstDateInterval));
  1454. currentDate = ruleDates[0]
  1455. }
  1456. }
  1457. return result
  1458. };
  1459. var getDatePartDiffs = function(date1, date2) {
  1460. return {
  1461. years: date1.getFullYear() - date2.getFullYear(),
  1462. months: date1.getMonth() - date2.getMonth(),
  1463. days: date1.getDate() - date2.getDate(),
  1464. hours: date1.getHours() - date2.getHours(),
  1465. minutes: date1.getMinutes() - date2.getMinutes(),
  1466. seconds: date1.getSeconds() - date2.getSeconds()
  1467. }
  1468. };
  1469. var getRecurrenceRule = function(recurrence) {
  1470. if (!recurrence)
  1471. return {};
  1472. var ruleObject = {},
  1473. ruleStrings = recurrence.split(";");
  1474. for (var i = 0, len = ruleStrings.length; i < len; i++) {
  1475. var rule = ruleStrings[i].split("="),
  1476. ruleName = rule[0].toLowerCase(),
  1477. ruleValue = rule[1];
  1478. ruleObject[ruleName] = ruleValue
  1479. }
  1480. return normalizeRRule(ruleObject)
  1481. };
  1482. var normalizeRRule = function(rule) {
  1483. var count = parseInt(rule.count);
  1484. if (!isNaN(count))
  1485. rule.count = count;
  1486. var interval = parseInt(rule.interval);
  1487. rule.interval = isNaN(interval) ? 1 : interval;
  1488. if (rule.freq && rule.until)
  1489. rule.until = getDateByAsciiString(rule.until);
  1490. return rule
  1491. };
  1492. var getDateByAsciiString = function(string) {
  1493. var date = Globalize.parseDate(string, "yyyyMMddThhmmss");
  1494. if (!date)
  1495. date = Globalize.parseDate(string, "yyyyMMdd");
  1496. return date
  1497. };
  1498. var getAsciiStringByDate = function(date) {
  1499. return date.getFullYear() + ('0' + (date.getMonth() + 1)).slice(-2) + ('0' + date.getDate()).slice(-2)
  1500. };
  1501. var splitDateRules = function(rule) {
  1502. var result = [];
  1503. for (var field in dateSetterMap) {
  1504. if (!rule[field])
  1505. continue;
  1506. var ruleFieldValues = rule[field].split(","),
  1507. ruleArray = getDateRuleArray(field, ruleFieldValues);
  1508. result = result.length ? extendObjectArray(ruleArray, result) : ruleArray
  1509. }
  1510. return result
  1511. };
  1512. var getDateRuleArray = function(field, values) {
  1513. var result = [];
  1514. for (var i = 0, length = values.length; i < length; i++) {
  1515. var dateRule = {};
  1516. dateRule[field] = handleRuleFieldValue(field, values[i]);
  1517. result.push(dateRule)
  1518. }
  1519. return result
  1520. };
  1521. var days = {
  1522. SU: 0,
  1523. MO: 1,
  1524. TU: 2,
  1525. WE: 3,
  1526. TH: 4,
  1527. FR: 5,
  1528. SA: 6
  1529. };
  1530. var handleRuleFieldValue = function(field, value) {
  1531. var result = parseInt(value);
  1532. if (field === "bymonth")
  1533. result -= 1;
  1534. if (field === "byday")
  1535. result = days[value];
  1536. return result
  1537. };
  1538. var extendObjectArray = function(firstArray, secondArray) {
  1539. var result = [];
  1540. for (var i = 0, firstArrayLength = firstArray.length; i < firstArrayLength; i++)
  1541. for (var j = 0, secondArrayLength = secondArray.length; j < secondArrayLength; j++)
  1542. result.push($.extend({}, firstArray[i], secondArray[j]));
  1543. return result
  1544. };
  1545. var getDatesByRules = function(dateRules, startDate) {
  1546. var updatedDate = new Date(startDate),
  1547. result = [];
  1548. for (var i = 0, len = dateRules.length; i < len; i++) {
  1549. var current = dateRules[i];
  1550. for (var field in current)
  1551. dateSetterMap[field](updatedDate, current[field]);
  1552. result.push(new Date(updatedDate))
  1553. }
  1554. if (!result.length)
  1555. result.push(updatedDate);
  1556. return result
  1557. };
  1558. var checkDateByRule = function(date, rules) {
  1559. var result = false;
  1560. for (var i = 0; i < rules.length; i++) {
  1561. var current = rules[i],
  1562. currentRuleResult = true;
  1563. for (var field in current)
  1564. if (current[field] !== date[dateGetterMap[field]]())
  1565. currentRuleResult = false;
  1566. result = result || currentRuleResult
  1567. }
  1568. return result || !rules.length
  1569. };
  1570. var getRecurrenceString = function(object) {
  1571. if (!object || !object.freq)
  1572. return;
  1573. var result = "";
  1574. for (var field in object) {
  1575. if (field === "interval" && object[field] < 2)
  1576. continue;
  1577. result += field + "=" + object[field] + ";"
  1578. }
  1579. result = result.substring(0, result.length - 1);
  1580. return result.toUpperCase()
  1581. };
  1582. $.extend(DX.utils, {
  1583. getRecurrenceString: getRecurrenceString,
  1584. getRecurrenceRule: getRecurrenceRule,
  1585. getAsciiStringByDate: getAsciiStringByDate,
  1586. getDatesByRecurrence: getDatesByRecurrence,
  1587. dateInRecurrenceRange: dateInRecurrenceRange
  1588. })
  1589. })(jQuery, DevExpress);
  1590. /*! Module core, file utils.dom.js */
  1591. (function($, DX, undefined) {
  1592. var windowResizeCallbacks = function() {
  1593. var prevSize,
  1594. callbacks = $.Callbacks(),
  1595. jqWindow = $(window),
  1596. resizeEventHandlerAttached = false,
  1597. originalCallbacksAdd = callbacks.add,
  1598. originalCallbacksRemove = callbacks.remove;
  1599. var formatSize = function() {
  1600. return [jqWindow.width(), jqWindow.height()].join()
  1601. };
  1602. var handleResize = function() {
  1603. var now = formatSize();
  1604. if (now === prevSize)
  1605. return;
  1606. prevSize = now;
  1607. setTimeout(callbacks.fire)
  1608. };
  1609. prevSize = formatSize();
  1610. callbacks.add = function() {
  1611. var result = originalCallbacksAdd.apply(callbacks, arguments);
  1612. if (!resizeEventHandlerAttached && callbacks.has()) {
  1613. jqWindow.on("resize", handleResize);
  1614. resizeEventHandlerAttached = true
  1615. }
  1616. return result
  1617. };
  1618. callbacks.remove = function() {
  1619. var result = originalCallbacksRemove.apply(callbacks, arguments);
  1620. if (!callbacks.has() && resizeEventHandlerAttached) {
  1621. jqWindow.off("resize", handleResize);
  1622. resizeEventHandlerAttached = false
  1623. }
  1624. return result
  1625. };
  1626. return callbacks
  1627. }();
  1628. var resetActiveElement = function() {
  1629. var activeElement = document.activeElement;
  1630. if (activeElement && activeElement !== document.body && activeElement.blur)
  1631. activeElement.blur()
  1632. };
  1633. var createMarkupFromString = function(str) {
  1634. var tempElement = $("<div />");
  1635. if (window.WinJS)
  1636. WinJS.Utilities.setInnerHTMLUnsafe(tempElement.get(0), str);
  1637. else
  1638. tempElement.append(str);
  1639. return tempElement.contents()
  1640. };
  1641. var initMobileViewport = function(options) {
  1642. options = $.extend({}, options);
  1643. var device = DX.devices.current();
  1644. var realDevice = DX.devices.real();
  1645. var allowZoom = options.allowZoom,
  1646. allowPan = options.allowPan,
  1647. allowSelection = "allowSelection" in options ? options.allowSelection : device.platform === "generic";
  1648. var metaSelector = "meta[name=viewport]";
  1649. if (!$(metaSelector).length)
  1650. $("<meta />").attr("name", "viewport").appendTo("head");
  1651. var metaVerbs = ["width=device-width"],
  1652. msTouchVerbs = [];
  1653. if (allowZoom)
  1654. msTouchVerbs.push("pinch-zoom");
  1655. else
  1656. metaVerbs.push("initial-scale=1.0", "maximum-scale=1.0, user-scalable=no");
  1657. if (allowPan)
  1658. msTouchVerbs.push("pan-x", "pan-y");
  1659. if (!allowPan && !allowZoom)
  1660. $("html, body").css({
  1661. "-ms-content-zooming": "none",
  1662. "-ms-user-select": "none",
  1663. overflow: "hidden"
  1664. });
  1665. else
  1666. $("html").css("-ms-overflow-style", "-ms-autohiding-scrollbar");
  1667. if (!allowSelection && DX.support.supportProp("user-select"))
  1668. $(".dx-viewport").css(DX.support.styleProp("user-select"), "none");
  1669. $(metaSelector).attr("content", metaVerbs.join());
  1670. $("html").css("-ms-touch-action", msTouchVerbs.join(" ") || "none");
  1671. if (DX.support.touch)
  1672. $(document).off(".dxInitMobileViewport").on("dxpointermove.dxInitMobileViewport", function(e) {
  1673. var count = e.pointers.length,
  1674. isTouchEvent = e.pointerType === "touch",
  1675. zoomDisabled = !allowZoom && count > 1,
  1676. panDisabled = !allowPan && count === 1 && !e.isScrollingEvent;
  1677. if (isTouchEvent && (zoomDisabled || panDisabled))
  1678. e.preventDefault()
  1679. });
  1680. realDevice = DX.devices.real();
  1681. if (realDevice.ios) {
  1682. var isPhoneGap = document.location.protocol === "file:";
  1683. if (!isPhoneGap)
  1684. windowResizeCallbacks.add(function() {
  1685. var windowWidth = $(window).width();
  1686. $("body").width(windowWidth)
  1687. })
  1688. }
  1689. if (realDevice.android)
  1690. windowResizeCallbacks.add(function() {
  1691. document.activeElement.scrollIntoViewIfNeeded()
  1692. })
  1693. };
  1694. var triggerVisibilityChangeEvent = function(eventName) {
  1695. var VISIBILITY_CHANGE_SELECTOR = ".dx-visibility-change-handler";
  1696. return function(element) {
  1697. var $element = $(element || "body");
  1698. var $changeHandlers = $element.find(VISIBILITY_CHANGE_SELECTOR).add($element.filter(VISIBILITY_CHANGE_SELECTOR));
  1699. $changeHandlers.each(function() {
  1700. $(this).triggerHandler(eventName)
  1701. })
  1702. }
  1703. };
  1704. var uniqueId = function() {
  1705. var counter = 0;
  1706. return function(prefix) {
  1707. return (prefix || "") + counter++
  1708. }
  1709. }();
  1710. DX.dataOptionsAttributeName = "data-options";
  1711. var getElementOptions = function(element) {
  1712. var optionsString = $(element).attr(DX.dataOptionsAttributeName),
  1713. result;
  1714. if ($.trim(optionsString).charAt(0) !== "{")
  1715. optionsString = "{" + optionsString + "}";
  1716. try {
  1717. result = new Function("return " + optionsString)()
  1718. }
  1719. catch(ex) {
  1720. throw DX.Error("E3018", ex, optionsString);
  1721. }
  1722. return result
  1723. };
  1724. var createComponents = function(elements, componentTypes) {
  1725. var result = [],
  1726. selector = "[" + DX.dataOptionsAttributeName + "]";
  1727. elements.find(selector).addBack(selector).each(function(index, element) {
  1728. var $element = $(element),
  1729. options = getElementOptions(element);
  1730. for (var componentName in options)
  1731. if (!componentTypes || $.inArray(componentName, componentTypes) > -1)
  1732. if ($element[componentName]) {
  1733. $element[componentName](options[componentName]);
  1734. result.push($element[componentName]("instance"))
  1735. }
  1736. });
  1737. return result
  1738. };
  1739. var normalizeTemplateElement = function(element) {
  1740. var $element = DX.utils.isDefined(element) && (element.nodeType || element.jquery) ? $(element) : $("<div>").html(element).contents();
  1741. if ($element.length === 1 && $element.is("script"))
  1742. $element = normalizeTemplateElement(element.html());
  1743. return $element
  1744. };
  1745. var clearSelection = function() {
  1746. if (window.getSelection) {
  1747. if (window.getSelection().empty)
  1748. window.getSelection().empty();
  1749. else if (window.getSelection().removeAllRanges)
  1750. window.getSelection().removeAllRanges()
  1751. }
  1752. else if (document.selection)
  1753. document.selection.empty()
  1754. };
  1755. var closestCommonParent = function(startTarget, endTarget) {
  1756. var $startParents = $(startTarget).parents().addBack(),
  1757. $endParents = $(endTarget).parents().addBack(),
  1758. startingParent = Math.min($startParents.length, $endParents.length) - 1;
  1759. for (var i = startingParent; i >= 0; i--)
  1760. if ($startParents.eq(i).is($endParents.eq(i)))
  1761. return $startParents.get(i)
  1762. };
  1763. var toggleAttr = function($target, attr, value) {
  1764. value ? $target.attr(attr, value) : $target.removeAttr(attr)
  1765. };
  1766. var clipboardText = function(event, text) {
  1767. var clipboard = event.originalEvent && event.originalEvent.clipboardData || window.clipboardData;
  1768. if (arguments.length === 1)
  1769. return clipboard && clipboard.getData("Text");
  1770. clipboard && clipboard.setData("Text", text)
  1771. };
  1772. $.extend(DX.utils, {
  1773. windowResizeCallbacks: windowResizeCallbacks,
  1774. resetActiveElement: resetActiveElement,
  1775. createMarkupFromString: createMarkupFromString,
  1776. triggerShownEvent: triggerVisibilityChangeEvent("dxshown"),
  1777. triggerHidingEvent: triggerVisibilityChangeEvent("dxhiding"),
  1778. initMobileViewport: initMobileViewport,
  1779. getElementOptions: getElementOptions,
  1780. createComponents: createComponents,
  1781. normalizeTemplateElement: normalizeTemplateElement,
  1782. clearSelection: clearSelection,
  1783. uniqueId: uniqueId,
  1784. closestCommonParent: closestCommonParent,
  1785. clipboardText: clipboardText,
  1786. toggleAttr: toggleAttr
  1787. })
  1788. })(jQuery, DevExpress);
  1789. /*! Module core, file utils.caret.js */
  1790. (function($, DX, undefined) {
  1791. var getCaret = function(input) {
  1792. if (isObsoleteBrowser(input))
  1793. return getCaretForObsoleteBrowser(input);
  1794. return {
  1795. start: input.selectionStart,
  1796. end: input.selectionEnd
  1797. }
  1798. };
  1799. var setCaret = function(input, position) {
  1800. if (isObsoleteBrowser(input)) {
  1801. setCaretForObsoleteBrowser(input, position);
  1802. return
  1803. }
  1804. if (!$.contains(document, input))
  1805. return;
  1806. input.selectionStart = position.start;
  1807. input.selectionEnd = position.end
  1808. };
  1809. var isObsoleteBrowser = function(input) {
  1810. return !input.setSelectionRange
  1811. };
  1812. var getCaretForObsoleteBrowser = function(input) {
  1813. var range = document.selection.createRange();
  1814. var rangeCopy = range.duplicate();
  1815. range.move('character', -input.value.length);
  1816. range.setEndPoint('EndToStart', rangeCopy);
  1817. return {
  1818. start: range.text.length,
  1819. end: range.text.length + rangeCopy.text.length
  1820. }
  1821. };
  1822. var setCaretForObsoleteBrowser = function(input, position) {
  1823. var range = input.createTextRange();
  1824. range.collapse(true);
  1825. range.moveStart("character", position.start);
  1826. range.moveEnd("character", position.end - position.start);
  1827. range.select()
  1828. };
  1829. var caret = function(input, position) {
  1830. input = $(input).get(0);
  1831. if (!DX.utils.isDefined(position))
  1832. return getCaret(input);
  1833. setCaret(input, position)
  1834. };
  1835. $.extend(DX.utils, {caret: caret})
  1836. })(jQuery, DevExpress);
  1837. /*! Module core, file utils.graphics.js */
  1838. (function($, DX, undefined) {
  1839. var _utils = DX.utils,
  1840. isFunction = _utils.isFunction,
  1841. _inArray = $.inArray,
  1842. isDefined = _utils.isDefined;
  1843. var processSeriesTemplate = function(seriesTemplate, items) {
  1844. var customizeSeries = isFunction(seriesTemplate.customizeSeries) ? seriesTemplate.customizeSeries : $.noop,
  1845. nameField = seriesTemplate.nameField || 'series',
  1846. generatedSeries = {},
  1847. seriesOrder = [],
  1848. series;
  1849. for (var i = 0, length = items.length; i < length; i++) {
  1850. var data = items[i];
  1851. if (nameField in data) {
  1852. series = generatedSeries[data[nameField]];
  1853. if (!series) {
  1854. series = generatedSeries[data[nameField]] = {
  1855. name: data[nameField],
  1856. data: []
  1857. };
  1858. seriesOrder.push(series.name)
  1859. }
  1860. series.data.push(data)
  1861. }
  1862. }
  1863. return $.map(seriesOrder, function(orderedName) {
  1864. var group = generatedSeries[orderedName],
  1865. seriesOptions = customizeSeries.call(null, group.name);
  1866. return $.extend(group, seriesOptions)
  1867. })
  1868. };
  1869. var getCategoriesInfo = function(categories, startValue, endValue) {
  1870. if (!(categories && categories.length > 0))
  1871. return {};
  1872. startValue = isDefined(startValue) ? startValue : categories[0];
  1873. endValue = isDefined(endValue) ? endValue : categories[categories.length - 1];
  1874. var categoriesValue = $.map(categories, function(category) {
  1875. return category && category.valueOf()
  1876. }),
  1877. visibleCategories = [],
  1878. indexStartValue = isDefined(startValue) ? _inArray(startValue.valueOf(), categoriesValue) : 0,
  1879. indexEndValue = isDefined(endValue) ? _inArray(endValue.valueOf(), categoriesValue) : categories.length - 1,
  1880. swapBuf,
  1881. hasVisibleCategories,
  1882. inverted = false,
  1883. visibleCategoriesLen;
  1884. indexStartValue < 0 && (indexStartValue = 0);
  1885. indexEndValue < 0 && (indexEndValue = categories.length - 1);
  1886. if (indexEndValue < indexStartValue) {
  1887. swapBuf = indexEndValue;
  1888. indexEndValue = indexStartValue;
  1889. indexStartValue = swapBuf;
  1890. inverted = true
  1891. }
  1892. visibleCategories = categories.slice(indexStartValue, indexEndValue + 1);
  1893. visibleCategoriesLen = visibleCategories.length;
  1894. hasVisibleCategories = visibleCategoriesLen > 0;
  1895. return {
  1896. categories: hasVisibleCategories ? visibleCategories : null,
  1897. start: hasVisibleCategories ? visibleCategories[inverted ? visibleCategoriesLen - 1 : 0] : null,
  1898. end: hasVisibleCategories ? visibleCategories[inverted ? 0 : visibleCategoriesLen - 1] : null,
  1899. inverted: inverted
  1900. }
  1901. };
  1902. $.extend(_utils, {
  1903. processSeriesTemplate: processSeriesTemplate,
  1904. getCategoriesInfo: getCategoriesInfo
  1905. })
  1906. })(jQuery, DevExpress);
  1907. /*! Module core, file utils.arrays.js */
  1908. (function($, DX, undefined) {
  1909. var isEmptyArray = function(entity) {
  1910. return $.isArray(entity) && !entity.length
  1911. };
  1912. var wrapToArray = function(entity) {
  1913. return $.isArray(entity) ? entity : [entity]
  1914. };
  1915. var removeDublicates = function(from, what) {
  1916. if (!$.isArray(from) || from.length === 0)
  1917. return [];
  1918. if (!$.isArray(what) || what.length === 0)
  1919. return from.slice();
  1920. var result = [];
  1921. $.each(from, function(_, value) {
  1922. var bIndex = $.inArray(value, what);
  1923. if (bIndex === -1)
  1924. result.push(value)
  1925. });
  1926. return result
  1927. };
  1928. $.extend(DX.utils, {
  1929. isEmptyArray: isEmptyArray,
  1930. wrapToArray: wrapToArray,
  1931. removeDublicates: removeDublicates
  1932. })
  1933. })(jQuery, DevExpress);
  1934. /*! Module core, file devices.js */
  1935. (function($, DX, undefined) {
  1936. var KNOWN_UA_TABLE = {
  1937. iPhone: "iPhone",
  1938. iPhone5: "iPhone",
  1939. iPhone6: "iPhone",
  1940. iPhone6plus: "iPhone",
  1941. iPad: "iPad",
  1942. iPadMini: "iPad Mini",
  1943. androidPhone: "Android Mobile",
  1944. androidTablet: "Android",
  1945. win8: "MSAppHost",
  1946. win8Phone: "Windows Phone 8",
  1947. msSurface: "MSIE ARM Tablet PC",
  1948. desktop: "desktop"
  1949. };
  1950. var DEFAULT_DEVICE = {
  1951. deviceType: "",
  1952. platform: "",
  1953. version: [],
  1954. phone: false,
  1955. tablet: false,
  1956. android: false,
  1957. ios: false,
  1958. win8: false,
  1959. generic: false,
  1960. grade: "A",
  1961. mac: false
  1962. };
  1963. $.extend(DEFAULT_DEVICE, {
  1964. platform: "generic",
  1965. deviceType: "desktop",
  1966. generic: true
  1967. });
  1968. var uaParsers = {
  1969. win8: function(userAgent) {
  1970. var isPhone = /windows phone/i.test(userAgent) || userAgent.match(/WPDesktop/),
  1971. isTablet = !isPhone && /arm(.*)trident/i.test(userAgent),
  1972. isDesktop = !isPhone && !isTablet && /msapphost/i.test(userAgent);
  1973. if (!(isPhone || isTablet || isDesktop))
  1974. return;
  1975. var matches = userAgent.match(/windows phone (\d+).(\d+)/i) || userAgent.match(/windows nt (\d+).(\d+)/i),
  1976. version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10)] : [];
  1977. return {
  1978. deviceType: isPhone ? "phone" : isTablet ? "tablet" : "desktop",
  1979. platform: "win8",
  1980. version: version,
  1981. grade: "A"
  1982. }
  1983. },
  1984. ios: function(userAgent) {
  1985. if (!/ip(hone|od|ad)/i.test(userAgent))
  1986. return;
  1987. var isPhone = /ip(hone|od)/i.test(userAgent),
  1988. matches = userAgent.match(/os (\d+)_(\d+)_?(\d+)?/i),
  1989. version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10), parseInt(matches[3] || 0, 10)] : [],
  1990. isIPhone4 = window.screen.height === 960 / 2,
  1991. grade = isIPhone4 ? "B" : "A";
  1992. return {
  1993. deviceType: isPhone ? "phone" : "tablet",
  1994. platform: "ios",
  1995. version: version,
  1996. grade: grade
  1997. }
  1998. },
  1999. android: function(userAgent) {
  2000. if (!/android|htc_|silk/i.test(userAgent))
  2001. return;
  2002. var isPhone = /mobile/i.test(userAgent),
  2003. matches = userAgent.match(/android (\d+)\.(\d+)\.?(\d+)?/i),
  2004. version = matches ? [parseInt(matches[1], 10), parseInt(matches[2], 10), parseInt(matches[3] || 0, 10)] : [],
  2005. worseThan4_4 = version.length > 1 && (version[0] < 4 || version[0] === 4 && version[1] < 4),
  2006. grade = worseThan4_4 ? "B" : "A";
  2007. return {
  2008. deviceType: isPhone ? "phone" : "tablet",
  2009. platform: "android",
  2010. version: version,
  2011. grade: grade
  2012. }
  2013. }
  2014. };
  2015. DX.Devices = DX.Class.inherit({
  2016. ctor: function(options) {
  2017. this._window = options && options.window || window;
  2018. this._realDevice = this._getDevice();
  2019. this._currentDevice = undefined;
  2020. this._currentOrientation = undefined;
  2021. this.orientationChanged = $.Callbacks();
  2022. this._callbacksToEvents("Devices", ["orientationChanged"]);
  2023. this._recalculateOrientation();
  2024. DX.utils.windowResizeCallbacks.add($.proxy(this._recalculateOrientation, this))
  2025. },
  2026. current: function(deviceOrName) {
  2027. if (deviceOrName) {
  2028. this._currentDevice = this._getDevice(deviceOrName);
  2029. this._forced = true;
  2030. DX.ui.themes.init({_autoInit: true})
  2031. }
  2032. else {
  2033. if (!this._currentDevice) {
  2034. deviceOrName = undefined;
  2035. try {
  2036. deviceOrName = this._getDeviceOrNameFromWindowScope()
  2037. }
  2038. catch(e) {
  2039. deviceOrName = this._getDeviceNameFromSessionStorage()
  2040. }
  2041. finally {
  2042. if (!deviceOrName)
  2043. deviceOrName = this._getDeviceNameFromSessionStorage();
  2044. if (deviceOrName)
  2045. this._forced = true
  2046. }
  2047. this._currentDevice = this._getDevice(deviceOrName)
  2048. }
  2049. return this._currentDevice
  2050. }
  2051. },
  2052. real: function() {
  2053. var forceDevice = arguments[0];
  2054. if ($.isPlainObject(forceDevice)) {
  2055. $.extend(this._realDevice, forceDevice);
  2056. return
  2057. }
  2058. return $.extend({}, this._realDevice)
  2059. },
  2060. orientation: function() {
  2061. return this._currentOrientation
  2062. },
  2063. isForced: function() {
  2064. return this._forced
  2065. },
  2066. isRippleEmulator: function() {
  2067. return !!this._window.tinyHippos
  2068. },
  2069. _getCssClasses: function(device) {
  2070. var result = [];
  2071. var realDevice = this._realDevice;
  2072. device = device || this.current();
  2073. if (device.deviceType) {
  2074. result.push("dx-device-" + device.deviceType);
  2075. if (device.deviceType !== "desktop")
  2076. result.push("dx-device-mobile")
  2077. }
  2078. result.push("dx-device-" + realDevice.platform);
  2079. if (realDevice.version && realDevice.version.length)
  2080. result.push("dx-device-" + realDevice.platform + "-" + realDevice.version[0]);
  2081. if (DX.devices.isSimulator())
  2082. result.push("dx-simulator");
  2083. if (DX.rtlEnabled)
  2084. result.push("dx-rtl");
  2085. return result
  2086. },
  2087. attachCssClasses: function(element, device) {
  2088. this._deviceClasses = this._getCssClasses(device).join(" ");
  2089. $(element).addClass(this._deviceClasses)
  2090. },
  2091. detachCssClasses: function(element) {
  2092. $(element).removeClass(this._deviceClasses)
  2093. },
  2094. isSimulator: function() {
  2095. try {
  2096. return this._isSimulator || this._window.top !== this._window.self && this._window.top["dx-force-device"] || this.isRippleEmulator()
  2097. }
  2098. catch(e) {
  2099. return false
  2100. }
  2101. },
  2102. forceSimulator: function() {
  2103. this._isSimulator = true
  2104. },
  2105. _getDevice: function(deviceName) {
  2106. if (deviceName === "genericPhone")
  2107. deviceName = {
  2108. deviceType: "phone",
  2109. platform: "generic",
  2110. generic: true
  2111. };
  2112. if ($.isPlainObject(deviceName))
  2113. return this._fromConfig(deviceName);
  2114. else {
  2115. var ua;
  2116. if (deviceName) {
  2117. ua = KNOWN_UA_TABLE[deviceName];
  2118. if (!ua)
  2119. throw DX.Error("E0005");
  2120. }
  2121. else
  2122. ua = navigator.userAgent;
  2123. return this._fromUA(ua)
  2124. }
  2125. },
  2126. _getDeviceOrNameFromWindowScope: function() {
  2127. var result;
  2128. if (this._window.top["dx-force-device-object"] || this._window.top["dx-force-device"])
  2129. result = this._window.top["dx-force-device-object"] || this._window.top["dx-force-device"];
  2130. return result
  2131. },
  2132. _getDeviceNameFromSessionStorage: function() {
  2133. var sessionStorage;
  2134. try {
  2135. sessionStorage = this._window.sessionStorage
  2136. }
  2137. catch(e) {}
  2138. if (!sessionStorage)
  2139. return;
  2140. var deviceOrName = sessionStorage.getItem("dx-force-device");
  2141. try {
  2142. return $.parseJSON(deviceOrName)
  2143. }
  2144. catch(ex) {
  2145. return deviceOrName
  2146. }
  2147. },
  2148. _fromConfig: function(config) {
  2149. var shortcuts = {
  2150. phone: config.deviceType === "phone",
  2151. tablet: config.deviceType === "tablet",
  2152. android: config.platform === "android",
  2153. ios: config.platform === "ios",
  2154. win8: config.platform === "win8",
  2155. generic: config.platform === "generic"
  2156. };
  2157. return $.extend({}, DEFAULT_DEVICE, this._currentDevice, shortcuts, config)
  2158. },
  2159. _fromUA: function(ua) {
  2160. var config;
  2161. $.each(uaParsers, function(platform, parser) {
  2162. config = parser(ua);
  2163. return !config
  2164. });
  2165. if (config)
  2166. return this._fromConfig(config);
  2167. var isMac = /(mac os)/.test(ua.toLowerCase()),
  2168. deviceWithOS = DEFAULT_DEVICE;
  2169. deviceWithOS.mac = isMac;
  2170. return deviceWithOS
  2171. },
  2172. _changeOrientation: function() {
  2173. var $window = $(this._window),
  2174. orientation = $window.height() > $window.width() ? "portrait" : "landscape";
  2175. if (this._currentOrientation === orientation)
  2176. return;
  2177. this._currentOrientation = orientation;
  2178. this.orientationChanged.fire({orientation: orientation})
  2179. },
  2180. _recalculateOrientation: function() {
  2181. var windowWidth = $(this._window).width();
  2182. if (this._currentWidth === windowWidth)
  2183. return;
  2184. this._currentWidth = windowWidth;
  2185. this._changeOrientation()
  2186. }
  2187. }).include(DX.EventsMixin);
  2188. DX.devices = new DX.Devices;
  2189. DX.viewPortChanged.add(function(viewPort, prevViewport) {
  2190. DX.devices.detachCssClasses(prevViewport);
  2191. DX.devices.attachCssClasses(viewPort)
  2192. })
  2193. })(jQuery, DevExpress);
  2194. /*! Module core, file browser.js */
  2195. (function($, DX, global, undefined) {
  2196. var webkitRegExp = /(webkit)[ \/]([\w.]+)/,
  2197. operaRegExp = /(opera)(?:.*version)?[ \/]([\w.]+)/,
  2198. ieRegExp = /(msie) (\d{1,2}\.\d)/,
  2199. ie11RegExp = /(trident).*rv:(\d{1,2}\.\d)/,
  2200. mozillaRegExp = /(mozilla)(?:.*? rv:([\w.]+))?/;
  2201. var ua = navigator.userAgent.toLowerCase();
  2202. var browser = function() {
  2203. var result = {},
  2204. matches = webkitRegExp.exec(ua) || operaRegExp.exec(ua) || ieRegExp.exec(ua) || ie11RegExp.exec(ua) || ua.indexOf("compatible") < 0 && mozillaRegExp.exec(ua) || [],
  2205. browserName = matches[1],
  2206. browserVersion = matches[2];
  2207. if (browserName === "trident")
  2208. browserName = "msie";
  2209. if (browserName) {
  2210. result[browserName] = true;
  2211. result.version = browserVersion
  2212. }
  2213. return result
  2214. }();
  2215. DX.browser = browser
  2216. })(jQuery, DevExpress, this);
  2217. /*! Module core, file support.js */
  2218. (function($, DX, window) {
  2219. var jsPrefixes = ["", "Webkit", "Moz", "O", "Ms"],
  2220. cssPrefixes = {
  2221. "": "",
  2222. Webkit: "-webkit-",
  2223. Moz: "-moz-",
  2224. O: "-o-",
  2225. ms: "-ms-"
  2226. },
  2227. styles = document.createElement("dx").style;
  2228. var transitionEndEventNames = {
  2229. webkitTransition: 'webkitTransitionEnd',
  2230. MozTransition: 'transitionend',
  2231. OTransition: 'oTransitionEnd',
  2232. msTransition: 'MsTransitionEnd',
  2233. transition: 'transitionend'
  2234. };
  2235. var forEachPrefixes = function(prop, callBack) {
  2236. prop = DX.inflector.camelize(prop, true);
  2237. var result;
  2238. for (var i = 0, cssPrefixesCount = jsPrefixes.length; i < cssPrefixesCount; i++) {
  2239. var jsPrefix = jsPrefixes[i];
  2240. var prefixedProp = jsPrefix + prop;
  2241. var lowerPrefixedProp = DX.inflector.camelize(prefixedProp);
  2242. result = callBack(lowerPrefixedProp, jsPrefix);
  2243. if (result === undefined)
  2244. result = callBack(prefixedProp, jsPrefix);
  2245. if (result !== undefined)
  2246. break
  2247. }
  2248. return result
  2249. };
  2250. var styleProp = function(prop) {
  2251. return forEachPrefixes(prop, function(specific) {
  2252. if (specific in styles)
  2253. return specific
  2254. })
  2255. };
  2256. var stylePropPrefix = function(prop) {
  2257. return forEachPrefixes(prop, function(specific, jsPrefix) {
  2258. if (specific in styles)
  2259. return cssPrefixes[jsPrefix]
  2260. })
  2261. };
  2262. var supportProp = function(prop) {
  2263. return !!styleProp(prop)
  2264. };
  2265. var isNativeScrollingSupported = function() {
  2266. var realDevice = DX.devices.real(),
  2267. realPlatform = realDevice.platform,
  2268. realVersion = realDevice.version,
  2269. isObsoleteAndroid = realVersion && realVersion[0] < 4 && realPlatform === "android",
  2270. isNativeScrollDevice = !isObsoleteAndroid && $.inArray(realPlatform, ["ios", "android", "win8"]) > -1 || realDevice.mac;
  2271. return isNativeScrollDevice
  2272. };
  2273. DX.support = {
  2274. touchEvents: "ontouchstart" in window,
  2275. touch: "ontouchstart" in window || !!window.navigator.msMaxTouchPoints,
  2276. pointer: window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
  2277. transform: supportProp("transform"),
  2278. transition: supportProp("transition"),
  2279. transitionEndEventName: transitionEndEventNames[styleProp("transition")],
  2280. animation: supportProp("animation"),
  2281. nativeScrolling: isNativeScrollingSupported(),
  2282. winJS: "WinJS" in window,
  2283. styleProp: styleProp,
  2284. stylePropPrefix: stylePropPrefix,
  2285. supportProp: supportProp,
  2286. hasKo: !!window.ko,
  2287. hasNg: !window.ko && !!window.angular,
  2288. inputType: function(type) {
  2289. if (type === "text")
  2290. return true;
  2291. var input = document.createElement("input");
  2292. try {
  2293. input.setAttribute("type", type);
  2294. input.value = "wrongValue";
  2295. return !input.value
  2296. }
  2297. catch(e) {
  2298. return false
  2299. }
  2300. }
  2301. }
  2302. })(jQuery, DevExpress, this);
  2303. /*! Module core, file position.js */
  2304. (function($, DX, undefined) {
  2305. var horzRe = /left|right/,
  2306. vertRe = /top|bottom/,
  2307. collisionRe = /fit|flip|none/;
  2308. var normalizeAlign = function(raw) {
  2309. var result = {
  2310. h: "center",
  2311. v: "center"
  2312. };
  2313. var pair = DX.utils.splitPair(raw);
  2314. if (pair)
  2315. $.each(pair, function() {
  2316. var w = String(this).toLowerCase();
  2317. if (horzRe.test(w))
  2318. result.h = w;
  2319. else if (vertRe.test(w))
  2320. result.v = w
  2321. });
  2322. return result
  2323. };
  2324. var normalizeOffset = function(raw) {
  2325. return DX.utils.stringPairToObject(raw)
  2326. };
  2327. var normalizeCollision = function(raw) {
  2328. var pair = DX.utils.splitPair(raw),
  2329. h = String(pair && pair[0]).toLowerCase(),
  2330. v = String(pair && pair[1]).toLowerCase();
  2331. if (!collisionRe.test(h))
  2332. h = "none";
  2333. if (!collisionRe.test(v))
  2334. v = h;
  2335. return {
  2336. h: h,
  2337. v: v
  2338. }
  2339. };
  2340. var getAlignFactor = function(align) {
  2341. switch (align) {
  2342. case"center":
  2343. return 0.5;
  2344. case"right":
  2345. case"bottom":
  2346. return 1;
  2347. default:
  2348. return 0
  2349. }
  2350. };
  2351. var inverseAlign = function(align) {
  2352. switch (align) {
  2353. case"left":
  2354. return "right";
  2355. case"right":
  2356. return "left";
  2357. case"top":
  2358. return "bottom";
  2359. case"bottom":
  2360. return "top";
  2361. default:
  2362. return align
  2363. }
  2364. };
  2365. var calculateOversize = function(data, bounds) {
  2366. var oversize = 0;
  2367. if (data.myLocation < bounds.min)
  2368. oversize += bounds.min - data.myLocation;
  2369. if (data.myLocation > bounds.max)
  2370. oversize += data.myLocation - bounds.max;
  2371. return oversize
  2372. };
  2373. var initMyLocation = function(data) {
  2374. data.myLocation = data.atLocation + getAlignFactor(data.atAlign) * data.atSize - getAlignFactor(data.myAlign) * data.mySize + data.offset
  2375. };
  2376. var decolliders = {
  2377. fit: function(data, bounds) {
  2378. var result = false;
  2379. if (data.myLocation > bounds.max) {
  2380. data.myLocation = bounds.max;
  2381. result = true
  2382. }
  2383. if (data.myLocation < bounds.min) {
  2384. data.myLocation = bounds.min;
  2385. result = true
  2386. }
  2387. return result
  2388. },
  2389. flip: function(data, bounds) {
  2390. if (data.myAlign === "center" && data.atAlign === "center")
  2391. return false;
  2392. if (data.myLocation < bounds.min || data.myLocation > bounds.max) {
  2393. var inverseData = $.extend({}, data, {
  2394. myAlign: inverseAlign(data.myAlign),
  2395. atAlign: inverseAlign(data.atAlign),
  2396. offset: -data.offset
  2397. });
  2398. initMyLocation(inverseData);
  2399. inverseData.oversize = calculateOversize(inverseData, bounds);
  2400. if (inverseData.myLocation >= bounds.min && inverseData.myLocation <= bounds.max || inverseData.myLocation > data.myLocation || inverseData.oversize < data.oversize) {
  2401. data.myLocation = inverseData.myLocation;
  2402. data.oversize = inverseData.oversize;
  2403. return true
  2404. }
  2405. }
  2406. return false
  2407. }
  2408. };
  2409. var scrollbarWidth;
  2410. var defaultPositionResult = {
  2411. h: {
  2412. location: 0,
  2413. flip: false,
  2414. fit: false,
  2415. oversize: 0
  2416. },
  2417. v: {
  2418. location: 0,
  2419. flip: false,
  2420. fit: false,
  2421. oversize: 0
  2422. }
  2423. };
  2424. var calculatePosition = function(what, options) {
  2425. var $what = $(what),
  2426. currentOffset = $what.offset(),
  2427. result = $.extend(true, {}, defaultPositionResult, {
  2428. h: {location: currentOffset.left},
  2429. v: {location: currentOffset.top}
  2430. });
  2431. if (!options)
  2432. return result;
  2433. var my = normalizeAlign(options.my),
  2434. at = normalizeAlign(options.at),
  2435. of = options.of || window,
  2436. offset = normalizeOffset(options.offset),
  2437. collision = normalizeCollision(options.collision),
  2438. boundary = options.boundary,
  2439. boundaryOffset = normalizeOffset(options.boundaryOffset);
  2440. var h = {
  2441. mySize: $what.outerWidth(),
  2442. myAlign: my.h,
  2443. atAlign: at.h,
  2444. offset: offset.h,
  2445. collision: collision.h,
  2446. boundaryOffset: boundaryOffset.h
  2447. };
  2448. var v = {
  2449. mySize: $what.outerHeight(),
  2450. myAlign: my.v,
  2451. atAlign: at.v,
  2452. offset: offset.v,
  2453. collision: collision.v,
  2454. boundaryOffset: boundaryOffset.v
  2455. };
  2456. if (of.preventDefault) {
  2457. h.atLocation = of.pageX;
  2458. v.atLocation = of.pageY;
  2459. h.atSize = 0;
  2460. v.atSize = 0
  2461. }
  2462. else {
  2463. of = $(of);
  2464. if ($.isWindow(of[0])) {
  2465. h.atLocation = of.scrollLeft();
  2466. v.atLocation = of.scrollTop();
  2467. h.atSize = of.width();
  2468. v.atSize = of.height()
  2469. }
  2470. else if (of[0].nodeType === 9) {
  2471. h.atLocation = 0;
  2472. v.atLocation = 0;
  2473. h.atSize = of.width();
  2474. v.atSize = of.height()
  2475. }
  2476. else {
  2477. var o = of.offset();
  2478. h.atLocation = o.left;
  2479. v.atLocation = o.top;
  2480. h.atSize = of.outerWidth();
  2481. v.atSize = of.outerHeight()
  2482. }
  2483. }
  2484. initMyLocation(h);
  2485. initMyLocation(v);
  2486. var bounds = function() {
  2487. var win = $(window),
  2488. windowWidth = win.width(),
  2489. windowHeight = win.height(),
  2490. left = win.scrollLeft(),
  2491. top = win.scrollTop(),
  2492. hScrollbar = document.width > document.documentElement.clientWidth,
  2493. vScrollbar = document.height > document.documentElement.clientHeight,
  2494. hZoomLevel = DX.support.touch ? document.documentElement.clientWidth / (vScrollbar ? windowWidth - scrollbarWidth : windowWidth) : 1,
  2495. vZoomLevel = DX.support.touch ? document.documentElement.clientHeight / (hScrollbar ? windowHeight - scrollbarWidth : windowHeight) : 1;
  2496. if (scrollbarWidth === undefined)
  2497. scrollbarWidth = calculateScrollbarWidth();
  2498. var boundaryWidth = windowWidth,
  2499. boundaryHeight = windowHeight;
  2500. if (boundary) {
  2501. var $boundary = $(boundary),
  2502. boundaryPosition = $boundary.offset();
  2503. left = boundaryPosition.left;
  2504. top = boundaryPosition.top;
  2505. boundaryWidth = $boundary.width();
  2506. boundaryHeight = $boundary.height()
  2507. }
  2508. return {
  2509. h: {
  2510. min: left + h.boundaryOffset,
  2511. max: left + boundaryWidth / hZoomLevel - h.mySize - h.boundaryOffset
  2512. },
  2513. v: {
  2514. min: top + v.boundaryOffset,
  2515. max: top + boundaryHeight / vZoomLevel - v.mySize - v.boundaryOffset
  2516. }
  2517. }
  2518. }();
  2519. h.oversize = calculateOversize(h, bounds.h);
  2520. v.oversize = calculateOversize(v, bounds.v);
  2521. if (decolliders[h.collision])
  2522. result.h[h.collision] = decolliders[h.collision](h, bounds.h);
  2523. if (decolliders[v.collision])
  2524. result.v[v.collision] = decolliders[v.collision](v, bounds.v);
  2525. var preciser = function(number) {
  2526. return options.precise ? number : Math.round(number)
  2527. };
  2528. $.extend(true, result, {
  2529. h: {
  2530. location: preciser(h.myLocation),
  2531. oversize: preciser(h.oversize)
  2532. },
  2533. v: {
  2534. location: preciser(v.myLocation),
  2535. oversize: preciser(v.oversize)
  2536. },
  2537. precise: options.precise
  2538. });
  2539. return result
  2540. };
  2541. var position = function(what, options) {
  2542. var $what = $(what);
  2543. if (!options)
  2544. return $what.offset();
  2545. DX.translator.resetPosition($what);
  2546. var offset = $what.offset(),
  2547. targetPosition = options.h && options.v ? options : calculatePosition($what, options);
  2548. var preciser = function(number) {
  2549. return options.precise ? number : Math.round(number)
  2550. };
  2551. DX.translator.move($what, {
  2552. left: targetPosition.h.location - preciser(offset.left),
  2553. top: targetPosition.v.location - preciser(offset.top)
  2554. });
  2555. return targetPosition
  2556. };
  2557. $.extend(DX, {
  2558. calculatePosition: calculatePosition,
  2559. position: position
  2560. });
  2561. $.extend(DX.position, {
  2562. inverseAlign: inverseAlign,
  2563. normalizeAlign: normalizeAlign
  2564. });
  2565. var calculateScrollbarWidth = function() {
  2566. var $scrollDiv = $("<div>").css({
  2567. width: 100,
  2568. height: 100,
  2569. overflow: "scroll",
  2570. position: "absolute",
  2571. top: -9999
  2572. }).appendTo($("body")),
  2573. result = $scrollDiv.get(0).offsetWidth - $scrollDiv.get(0).clientWidth;
  2574. $scrollDiv.remove();
  2575. return result
  2576. }
  2577. })(jQuery, DevExpress);
  2578. /*! Module core, file action.js */
  2579. (function($, DX, undefined) {
  2580. var actionExecutors = {};
  2581. var registerExecutor = function(name, executor) {
  2582. if ($.isPlainObject(name)) {
  2583. $.each(name, registerExecutor);
  2584. return
  2585. }
  2586. actionExecutors[name] = executor
  2587. };
  2588. var unregisterExecutor = function() {
  2589. var args = $.makeArray(arguments);
  2590. $.each(args, function() {
  2591. delete actionExecutors[this]
  2592. })
  2593. };
  2594. registerExecutor({
  2595. func: {execute: function(e) {
  2596. if ($.isFunction(e.action)) {
  2597. e.result = e.action.apply(e.context, e.args);
  2598. e.handled = true
  2599. }
  2600. }},
  2601. url: {execute: function(e) {
  2602. if (typeof e.action === "string" && e.action.charAt(0) !== "#")
  2603. document.location = e.action
  2604. }},
  2605. hash: {execute: function(e) {
  2606. if (typeof e.action === "string" && e.action.charAt(0) === "#")
  2607. document.location.hash = e.action
  2608. }}
  2609. });
  2610. var Action = DX.Class.inherit({
  2611. ctor: function(action, config) {
  2612. config = config || {};
  2613. this._action = action || $.noop;
  2614. this._context = config.context || window;
  2615. this._beforeExecute = config.beforeExecute || $.noop;
  2616. this._afterExecute = config.afterExecute || $.noop;
  2617. this._component = config.component;
  2618. this._excludeValidators = config.excludeValidators;
  2619. this._validatingTargetName = config.validatingTargetName
  2620. },
  2621. execute: function() {
  2622. var e = {
  2623. action: this._action,
  2624. args: Array.prototype.slice.call(arguments),
  2625. context: this._context,
  2626. component: this._component,
  2627. validatingTargetName: this._validatingTargetName,
  2628. cancel: false,
  2629. handled: false
  2630. };
  2631. if (!this._validateAction(e))
  2632. return;
  2633. this._beforeExecute.call(this._context, e);
  2634. if (e.cancel)
  2635. return;
  2636. var result = this._executeAction(e);
  2637. this._afterExecute.call(this._context, e);
  2638. return result
  2639. },
  2640. _validateAction: function(e) {
  2641. var excludeValidators = this._excludeValidators;
  2642. $.each(actionExecutors, function(name, executor) {
  2643. if (excludeValidators && $.inArray(name, excludeValidators) > -1)
  2644. return;
  2645. if (executor.validate)
  2646. executor.validate(e);
  2647. if (e.cancel)
  2648. return false
  2649. });
  2650. return !e.cancel
  2651. },
  2652. _executeAction: function(e) {
  2653. var result;
  2654. $.each(actionExecutors, function(index, executor) {
  2655. if (executor.execute)
  2656. executor.execute(e);
  2657. if (e.handled) {
  2658. result = e.result;
  2659. return false
  2660. }
  2661. });
  2662. return result
  2663. }
  2664. });
  2665. $.extend(DX, {
  2666. registerActionExecutor: registerExecutor,
  2667. unregisterActionExecutor: unregisterExecutor,
  2668. Action: Action
  2669. });
  2670. DX.__internals = {actionExecutors: actionExecutors}
  2671. })(jQuery, DevExpress);
  2672. /*! Module core, file translator.js */
  2673. (function($, DX, undefined) {
  2674. var support = DX.support,
  2675. TRANSLATOR_DATA_KEY = "dxTranslator",
  2676. TRANSFORM_MATRIX_REGEX = /matrix(3d)?\((.+?)\)/,
  2677. TRANSLATE_REGEX = /translate(?:3d)?\((.+?)\)/;
  2678. var locate = function($element) {
  2679. var translate = support.transform ? getTranslate($element) : getTranslateFallback($element);
  2680. return {
  2681. left: translate.x,
  2682. top: translate.y
  2683. }
  2684. };
  2685. var move = function($element, position) {
  2686. if (!support.transform) {
  2687. $element.css(position);
  2688. return
  2689. }
  2690. var translate = getTranslate($element),
  2691. left = position.left,
  2692. top = position.top;
  2693. if (left !== undefined)
  2694. translate.x = left || 0;
  2695. if (top !== undefined)
  2696. translate.y = top || 0;
  2697. $element.css({transform: getTranslateCss(translate)});
  2698. if (isPersentValue(left) || isPersentValue(top))
  2699. clearCache($element)
  2700. };
  2701. var isPersentValue = function(value) {
  2702. return $.type(value) === "string" && value[value.length - 1] === "%"
  2703. };
  2704. var getTranslateFallback = function($element) {
  2705. var result;
  2706. try {
  2707. var originalTop = $element.css("top"),
  2708. originalLeft = $element.css("left");
  2709. var position = $element.position();
  2710. $element.css({
  2711. transform: "none",
  2712. top: 0,
  2713. left: 0
  2714. });
  2715. clearCache($element);
  2716. var finalPosition = $element.position();
  2717. result = {
  2718. x: position.left - finalPosition.left || parseInt(originalLeft) || 0,
  2719. y: position.top - finalPosition.top || parseInt(originalTop) || 0
  2720. };
  2721. $element.css({
  2722. top: originalTop,
  2723. left: originalLeft
  2724. })
  2725. }
  2726. catch(e) {
  2727. result = {
  2728. x: 0,
  2729. y: 0
  2730. }
  2731. }
  2732. return result
  2733. };
  2734. var getTranslate = function($element) {
  2735. var result = $element.data(TRANSLATOR_DATA_KEY);
  2736. if (!result) {
  2737. var transformValue = $element.css("transform") || getTranslateCss({
  2738. x: 0,
  2739. y: 0
  2740. }),
  2741. matrix = transformValue.match(TRANSFORM_MATRIX_REGEX),
  2742. is3D = matrix && matrix[1];
  2743. if (matrix) {
  2744. matrix = matrix[2].split(",");
  2745. if (is3D === "3d")
  2746. matrix = matrix.slice(12, 15);
  2747. else {
  2748. matrix.push(0);
  2749. matrix = matrix.slice(4, 7)
  2750. }
  2751. }
  2752. else
  2753. matrix = [0, 0, 0];
  2754. result = {
  2755. x: parseFloat(matrix[0]),
  2756. y: parseFloat(matrix[1]),
  2757. z: parseFloat(matrix[2])
  2758. };
  2759. cacheTranslate($element, result)
  2760. }
  2761. return result
  2762. };
  2763. var cacheTranslate = function($element, translate) {
  2764. $element.data(TRANSLATOR_DATA_KEY, translate)
  2765. };
  2766. var clearCache = function($element) {
  2767. $element.removeData(TRANSLATOR_DATA_KEY)
  2768. };
  2769. var resetPosition = function($element) {
  2770. $element.css({
  2771. left: 0,
  2772. top: 0,
  2773. transform: "none"
  2774. });
  2775. clearCache($element)
  2776. };
  2777. var parseTranslate = function(translateString) {
  2778. var result = translateString.match(TRANSLATE_REGEX);
  2779. if (!result || !result[1])
  2780. return;
  2781. result = result[1].split(",");
  2782. result = {
  2783. x: parseFloat(result[0]),
  2784. y: parseFloat(result[1]),
  2785. z: parseFloat(result[2])
  2786. };
  2787. return result
  2788. };
  2789. var getTranslateCss = function(translate) {
  2790. translate.x = translate.x || 0;
  2791. translate.y = translate.y || 0;
  2792. var xValueString = isPersentValue(translate.x) ? translate.x : translate.x + "px";
  2793. var yValueString = isPersentValue(translate.y) ? translate.y : translate.y + "px";
  2794. return "translate(" + xValueString + ", " + yValueString + ")"
  2795. };
  2796. DX.translator = {
  2797. move: move,
  2798. locate: locate,
  2799. clearCache: clearCache,
  2800. parseTranslate: parseTranslate,
  2801. getTranslate: getTranslate,
  2802. getTranslateCss: getTranslateCss,
  2803. resetPosition: resetPosition
  2804. }
  2805. })(jQuery, DevExpress);
  2806. /*! Module core, file animationFrame.js */
  2807. (function($, DX, undefined) {
  2808. var FRAME_ANIMATION_STEP_TIME = 1000 / 60,
  2809. requestAnimationFrame = function(callback) {
  2810. return this.setTimeout(callback, FRAME_ANIMATION_STEP_TIME)
  2811. },
  2812. cancelAnimationFrame = function(requestID) {
  2813. this.clearTimeout(requestID)
  2814. },
  2815. nativeRequestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame,
  2816. nativeCancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame;
  2817. if (nativeRequestAnimationFrame && nativeCancelAnimationFrame) {
  2818. requestAnimationFrame = nativeRequestAnimationFrame;
  2819. cancelAnimationFrame = nativeCancelAnimationFrame
  2820. }
  2821. if (nativeRequestAnimationFrame && !nativeCancelAnimationFrame) {
  2822. var cancelledRequests = {};
  2823. requestAnimationFrame = function(callback) {
  2824. var requestId = nativeRequestAnimationFrame.call(window, function() {
  2825. try {
  2826. if (requestId in cancelledRequests)
  2827. return;
  2828. callback.apply(this, arguments)
  2829. }
  2830. finally {
  2831. delete cancelledRequests[requestId]
  2832. }
  2833. });
  2834. return requestId
  2835. };
  2836. cancelAnimationFrame = function(requestId) {
  2837. cancelledRequests[requestId] = true
  2838. }
  2839. }
  2840. requestAnimationFrame = $.proxy(requestAnimationFrame, window);
  2841. cancelAnimationFrame = $.proxy(cancelAnimationFrame, window);
  2842. $.extend(DX, {
  2843. requestAnimationFrame: requestAnimationFrame,
  2844. cancelAnimationFrame: cancelAnimationFrame
  2845. })
  2846. })(jQuery, DevExpress);
  2847. /*! Module core, file animator.js */
  2848. (function($, DX, undefined) {
  2849. DX.Animator = DX.Class.inherit({
  2850. ctor: function() {
  2851. this._finished = true;
  2852. this._stopped = false;
  2853. this._proxiedStepCore = $.proxy(this._stepCore, this)
  2854. },
  2855. start: function() {
  2856. this._stopped = false;
  2857. this._finished = false;
  2858. this._stepCore()
  2859. },
  2860. stop: function() {
  2861. this._stopped = true;
  2862. DX.cancelAnimationFrame(this._stepAnimationFrame)
  2863. },
  2864. _stepCore: function() {
  2865. if (this._isStopped()) {
  2866. this._stop();
  2867. return
  2868. }
  2869. if (this._isFinished()) {
  2870. this._finished = true;
  2871. this._complete();
  2872. return
  2873. }
  2874. this._step();
  2875. this._stepAnimationFrame = DX.requestAnimationFrame.call(window, this._proxiedStepCore)
  2876. },
  2877. _step: DX.abstract,
  2878. _isFinished: $.noop,
  2879. _stop: $.noop,
  2880. _complete: $.noop,
  2881. _isStopped: function() {
  2882. return this._stopped
  2883. },
  2884. inProgress: function() {
  2885. return !(this._stopped || this._finished)
  2886. }
  2887. })
  2888. })(jQuery, DevExpress);
  2889. /*! Module core, file fx.js */
  2890. (function($, DX, undefined) {
  2891. var translator = DX.translator,
  2892. support = DX.support,
  2893. transitionEndEventName = support.transitionEndEventName + ".dxFX",
  2894. removeEventName = "dxremove.dxFX";
  2895. var CSS_TRANSITION_EASING_REGEX = /cubic-bezier\((\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\)/,
  2896. RELATIVE_VALUE_REGEX = /^([+-])=(.*)/i,
  2897. ANIM_DATA_KEY = "dxAnimData",
  2898. ANIM_QUEUE_KEY = "dxAnimQueue",
  2899. TRANSFORM_PROP = "transform";
  2900. var TransitionAnimationStrategy = {
  2901. initAnimation: function($element, config) {
  2902. $element.css({transitionProperty: "none"});
  2903. if (typeof config.from === "string")
  2904. $element.addClass(config.from);
  2905. else
  2906. setProps($element, config.from)
  2907. },
  2908. animate: function($element, config) {
  2909. var that = this,
  2910. deferred = $.Deferred(),
  2911. cleanupWhen = config.cleanupWhen;
  2912. config.transitionAnimation = {finish: function() {
  2913. that._finishTransition($element, config);
  2914. if (cleanupWhen)
  2915. $.when(deferred, cleanupWhen).always(function() {
  2916. that._cleanup($element, config)
  2917. });
  2918. else
  2919. that._cleanup($element, config);
  2920. deferred.resolveWith($element, [config, $element])
  2921. }};
  2922. this._startAnimation($element, config);
  2923. this._completeAnimationCallback($element, config).done(function() {
  2924. config.transitionAnimation.finish()
  2925. });
  2926. if (!config.duration)
  2927. config.transitionAnimation.finish();
  2928. return deferred.promise()
  2929. },
  2930. _completeAnimationCallback: function($element, config) {
  2931. var startTime = $.now() + config.delay,
  2932. deferred = $.Deferred(),
  2933. transitionEndFired = $.Deferred(),
  2934. simulatedTransitionEndFired = $.Deferred(),
  2935. simulatedEndEventTimer,
  2936. waitForJSCompleteTimer;
  2937. config.transitionAnimation.cleanup = function() {
  2938. clearTimeout(simulatedEndEventTimer);
  2939. clearTimeout(waitForJSCompleteTimer)
  2940. };
  2941. $element.one(transitionEndEventName, function() {
  2942. if ($.now() - startTime >= config.duration)
  2943. transitionEndFired.reject()
  2944. }).off(removeEventName).on(removeEventName, function() {
  2945. config.transitionAnimation.cleanup()
  2946. });
  2947. waitForJSCompleteTimer = setTimeout(function() {
  2948. simulatedEndEventTimer = setTimeout(function() {
  2949. simulatedTransitionEndFired.reject()
  2950. }, config.duration + config.delay + DX.fx._simulatedTransitionEndDelay);
  2951. $.when(transitionEndFired, simulatedTransitionEndFired).fail($.proxy(function() {
  2952. deferred.resolve()
  2953. }, this))
  2954. });
  2955. return deferred.promise()
  2956. },
  2957. _startAnimation: function($element, config) {
  2958. $element.css("transform");
  2959. $element.css({
  2960. transitionProperty: "all",
  2961. transitionDelay: config.delay + "ms",
  2962. transitionDuration: config.duration + "ms",
  2963. transitionTimingFunction: config.easing
  2964. });
  2965. if (typeof config.to === "string")
  2966. $element.addClass(config.to);
  2967. else if (config.to)
  2968. setProps($element, config.to)
  2969. },
  2970. _finishTransition: function($element, config) {
  2971. $element.css("transition", "none")
  2972. },
  2973. _cleanup: function($element, config) {
  2974. $element.off(transitionEndEventName);
  2975. config.transitionAnimation.cleanup();
  2976. if (typeof config.from === "string") {
  2977. $element.removeClass(config.from);
  2978. $element.removeClass(config.to)
  2979. }
  2980. },
  2981. stop: function($element, config, jumpToEnd) {
  2982. if (!config)
  2983. return;
  2984. if (jumpToEnd)
  2985. config.transitionAnimation.finish();
  2986. else {
  2987. if ($.isPlainObject(config.to))
  2988. $.each(config.to, function(key) {
  2989. $element.css(key, $element.css(key))
  2990. });
  2991. this._finishTransition($element, config);
  2992. this._cleanup($element, config)
  2993. }
  2994. }
  2995. };
  2996. var FrameAnimationStrategy = {
  2997. initAnimation: function($element, config) {
  2998. setProps($element, config.from)
  2999. },
  3000. animate: function($element, config) {
  3001. var deferred = $.Deferred(),
  3002. that = this;
  3003. if (!config)
  3004. return deferred.reject().promise();
  3005. $.each(config.to, function(prop) {
  3006. if (config.from[prop] === undefined)
  3007. config.from[prop] = that._normalizeValue($element.css(prop))
  3008. });
  3009. if (config.to[TRANSFORM_PROP]) {
  3010. config.from[TRANSFORM_PROP] = that._parseTransform(config.from[TRANSFORM_PROP]);
  3011. config.to[TRANSFORM_PROP] = that._parseTransform(config.to[TRANSFORM_PROP])
  3012. }
  3013. config.frameAnimation = {
  3014. to: config.to,
  3015. from: config.from,
  3016. currentValue: config.from,
  3017. easing: convertTransitionTimingFuncToJQueryEasing(config.easing),
  3018. duration: config.duration,
  3019. startTime: (new Date).valueOf(),
  3020. finish: function() {
  3021. this.currentValue = this.to;
  3022. this.draw();
  3023. deferred.resolve()
  3024. },
  3025. draw: function() {
  3026. var currentValue = $.extend({}, this.currentValue);
  3027. if (currentValue[TRANSFORM_PROP])
  3028. currentValue[TRANSFORM_PROP] = $.map(currentValue[TRANSFORM_PROP], function(value, prop) {
  3029. if (prop === "translate")
  3030. return translator.getTranslateCss(value);
  3031. else if (prop === "scale")
  3032. return "scale(" + value + ")";
  3033. else if (prop.substr(0, prop.length - 1) === "rotate")
  3034. return prop + "(" + value + "deg)"
  3035. }).join(" ");
  3036. $element.css(currentValue)
  3037. }
  3038. };
  3039. if (config.delay) {
  3040. config.frameAnimation.startTime += config.delay;
  3041. config.frameAnimation.delayTimeout = setTimeout(function() {
  3042. that._animationStep($element, config)
  3043. }, config.delay)
  3044. }
  3045. else
  3046. that._animationStep($element, config);
  3047. return deferred.promise()
  3048. },
  3049. _parseTransform: function(transformString) {
  3050. var result = {};
  3051. $.each(transformString.match(/(\w|\d)+\([^\)]*\)\s*/g), function(i, part) {
  3052. var translateData = translator.parseTranslate(part),
  3053. scaleData = part.match(/scale\((.+?)\)/),
  3054. rotateData = part.match(/(rotate.)\((.+)deg\)/);
  3055. if (translateData)
  3056. result.translate = translateData;
  3057. if (scaleData && scaleData[1])
  3058. result.scale = parseFloat(scaleData[1]);
  3059. if (rotateData && rotateData[1])
  3060. result[rotateData[1]] = parseFloat(rotateData[2])
  3061. });
  3062. return result
  3063. },
  3064. stop: function($element, config, jumpToEnd) {
  3065. var frameAnimation = config && config.frameAnimation;
  3066. if (!frameAnimation)
  3067. return;
  3068. clearTimeout(frameAnimation.delayTimeout);
  3069. if (jumpToEnd)
  3070. frameAnimation.finish();
  3071. delete config.frameAnimation
  3072. },
  3073. _animationStep: function($element, config) {
  3074. var frameAnimation = config && config.frameAnimation;
  3075. if (!frameAnimation)
  3076. return;
  3077. var now = (new Date).valueOf();
  3078. if (now >= frameAnimation.startTime + frameAnimation.duration) {
  3079. frameAnimation.finish();
  3080. return
  3081. }
  3082. frameAnimation.currentValue = this._calcStepValue(frameAnimation, now - frameAnimation.startTime);
  3083. frameAnimation.draw();
  3084. DX.requestAnimationFrame($.proxy(function() {
  3085. this._animationStep($element, config)
  3086. }, this))
  3087. },
  3088. _calcStepValue: function(frameAnimation, currentDuration) {
  3089. var calcValueRecursively = function(from, to) {
  3090. var result = $.isArray(to) ? [] : {};
  3091. var calcEasedValue = function(propName) {
  3092. var x = currentDuration / frameAnimation.duration,
  3093. t = currentDuration,
  3094. b = 1 * from[propName],
  3095. c = to[propName] - from[propName],
  3096. d = frameAnimation.duration;
  3097. return $.easing[frameAnimation.easing](x, t, b, c, d)
  3098. };
  3099. $.each(to, function(propName, endPropValue) {
  3100. if (typeof endPropValue === "string" && parseFloat(endPropValue, 10) === false)
  3101. return true;
  3102. result[propName] = typeof endPropValue === "object" ? calcValueRecursively(from[propName], endPropValue) : calcEasedValue(propName)
  3103. });
  3104. return result
  3105. };
  3106. return calcValueRecursively(frameAnimation.from, frameAnimation.to)
  3107. },
  3108. _normalizeValue: function(value) {
  3109. var numericValue = parseFloat(value, 10);
  3110. if (numericValue === false)
  3111. return value;
  3112. return numericValue
  3113. }
  3114. };
  3115. var FallbackToNoAnimationStrategy = {
  3116. initAnimation: function($element, config){},
  3117. animate: function($element, config) {
  3118. return $.Deferred().resolve().promise()
  3119. }
  3120. };
  3121. var animationStrategies = {
  3122. transition: support.transition ? TransitionAnimationStrategy : FrameAnimationStrategy,
  3123. frame: FrameAnimationStrategy,
  3124. noAnimation: FallbackToNoAnimationStrategy
  3125. };
  3126. var getAnimationStrategy = function(config) {
  3127. config = config || {};
  3128. var strategy = config.strategy || "transition";
  3129. if (config.type === "css" && !support.transition)
  3130. strategy = "noAnimation";
  3131. return animationStrategies[strategy]
  3132. };
  3133. var TransitionTimingFuncMap = {
  3134. linear: "cubic-bezier(0, 0, 1, 1)",
  3135. ease: "cubic-bezier(0.25, 0.1, 0.25, 1)",
  3136. "ease-in": "cubic-bezier(0.42, 0, 1, 1)",
  3137. "ease-out": "cubic-bezier(0, 0, 0.58, 1)",
  3138. "ease-in-out": "cubic-bezier(0.42, 0, 0.58, 1)"
  3139. };
  3140. var convertTransitionTimingFuncToJQueryEasing = function(cssTransitionEasing) {
  3141. cssTransitionEasing = TransitionTimingFuncMap[cssTransitionEasing] || cssTransitionEasing;
  3142. var bezCoeffs = cssTransitionEasing.match(CSS_TRANSITION_EASING_REGEX);
  3143. if (!bezCoeffs)
  3144. return "linear";
  3145. bezCoeffs = bezCoeffs.slice(1, 5);
  3146. $.each(bezCoeffs, function(index, value) {
  3147. bezCoeffs[index] = parseFloat(value)
  3148. });
  3149. var easingName = "cubicbezier_" + bezCoeffs.join("_").replace(/\./g, "p");
  3150. if (!$.isFunction($.easing[easingName])) {
  3151. var polynomBezier = function(x1, y1, x2, y2) {
  3152. var Cx = 3 * x1,
  3153. Bx = 3 * (x2 - x1) - Cx,
  3154. Ax = 1 - Cx - Bx,
  3155. Cy = 3 * y1,
  3156. By = 3 * (y2 - y1) - Cy,
  3157. Ay = 1 - Cy - By;
  3158. var bezierX = function(t) {
  3159. return t * (Cx + t * (Bx + t * Ax))
  3160. };
  3161. var bezierY = function(t) {
  3162. return t * (Cy + t * (By + t * Ay))
  3163. };
  3164. var findXfor = function(t) {
  3165. var x = t,
  3166. i = 0,
  3167. z;
  3168. while (i < 14) {
  3169. z = bezierX(x) - t;
  3170. if (Math.abs(z) < 1e-3)
  3171. break;
  3172. x = x - z / derivativeX(x);
  3173. i++
  3174. }
  3175. return x
  3176. };
  3177. var derivativeX = function(t) {
  3178. return Cx + t * (2 * Bx + t * 3 * Ax)
  3179. };
  3180. return function(t) {
  3181. return bezierY(findXfor(t))
  3182. }
  3183. };
  3184. $.easing[easingName] = function(x, t, b, c, d) {
  3185. return c * polynomBezier(bezCoeffs[0], bezCoeffs[1], bezCoeffs[2], bezCoeffs[3])(t / d) + b
  3186. }
  3187. }
  3188. return easingName
  3189. };
  3190. var baseConfigValidator = function(config, animationType, validate, typeMessage) {
  3191. $.each(["from", "to"], function() {
  3192. if (!validate(config[this]))
  3193. throw DX.Error("E0010", animationType, this, typeMessage);
  3194. })
  3195. };
  3196. var isObjectConfigValidator = function(config, animationType) {
  3197. return baseConfigValidator(config, animationType, function(target) {
  3198. return $.isPlainObject(target)
  3199. }, "a plain object")
  3200. };
  3201. var isStringConfigValidator = function(config, animationType) {
  3202. return baseConfigValidator(config, animationType, function(target) {
  3203. return typeof target === "string"
  3204. }, "a string")
  3205. };
  3206. var CustomAnimationConfigurator = {setup: function($element, config){}};
  3207. var CssAnimationConfigurator = {
  3208. validateConfig: function(config) {
  3209. isStringConfigValidator(config, "css")
  3210. },
  3211. setup: function($element, config){}
  3212. };
  3213. var positionAliases = {
  3214. top: {
  3215. my: "bottom center",
  3216. at: "top center"
  3217. },
  3218. bottom: {
  3219. my: "top center",
  3220. at: "bottom center"
  3221. },
  3222. right: {
  3223. my: "left center",
  3224. at: "right center"
  3225. },
  3226. left: {
  3227. my: "right center",
  3228. at: "left center"
  3229. }
  3230. };
  3231. var SlideAnimationConfigurator = {
  3232. validateConfig: function(config) {
  3233. isObjectConfigValidator(config, "slide")
  3234. },
  3235. setup: function($element, config) {
  3236. var location = translator.locate($element);
  3237. if (config.type !== "slide") {
  3238. var positioningConfig = config.type === "slideIn" ? config.from : config.to;
  3239. positioningConfig.position = $.extend({of: window}, positionAliases[config.direction]);
  3240. setupPosition($element, positioningConfig)
  3241. }
  3242. this._setUpConfig(location, config.from);
  3243. this._setUpConfig(location, config.to);
  3244. translator.clearCache($element);
  3245. if (!support.transform && $element.css("position") === "static")
  3246. $element.css("position", "relative")
  3247. },
  3248. _setUpConfig: function(location, config) {
  3249. config.left = "left" in config ? config.left : "+=0";
  3250. config.top = "top" in config ? config.top : "+=0";
  3251. this._initNewPosition(location, config)
  3252. },
  3253. _initNewPosition: function(location, config) {
  3254. var position = {
  3255. left: config.left,
  3256. top: config.top
  3257. };
  3258. delete config.left;
  3259. delete config.top;
  3260. var relativeValue = this._getRelativeValue(position.left);
  3261. if (relativeValue !== undefined)
  3262. position.left = relativeValue + location.left;
  3263. else
  3264. config.left = 0;
  3265. relativeValue = this._getRelativeValue(position.top);
  3266. if (relativeValue !== undefined)
  3267. position.top = relativeValue + location.top;
  3268. else
  3269. config.top = 0;
  3270. var translate = {
  3271. x: 0,
  3272. y: 0
  3273. };
  3274. if (support.transform)
  3275. translate = {
  3276. x: position.left,
  3277. y: position.top
  3278. };
  3279. else {
  3280. config.left = position.left;
  3281. config.top = position.top
  3282. }
  3283. config[TRANSFORM_PROP] = translator.getTranslateCss(translate)
  3284. },
  3285. _getRelativeValue: function(value) {
  3286. var relativeValue;
  3287. if (typeof value === "string" && (relativeValue = RELATIVE_VALUE_REGEX.exec(value)))
  3288. return parseInt(relativeValue[1] + "1") * relativeValue[2]
  3289. }
  3290. };
  3291. var FadeAnimationConfigurator = {setup: function($element, config) {
  3292. var from = config.from,
  3293. fromOpacity = $.isPlainObject(from) ? config.skipElementInitialStyles ? 0 : $element.css("opacity") : String(from),
  3294. toOpacity;
  3295. switch (config.type) {
  3296. case"fadeIn":
  3297. toOpacity = 1;
  3298. break;
  3299. case"fadeOut":
  3300. toOpacity = 0;
  3301. break;
  3302. default:
  3303. toOpacity = String(config.to)
  3304. }
  3305. config.from = {
  3306. visibility: "visible",
  3307. opacity: fromOpacity
  3308. };
  3309. config.to = {opacity: toOpacity}
  3310. }};
  3311. var PopAnimationConfigurator = {
  3312. validateConfig: function(config) {
  3313. isObjectConfigValidator(config, "pop")
  3314. },
  3315. setup: function($element, config) {
  3316. var from = config.from,
  3317. to = config.to,
  3318. fromOpacity = "opacity" in from ? from.opacity : $element.css("opacity"),
  3319. toOpacity = "opacity" in to ? to.opacity : 1,
  3320. fromScale = "scale" in from ? from.scale : 0,
  3321. toScale = "scale" in to ? to.scale : 1;
  3322. config.from = {opacity: fromOpacity};
  3323. var translate = translator.getTranslate($element);
  3324. config.from[TRANSFORM_PROP] = this._getCssTransform(translate, fromScale);
  3325. config.to = {opacity: toOpacity};
  3326. config.to[TRANSFORM_PROP] = this._getCssTransform(translate, toScale)
  3327. },
  3328. _getCssTransform: function(translate, scale) {
  3329. return translator.getTranslateCss(translate) + "scale(" + scale + ")"
  3330. }
  3331. };
  3332. var animationConfigurators = {
  3333. custom: CustomAnimationConfigurator,
  3334. slide: SlideAnimationConfigurator,
  3335. slideIn: SlideAnimationConfigurator,
  3336. slideOut: SlideAnimationConfigurator,
  3337. fade: FadeAnimationConfigurator,
  3338. fadeIn: FadeAnimationConfigurator,
  3339. fadeOut: FadeAnimationConfigurator,
  3340. pop: PopAnimationConfigurator,
  3341. css: CssAnimationConfigurator
  3342. };
  3343. var getAnimationConfigurator = function(config) {
  3344. var result = animationConfigurators[config.type];
  3345. if (!result)
  3346. throw DX.Error("E0011", config.type);
  3347. return result
  3348. };
  3349. var defaultJSConfig = {
  3350. type: "custom",
  3351. from: {},
  3352. to: {},
  3353. duration: 400,
  3354. start: $.noop,
  3355. complete: $.noop,
  3356. easing: "ease",
  3357. delay: 0
  3358. },
  3359. defaultCssConfig = {
  3360. duration: 400,
  3361. easing: "ease",
  3362. delay: 0
  3363. };
  3364. var setupAnimationOnElement = function() {
  3365. var animation = this,
  3366. $element = animation.$element,
  3367. config = animation.config;
  3368. setupPosition($element, config.from);
  3369. setupPosition($element, config.to);
  3370. animation.configurator.setup($element, config);
  3371. $element.data(ANIM_DATA_KEY, animation);
  3372. if (DX.fx.off)
  3373. config.duration = 0;
  3374. animation.strategy.initAnimation($element, config);
  3375. if (config.start)
  3376. config.start.apply(this, [$element, config])
  3377. };
  3378. var startAnimationOnElement = function() {
  3379. var animation = this,
  3380. $element = animation.$element,
  3381. config = animation.config;
  3382. return animation.strategy.animate($element, config).done(function() {
  3383. $element.removeData(ANIM_DATA_KEY);
  3384. if (config.complete)
  3385. config.complete.apply(this, [$element, config]);
  3386. animation.deferred.resolveWith(this, [$element, config])
  3387. })
  3388. };
  3389. var createAnimation = function($element, initialConfig) {
  3390. var defaultConfig = initialConfig.type === "css" ? defaultCssConfig : defaultJSConfig,
  3391. config = $.extend(true, {}, defaultConfig, initialConfig),
  3392. configurator = getAnimationConfigurator(config),
  3393. strategy = getAnimationStrategy(config),
  3394. animation = {
  3395. $element: $element,
  3396. config: config,
  3397. configurator: configurator,
  3398. strategy: strategy,
  3399. setup: setupAnimationOnElement,
  3400. start: startAnimationOnElement,
  3401. deferred: $.Deferred()
  3402. };
  3403. if ($.isFunction(configurator.validateConfig))
  3404. configurator.validateConfig(config);
  3405. return animation
  3406. };
  3407. var animate = function(element, config) {
  3408. var $element = $(element);
  3409. if (!$element.length)
  3410. return $.Deferred().resolve().promise();
  3411. var animation = createAnimation($element, config);
  3412. pushInAnimationQueue($element, animation);
  3413. return animation.deferred.promise()
  3414. };
  3415. var pushInAnimationQueue = function($element, animation) {
  3416. var queueData = getAnimQueueData($element);
  3417. writeAnimQueueData($element, queueData);
  3418. queueData.push(animation);
  3419. if (!isAnimating($element))
  3420. shiftFromAnimationQueue($element, queueData)
  3421. };
  3422. var getAnimQueueData = function($element) {
  3423. return $element.data(ANIM_QUEUE_KEY) || []
  3424. };
  3425. var writeAnimQueueData = function($element, queueData) {
  3426. $element.data(ANIM_QUEUE_KEY, queueData)
  3427. };
  3428. var destroyAnimQueueData = function($element) {
  3429. $element.removeData(ANIM_QUEUE_KEY)
  3430. };
  3431. var isAnimating = function($element) {
  3432. return !!$element.data(ANIM_DATA_KEY)
  3433. };
  3434. var shiftFromAnimationQueue = function($element, queueData) {
  3435. queueData = getAnimQueueData($element);
  3436. if (!queueData.length)
  3437. return;
  3438. var animation = queueData.shift();
  3439. if (queueData.length === 0)
  3440. destroyAnimQueueData($element);
  3441. executeAnimation(animation).done(function() {
  3442. shiftFromAnimationQueue($element)
  3443. })
  3444. };
  3445. var executeAnimation = function(animation) {
  3446. animation.setup();
  3447. return animation.start()
  3448. };
  3449. var setupPosition = function($element, config) {
  3450. if (!config || !config.position)
  3451. return;
  3452. var position = DX.calculatePosition($element, config.position),
  3453. offset = $element.offset(),
  3454. currentPosition = $element.position();
  3455. $.extend(config, {
  3456. left: position.h.location - offset.left + currentPosition.left,
  3457. top: position.v.location - offset.top + currentPosition.top
  3458. });
  3459. delete config.position
  3460. };
  3461. var setProps = function($element, props) {
  3462. $.each(props, function(key, value) {
  3463. $element.css(key, value)
  3464. })
  3465. };
  3466. var stop = function(element, jumpToEnd) {
  3467. var $element = $(element),
  3468. queueData = getAnimQueueData($element);
  3469. $.each(queueData, function(_, animation) {
  3470. animation.config.duration = 0
  3471. });
  3472. if (!isAnimating($element))
  3473. shiftFromAnimationQueue($element, queueData);
  3474. var animation = $element.data(ANIM_DATA_KEY);
  3475. if (animation)
  3476. animation.strategy.stop($element, animation.config, jumpToEnd);
  3477. $element.removeData(ANIM_DATA_KEY);
  3478. destroyAnimQueueData($element)
  3479. };
  3480. DX.fx = {
  3481. off: false,
  3482. animationTypes: animationConfigurators,
  3483. animate: animate,
  3484. createAnimation: createAnimation,
  3485. isAnimating: isAnimating,
  3486. stop: stop,
  3487. _simulatedTransitionEndDelay: 100
  3488. };
  3489. DX.fx.__internals = {convertTransitionTimingFuncToJQueryEasing: convertTransitionTimingFuncToJQueryEasing}
  3490. })(jQuery, DevExpress);
  3491. /*! Module core, file dxProxyUrlFormatter.js */
  3492. (function($, DX, undefined) {
  3493. var location = window.location,
  3494. DXPROXY_HOST = "dxproxy.devexpress.com:8000",
  3495. IS_DXPROXY_ORIGIN = location.host === DXPROXY_HOST,
  3496. urlMapping = {};
  3497. var extractProxyAppId = function() {
  3498. return location.pathname.split("/")[1]
  3499. };
  3500. var urlFormatter = {
  3501. isProxyUsed: function() {
  3502. return IS_DXPROXY_ORIGIN
  3503. },
  3504. formatProxyUrl: function(localUrl) {
  3505. var urlData = DX.parseUrl(localUrl);
  3506. if (!/^(localhost$|127\.)/i.test(urlData.hostname))
  3507. return localUrl;
  3508. var proxyUrlPart = DXPROXY_HOST + "/" + extractProxyAppId() + "_" + urlData.port;
  3509. urlMapping[proxyUrlPart] = urlData.hostname + ":" + urlData.port;
  3510. var resultUrl = "http://" + proxyUrlPart + urlData.pathname + urlData.search;
  3511. return resultUrl
  3512. },
  3513. formatLocalUrl: function(proxyUrl) {
  3514. if (proxyUrl.indexOf(DXPROXY_HOST) < 0)
  3515. return proxyUrl;
  3516. var resultUrl = proxyUrl;
  3517. for (var proxyUrlPart in urlMapping)
  3518. if (urlMapping.hasOwnProperty(proxyUrlPart))
  3519. if (proxyUrl.indexOf(proxyUrlPart) >= 0) {
  3520. resultUrl = proxyUrl.replace(proxyUrlPart, urlMapping[proxyUrlPart]);
  3521. break
  3522. }
  3523. return resultUrl
  3524. }
  3525. };
  3526. DX._proxyUrlFormatter = urlFormatter
  3527. })(jQuery, DevExpress);
  3528. /*! Module core, file endpointSelector.js */
  3529. (function($, DX, undefined) {
  3530. var location = window.location,
  3531. IS_WINJS_ORIGIN = location.protocol === "ms-appx:",
  3532. IS_LOCAL_ORIGIN = isLocalHostName(location.hostname);
  3533. function isLocalHostName(url) {
  3534. return /^(localhost$|127\.)/i.test(url)
  3535. }
  3536. var EndpointSelector = DX.EndpointSelector = function(config) {
  3537. this.config = config
  3538. };
  3539. EndpointSelector.prototype = {urlFor: function(key) {
  3540. var bag = this.config[key];
  3541. if (!bag)
  3542. throw DX.Error("E0006");
  3543. if (DX._proxyUrlFormatter.isProxyUsed())
  3544. return DX._proxyUrlFormatter.formatProxyUrl(bag.local);
  3545. if (bag.production)
  3546. if (IS_WINJS_ORIGIN && !Debug.debuggerEnabled || !IS_WINJS_ORIGIN && !IS_LOCAL_ORIGIN)
  3547. return bag.production;
  3548. return bag.local
  3549. }}
  3550. })(jQuery, DevExpress);
  3551. /*! Module core, file formatHelper.js */
  3552. (function($, DX, undefined) {
  3553. var utils = DX.utils;
  3554. DX.NumericFormat = {
  3555. currency: 'C',
  3556. fixedpoint: 'N',
  3557. exponential: '',
  3558. percent: 'P',
  3559. decimal: 'D'
  3560. };
  3561. DX.LargeNumberFormatPostfixes = {
  3562. 1: 'K',
  3563. 2: 'M',
  3564. 3: 'B',
  3565. 4: 'T'
  3566. };
  3567. var MAX_LARGE_NUMBER_POWER = 4,
  3568. DECIMAL_BASE = 10;
  3569. DX.LargeNumberFormatPowers = {
  3570. largenumber: 'auto',
  3571. thousands: 1,
  3572. millions: 2,
  3573. billions: 3,
  3574. trillions: 4
  3575. };
  3576. DX.DateTimeFormat = {
  3577. longdate: 'D',
  3578. longtime: 'T',
  3579. monthandday: 'M',
  3580. monthandyear: 'Y',
  3581. quarterandyear: 'qq',
  3582. shortdate: 'd',
  3583. shorttime: 't',
  3584. millisecond: 'fff',
  3585. second: 'T',
  3586. minute: 't',
  3587. hour: 't',
  3588. day: 'dd',
  3589. week: 'dd',
  3590. month: 'MMMM',
  3591. quarter: 'qq',
  3592. year: 'yyyy',
  3593. longdatelongtime: 'D',
  3594. shortdateshorttime: 'd',
  3595. shortyear: 'yy'
  3596. };
  3597. DX.formatHelper = {
  3598. defaultQuarterFormat: 'Q{0}',
  3599. romanDigits: ['I', 'II', 'III', 'IV'],
  3600. _addFormatSeparator: function(format1, format2) {
  3601. var separator = ' ';
  3602. if (format2)
  3603. return format1 + separator + format2;
  3604. return format1
  3605. },
  3606. _getDateTimeFormatPattern: function(dateTimeFormat) {
  3607. return Globalize.findClosestCulture().calendar.patterns[DX.DateTimeFormat[dateTimeFormat.toLowerCase()]]
  3608. },
  3609. _isDateFormatContains: function(format) {
  3610. var result = false;
  3611. $.each(DX.DateTimeFormat, function(key) {
  3612. result = key === format.toLowerCase();
  3613. return !result
  3614. });
  3615. return result
  3616. },
  3617. getQuarter: function(month) {
  3618. return Math.floor(month / 3)
  3619. },
  3620. getFirstQuarterMonth: function(month) {
  3621. return this.getQuarter(month) * 3
  3622. },
  3623. _getQuarterString: function(date, format) {
  3624. var quarter = this.getQuarter(date.getMonth());
  3625. switch (format) {
  3626. case'q':
  3627. return this.romanDigits[quarter];
  3628. case'qq':
  3629. return utils.stringFormat(this.defaultQuarterFormat, this.romanDigits[quarter]);
  3630. case'Q':
  3631. return (quarter + 1).toString();
  3632. case'QQ':
  3633. return utils.stringFormat(this.defaultQuarterFormat, (quarter + 1).toString())
  3634. }
  3635. return ''
  3636. },
  3637. _formatCustomString: function(value, format) {
  3638. var regExp = /qq|q|QQ|Q/g,
  3639. quarterFormat,
  3640. result = '',
  3641. index = 0;
  3642. regExp.lastIndex = 0;
  3643. while (index < format.length) {
  3644. quarterFormat = regExp.exec(format);
  3645. if (!quarterFormat || quarterFormat.index > index)
  3646. result += Globalize.format(value, format.substring(index, quarterFormat ? quarterFormat.index : format.length));
  3647. if (quarterFormat) {
  3648. result += this._getQuarterString(value, quarterFormat[0]);
  3649. index = quarterFormat.index + quarterFormat[0].length
  3650. }
  3651. else
  3652. index = format.length
  3653. }
  3654. return result
  3655. },
  3656. _parseNumberFormatString: function(format) {
  3657. var formatList,
  3658. formatObject = {};
  3659. if (!format || typeof format !== 'string')
  3660. return;
  3661. formatList = format.toLowerCase().split(' ');
  3662. $.each(formatList, function(index, value) {
  3663. if (value in DX.NumericFormat)
  3664. formatObject.formatType = value;
  3665. else if (value in DX.LargeNumberFormatPowers)
  3666. formatObject.power = DX.LargeNumberFormatPowers[value]
  3667. });
  3668. if (formatObject.power && !formatObject.formatType)
  3669. formatObject.formatType = 'fixedpoint';
  3670. if (formatObject.formatType)
  3671. return formatObject
  3672. },
  3673. _calculateNumberPower: function(value, base, minPower, maxPower) {
  3674. var number = Math.abs(value);
  3675. var power = 0;
  3676. if (number > 1)
  3677. while (number && number >= base && (maxPower === undefined || power < maxPower)) {
  3678. power++;
  3679. number = number / base
  3680. }
  3681. else if (number > 0 && number < 1)
  3682. while (number < 1 && (minPower === undefined || power > minPower)) {
  3683. power--;
  3684. number = number * base
  3685. }
  3686. return power
  3687. },
  3688. _getNumberByPower: function(number, power, base) {
  3689. var result = number;
  3690. while (power > 0) {
  3691. result = result / base;
  3692. power--
  3693. }
  3694. while (power < 0) {
  3695. result = result * base;
  3696. power++
  3697. }
  3698. return result
  3699. },
  3700. _formatNumber: function(value, formatObject, precision) {
  3701. var powerPostfix;
  3702. if (formatObject.power === 'auto')
  3703. formatObject.power = this._calculateNumberPower(value, 1000, 0, MAX_LARGE_NUMBER_POWER);
  3704. if (formatObject.power)
  3705. value = this._getNumberByPower(value, formatObject.power, 1000);
  3706. powerPostfix = DX.LargeNumberFormatPostfixes[formatObject.power] || '';
  3707. return this._formatNumberCore(value, formatObject.formatType, precision) + powerPostfix
  3708. },
  3709. _formatNumberExponential: function(value, precision) {
  3710. var power = this._calculateNumberPower(value, DECIMAL_BASE),
  3711. number = this._getNumberByPower(value, power, DECIMAL_BASE),
  3712. powString;
  3713. precision = precision === undefined ? 1 : precision;
  3714. if (number.toFixed(precision || 0) >= DECIMAL_BASE) {
  3715. power++;
  3716. number = number / DECIMAL_BASE
  3717. }
  3718. powString = (power >= 0 ? '+' : '') + power.toString();
  3719. return this._formatNumberCore(number, 'fixedpoint', precision) + 'E' + powString
  3720. },
  3721. _formatNumberCore: function(value, format, precision) {
  3722. if (format === 'exponential')
  3723. return this._formatNumberExponential(value, precision);
  3724. else
  3725. return Globalize.format(value, DX.NumericFormat[format] + (utils.isNumber(precision) ? precision : 0))
  3726. },
  3727. _formatDate: function(date, format) {
  3728. var resultFormat = DX.DateTimeFormat[format.toLowerCase()];
  3729. format = format.toLowerCase();
  3730. if (format === 'quarterandyear')
  3731. resultFormat = this._getQuarterString(date, resultFormat) + ' yyyy';
  3732. if (format === 'quarter')
  3733. return this._getQuarterString(date, resultFormat);
  3734. if (format === 'longdatelongtime')
  3735. return this._formatDate(date, 'longdate') + ' ' + this._formatDate(date, 'longtime');
  3736. if (format === 'shortdateshorttime')
  3737. return this._formatDate(date, 'shortDate') + ' ' + this._formatDate(date, 'shortTime');
  3738. return Globalize.format(date, resultFormat)
  3739. },
  3740. format: function(value, format, precision) {
  3741. if ($.isPlainObject(format) && format.format)
  3742. if (format.dateType)
  3743. return this._formatDateEx(value, format);
  3744. else if (utils.isNumber(value) && isFinite(value))
  3745. return this._formatNumberEx(value, format);
  3746. return this._format(value, format, precision)
  3747. },
  3748. _format: function(value, format, precision) {
  3749. var numberFormatObject;
  3750. if (!utils.isString(format) || format === '' || !utils.isNumber(value) && !utils.isDate(value))
  3751. return utils.isDefined(value) ? value.toString() : '';
  3752. numberFormatObject = this._parseNumberFormatString(format);
  3753. if (utils.isNumber(value) && numberFormatObject)
  3754. return this._formatNumber(value, numberFormatObject, precision);
  3755. if (utils.isDate(value) && this._isDateFormatContains(format))
  3756. return this._formatDate(value, format);
  3757. if (!numberFormatObject && !this._isDateFormatContains(format))
  3758. return this._formatCustomString(value, format)
  3759. },
  3760. _formatNumberEx: function(value, formatInfo) {
  3761. var that = this,
  3762. numericFormatType = DX.NumericFormat[formatInfo.format.toLowerCase()],
  3763. numberFormat = Globalize.culture().numberFormat,
  3764. currencyFormat = formatInfo.currencyCulture && Globalize.cultures[formatInfo.currencyCulture] ? Globalize.cultures[formatInfo.currencyCulture].numberFormat.currency : numberFormat.currency,
  3765. percentFormat = numberFormat.percent,
  3766. formatSettings = that._getUnitFormatSettings(value, formatInfo),
  3767. unit = formatSettings.unit,
  3768. precision = formatSettings.precision,
  3769. showTrailingZeros = formatSettings.showTrailingZeros,
  3770. includeGroupSeparator = formatSettings.includeGroupSeparator,
  3771. groupSymbol = numberFormat[","],
  3772. floatingSymbol = numberFormat["."],
  3773. number,
  3774. isNegative,
  3775. pattern,
  3776. currentFormat,
  3777. regexParts = /n|\$|-|%/g,
  3778. result = "";
  3779. if (!utils.isDefined(value))
  3780. return '';
  3781. value = that._applyUnitToValue(value, unit);
  3782. number = Math.abs(value);
  3783. isNegative = value < 0;
  3784. switch (numericFormatType) {
  3785. case DX.NumericFormat.decimal:
  3786. pattern = "n";
  3787. number = Math[isNegative ? "ceil" : "floor"](number);
  3788. if (precision > 0) {
  3789. var str = "" + number;
  3790. for (var i = str.length; i < precision; i += 1)
  3791. str = "0" + str;
  3792. number = str
  3793. }
  3794. if (isNegative)
  3795. number = "-" + number;
  3796. break;
  3797. case DX.NumericFormat.fixedpoint:
  3798. currentFormat = numberFormat;
  3799. case DX.NumericFormat.currency:
  3800. currentFormat = currentFormat || currencyFormat;
  3801. case DX.NumericFormat.percent:
  3802. currentFormat = currentFormat || percentFormat;
  3803. pattern = isNegative ? currentFormat.pattern[0] : currentFormat.pattern[1] || "n";
  3804. number = Globalize.format(number * (numericFormatType === DX.NumericFormat.percent ? 100 : 1), "N" + precision);
  3805. if (!showTrailingZeros)
  3806. number = that._excludeTrailingZeros(number, floatingSymbol);
  3807. if (!includeGroupSeparator)
  3808. number = number.replace(new RegExp('\\' + groupSymbol, 'g'), '');
  3809. break;
  3810. case DX.NumericFormat.exponential:
  3811. return that._formatNumberExponential(value, precision);
  3812. default:
  3813. throw"Illegal numeric format: '" + numericFormatType + "'";
  3814. }
  3815. for (; ; ) {
  3816. var lastIndex = regexParts.lastIndex,
  3817. matches = regexParts.exec(pattern);
  3818. result += pattern.slice(lastIndex, matches ? matches.index : pattern.length);
  3819. if (matches)
  3820. switch (matches[0]) {
  3821. case"-":
  3822. if (/[1-9]/.test(number))
  3823. result += numberFormat["-"];
  3824. break;
  3825. case"$":
  3826. result += currencyFormat.symbol;
  3827. break;
  3828. case"%":
  3829. result += percentFormat.symbol;
  3830. break;
  3831. case"n":
  3832. result += number + unit;
  3833. break
  3834. }
  3835. else
  3836. break
  3837. }
  3838. return (formatInfo.plus && value > 0 ? "+" : '') + result
  3839. },
  3840. _excludeTrailingZeros: function(strValue, floatingSymbol) {
  3841. var floatingIndex = strValue.indexOf(floatingSymbol),
  3842. stopIndex,
  3843. i;
  3844. if (floatingIndex < 0)
  3845. return strValue;
  3846. stopIndex = strValue.length;
  3847. for (i = stopIndex - 1; i >= floatingIndex && (strValue[i] === '0' || i === floatingIndex); i--)
  3848. stopIndex--;
  3849. return strValue.substring(0, stopIndex)
  3850. },
  3851. _getUnitFormatSettings: function(value, formatInfo) {
  3852. var unit = formatInfo.unit || '',
  3853. precision = formatInfo.precision || 0,
  3854. includeGroupSeparator = formatInfo.includeGroupSeparator || false,
  3855. showTrailingZeros = formatInfo.showTrailingZeros === undefined ? true : formatInfo.showTrailingZeros,
  3856. significantDigits = formatInfo.significantDigits || 1,
  3857. absValue;
  3858. if (unit.toLowerCase() === 'auto') {
  3859. showTrailingZeros = false;
  3860. absValue = Math.abs(value);
  3861. if (significantDigits < 1)
  3862. significantDigits = 1;
  3863. if (absValue >= 1000000000) {
  3864. unit = 'B';
  3865. absValue /= 1000000000
  3866. }
  3867. else if (absValue >= 1000000) {
  3868. unit = 'M';
  3869. absValue /= 1000000
  3870. }
  3871. else if (absValue >= 1000) {
  3872. unit = 'K';
  3873. absValue /= 1000
  3874. }
  3875. else
  3876. unit = '';
  3877. if (absValue === 0)
  3878. precision = 0;
  3879. else if (absValue < 1) {
  3880. precision = significantDigits;
  3881. var smallValue = Math.pow(10, -significantDigits);
  3882. while (absValue < smallValue) {
  3883. smallValue /= 10;
  3884. precision++
  3885. }
  3886. }
  3887. else if (absValue >= 100)
  3888. precision = significantDigits - 3;
  3889. else if (absValue >= 10)
  3890. precision = significantDigits - 2;
  3891. else
  3892. precision = significantDigits - 1
  3893. }
  3894. if (precision < 0)
  3895. precision = 0;
  3896. return {
  3897. unit: unit,
  3898. precision: precision,
  3899. showTrailingZeros: showTrailingZeros,
  3900. includeGroupSeparator: includeGroupSeparator
  3901. }
  3902. },
  3903. _applyUnitToValue: function(value, unit) {
  3904. if (unit === 'B')
  3905. return value.toFixed(1) / 1000000000;
  3906. if (unit === 'M')
  3907. return value / 1000000;
  3908. if (unit === 'K')
  3909. return value / 1000;
  3910. return value
  3911. },
  3912. _formatDateEx: function(value, formatInfo) {
  3913. var that = this,
  3914. format = formatInfo.format,
  3915. dateType = formatInfo.dateType,
  3916. calendar = Globalize.culture().calendars.standard,
  3917. time,
  3918. index,
  3919. dateStr;
  3920. format = format.toLowerCase();
  3921. if (!utils.isDefined(value))
  3922. return '';
  3923. if (dateType !== 'num' || format === 'dayofweek')
  3924. switch (format) {
  3925. case'monthyear':
  3926. return that._formatDate(value, 'monthandyear');
  3927. case'quarteryear':
  3928. return that._getQuarterString(value, 'QQ') + ' ' + value.getFullYear();
  3929. case'daymonthyear':
  3930. return that._formatDate(value, dateType + 'Date');
  3931. case'datehour':
  3932. time = new Date(value.getTime());
  3933. time.setMinutes(0);
  3934. dateStr = dateType === 'timeOnly' ? '' : that._formatDate(value, dateType + 'Date');
  3935. return dateType === 'timeOnly' ? that._formatDate(time, 'shorttime') : dateStr + ' ' + that._formatDate(time, 'shorttime');
  3936. case'datehourminute':
  3937. dateStr = dateType === 'timeOnly' ? '' : that._formatDate(value, dateType + 'Date');
  3938. return dateType === 'timeOnly' ? that._formatDate(value, 'shorttime') : dateStr + ' ' + that._formatDate(value, 'shorttime');
  3939. case'datehourminutesecond':
  3940. dateStr = dateType === 'timeOnly' ? '' : that._formatDate(value, dateType + 'Date');
  3941. return dateType === 'timeOnly' ? that._formatDate(value, 'longtime') : dateStr + ' ' + that._formatDate(value, 'longtime');
  3942. case'year':
  3943. dateStr = value.toString();
  3944. return dateType === 'abbr' ? dateStr.slice(2, 4) : dateStr;
  3945. case'dateyear':
  3946. return dateType === 'abbr' ? that._formatDate(value, 'shortyear') : that._formatDate(value, 'year');
  3947. case'quarter':
  3948. return utils.stringFormat(that.defaultQuarterFormat, value.toString());
  3949. case'month':
  3950. index = value - 1;
  3951. return dateType === 'abbr' ? calendar.months.namesAbbr[index] : calendar.months.names[index];
  3952. case'hour':
  3953. if (dateType === 'long') {
  3954. time = new Date;
  3955. time.setHours(value);
  3956. time.setMinutes(0);
  3957. return that._formatDate(time, 'shorttime')
  3958. }
  3959. return value.toString();
  3960. case'dayofweek':
  3961. index = utils.isString(value) ? $.inArray(value, ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']) : value;
  3962. if (dateType !== 'num')
  3963. return dateType === 'abbr' ? calendar.days.namesAbbr[index] : calendar.days.names[index];
  3964. return ((index - calendar.firstDay + 1 + 7) % 8).toString();
  3965. default:
  3966. return value.toString()
  3967. }
  3968. else
  3969. return value.toString()
  3970. },
  3971. getTimeFormat: function(showSecond) {
  3972. if (showSecond)
  3973. return this._getDateTimeFormatPattern('longtime');
  3974. return this._getDateTimeFormatPattern('shorttime')
  3975. },
  3976. getDateFormatByDifferences: function(dateDifferences) {
  3977. var resultFormat = '';
  3978. if (dateDifferences.millisecond)
  3979. resultFormat = DX.DateTimeFormat.millisecond;
  3980. if (dateDifferences.hour || dateDifferences.minute || dateDifferences.second)
  3981. resultFormat = this._addFormatSeparator(this.getTimeFormat(dateDifferences.second), resultFormat);
  3982. if (dateDifferences.year && dateDifferences.month && dateDifferences.day)
  3983. return this._addFormatSeparator(this._getDateTimeFormatPattern('shortdate'), resultFormat);
  3984. if (dateDifferences.year && dateDifferences.month)
  3985. return DX.DateTimeFormat['monthandyear'];
  3986. if (dateDifferences.year)
  3987. return DX.DateTimeFormat['year'];
  3988. if (dateDifferences.month && dateDifferences.day)
  3989. return this._addFormatSeparator(this._getDateTimeFormatPattern('monthandday'), resultFormat);
  3990. if (dateDifferences.month)
  3991. return DX.DateTimeFormat['month'];
  3992. if (dateDifferences.day)
  3993. return this._addFormatSeparator('dddd, dd', resultFormat);
  3994. return resultFormat
  3995. },
  3996. getDateFormatByTicks: function(ticks) {
  3997. var resultFormat,
  3998. maxDif,
  3999. currentDif,
  4000. i;
  4001. if (ticks.length > 1) {
  4002. maxDif = utils.getDatesDifferences(ticks[0], ticks[1]);
  4003. for (i = 1; i < ticks.length - 1; i++) {
  4004. currentDif = utils.getDatesDifferences(ticks[i], ticks[i + 1]);
  4005. if (maxDif.count < currentDif.count)
  4006. maxDif = currentDif
  4007. }
  4008. }
  4009. else
  4010. maxDif = {
  4011. year: true,
  4012. month: true,
  4013. day: true,
  4014. hour: ticks[0].getHours() > 0,
  4015. minute: ticks[0].getMinutes() > 0,
  4016. second: ticks[0].getSeconds() > 0
  4017. };
  4018. resultFormat = this.getDateFormatByDifferences(maxDif);
  4019. return resultFormat
  4020. },
  4021. getDateFormatByTickInterval: function(startValue, endValue, tickInterval) {
  4022. var resultFormat,
  4023. dateDifferences,
  4024. dateUnitInterval,
  4025. dateDifferencesConverter = {
  4026. quarter: 'month',
  4027. week: 'day'
  4028. },
  4029. correctDateDifferences = function(dateDifferences, tickInterval, value) {
  4030. switch (tickInterval) {
  4031. case'year':
  4032. dateDifferences.month = value;
  4033. case'quarter':
  4034. case'month':
  4035. dateDifferences.day = value;
  4036. case'week':
  4037. case'day':
  4038. dateDifferences.hour = value;
  4039. case'hour':
  4040. dateDifferences.minute = value;
  4041. case'minute':
  4042. dateDifferences.second = value;
  4043. case'second':
  4044. dateDifferences.millisecond = value
  4045. }
  4046. },
  4047. correctDifferencesByMaxDate = function(differences, minDate, maxDate) {
  4048. if (!maxDate.getMilliseconds() && maxDate.getSeconds()) {
  4049. if (maxDate.getSeconds() - minDate.getSeconds() === 1) {
  4050. differences.millisecond = true;
  4051. differences.second = false
  4052. }
  4053. }
  4054. else if (!maxDate.getSeconds() && maxDate.getMinutes()) {
  4055. if (maxDate.getMinutes() - minDate.getMinutes() === 1) {
  4056. differences.second = true;
  4057. differences.minute = false
  4058. }
  4059. }
  4060. else if (!maxDate.getMinutes() && maxDate.getHours()) {
  4061. if (maxDate.getHours() - minDate.getHours() === 1) {
  4062. differences.minute = true;
  4063. differences.hour = false
  4064. }
  4065. }
  4066. else if (!maxDate.getHours() && maxDate.getDate() > 1) {
  4067. if (maxDate.getDate() - minDate.getDate() === 1) {
  4068. differences.hour = true;
  4069. differences.day = false
  4070. }
  4071. }
  4072. else if (maxDate.getDate() === 1 && maxDate.getMonth()) {
  4073. if (maxDate.getMonth() - minDate.getMonth() === 1) {
  4074. differences.day = true;
  4075. differences.month = false
  4076. }
  4077. }
  4078. else if (!maxDate.getMonth() && maxDate.getFullYear())
  4079. if (maxDate.getFullYear() - minDate.getFullYear() === 1) {
  4080. differences.month = true;
  4081. differences.year = false
  4082. }
  4083. };
  4084. tickInterval = utils.isString(tickInterval) ? tickInterval.toLowerCase() : tickInterval;
  4085. dateDifferences = utils.getDatesDifferences(startValue, endValue);
  4086. if (startValue !== endValue)
  4087. correctDifferencesByMaxDate(dateDifferences, startValue > endValue ? endValue : startValue, startValue > endValue ? startValue : endValue);
  4088. dateUnitInterval = utils.getDateUnitInterval(dateDifferences);
  4089. correctDateDifferences(dateDifferences, dateUnitInterval, true);
  4090. dateUnitInterval = utils.getDateUnitInterval(tickInterval || 'second');
  4091. correctDateDifferences(dateDifferences, dateUnitInterval, false);
  4092. dateDifferences[dateDifferencesConverter[dateUnitInterval] || dateUnitInterval] = true;
  4093. resultFormat = this.getDateFormatByDifferences(dateDifferences);
  4094. return resultFormat
  4095. }
  4096. }
  4097. })(jQuery, DevExpress);
  4098. /*! Module core, file color.js */
  4099. (function(DX, undefined) {
  4100. var standardColorNames = {
  4101. aliceblue: 'f0f8ff',
  4102. antiquewhite: 'faebd7',
  4103. aqua: '00ffff',
  4104. aquamarine: '7fffd4',
  4105. azure: 'f0ffff',
  4106. beige: 'f5f5dc',
  4107. bisque: 'ffe4c4',
  4108. black: '000000',
  4109. blanchedalmond: 'ffebcd',
  4110. blue: '0000ff',
  4111. blueviolet: '8a2be2',
  4112. brown: 'a52a2a',
  4113. burlywood: 'deb887',
  4114. cadetblue: '5f9ea0',
  4115. chartreuse: '7fff00',
  4116. chocolate: 'd2691e',
  4117. coral: 'ff7f50',
  4118. cornflowerblue: '6495ed',
  4119. cornsilk: 'fff8dc',
  4120. crimson: 'dc143c',
  4121. cyan: '00ffff',
  4122. darkblue: '00008b',
  4123. darkcyan: '008b8b',
  4124. darkgoldenrod: 'b8860b',
  4125. darkgray: 'a9a9a9',
  4126. darkgreen: '006400',
  4127. darkkhaki: 'bdb76b',
  4128. darkmagenta: '8b008b',
  4129. darkolivegreen: '556b2f',
  4130. darkorange: 'ff8c00',
  4131. darkorchid: '9932cc',
  4132. darkred: '8b0000',
  4133. darksalmon: 'e9967a',
  4134. darkseagreen: '8fbc8f',
  4135. darkslateblue: '483d8b',
  4136. darkslategray: '2f4f4f',
  4137. darkturquoise: '00ced1',
  4138. darkviolet: '9400d3',
  4139. deeppink: 'ff1493',
  4140. deepskyblue: '00bfff',
  4141. dimgray: '696969',
  4142. dodgerblue: '1e90ff',
  4143. feldspar: 'd19275',
  4144. firebrick: 'b22222',
  4145. floralwhite: 'fffaf0',
  4146. forestgreen: '228b22',
  4147. fuchsia: 'ff00ff',
  4148. gainsboro: 'dcdcdc',
  4149. ghostwhite: 'f8f8ff',
  4150. gold: 'ffd700',
  4151. goldenrod: 'daa520',
  4152. gray: '808080',
  4153. green: '008000',
  4154. greenyellow: 'adff2f',
  4155. honeydew: 'f0fff0',
  4156. hotpink: 'ff69b4',
  4157. indianred: 'cd5c5c',
  4158. indigo: '4b0082',
  4159. ivory: 'fffff0',
  4160. khaki: 'f0e68c',
  4161. lavender: 'e6e6fa',
  4162. lavenderblush: 'fff0f5',
  4163. lawngreen: '7cfc00',
  4164. lemonchiffon: 'fffacd',
  4165. lightblue: 'add8e6',
  4166. lightcoral: 'f08080',
  4167. lightcyan: 'e0ffff',
  4168. lightgoldenrodyellow: 'fafad2',
  4169. lightgrey: 'd3d3d3',
  4170. lightgreen: '90ee90',
  4171. lightpink: 'ffb6c1',
  4172. lightsalmon: 'ffa07a',
  4173. lightseagreen: '20b2aa',
  4174. lightskyblue: '87cefa',
  4175. lightslateblue: '8470ff',
  4176. lightslategray: '778899',
  4177. lightsteelblue: 'b0c4de',
  4178. lightyellow: 'ffffe0',
  4179. lime: '00ff00',
  4180. limegreen: '32cd32',
  4181. linen: 'faf0e6',
  4182. magenta: 'ff00ff',
  4183. maroon: '800000',
  4184. mediumaquamarine: '66cdaa',
  4185. mediumblue: '0000cd',
  4186. mediumorchid: 'ba55d3',
  4187. mediumpurple: '9370d8',
  4188. mediumseagreen: '3cb371',
  4189. mediumslateblue: '7b68ee',
  4190. mediumspringgreen: '00fa9a',
  4191. mediumturquoise: '48d1cc',
  4192. mediumvioletred: 'c71585',
  4193. midnightblue: '191970',
  4194. mintcream: 'f5fffa',
  4195. mistyrose: 'ffe4e1',
  4196. moccasin: 'ffe4b5',
  4197. navajowhite: 'ffdead',
  4198. navy: '000080',
  4199. oldlace: 'fdf5e6',
  4200. olive: '808000',
  4201. olivedrab: '6b8e23',
  4202. orange: 'ffa500',
  4203. orangered: 'ff4500',
  4204. orchid: 'da70d6',
  4205. palegoldenrod: 'eee8aa',
  4206. palegreen: '98fb98',
  4207. paleturquoise: 'afeeee',
  4208. palevioletred: 'd87093',
  4209. papayawhip: 'ffefd5',
  4210. peachpuff: 'ffdab9',
  4211. peru: 'cd853f',
  4212. pink: 'ffc0cb',
  4213. plum: 'dda0dd',
  4214. powderblue: 'b0e0e6',
  4215. purple: '800080',
  4216. red: 'ff0000',
  4217. rosybrown: 'bc8f8f',
  4218. royalblue: '4169e1',
  4219. saddlebrown: '8b4513',
  4220. salmon: 'fa8072',
  4221. sandybrown: 'f4a460',
  4222. seagreen: '2e8b57',
  4223. seashell: 'fff5ee',
  4224. sienna: 'a0522d',
  4225. silver: 'c0c0c0',
  4226. skyblue: '87ceeb',
  4227. slateblue: '6a5acd',
  4228. slategray: '708090',
  4229. snow: 'fffafa',
  4230. springgreen: '00ff7f',
  4231. steelblue: '4682b4',
  4232. tan: 'd2b48c',
  4233. teal: '008080',
  4234. thistle: 'd8bfd8',
  4235. tomato: 'ff6347',
  4236. turquoise: '40e0d0',
  4237. violet: 'ee82ee',
  4238. violetred: 'd02090',
  4239. wheat: 'f5deb3',
  4240. white: 'ffffff',
  4241. whitesmoke: 'f5f5f5',
  4242. yellow: 'ffff00',
  4243. yellowgreen: '9acd32'
  4244. };
  4245. var standardColorTypes = [{
  4246. re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
  4247. process: function(colorString) {
  4248. return [parseInt(colorString[1], 10), parseInt(colorString[2], 10), parseInt(colorString[3], 10)]
  4249. }
  4250. }, {
  4251. re: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d*\.*\d+)\)$/,
  4252. process: function(colorString) {
  4253. return [parseInt(colorString[1], 10), parseInt(colorString[2], 10), parseInt(colorString[3], 10), parseFloat(colorString[4])]
  4254. }
  4255. }, {
  4256. re: /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/,
  4257. process: function(colorString) {
  4258. return [parseInt(colorString[1], 16), parseInt(colorString[2], 16), parseInt(colorString[3], 16)]
  4259. }
  4260. }, {
  4261. re: /^#([a-f0-9]{1})([a-f0-9]{1})([a-f0-9]{1})$/,
  4262. process: function(colorString) {
  4263. return [parseInt(colorString[1] + colorString[1], 16), parseInt(colorString[2] + colorString[2], 16), parseInt(colorString[3] + colorString[3], 16)]
  4264. }
  4265. }, {
  4266. re: /^hsv\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
  4267. process: function(colorString) {
  4268. var h = parseInt(colorString[1], 10),
  4269. s = parseInt(colorString[2], 10),
  4270. v = parseInt(colorString[3], 10),
  4271. rgb = hsvToRgb(h, s, v);
  4272. return [rgb[0], rgb[1], rgb[2], 1, [h, s, v]]
  4273. }
  4274. }, {
  4275. re: /^hsl\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
  4276. process: function(colorString) {
  4277. var h = parseInt(colorString[1], 10),
  4278. s = parseInt(colorString[2], 10),
  4279. l = parseInt(colorString[3], 10),
  4280. rgb = hslToRgb(h, s, l);
  4281. return [rgb[0], rgb[1], rgb[2], 1, null, [h, s, l]]
  4282. }
  4283. }];
  4284. function Color(value) {
  4285. this.baseColor = value;
  4286. var color;
  4287. if (value) {
  4288. color = String(value).toLowerCase().replace(/ /g, '');
  4289. color = standardColorNames[color] ? '#' + standardColorNames[color] : color;
  4290. color = parseColor(color)
  4291. }
  4292. if (!color)
  4293. this.colorIsInvalid = true;
  4294. color = color || {};
  4295. this.r = normalize(color[0]);
  4296. this.g = normalize(color[1]);
  4297. this.b = normalize(color[2]);
  4298. this.a = normalize(color[3], 1, 1);
  4299. if (color[4])
  4300. this.hsv = {
  4301. h: color[4][0],
  4302. s: color[4][1],
  4303. v: color[4][2]
  4304. };
  4305. else
  4306. this.hsv = toHsvFromRgb(this.r, this.g, this.b);
  4307. if (color[5])
  4308. this.hsl = {
  4309. h: color[5][0],
  4310. s: color[5][1],
  4311. l: color[5][2]
  4312. };
  4313. else
  4314. this.hsl = toHslFromRgb(this.r, this.g, this.b)
  4315. }
  4316. function parseColor(color) {
  4317. if (color === "transparent")
  4318. return [0, 0, 0, 0];
  4319. var i = 0,
  4320. ii = standardColorTypes.length,
  4321. str;
  4322. for (; i < ii; ++i) {
  4323. str = standardColorTypes[i].re.exec(color);
  4324. if (str)
  4325. return standardColorTypes[i].process(str)
  4326. }
  4327. return null
  4328. }
  4329. function normalize(colorComponent, def, max) {
  4330. def = def || 0;
  4331. max = max || 255;
  4332. return colorComponent < 0 || isNaN(colorComponent) ? def : colorComponent > max ? max : colorComponent
  4333. }
  4334. function toHexFromRgb(r, g, b) {
  4335. return '#' + (0X01000000 | r << 16 | g << 8 | b).toString(16).slice(1)
  4336. }
  4337. function toHsvFromRgb(r, g, b) {
  4338. var max = Math.max(r, g, b),
  4339. min = Math.min(r, g, b),
  4340. delta = max - min,
  4341. H,
  4342. S,
  4343. V;
  4344. V = max;
  4345. S = max === 0 ? 0 : 1 - min / max;
  4346. if (max === min)
  4347. H = 0;
  4348. else
  4349. switch (max) {
  4350. case r:
  4351. H = 60 * ((g - b) / delta);
  4352. if (g < b)
  4353. H = H + 360;
  4354. break;
  4355. case g:
  4356. H = 60 * ((b - r) / delta) + 120;
  4357. break;
  4358. case b:
  4359. H = 60 * ((r - g) / delta) + 240;
  4360. break
  4361. }
  4362. S *= 100;
  4363. V *= 100 / 255;
  4364. return {
  4365. h: Math.round(H),
  4366. s: Math.round(S),
  4367. v: Math.round(V)
  4368. }
  4369. }
  4370. function hsvToRgb(h, s, v) {
  4371. var Vdec,
  4372. Vinc,
  4373. Vmin,
  4374. Hi,
  4375. a,
  4376. r,
  4377. g,
  4378. b;
  4379. Hi = Math.floor(h / 60);
  4380. Vmin = (100 - s) * v / 100;
  4381. a = (v - Vmin) * (h % 60 / 60);
  4382. Vinc = Vmin + a;
  4383. Vdec = v - a;
  4384. switch (Hi) {
  4385. case 0:
  4386. r = v;
  4387. g = Vinc;
  4388. b = Vmin;
  4389. break;
  4390. case 1:
  4391. r = Vdec;
  4392. g = v;
  4393. b = Vmin;
  4394. break;
  4395. case 2:
  4396. r = Vmin;
  4397. g = v;
  4398. b = Vinc;
  4399. break;
  4400. case 3:
  4401. r = Vmin;
  4402. g = Vdec;
  4403. b = v;
  4404. break;
  4405. case 4:
  4406. r = Vinc;
  4407. g = Vmin;
  4408. b = v;
  4409. break;
  4410. case 5:
  4411. r = v;
  4412. g = Vmin;
  4413. b = Vdec;
  4414. break
  4415. }
  4416. return [Math.round(r * 2.55), Math.round(g * 2.55), Math.round(b * 2.55)]
  4417. }
  4418. function calculateHue(r, g, b, delta) {
  4419. var max = Math.max(r, g, b);
  4420. switch (max) {
  4421. case r:
  4422. return (g - b) / delta + (g < b ? 6 : 0);
  4423. case g:
  4424. return (b - r) / delta + 2;
  4425. case b:
  4426. return (r - g) / delta + 4
  4427. }
  4428. }
  4429. function toHslFromRgb(r, g, b) {
  4430. r = convertTo01Bounds(r, 255);
  4431. g = convertTo01Bounds(g, 255);
  4432. b = convertTo01Bounds(b, 255);
  4433. var max = Math.max(r, g, b),
  4434. min = Math.min(r, g, b),
  4435. maxMinSumm = max + min,
  4436. h,
  4437. s,
  4438. l = maxMinSumm / 2;
  4439. if (max === min)
  4440. h = s = 0;
  4441. else {
  4442. var delta = max - min;
  4443. if (l > 0.5)
  4444. s = delta / (2 - maxMinSumm);
  4445. else
  4446. s = delta / maxMinSumm;
  4447. h = calculateHue(r, g, b, delta);
  4448. h /= 6
  4449. }
  4450. return {
  4451. h: _round(h * 360),
  4452. s: _round(s * 100),
  4453. l: _round(l * 100)
  4454. }
  4455. }
  4456. function makeTc(colorPart, h) {
  4457. var Tc = h;
  4458. if (colorPart === "r")
  4459. Tc = h + 1 / 3;
  4460. if (colorPart === "b")
  4461. Tc = h - 1 / 3;
  4462. return Tc
  4463. }
  4464. function modifyTc(Tc) {
  4465. if (Tc < 0)
  4466. Tc += 1;
  4467. if (Tc > 1)
  4468. Tc -= 1;
  4469. return Tc
  4470. }
  4471. function hueToRgb(p, q, Tc) {
  4472. Tc = modifyTc(Tc);
  4473. if (Tc < 1 / 6)
  4474. return p + (q - p) * 6 * Tc;
  4475. if (Tc < 1 / 2)
  4476. return q;
  4477. if (Tc < 2 / 3)
  4478. return p + (q - p) * (2 / 3 - Tc) * 6;
  4479. return p
  4480. }
  4481. function hslToRgb(h, s, l) {
  4482. var r,
  4483. g,
  4484. b;
  4485. h = convertTo01Bounds(h, 360),
  4486. s = convertTo01Bounds(s, 100),
  4487. l = convertTo01Bounds(l, 100);
  4488. if (s === 0)
  4489. r = g = b = l;
  4490. else {
  4491. var q = l < 0.5 ? l * (1 + s) : l + s - l * s,
  4492. p = 2 * l - q;
  4493. r = hueToRgb(p, q, makeTc("r", h));
  4494. g = hueToRgb(p, q, makeTc("g", h));
  4495. b = hueToRgb(p, q, makeTc("b", h))
  4496. }
  4497. return [_round(r * 255), _round(g * 255), _round(b * 255)]
  4498. }
  4499. function convertTo01Bounds(n, max) {
  4500. n = Math.min(max, Math.max(0, parseFloat(n)));
  4501. if (Math.abs(n - max) < 0.000001)
  4502. return 1;
  4503. return n % max / parseFloat(max)
  4504. }
  4505. function isIntegerBtwMinAndMax(number, min, max) {
  4506. min = min || 0;
  4507. max = max || 255;
  4508. if (number % 1 !== 0 || number < min || number > max || typeof number !== 'number' || isNaN(number))
  4509. return false;
  4510. return true
  4511. }
  4512. var _round = Math.round;
  4513. Color.prototype = {
  4514. constructor: Color,
  4515. highlight: function(step) {
  4516. step = step || 10;
  4517. return this.alter(step).toHex()
  4518. },
  4519. darken: function(step) {
  4520. step = step || 10;
  4521. return this.alter(-step).toHex()
  4522. },
  4523. alter: function(step) {
  4524. var result = new Color;
  4525. result.r = normalize(this.r + step);
  4526. result.g = normalize(this.g + step);
  4527. result.b = normalize(this.b + step);
  4528. return result
  4529. },
  4530. blend: function(blendColor, opacity) {
  4531. var other = blendColor instanceof Color ? blendColor : new Color(blendColor),
  4532. result = new Color;
  4533. result.r = normalize(_round(this.r * (1 - opacity) + other.r * opacity));
  4534. result.g = normalize(_round(this.g * (1 - opacity) + other.g * opacity));
  4535. result.b = normalize(_round(this.b * (1 - opacity) + other.b * opacity));
  4536. return result
  4537. },
  4538. toHex: function() {
  4539. return toHexFromRgb(this.r, this.g, this.b)
  4540. },
  4541. getPureColor: function() {
  4542. var rgb = hsvToRgb(this.hsv.h, 100, 100);
  4543. return new Color("rgb(" + rgb.join(",") + ")")
  4544. },
  4545. isValidHex: function(hex) {
  4546. return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(hex)
  4547. },
  4548. isValidRGB: function(r, g, b) {
  4549. if (!isIntegerBtwMinAndMax(r) || !isIntegerBtwMinAndMax(g) || !isIntegerBtwMinAndMax(b))
  4550. return false;
  4551. return true
  4552. },
  4553. isValidAlpha: function(a) {
  4554. if (isNaN(a) || a < 0 || a > 1 || typeof a !== 'number')
  4555. return false;
  4556. return true
  4557. },
  4558. colorIsInvalid: false
  4559. };
  4560. DX.Color = Color
  4561. })(DevExpress);
  4562. /*! Module core, file localization.js */
  4563. (function($, DX, undefined) {
  4564. Globalize.localize = function(key, cultureSelector) {
  4565. var neutral = (cultureSelector || this.cultureSelector || "").substring(0, 2);
  4566. return this.findClosestCulture(cultureSelector).messages[key] || this.findClosestCulture(neutral).messages[key] || this.cultures["default"].messages[key]
  4567. };
  4568. var localization = function() {
  4569. var newMessages = {};
  4570. return {
  4571. setup: function(localizablePrefix) {
  4572. this.localizeString = function(text) {
  4573. var regex = new RegExp("(^|[^a-zA-Z_0-9" + localizablePrefix + "-]+)(" + localizablePrefix + "{1,2})([a-zA-Z_0-9-]+)", "g"),
  4574. escapeString = localizablePrefix + localizablePrefix;
  4575. return text.replace(regex, function(str, prefix, escape, localizationKey) {
  4576. var result = prefix + localizablePrefix + localizationKey;
  4577. if (escape !== escapeString)
  4578. if (Globalize.cultures["default"].messages[localizationKey])
  4579. result = prefix + Globalize.localize(localizationKey);
  4580. else
  4581. newMessages[localizationKey] = DX.inflector.humanize(localizationKey);
  4582. return result
  4583. })
  4584. }
  4585. },
  4586. localizeNode: function(node) {
  4587. var that = this;
  4588. $(node).each(function(index, nodeItem) {
  4589. if (!nodeItem.nodeType)
  4590. return;
  4591. if (nodeItem.nodeType === 3)
  4592. nodeItem.nodeValue = that.localizeString(nodeItem.nodeValue);
  4593. else if (!$(nodeItem).is("iframe")) {
  4594. $.each(nodeItem.attributes || [], function(index, attr) {
  4595. if (typeof attr.value === "string") {
  4596. var localizedValue = that.localizeString(attr.value);
  4597. if (attr.value !== localizedValue)
  4598. attr.value = localizedValue
  4599. }
  4600. });
  4601. $(nodeItem).contents().each(function(index, node) {
  4602. that.localizeNode(node)
  4603. })
  4604. }
  4605. })
  4606. },
  4607. getDictionary: function(onlyNew) {
  4608. if (onlyNew)
  4609. return newMessages;
  4610. return $.extend({}, newMessages, Globalize.cultures["default"].messages)
  4611. }
  4612. }
  4613. }();
  4614. localization.setup("@");
  4615. DX.localization = localization
  4616. })(jQuery, DevExpress);
  4617. /*! Module core, file core.en.js */
  4618. Globalize.addCultureInfo("default", {messages: {
  4619. Yes: "Yes",
  4620. No: "No",
  4621. Cancel: "Cancel",
  4622. Clear: "Clear",
  4623. Done: "Done",
  4624. Loading: "Loading...",
  4625. Select: "Select...",
  4626. Search: "Search",
  4627. Back: "Back",
  4628. OK: "OK",
  4629. "dxCollectionWidget-noDataText": "No data to display",
  4630. "validation-required": "Required",
  4631. "validation-required-formatted": "{0} is required",
  4632. "validation-numeric": "Value must be a number",
  4633. "validation-numeric-formatted": "{0} must be a number",
  4634. "validation-range": "Value is out of range",
  4635. "validation-range-formatted": "{0} is out of range",
  4636. "validation-stringLength": "The length of the value is not correct",
  4637. "validation-stringLength-formatted": "The length of {0} is not correct",
  4638. "validation-custom": "Value is invalid",
  4639. "validation-custom-formatted": "{0} is invalid",
  4640. "validation-compare": "Values do not match",
  4641. "validation-compare-formatted": "{0} does not match",
  4642. "validation-pattern": "Value does not match pattern",
  4643. "validation-pattern-formatted": "{0} does not match pattern",
  4644. "validation-email": "Email is invalid",
  4645. "validation-email-formatted": "{0} is invalid",
  4646. "validation-mask": "Value is invalid"
  4647. }});
  4648. /*! Module core, file widgets-base.en.js */
  4649. Globalize.addCultureInfo("default", {messages: {
  4650. "dxLookup-searchPlaceholder": "Minimum character number: {0}",
  4651. "dxList-pullingDownText": "Pull down to refresh...",
  4652. "dxList-pulledDownText": "Release to refresh...",
  4653. "dxList-refreshingText": "Refreshing...",
  4654. "dxList-pageLoadingText": "Loading...",
  4655. "dxList-nextButtonText": "More",
  4656. "dxList-selectAll": "Select All",
  4657. "dxListEditDecorator-delete": "Delete",
  4658. "dxListEditDecorator-more": "More",
  4659. "dxScrollView-pullingDownText": "Pull down to refresh...",
  4660. "dxScrollView-pulledDownText": "Release to refresh...",
  4661. "dxScrollView-refreshingText": "Refreshing...",
  4662. "dxScrollView-reachBottomText": "Loading...",
  4663. "dxDateBox-simulatedDataPickerTitleTime": "Select time",
  4664. "dxDateBox-simulatedDataPickerTitleDate": "Select date",
  4665. "dxDateBox-simulatedDataPickerTitleDateTime": "Select date and time",
  4666. "dxDateBox-validation-datetime": "Value must be a date or time",
  4667. "dxFileUploader-selectFile": "Select file",
  4668. "dxFileUploader-dropFile": "or Drop file here",
  4669. "dxFileUploader-bytes": "bytes",
  4670. "dxFileUploader-kb": "kb",
  4671. "dxFileUploader-Mb": "Mb",
  4672. "dxFileUploader-Gb": "Gb",
  4673. "dxFileUploader-upload": "Upload",
  4674. "dxFileUploader-uploaded": "Uploaded",
  4675. "dxFileUploader-readyToUpload": "Ready to upload",
  4676. "dxFileUploader-uploadFailedMessage": "Upload failed",
  4677. "dxRangeSlider-ariaFrom": "From {0}",
  4678. "dxRangeSlider-ariaTill": "Till {0}",
  4679. "dxSwitch-onText": "ON",
  4680. "dxSwitch-offText": "OFF"
  4681. }});
  4682. /*! Module core, file widgets-mobile.en.js */
  4683. /*! Module core, file widgets-web.en.js */
  4684. Globalize.addCultureInfo("default", {messages: {
  4685. "dxDataGrid-columnChooserTitle": "Column Chooser",
  4686. "dxDataGrid-columnChooserEmptyText": "Drag a column here to hide it",
  4687. "dxDataGrid-groupContinuesMessage": "Continues on the next page",
  4688. "dxDataGrid-groupContinuedMessage": "Continued from the previous page",
  4689. "dxDataGrid-editingEditRow": "Edit",
  4690. "dxDataGrid-editingSaveRowChanges": "Save",
  4691. "dxDataGrid-editingCancelRowChanges": "Cancel",
  4692. "dxDataGrid-editingDeleteRow": "Delete",
  4693. "dxDataGrid-editingUndeleteRow": "Undelete",
  4694. "dxDataGrid-editingConfirmDeleteMessage": "Are you sure you want to delete this record?",
  4695. "dxDataGrid-editingConfirmDeleteTitle": "",
  4696. "dxDataGrid-groupPanelEmptyText": "Drag a column header here to group by that column",
  4697. "dxDataGrid-noDataText": "No data",
  4698. "dxDataGrid-searchPanelPlaceholder": "Search...",
  4699. "dxDataGrid-filterRowShowAllText": "(All)",
  4700. "dxDataGrid-filterRowResetOperationText": "Reset",
  4701. "dxDataGrid-filterRowOperationEquals": "Equals",
  4702. "dxDataGrid-filterRowOperationNotEquals": "Does not equal",
  4703. "dxDataGrid-filterRowOperationLess": "Less than",
  4704. "dxDataGrid-filterRowOperationLessOrEquals": "Less than or equal to",
  4705. "dxDataGrid-filterRowOperationGreater": "Greater than",
  4706. "dxDataGrid-filterRowOperationGreaterOrEquals": "Greater than or equal to",
  4707. "dxDataGrid-filterRowOperationStartsWith": "Starts with",
  4708. "dxDataGrid-filterRowOperationContains": "Contains",
  4709. "dxDataGrid-filterRowOperationNotContains": "Does not contain",
  4710. "dxDataGrid-filterRowOperationEndsWith": "Ends with",
  4711. "dxDataGrid-applyFilterText": "Apply filter",
  4712. "dxDataGrid-trueText": "true",
  4713. "dxDataGrid-falseText": "false",
  4714. "dxDataGrid-sortingAscendingText": "Sort Ascending",
  4715. "dxDataGrid-sortingDescendingText": "Sort Descending",
  4716. "dxDataGrid-sortingClearText": "Clear Sorting",
  4717. "dxDataGrid-editingSaveAllChanges": "Save changes",
  4718. "dxDataGrid-editingCancelAllChanges": "Discard changes",
  4719. "dxDataGrid-editingAddRow": "Add a row",
  4720. "dxDataGrid-summaryMin": "Min: {0}",
  4721. "dxDataGrid-summaryMinOtherColumn": "Min of {1} is {0}",
  4722. "dxDataGrid-summaryMax": "Max: {0}",
  4723. "dxDataGrid-summaryMaxOtherColumn": "Max of {1} is {0}",
  4724. "dxDataGrid-summaryAvg": "Avg: {0}",
  4725. "dxDataGrid-summaryAvgOtherColumn": "Avg of {1} is {0}",
  4726. "dxDataGrid-summarySum": "Sum: {0}",
  4727. "dxDataGrid-summarySumOtherColumn": "Sum of {1} is {0}",
  4728. "dxDataGrid-summaryCount": "Count: {0}",
  4729. "dxDataGrid-columnFixingFix": "Fix",
  4730. "dxDataGrid-columnFixingUnfix": "Unfix",
  4731. "dxDataGrid-columnFixingLeftPosition": "To the left",
  4732. "dxDataGrid-columnFixingRightPosition": "To the right",
  4733. "dxDataGrid-exportTo": "Export to",
  4734. "dxDataGrid-exportToExcel": "Export to Excel file",
  4735. "dxDataGrid-excelFormat": "Excel file",
  4736. "dxDataGrid-selectedRows": "Selected rows",
  4737. "dxDataGrid-headerFilterEmptyValue": "(Blanks)",
  4738. "dxDataGrid-headerFilterOK": "OK",
  4739. "dxDataGrid-headerFilterCancel": "Cancel",
  4740. "dxDataGrid-ariaColumn": "Column",
  4741. "dxDataGrid-ariaValue": "Value",
  4742. "dxDataGrid-ariaFilterCell": "Filter cell",
  4743. "dxDataGrid-ariaCollapse": "Collapse",
  4744. "dxDataGrid-ariaExpand": "Expand",
  4745. "dxDataGrid-ariaDataGrid": "Data grid",
  4746. "dxDataGrid-ariaSearchInGrid": "Search in data grid",
  4747. "dxDataGrid-ariaSelectAll": "Select all",
  4748. "dxDataGrid-ariaSelectRow": "Select row",
  4749. "dxPager-infoText": "Page {0} of {1}",
  4750. "dxPivotGrid-grandTotal": "Grand Total",
  4751. "dxPivotGrid-total": "{0} Total",
  4752. "dxPivotGrid-fieldChooserTitle": "Field Chooser",
  4753. "dxPivotGrid-showFieldChooser": "Show Field Chooser",
  4754. "dxPivotGrid-expandAll": "Expand All",
  4755. "dxPivotGrid-collapseAll": "Collapse All",
  4756. "dxPivotGrid-sortColumnBySummary": "Sort \"{0}\" by This Column",
  4757. "dxPivotGrid-sortRowBySummary": "Sort \"{0}\" by This Row",
  4758. "dxPivotGrid-removeAllSorting": "Remove All Sorting",
  4759. "dxPivotGrid-rowFields": "Row Fields",
  4760. "dxPivotGrid-columnFields": "Column Fields",
  4761. "dxPivotGrid-dataFields": "Data Fields",
  4762. "dxPivotGrid-filterFields": "Filter Fields",
  4763. "dxPivotGrid-allFields": "All Fields",
  4764. "dxScheduler-editorLabelTitle": "Subject",
  4765. "dxScheduler-editorLabelStartDate": "Start Date",
  4766. "dxScheduler-editorLabelEndDate": "End Date",
  4767. "dxScheduler-editorLabelDescription": "Description",
  4768. "dxScheduler-editorLabelRecurrence": "Repeat",
  4769. "dxScheduler-openAppointment": "Open appointment",
  4770. "dxScheduler-recurrenceNever": "Never",
  4771. "dxScheduler-recurrenceDaily": "Daily",
  4772. "dxScheduler-recurrenceWeekly": "Weekly",
  4773. "dxScheduler-recurrenceMonthly": "Monthly",
  4774. "dxScheduler-recurrenceYearly": "Yearly",
  4775. "dxScheduler-recurrenceEvery": "Every",
  4776. "dxScheduler-recurrenceEnd": "End repeat",
  4777. "dxScheduler-recurrenceAfter": "After",
  4778. "dxScheduler-recurrenceOn": "On",
  4779. "dxScheduler-recurrenceRepeatDaily": "day(s)",
  4780. "dxScheduler-recurrenceRepeatWeekly": "week(s)",
  4781. "dxScheduler-recurrenceRepeatMonthly": "month(s)",
  4782. "dxScheduler-recurrenceRepeatYearly": "year(s)",
  4783. "dxScheduler-switcherDay": "Day",
  4784. "dxScheduler-switcherWeek": "Week",
  4785. "dxScheduler-switcherWorkWeek": "Work week",
  4786. "dxScheduler-switcherMonth": "Month",
  4787. "dxScheduler-recurrenceRepeatOnDate": "on date",
  4788. "dxScheduler-recurrenceRepeatCount": "occurrence(s)",
  4789. "dxScheduler-allDay": "All day",
  4790. "dxCalendar-todayButtonText": "Today",
  4791. "dxCalendar-ariaWidgetName": "Calendar",
  4792. "dxColorView-ariaRed": "Red",
  4793. "dxColorView-ariaGreen": "Green",
  4794. "dxColorView-ariaBlue": "Blue",
  4795. "dxColorView-ariaAlpha": "Transparency",
  4796. "dxColorView-ariaHex": "Color code"
  4797. }});
  4798. /*! Module core, file validationEngine.js */
  4799. (function($, DX, undefined) {
  4800. var utils = DX.utils;
  4801. var rulesValidators = {
  4802. required: {
  4803. validate: function(value, rule) {
  4804. if (!utils.isDefined(value))
  4805. return false;
  4806. if (value === false)
  4807. return false;
  4808. value = String(value);
  4809. if (rule.trim || !utils.isDefined(rule.trim))
  4810. value = $.trim(value);
  4811. return value !== ""
  4812. },
  4813. defaultMessage: function() {
  4814. return Globalize.localize("validation-required")
  4815. },
  4816. defaultFormattedMessage: function() {
  4817. return Globalize.localize("validation-required-formatted")
  4818. }
  4819. },
  4820. numeric: {
  4821. validate: function(value, rule) {
  4822. if (!rulesValidators.required.validate(value, {}))
  4823. return true;
  4824. if (rule.useCultureSettings && utils.isString(value))
  4825. return !isNaN(Globalize.parseFloat(value));
  4826. else
  4827. return $.isNumeric(value)
  4828. },
  4829. defaultMessage: function() {
  4830. return Globalize.localize("validation-numeric")
  4831. },
  4832. defaultFormattedMessage: function() {
  4833. return Globalize.localize("validation-numeric-formatted")
  4834. }
  4835. },
  4836. range: {
  4837. validate: function(value, rule) {
  4838. if (!rulesValidators.required.validate(value, {}))
  4839. return true;
  4840. var validNumber = rulesValidators["numeric"].validate(value, rule),
  4841. validValue = utils.isDefined(value),
  4842. number = validNumber ? parseFloat(value) : validValue && value.valueOf(),
  4843. min = rule.min,
  4844. max = rule.max;
  4845. if (!(validNumber || utils.isDate(value)) && !validValue)
  4846. return false;
  4847. if (utils.isDefined(min)) {
  4848. if (utils.isDefined(max))
  4849. return number >= min && number <= max;
  4850. return number >= min
  4851. }
  4852. else if (utils.isDefined(max))
  4853. return number <= max;
  4854. else
  4855. throw DX.Error("E0101");
  4856. return false
  4857. },
  4858. defaultMessage: function() {
  4859. return Globalize.localize("validation-range")
  4860. },
  4861. defaultFormattedMessage: function() {
  4862. return Globalize.localize("validation-range-formatted")
  4863. }
  4864. },
  4865. stringLength: {
  4866. validate: function(value, rule) {
  4867. value = String(value);
  4868. if (rule.trim || !utils.isDefined(rule.trim))
  4869. value = $.trim(value);
  4870. return rulesValidators.range.validate(value.length, $.extend({}, rule))
  4871. },
  4872. defaultMessage: function() {
  4873. return Globalize.localize("validation-stringLength")
  4874. },
  4875. defaultFormattedMessage: function() {
  4876. return Globalize.localize("validation-stringLength-formatted")
  4877. }
  4878. },
  4879. custom: {
  4880. validate: function(value, rule) {
  4881. return rule.validationCallback({
  4882. value: value,
  4883. validator: rule.validator,
  4884. rule: rule
  4885. })
  4886. },
  4887. defaultMessage: function() {
  4888. return Globalize.localize("validation-custom")
  4889. },
  4890. defaultFormattedMessage: function() {
  4891. return Globalize.localize("validation-custom-formatted")
  4892. }
  4893. },
  4894. compare: {
  4895. validate: function(value, rule) {
  4896. if (!rule.comparisonTarget)
  4897. throw DX.Error("E0102");
  4898. $.extend(rule, {reevaluate: true});
  4899. var otherValue = rule.comparisonTarget(),
  4900. type = rule.comparisonType || "==";
  4901. switch (type) {
  4902. case"==":
  4903. return value == otherValue;
  4904. case"!=":
  4905. return value != otherValue;
  4906. case"===":
  4907. return value === otherValue;
  4908. case"!==":
  4909. return value !== otherValue;
  4910. case">":
  4911. return value > otherValue;
  4912. case">=":
  4913. return value >= otherValue;
  4914. case"<":
  4915. return value < otherValue;
  4916. case"<=":
  4917. return value <= otherValue
  4918. }
  4919. },
  4920. defaultMessage: function() {
  4921. return Globalize.localize("validation-compare")
  4922. },
  4923. defaultFormattedMessage: function() {
  4924. return Globalize.localize("validation-compare-formatted")
  4925. }
  4926. },
  4927. pattern: {
  4928. validate: function(value, rule) {
  4929. if (!rulesValidators.required.validate(value, {}))
  4930. return true;
  4931. var pattern = rule.pattern;
  4932. if (utils.isString(pattern))
  4933. pattern = new RegExp(pattern);
  4934. return pattern.test(value)
  4935. },
  4936. defaultMessage: function() {
  4937. return Globalize.localize("validation-pattern")
  4938. },
  4939. defaultFormattedMessage: function() {
  4940. return Globalize.localize("validation-pattern-formatted")
  4941. }
  4942. },
  4943. email: {
  4944. validate: function(value, rule) {
  4945. if (!rulesValidators.required.validate(value, {}))
  4946. return true;
  4947. return rulesValidators.pattern.validate(value, $.extend({}, rule, {pattern: /^[\d\w\._\-]+@([\d\w\._\-]+\.)+[\w]+$/i}))
  4948. },
  4949. defaultMessage: function() {
  4950. return Globalize.localize("validation-email")
  4951. },
  4952. defaultFormattedMessage: function() {
  4953. return Globalize.localize("validation-email-formatted")
  4954. }
  4955. }
  4956. };
  4957. var GroupConfig = DX.Class.inherit({
  4958. ctor: function(group) {
  4959. this.group = group;
  4960. this.validators = []
  4961. },
  4962. validate: function() {
  4963. var result = {
  4964. isValid: true,
  4965. brokenRules: [],
  4966. validators: []
  4967. };
  4968. $.each(this.validators, function(_, validator) {
  4969. var validatorResult = validator.validate();
  4970. result.isValid = result.isValid && validatorResult.isValid;
  4971. if (validatorResult.brokenRule)
  4972. result.brokenRules.push(validatorResult.brokenRule);
  4973. result.validators.push(validator)
  4974. });
  4975. this.fireEvent("validated", [{
  4976. validators: result.validators,
  4977. brokenRules: result.brokenRules,
  4978. isValid: result.isValid
  4979. }]);
  4980. return result
  4981. },
  4982. reset: function() {
  4983. $.each(this.validators, function(_, validator) {
  4984. validator.reset()
  4985. })
  4986. }
  4987. }).include(DX.EventsMixin);
  4988. DX.validationEngine = {
  4989. groups: [],
  4990. getGroupConfig: function(group) {
  4991. var result = $.grep(this.groups, function(config) {
  4992. return config.group === group
  4993. });
  4994. if (result.length)
  4995. return result[0]
  4996. },
  4997. initGroups: function() {
  4998. this.groups = [];
  4999. this.addGroup()
  5000. },
  5001. addGroup: function(group) {
  5002. var config = this.getGroupConfig(group);
  5003. if (!config) {
  5004. config = new GroupConfig(group);
  5005. this.groups.push(config)
  5006. }
  5007. return config
  5008. },
  5009. removeGroup: function(group) {
  5010. var config = this.getGroupConfig(group),
  5011. index = $.inArray(config, this.groups);
  5012. if (index > -1)
  5013. this.groups.splice(index, 1);
  5014. return config
  5015. },
  5016. _setDefaultMessage: function(rule, validator, name) {
  5017. if (!utils.isDefined(rule.message))
  5018. if (validator.defaultFormattedMessage && utils.isDefined(name))
  5019. rule.message = validator.defaultFormattedMessage().replace(/\{0\}/, name);
  5020. else
  5021. rule.message = validator.defaultMessage()
  5022. },
  5023. validate: function validate(value, rules, name) {
  5024. var result = {
  5025. name: name,
  5026. value: value,
  5027. brokenRule: null,
  5028. isValid: true,
  5029. validationRules: rules
  5030. },
  5031. that = this;
  5032. $.each(rules || [], function(_, rule) {
  5033. var ruleValidator = rulesValidators[rule.type],
  5034. ruleValidationResult;
  5035. if (ruleValidator) {
  5036. if (utils.isDefined(rule.isValid) && rule.value === value && !rule.reevaluate) {
  5037. if (!rule.isValid) {
  5038. result.isValid = false;
  5039. result.brokenRule = rule;
  5040. return false
  5041. }
  5042. return true
  5043. }
  5044. rule.value = value;
  5045. ruleValidationResult = ruleValidator.validate(value, rule);
  5046. rule.isValid = ruleValidationResult;
  5047. if (!ruleValidationResult) {
  5048. result.isValid = false;
  5049. that._setDefaultMessage(rule, ruleValidator, name);
  5050. result.brokenRule = rule
  5051. }
  5052. if (!rule.isValid)
  5053. return false
  5054. }
  5055. else
  5056. throw DX.Error("E0100");
  5057. });
  5058. return result
  5059. },
  5060. registerValidatorInGroup: function(group, validator) {
  5061. var groupConfig = DX.validationEngine.addGroup(group);
  5062. if ($.inArray(validator, groupConfig.validators) < 0)
  5063. groupConfig.validators.push(validator)
  5064. },
  5065. removeRegistredValidator: function(group, validator) {
  5066. var config = DX.validationEngine.getGroupConfig(group),
  5067. validatorsInGroup = config && config.validators;
  5068. var index = $.inArray(validator, validatorsInGroup);
  5069. if (index > -1)
  5070. validatorsInGroup.splice(index, 1)
  5071. },
  5072. validateGroup: function(group) {
  5073. var groupConfig = DX.validationEngine.getGroupConfig(group);
  5074. if (!groupConfig)
  5075. throw DX.Error("E0110");
  5076. return groupConfig.validate()
  5077. },
  5078. resetGroup: function(group) {
  5079. var groupConfig = DX.validationEngine.getGroupConfig(group);
  5080. if (!groupConfig)
  5081. throw DX.Error("E0110");
  5082. return groupConfig.reset()
  5083. }
  5084. };
  5085. DX.validationEngine.initGroups()
  5086. })(jQuery, DevExpress);
  5087. /*! Module core, file data.errors.js */
  5088. (function($, DX) {
  5089. $.extend(DX.ERROR_MESSAGES, {
  5090. E4000: "[DevExpress.data]: {0}",
  5091. E4001: "Unknown aggregating function is detected: '{0}'",
  5092. E4002: "Unsupported OData protocol version is used",
  5093. E4003: "Unknown filter operation is used: {0}",
  5094. E4004: "The thenby() method is called before the sortby() method",
  5095. E4005: "Store requires a key expression for this operation",
  5096. E4006: "ArrayStore 'data' option must be an array",
  5097. E4007: "Compound keys cannot be auto-generated",
  5098. E4008: "Attempt to insert an item with the a duplicated key",
  5099. E4009: "Data item with specified key value cannot be found",
  5100. E4010: "CustomStore does not support creating queries",
  5101. E4011: "Custom Store method is not implemented or is not a function: {0}",
  5102. E4012: "Custom Store method returns an invalid value: {0}",
  5103. E4013: "Local Store requires the 'name' configuration option is specified",
  5104. E4014: "Unknown key type is detected: {0}",
  5105. E4015: "Unknown entity name or alias is used: {0}",
  5106. E4016: "The compileSetter(expr) method is called with 'self' passed as a parameter",
  5107. E4017: "Keys cannot be modified"
  5108. })
  5109. })(jQuery, DevExpress);
  5110. /*! Module core, file data.js */
  5111. (function($, DX, undefined) {
  5112. var bracketsToDots = function(expr) {
  5113. return expr.replace(/\[/g, ".").replace(/\]/g, "")
  5114. };
  5115. var unwrapObservable = DX.utils.unwrapObservable;
  5116. var isObservable = function(value) {
  5117. return DX.support.hasKo && ko.isObservable(value)
  5118. };
  5119. var readPropValue = function(obj, propName) {
  5120. if (propName === "this")
  5121. return obj;
  5122. return obj[propName]
  5123. };
  5124. var assignPropValue = function(obj, propName, value, options) {
  5125. if (propName === "this")
  5126. throw new DX.Error("E4016");
  5127. var propValue = obj[propName];
  5128. if (options.unwrapObservables && isObservable(propValue))
  5129. propValue(value);
  5130. else
  5131. obj[propName] = value
  5132. };
  5133. var prepareOptions = function(options) {
  5134. options = options || {};
  5135. options.unwrapObservables = options.unwrapObservables !== undefined ? options.unwrapObservables : true;
  5136. return options
  5137. };
  5138. var unwrap = function(value, options) {
  5139. return options.unwrapObservables ? unwrapObservable(value) : value
  5140. };
  5141. var compileGetter = function(expr) {
  5142. if (arguments.length > 1)
  5143. expr = $.makeArray(arguments);
  5144. if (!expr || expr === "this")
  5145. return function(obj) {
  5146. return obj
  5147. };
  5148. if ($.isFunction(expr))
  5149. return expr;
  5150. if ($.isArray(expr))
  5151. return combineGetters(expr);
  5152. expr = bracketsToDots(expr);
  5153. var path = expr.split(".");
  5154. return function(obj, options) {
  5155. options = prepareOptions(options);
  5156. var current = unwrap(obj, options);
  5157. $.each(path, function() {
  5158. if (!current)
  5159. return false;
  5160. var next = unwrap(current[this], options);
  5161. if ($.isFunction(next) && !options.functionsAsIs)
  5162. next = next.call(current);
  5163. current = next
  5164. });
  5165. return current
  5166. }
  5167. };
  5168. var combineGetters = function(getters) {
  5169. var compiledGetters = {};
  5170. $.each(getters, function() {
  5171. compiledGetters[this] = compileGetter(this)
  5172. });
  5173. return function(obj, options) {
  5174. var result = {};
  5175. $.each(compiledGetters, function(name) {
  5176. var value = this(obj, options),
  5177. current,
  5178. path,
  5179. last,
  5180. i;
  5181. if (value === undefined)
  5182. return;
  5183. current = result;
  5184. path = name.split(".");
  5185. last = path.length - 1;
  5186. for (i = 0; i < last; i++)
  5187. current = current[path[i]] = {};
  5188. current[path[i]] = value
  5189. });
  5190. return result
  5191. }
  5192. };
  5193. var compileSetter = function(expr) {
  5194. expr = expr || "this";
  5195. expr = bracketsToDots(expr);
  5196. var pos = expr.lastIndexOf("."),
  5197. targetGetter = compileGetter(expr.substr(0, pos)),
  5198. targetPropName = expr.substr(1 + pos);
  5199. return function(obj, value, options) {
  5200. options = prepareOptions(options);
  5201. var target = targetGetter(obj, {
  5202. functionsAsIs: options.functionsAsIs,
  5203. unwrapObservables: options.unwrapObservables
  5204. }),
  5205. prevTargetValue = readPropValue(target, targetPropName);
  5206. if (!options.functionsAsIs && $.isFunction(prevTargetValue) && !isObservable(prevTargetValue))
  5207. target[targetPropName](value);
  5208. else {
  5209. prevTargetValue = unwrap(prevTargetValue, options);
  5210. if (options.merge && $.isPlainObject(value) && (prevTargetValue === undefined || $.isPlainObject(prevTargetValue)) && !(value instanceof $.Event)) {
  5211. if (!prevTargetValue)
  5212. assignPropValue(target, targetPropName, {}, options);
  5213. DX.utils.deepExtendArraySafe(unwrap(readPropValue(target, targetPropName), options), value)
  5214. }
  5215. else
  5216. assignPropValue(target, targetPropName, value, options)
  5217. }
  5218. }
  5219. };
  5220. var normalizeBinaryCriterion = function(crit) {
  5221. return [crit[0], crit.length < 3 ? "=" : String(crit[1]).toLowerCase(), crit.length < 2 ? true : crit[crit.length - 1]]
  5222. };
  5223. var normalizeSortingInfo = function(info) {
  5224. if (!$.isArray(info))
  5225. info = [info];
  5226. return $.map(info, function(i) {
  5227. return {
  5228. selector: $.isFunction(i) || typeof i === "string" ? i : i.getter || i.field || i.selector,
  5229. desc: !!(i.desc || String(i.dir).charAt(0).toLowerCase() === "d")
  5230. }
  5231. })
  5232. };
  5233. var Guid = DX.Class.inherit({
  5234. ctor: function(value) {
  5235. if (value)
  5236. value = String(value);
  5237. this._value = this._normalize(value || this._generate())
  5238. },
  5239. _normalize: function(value) {
  5240. value = value.replace(/[^a-f0-9]/ig, "").toLowerCase();
  5241. while (value.length < 32)
  5242. value += "0";
  5243. return [value.substr(0, 8), value.substr(8, 4), value.substr(12, 4), value.substr(16, 4), value.substr(20, 12)].join("-")
  5244. },
  5245. _generate: function() {
  5246. var value = "";
  5247. for (var i = 0; i < 32; i++)
  5248. value += Math.round(Math.random() * 15).toString(16);
  5249. return value
  5250. },
  5251. toString: function() {
  5252. return this._value
  5253. },
  5254. valueOf: function() {
  5255. return this._value
  5256. },
  5257. toJSON: function() {
  5258. return this._value
  5259. }
  5260. });
  5261. var toComparable = function(value, caseSensitive) {
  5262. if (value instanceof Date)
  5263. return value.getTime();
  5264. if (value instanceof Guid)
  5265. return value.valueOf();
  5266. if (!caseSensitive && typeof value === "string")
  5267. return value.toLowerCase();
  5268. return value
  5269. };
  5270. var keysEqual = function(keyExpr, key1, key2) {
  5271. if ($.isArray(keyExpr)) {
  5272. var names = $.map(key1, function(v, k) {
  5273. return k
  5274. }),
  5275. name;
  5276. for (var i = 0; i < names.length; i++) {
  5277. name = names[i];
  5278. if (toComparable(key1[name], true) != toComparable(key2[name], true))
  5279. return false
  5280. }
  5281. return true
  5282. }
  5283. return toComparable(key1, true) == toComparable(key2, true)
  5284. };
  5285. var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  5286. var base64_encode = function(input) {
  5287. if (!$.isArray(input))
  5288. input = stringToByteArray(String(input));
  5289. var result = "";
  5290. function getBase64Char(index) {
  5291. return BASE64_CHARS.charAt(index)
  5292. }
  5293. for (var i = 0; i < input.length; i += 3) {
  5294. var octet1 = input[i],
  5295. octet2 = input[i + 1],
  5296. octet3 = input[i + 2];
  5297. result += $.map([octet1 >> 2, (octet1 & 3) << 4 | octet2 >> 4, isNaN(octet2) ? 64 : (octet2 & 15) << 2 | octet3 >> 6, isNaN(octet3) ? 64 : octet3 & 63], getBase64Char).join("")
  5298. }
  5299. return result
  5300. };
  5301. var stringToByteArray = function(str) {
  5302. var bytes = [],
  5303. code,
  5304. i;
  5305. for (i = 0; i < str.length; i++) {
  5306. code = str.charCodeAt(i);
  5307. if (code < 128)
  5308. bytes.push(code);
  5309. else if (code < 2048)
  5310. bytes.push(192 + (code >> 6), 128 + (code & 63));
  5311. else if (code < 65536)
  5312. bytes.push(224 + (code >> 12), 128 + (code >> 6 & 63), 128 + (code & 63));
  5313. else if (code < 2097152)
  5314. bytes.push(240 + (code >> 18), 128 + (code >> 12 & 63), 128 + (code >> 6 & 63), 128 + (code & 63))
  5315. }
  5316. return bytes
  5317. };
  5318. var errorMessageFromXhr = function() {
  5319. var textStatusMessages = {
  5320. timeout: "Network connection timeout",
  5321. error: "Unspecified network error",
  5322. parsererror: "Unexpected server response"
  5323. };
  5324. var textStatusDetails = {
  5325. timeout: "possible causes: the remote host is not accessible, overloaded or is not included into the domain white-list when being run in the native container",
  5326. error: "if the remote host is located on another domain, make sure it properly supports cross-origin resource sharing (CORS), or use the JSONP approach instead",
  5327. parsererror: "the remote host did not respond with valid JSON data"
  5328. };
  5329. var explainTextStatus = function(textStatus) {
  5330. var result = textStatusMessages[textStatus];
  5331. if (!result)
  5332. return textStatus;
  5333. result += " (" + textStatusDetails[textStatus] + ")";
  5334. return result
  5335. };
  5336. return function(xhr, textStatus) {
  5337. if (xhr.status < 400)
  5338. return explainTextStatus(textStatus);
  5339. return xhr.statusText
  5340. }
  5341. }();
  5342. var aggregators = {
  5343. count: {
  5344. seed: 0,
  5345. step: function(count) {
  5346. return 1 + count
  5347. }
  5348. },
  5349. sum: {
  5350. seed: 0,
  5351. step: function(sum, item) {
  5352. return sum + item
  5353. }
  5354. },
  5355. min: {step: function(min, item) {
  5356. return item < min ? item : min
  5357. }},
  5358. max: {step: function(max, item) {
  5359. return item > max ? item : max
  5360. }},
  5361. avg: {
  5362. seed: [0, 0],
  5363. step: function(pair, value) {
  5364. return [pair[0] + value, pair[1] + 1]
  5365. },
  5366. finalize: function(pair) {
  5367. return pair[1] ? pair[0] / pair[1] : NaN
  5368. }
  5369. }
  5370. };
  5371. function handleError(error) {
  5372. var id = "E4000";
  5373. if (error && "__id" in error)
  5374. id = error.__id;
  5375. DX.log(id, error)
  5376. }
  5377. function multiLevelSearch(options) {
  5378. var itemsGetter = options.itemsGetter,
  5379. itemsSetter = options.itemsSetter,
  5380. criteria = options.criteria,
  5381. data = options.data;
  5382. function selector(x) {
  5383. var hash,
  5384. items = itemsGetter(x);
  5385. if (isNotAnEmptyArray(items)) {
  5386. hash = {};
  5387. itemsSetter(hash, multiLevelSearch({
  5388. data: items,
  5389. criteria: criteria,
  5390. itemsGetter: itemsGetter,
  5391. itemsSetter: itemsSetter
  5392. }));
  5393. return $.extend({}, x, hash)
  5394. }
  5395. return x
  5396. }
  5397. function criterion(x) {
  5398. return isNotAnEmptyArray(itemsGetter(x))
  5399. }
  5400. function isNotAnEmptyArray(x) {
  5401. return $.isArray(x) && x.length > 0
  5402. }
  5403. return DX.data.query(data).select(selector).filter([[criterion], "or", criteria]).toArray()
  5404. }
  5405. var data = DX.data = {
  5406. utils: {
  5407. compileGetter: compileGetter,
  5408. compileSetter: compileSetter,
  5409. normalizeBinaryCriterion: normalizeBinaryCriterion,
  5410. normalizeSortingInfo: normalizeSortingInfo,
  5411. toComparable: toComparable,
  5412. keysEqual: keysEqual,
  5413. errorMessageFromXhr: errorMessageFromXhr,
  5414. aggregators: aggregators,
  5415. multiLevelSearch: multiLevelSearch
  5416. },
  5417. Guid: Guid,
  5418. base64_encode: base64_encode,
  5419. queryImpl: {},
  5420. queryAdapters: {},
  5421. query: function() {
  5422. var impl = $.isArray(arguments[0]) ? "array" : "remote";
  5423. return data.queryImpl[impl].apply(this, arguments)
  5424. },
  5425. errorHandler: null,
  5426. _errorHandler: function(error) {
  5427. handleError(error);
  5428. if (data.errorHandler)
  5429. data.errorHandler(error)
  5430. }
  5431. }
  5432. })(jQuery, DevExpress);
  5433. /*! Module core, file data.aggregateCalculator.js */
  5434. (function($, DX, undefined) {
  5435. var data = DX.data,
  5436. utils = data.utils;
  5437. function isCount(aggregator) {
  5438. return aggregator === utils.aggregators.count
  5439. }
  5440. function normalizeAggregate(aggregate) {
  5441. var selector = utils.compileGetter(aggregate.selector),
  5442. aggregator = aggregate.aggregator;
  5443. if (typeof aggregator === "string") {
  5444. aggregator = data.utils.aggregators[aggregator];
  5445. if (!aggregator)
  5446. throw DX.Error("E4001", aggregate.aggregator);
  5447. }
  5448. return {
  5449. selector: selector,
  5450. aggregator: aggregator
  5451. }
  5452. }
  5453. data.AggregateCalculator = DX.Class.inherit({
  5454. ctor: function(options) {
  5455. this._data = options.data;
  5456. this._groupLevel = options.groupLevel || 0;
  5457. this._totalAggregates = $.map(options.totalAggregates || [], normalizeAggregate);
  5458. this._groupAggregates = $.map(options.groupAggregates || [], normalizeAggregate);
  5459. this._totals = []
  5460. },
  5461. calculate: function() {
  5462. if (this._totalAggregates.length)
  5463. this._calculateTotals(0, {items: this._data});
  5464. if (this._groupAggregates.length && this._groupLevel > 0)
  5465. this._calculateGroups(0, {items: this._data})
  5466. },
  5467. totalAggregates: function() {
  5468. return this._totals
  5469. },
  5470. _aggregate: function(data, aggregates, container) {
  5471. var i,
  5472. j;
  5473. for (i = 0; i < aggregates.length; i++) {
  5474. if (isCount(aggregates[i].aggregator)) {
  5475. container[i] = (container[i] || 0) + data.items.length;
  5476. continue
  5477. }
  5478. for (j = 0; j < data.items.length; j++)
  5479. this._accumulate(i, aggregates[i], container, data.items[j])
  5480. }
  5481. },
  5482. _calculateTotals: function(level, data) {
  5483. var i;
  5484. if (level === 0)
  5485. this._totals = this._seed(this._totalAggregates);
  5486. if (level === this._groupLevel)
  5487. this._aggregate(data, this._totalAggregates, this._totals);
  5488. else
  5489. for (i = 0; i < data.items.length; i++)
  5490. this._calculateTotals(level + 1, data.items[i]);
  5491. if (level === 0)
  5492. this._totals = this._finalize(this._totalAggregates, this._totals)
  5493. },
  5494. _calculateGroups: function(level, data, outerAggregates) {
  5495. var i,
  5496. innerAggregates;
  5497. if (level === this._groupLevel)
  5498. this._aggregate(data, this._groupAggregates, outerAggregates);
  5499. else
  5500. for (i = 0; i < data.items.length; i++) {
  5501. innerAggregates = this._seed(this._groupAggregates);
  5502. this._calculateGroups(level + 1, data.items[i], innerAggregates);
  5503. data.items[i].aggregates = this._finalize(this._groupAggregates, innerAggregates);
  5504. if (level > 0) {
  5505. outerAggregates = outerAggregates || this._seed(this._groupAggregates);
  5506. this._calculateGroups(level + 1, data.items[i], outerAggregates)
  5507. }
  5508. }
  5509. },
  5510. _seed: function(aggregates) {
  5511. return $.map(aggregates, function(aggregate) {
  5512. var aggregator = aggregate.aggregator,
  5513. seed = "seed" in aggregator ? aggregator.seed : NaN;
  5514. return $.isArray(seed) ? [seed] : seed
  5515. })
  5516. },
  5517. _accumulate: function(aggregateIndex, aggregate, results, item) {
  5518. var value = aggregate.selector(item),
  5519. aggregator = aggregate.aggregator;
  5520. results[aggregateIndex] = results[aggregateIndex] !== results[aggregateIndex] ? value : aggregator.step(results[aggregateIndex], value)
  5521. },
  5522. _finalize: function(aggregates, results) {
  5523. return $.map(aggregates, function(aggregate, index) {
  5524. var fin = aggregate.aggregator.finalize;
  5525. return fin ? fin(results[index]) : results[index]
  5526. })
  5527. }
  5528. })
  5529. })(jQuery, DevExpress);
  5530. /*! Module core, file data.query.array.js */
  5531. (function($, DX, undefined) {
  5532. var Class = DX.Class,
  5533. data = DX.data,
  5534. queryImpl = data.queryImpl,
  5535. compileGetter = data.utils.compileGetter,
  5536. toComparable = data.utils.toComparable;
  5537. var Iterator = Class.inherit({
  5538. toArray: function() {
  5539. var result = [];
  5540. this.reset();
  5541. while (this.next())
  5542. result.push(this.current());
  5543. return result
  5544. },
  5545. countable: function() {
  5546. return false
  5547. }
  5548. });
  5549. var ArrayIterator = Iterator.inherit({
  5550. ctor: function(array) {
  5551. this.array = array;
  5552. this.index = -1
  5553. },
  5554. next: function() {
  5555. if (this.index + 1 < this.array.length) {
  5556. this.index++;
  5557. return true
  5558. }
  5559. return false
  5560. },
  5561. current: function() {
  5562. return this.array[this.index]
  5563. },
  5564. reset: function() {
  5565. this.index = -1
  5566. },
  5567. toArray: function() {
  5568. return this.array.slice(0)
  5569. },
  5570. countable: function() {
  5571. return true
  5572. },
  5573. count: function() {
  5574. return this.array.length
  5575. }
  5576. });
  5577. var WrappedIterator = Iterator.inherit({
  5578. ctor: function(iter) {
  5579. this.iter = iter
  5580. },
  5581. next: function() {
  5582. return this.iter.next()
  5583. },
  5584. current: function() {
  5585. return this.iter.current()
  5586. },
  5587. reset: function() {
  5588. return this.iter.reset()
  5589. }
  5590. });
  5591. var MapIterator = WrappedIterator.inherit({
  5592. ctor: function(iter, mapper) {
  5593. this.callBase(iter);
  5594. this.index = -1;
  5595. this.mapper = mapper
  5596. },
  5597. current: function() {
  5598. return this.mapper(this.callBase(), this.index)
  5599. },
  5600. next: function() {
  5601. var hasNext = this.callBase();
  5602. if (hasNext)
  5603. this.index++;
  5604. return hasNext
  5605. }
  5606. });
  5607. var SortIterator = Iterator.inherit({
  5608. ctor: function(iter, getter, desc) {
  5609. if (!(iter instanceof MapIterator))
  5610. iter = new MapIterator(iter, this._wrap);
  5611. this.iter = iter;
  5612. this.rules = [{
  5613. getter: getter,
  5614. desc: desc
  5615. }]
  5616. },
  5617. thenBy: function(getter, desc) {
  5618. var result = new SortIterator(this.sortedIter || this.iter, getter, desc);
  5619. if (!this.sortedIter)
  5620. result.rules = this.rules.concat(result.rules);
  5621. return result
  5622. },
  5623. next: function() {
  5624. this._ensureSorted();
  5625. return this.sortedIter.next()
  5626. },
  5627. current: function() {
  5628. this._ensureSorted();
  5629. return this.sortedIter.current()
  5630. },
  5631. reset: function() {
  5632. delete this.sortedIter
  5633. },
  5634. countable: function() {
  5635. return this.sortedIter || this.iter.countable()
  5636. },
  5637. count: function() {
  5638. if (this.sortedIter)
  5639. return this.sortedIter.count();
  5640. return this.iter.count()
  5641. },
  5642. _ensureSorted: function() {
  5643. if (this.sortedIter)
  5644. return;
  5645. $.each(this.rules, function() {
  5646. this.getter = compileGetter(this.getter)
  5647. });
  5648. this.sortedIter = new MapIterator(new ArrayIterator(this.iter.toArray().sort($.proxy(this._compare, this))), this._unwrap)
  5649. },
  5650. _wrap: function(record, index) {
  5651. return {
  5652. index: index,
  5653. value: record
  5654. }
  5655. },
  5656. _unwrap: function(wrappedItem) {
  5657. return wrappedItem.value
  5658. },
  5659. _compare: function(x, y) {
  5660. var xIndex = x.index,
  5661. yIndex = y.index;
  5662. x = x.value;
  5663. y = y.value;
  5664. if (x === y)
  5665. return xIndex - yIndex;
  5666. for (var i = 0, rulesCount = this.rules.length; i < rulesCount; i++) {
  5667. var rule = this.rules[i],
  5668. xValue = toComparable(rule.getter(x)),
  5669. yValue = toComparable(rule.getter(y)),
  5670. factor = rule.desc ? -1 : 1;
  5671. if (xValue < yValue)
  5672. return -factor;
  5673. if (xValue > yValue)
  5674. return factor;
  5675. if (xValue !== yValue)
  5676. return !xValue ? -factor : factor
  5677. }
  5678. return xIndex - yIndex
  5679. }
  5680. });
  5681. var compileCriteria = function() {
  5682. var compileGroup = function(crit) {
  5683. var operands = [],
  5684. bag = ["return function(d) { return "],
  5685. index = 0,
  5686. pushAnd = false;
  5687. $.each(crit, function() {
  5688. if ($.isArray(this) || $.isFunction(this)) {
  5689. if (pushAnd)
  5690. bag.push(" && ");
  5691. operands.push(compileCriteria(this));
  5692. bag.push("op[", index, "](d)");
  5693. index++;
  5694. pushAnd = true
  5695. }
  5696. else {
  5697. bag.push(/and|&/i.test(this) ? " && " : " || ");
  5698. pushAnd = false
  5699. }
  5700. });
  5701. bag.push(" }");
  5702. return new Function("op", bag.join(""))(operands)
  5703. };
  5704. var toString = function(value) {
  5705. return DX.utils.isDefined(value) ? value.toString() : ''
  5706. };
  5707. var compileBinary = function(crit) {
  5708. crit = data.utils.normalizeBinaryCriterion(crit);
  5709. var getter = compileGetter(crit[0]),
  5710. op = crit[1],
  5711. value = crit[2];
  5712. value = toComparable(value);
  5713. switch (op.toLowerCase()) {
  5714. case"=":
  5715. return compileEquals(getter, value);
  5716. case"<>":
  5717. return compileEquals(getter, value, true);
  5718. case">":
  5719. return function(obj) {
  5720. return toComparable(getter(obj)) > value
  5721. };
  5722. case"<":
  5723. return function(obj) {
  5724. return toComparable(getter(obj)) < value
  5725. };
  5726. case">=":
  5727. return function(obj) {
  5728. return toComparable(getter(obj)) >= value
  5729. };
  5730. case"<=":
  5731. return function(obj) {
  5732. return toComparable(getter(obj)) <= value
  5733. };
  5734. case"startswith":
  5735. return function(obj) {
  5736. return toComparable(toString(getter(obj))).indexOf(value) === 0
  5737. };
  5738. case"endswith":
  5739. return function(obj) {
  5740. var getterValue = toComparable(toString(getter(obj))),
  5741. searchValue = toString(value);
  5742. if (getterValue.length < searchValue.length)
  5743. return false;
  5744. return getterValue.lastIndexOf(value) === getterValue.length - value.length
  5745. };
  5746. case"contains":
  5747. return function(obj) {
  5748. return toComparable(toString(getter(obj))).indexOf(value) > -1
  5749. };
  5750. case"notcontains":
  5751. return function(obj) {
  5752. return toComparable(toString(getter(obj))).indexOf(value) === -1
  5753. }
  5754. }
  5755. throw DX.Error("E4003", op);
  5756. };
  5757. function compileEquals(getter, value, negate) {
  5758. return function(obj) {
  5759. obj = toComparable(getter(obj));
  5760. var result = useStrictComparison(value) ? obj === value : obj == value;
  5761. if (negate)
  5762. result = !result;
  5763. return result
  5764. }
  5765. }
  5766. function useStrictComparison(value) {
  5767. return value === "" || value === 0 || value === null || value === false || value === undefined
  5768. }
  5769. return function(crit) {
  5770. if ($.isFunction(crit))
  5771. return crit;
  5772. if ($.isArray(crit[0]))
  5773. return compileGroup(crit);
  5774. return compileBinary(crit)
  5775. }
  5776. }();
  5777. var FilterIterator = WrappedIterator.inherit({
  5778. ctor: function(iter, criteria) {
  5779. this.callBase(iter);
  5780. this.criteria = compileCriteria(criteria)
  5781. },
  5782. next: function() {
  5783. while (this.iter.next())
  5784. if (this.criteria(this.current()))
  5785. return true;
  5786. return false
  5787. }
  5788. });
  5789. var GroupIterator = Iterator.inherit({
  5790. ctor: function(iter, getter) {
  5791. this.iter = iter;
  5792. this.getter = getter
  5793. },
  5794. next: function() {
  5795. this._ensureGrouped();
  5796. return this.groupedIter.next()
  5797. },
  5798. current: function() {
  5799. this._ensureGrouped();
  5800. return this.groupedIter.current()
  5801. },
  5802. reset: function() {
  5803. delete this.groupedIter
  5804. },
  5805. countable: function() {
  5806. return !!this.groupedIter
  5807. },
  5808. count: function() {
  5809. return this.groupedIter.count()
  5810. },
  5811. _ensureGrouped: function() {
  5812. if (this.groupedIter)
  5813. return;
  5814. var hash = {},
  5815. keys = [],
  5816. iter = this.iter,
  5817. getter = compileGetter(this.getter);
  5818. iter.reset();
  5819. while (iter.next()) {
  5820. var current = iter.current(),
  5821. key = getter(current);
  5822. if (key in hash)
  5823. hash[key].push(current);
  5824. else {
  5825. hash[key] = [current];
  5826. keys.push(key)
  5827. }
  5828. }
  5829. this.groupedIter = new ArrayIterator($.map(keys, function(key) {
  5830. return {
  5831. key: key,
  5832. items: hash[key]
  5833. }
  5834. }))
  5835. }
  5836. });
  5837. var SelectIterator = WrappedIterator.inherit({
  5838. ctor: function(iter, getter) {
  5839. this.callBase(iter);
  5840. this.getter = compileGetter(getter)
  5841. },
  5842. current: function() {
  5843. return this.getter(this.callBase())
  5844. },
  5845. countable: function() {
  5846. return this.iter.countable()
  5847. },
  5848. count: function() {
  5849. return this.iter.count()
  5850. }
  5851. });
  5852. var SliceIterator = WrappedIterator.inherit({
  5853. ctor: function(iter, skip, take) {
  5854. this.callBase(iter);
  5855. this.skip = Math.max(0, skip);
  5856. this.take = Math.max(0, take);
  5857. this.pos = 0
  5858. },
  5859. next: function() {
  5860. if (this.pos >= this.skip + this.take)
  5861. return false;
  5862. while (this.pos < this.skip && this.iter.next())
  5863. this.pos++;
  5864. this.pos++;
  5865. return this.iter.next()
  5866. },
  5867. reset: function() {
  5868. this.callBase();
  5869. this.pos = 0
  5870. },
  5871. countable: function() {
  5872. return this.iter.countable()
  5873. },
  5874. count: function() {
  5875. return Math.min(this.iter.count() - this.skip, this.take)
  5876. }
  5877. });
  5878. queryImpl.array = function(iter, queryOptions) {
  5879. queryOptions = queryOptions || {};
  5880. if (!(iter instanceof Iterator))
  5881. iter = new ArrayIterator(iter);
  5882. var handleError = function(error) {
  5883. var handler = queryOptions.errorHandler;
  5884. if (handler)
  5885. handler(error);
  5886. data._errorHandler(error)
  5887. };
  5888. var aggregateCore = function(aggregator) {
  5889. var d = $.Deferred().fail(handleError),
  5890. seed,
  5891. step = aggregator.step,
  5892. finalize = aggregator.finalize;
  5893. try {
  5894. iter.reset();
  5895. if ("seed" in aggregator)
  5896. seed = aggregator.seed;
  5897. else
  5898. seed = iter.next() ? iter.current() : NaN;
  5899. var accumulator = seed;
  5900. while (iter.next())
  5901. accumulator = step(accumulator, iter.current());
  5902. d.resolve(finalize ? finalize(accumulator) : accumulator)
  5903. }
  5904. catch(x) {
  5905. d.reject(x)
  5906. }
  5907. return d.promise()
  5908. };
  5909. var aggregate = function(seed, step, finalize) {
  5910. if (arguments.length < 2)
  5911. return aggregateCore({step: arguments[0]});
  5912. return aggregateCore({
  5913. seed: seed,
  5914. step: step,
  5915. finalize: finalize
  5916. })
  5917. };
  5918. var standardAggregate = function(name) {
  5919. return aggregateCore(data.utils.aggregators[name])
  5920. };
  5921. var select = function(getter) {
  5922. if (!$.isFunction(getter) && !$.isArray(getter))
  5923. getter = $.makeArray(arguments);
  5924. return chainQuery(new SelectIterator(iter, getter))
  5925. };
  5926. var selectProp = function(name) {
  5927. return select(compileGetter(name))
  5928. };
  5929. var chainQuery = function(iter) {
  5930. return queryImpl.array(iter, queryOptions)
  5931. };
  5932. return {
  5933. toArray: function() {
  5934. return iter.toArray()
  5935. },
  5936. enumerate: function() {
  5937. var d = $.Deferred().fail(handleError);
  5938. try {
  5939. d.resolve(iter.toArray())
  5940. }
  5941. catch(x) {
  5942. d.reject(x)
  5943. }
  5944. return d.promise()
  5945. },
  5946. sortBy: function(getter, desc) {
  5947. return chainQuery(new SortIterator(iter, getter, desc))
  5948. },
  5949. thenBy: function(getter, desc) {
  5950. if (iter instanceof SortIterator)
  5951. return chainQuery(iter.thenBy(getter, desc));
  5952. throw DX.Error("E4004");
  5953. },
  5954. filter: function(criteria) {
  5955. if (!$.isArray(criteria))
  5956. criteria = $.makeArray(arguments);
  5957. return chainQuery(new FilterIterator(iter, criteria))
  5958. },
  5959. slice: function(skip, take) {
  5960. if (take === undefined)
  5961. take = Number.MAX_VALUE;
  5962. return chainQuery(new SliceIterator(iter, skip, take))
  5963. },
  5964. select: select,
  5965. groupBy: function(getter) {
  5966. return chainQuery(new GroupIterator(iter, getter))
  5967. },
  5968. aggregate: aggregate,
  5969. count: function() {
  5970. if (iter.countable()) {
  5971. var d = $.Deferred().fail(handleError);
  5972. try {
  5973. d.resolve(iter.count())
  5974. }
  5975. catch(x) {
  5976. d.reject(x)
  5977. }
  5978. return d.promise()
  5979. }
  5980. return standardAggregate("count")
  5981. },
  5982. sum: function(getter) {
  5983. if (getter)
  5984. return selectProp(getter).sum();
  5985. return standardAggregate("sum")
  5986. },
  5987. min: function(getter) {
  5988. if (getter)
  5989. return selectProp(getter).min();
  5990. return standardAggregate("min")
  5991. },
  5992. max: function(getter) {
  5993. if (getter)
  5994. return selectProp(getter).max();
  5995. return standardAggregate("max")
  5996. },
  5997. avg: function(getter) {
  5998. if (getter)
  5999. return selectProp(getter).avg();
  6000. return standardAggregate("avg")
  6001. }
  6002. }
  6003. }
  6004. })(jQuery, DevExpress);
  6005. /*! Module core, file data.query.remote.js */
  6006. (function($, DX, undefined) {
  6007. var data = DX.data,
  6008. queryImpl = data.queryImpl;
  6009. queryImpl.remote = function(url, queryOptions, tasks) {
  6010. tasks = tasks || [];
  6011. queryOptions = queryOptions || {};
  6012. var createTask = function(name, args) {
  6013. return {
  6014. name: name,
  6015. args: args
  6016. }
  6017. };
  6018. var exec = function(executorTask) {
  6019. var d = $.Deferred(),
  6020. _adapterFactory,
  6021. _adapter,
  6022. _taskQueue,
  6023. _currentTask,
  6024. _mergedSortArgs;
  6025. var rejectWithNotify = function(error) {
  6026. var handler = queryOptions.errorHandler;
  6027. if (handler)
  6028. handler(error);
  6029. data._errorHandler(error);
  6030. d.reject(error)
  6031. };
  6032. function mergeSortTask(task) {
  6033. switch (task.name) {
  6034. case"sortBy":
  6035. _mergedSortArgs = [task.args];
  6036. return true;
  6037. case"thenBy":
  6038. if (!_mergedSortArgs)
  6039. throw DX.Error("E4004");
  6040. _mergedSortArgs.push(task.args);
  6041. return true
  6042. }
  6043. return false
  6044. }
  6045. function unmergeSortTasks() {
  6046. var head = _taskQueue[0],
  6047. unmergedTasks = [];
  6048. if (head && head.name === "multiSort") {
  6049. _taskQueue.shift();
  6050. $.each(head.args[0], function() {
  6051. unmergedTasks.push(createTask(unmergedTasks.length ? "thenBy" : "sortBy", this))
  6052. })
  6053. }
  6054. _taskQueue = unmergedTasks.concat(_taskQueue)
  6055. }
  6056. try {
  6057. _adapterFactory = queryOptions.adapter || "odata";
  6058. if (!$.isFunction(_adapterFactory))
  6059. _adapterFactory = data.queryAdapters[_adapterFactory];
  6060. _adapter = _adapterFactory(queryOptions);
  6061. _taskQueue = [].concat(tasks).concat(executorTask);
  6062. while (_taskQueue.length) {
  6063. _currentTask = _taskQueue[0];
  6064. if (!mergeSortTask(_currentTask)) {
  6065. if (_mergedSortArgs) {
  6066. _taskQueue.unshift(createTask("multiSort", [_mergedSortArgs]));
  6067. _mergedSortArgs = null;
  6068. continue
  6069. }
  6070. if (String(_currentTask.name) !== "enumerate")
  6071. if (!_adapter[_currentTask.name] || _adapter[_currentTask.name].apply(_adapter, _currentTask.args) === false)
  6072. break
  6073. }
  6074. _taskQueue.shift()
  6075. }
  6076. unmergeSortTasks();
  6077. _adapter.exec(url).done(function(result, extra) {
  6078. if (!_taskQueue.length)
  6079. d.resolve(result, extra);
  6080. else {
  6081. var clientChain = queryImpl.array(result, {errorHandler: queryOptions.errorHandler});
  6082. $.each(_taskQueue, function() {
  6083. clientChain = clientChain[this.name].apply(clientChain, this.args)
  6084. });
  6085. clientChain.done(d.resolve).fail(d.reject)
  6086. }
  6087. }).fail(rejectWithNotify)
  6088. }
  6089. catch(x) {
  6090. rejectWithNotify(x)
  6091. }
  6092. return d.promise()
  6093. };
  6094. var query = {};
  6095. $.each(["sortBy", "thenBy", "filter", "slice", "select", "groupBy"], function() {
  6096. var name = String(this);
  6097. query[name] = function() {
  6098. return queryImpl.remote(url, queryOptions, tasks.concat(createTask(name, arguments)))
  6099. }
  6100. });
  6101. $.each(["count", "min", "max", "sum", "avg", "aggregate", "enumerate"], function() {
  6102. var name = String(this);
  6103. query[name] = function() {
  6104. return exec.call(this, createTask(name, arguments))
  6105. }
  6106. });
  6107. return query
  6108. }
  6109. })(jQuery, DevExpress);
  6110. /*! Module core, file data.odata.js */
  6111. (function($, DX, undefined) {
  6112. var data = DX.data,
  6113. utils = DX.utils,
  6114. Guid = data.Guid,
  6115. isDefined = utils.isDefined;
  6116. var DEFAULT_PROTOCOL_VERSION = 2;
  6117. var GUID_REGEX = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/;
  6118. var VERBOSE_DATE_REGEX = /^\/Date\((-?\d+)((\+|-)?(\d+)?)\)\/$/;
  6119. var ISO8601_DATE_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[-+]{1}\d{2}(:?)(\d{2})?)?$/;
  6120. var JSON_VERBOSE_MIME_TYPE = "application/json;odata=verbose";
  6121. function formatISO8601(date, skipZeroTime, skipTimezone) {
  6122. var ret = [];
  6123. var pad = function(n) {
  6124. if (n < 10)
  6125. return "0".concat(n);
  6126. return String(n)
  6127. };
  6128. var isZeroTime = function() {
  6129. return date.getHours() + date.getMinutes() + date.getSeconds() + date.getMilliseconds() < 1
  6130. };
  6131. ret.push(date.getFullYear());
  6132. ret.push("-");
  6133. ret.push(pad(date.getMonth() + 1));
  6134. ret.push("-");
  6135. ret.push(pad(date.getDate()));
  6136. if (!(skipZeroTime && isZeroTime())) {
  6137. ret.push("T");
  6138. ret.push(pad(date.getHours()));
  6139. ret.push(":");
  6140. ret.push(pad(date.getMinutes()));
  6141. ret.push(":");
  6142. ret.push(pad(date.getSeconds()));
  6143. if (date.getMilliseconds()) {
  6144. ret.push(".");
  6145. ret.push(date.getMilliseconds())
  6146. }
  6147. if (!skipTimezone)
  6148. ret.push("Z")
  6149. }
  6150. return ret.join("")
  6151. }
  6152. function parseISO8601(isoString) {
  6153. var result = new Date(0);
  6154. var chunks = isoString.replace("Z", "").split("T"),
  6155. date = /(\d{4})-(\d{2})-(\d{2})/.exec(chunks[0]),
  6156. time = /(\d{2}):(\d{2}):(\d{2})\.?(\d{0,7})?/.exec(chunks[1]);
  6157. result.setDate(Number(date[3]));
  6158. result.setMonth(Number(date[2]) - 1);
  6159. result.setFullYear(Number(date[1]));
  6160. if ($.isArray(time) && time.length) {
  6161. result.setHours(Number(time[1]));
  6162. result.setMinutes(Number(time[2]));
  6163. result.setSeconds(Number(time[3]));
  6164. result.setMilliseconds(Number(String(time[4]).substr(0, 3)) || 0)
  6165. }
  6166. return result
  6167. }
  6168. function isAbsoluteUrl(url) {
  6169. return /^(?:[a-z]+:)?\/\//i.test(url)
  6170. }
  6171. function toAbsoluteUrl(basePath, relativePath) {
  6172. var part,
  6173. baseParts = basePath.split("/"),
  6174. relativeParts = relativePath.split("/");
  6175. baseParts.pop();
  6176. while (relativeParts.length) {
  6177. part = relativeParts.shift();
  6178. if (part === "..")
  6179. baseParts.pop();
  6180. else
  6181. baseParts.push(part)
  6182. }
  6183. return baseParts.join("/")
  6184. }
  6185. var ajaxOptionsForRequest = function(protocolVersion, request, requestOptions) {
  6186. request = $.extend({
  6187. method: "get",
  6188. url: "",
  6189. params: {},
  6190. payload: null,
  6191. headers: {},
  6192. timeout: 30000
  6193. }, request);
  6194. requestOptions = requestOptions || {};
  6195. var beforeSend = requestOptions.beforeSend;
  6196. if (beforeSend)
  6197. beforeSend(request);
  6198. var method = (request.method || "get").toLowerCase(),
  6199. isGet = method === "get",
  6200. useJsonp = isGet && requestOptions.jsonp,
  6201. params = $.extend({}, request.params),
  6202. ajaxData = isGet ? params : formatPayload(request.payload),
  6203. qs = !isGet && $.param(params),
  6204. url = request.url,
  6205. contentType = !isGet && JSON_VERBOSE_MIME_TYPE;
  6206. if (qs)
  6207. url += (url.indexOf("?") > -1 ? "&" : "?") + qs;
  6208. if (useJsonp)
  6209. ajaxData["$format"] = "json";
  6210. return {
  6211. url: url,
  6212. data: ajaxData,
  6213. dataType: useJsonp ? "jsonp" : "json",
  6214. jsonp: useJsonp && "$callback",
  6215. type: method,
  6216. timeout: request.timeout,
  6217. headers: request.headers,
  6218. contentType: contentType,
  6219. accepts: {json: [JSON_VERBOSE_MIME_TYPE, "text/plain"].join()},
  6220. xhrFields: {withCredentials: requestOptions.withCredentials}
  6221. };
  6222. function formatPayload(payload) {
  6223. return JSON.stringify(payload, function(key, value) {
  6224. if (!(this[key] instanceof Date))
  6225. return value;
  6226. value = formatISO8601(this[key]);
  6227. switch (protocolVersion) {
  6228. case 2:
  6229. return value.substr(0, value.length - 1);
  6230. case 3:
  6231. case 4:
  6232. return value;
  6233. default:
  6234. throw DX.Error("E4002");
  6235. }
  6236. })
  6237. }
  6238. };
  6239. var sendRequest = function(protocolVersion, request, requestOptions) {
  6240. var d = $.Deferred();
  6241. var options = ajaxOptionsForRequest(protocolVersion, request, requestOptions);
  6242. $.ajax(options).always(function(obj, textStatus) {
  6243. var tuplet = interpretJsonFormat(obj, textStatus),
  6244. error = tuplet.error,
  6245. data = tuplet.data,
  6246. nextUrl = tuplet.nextUrl,
  6247. extra;
  6248. if (error)
  6249. d.reject(error);
  6250. else if (requestOptions.countOnly)
  6251. d.resolve(tuplet.count);
  6252. else if (nextUrl) {
  6253. if (!isAbsoluteUrl(nextUrl))
  6254. nextUrl = toAbsoluteUrl(options.url, nextUrl);
  6255. sendRequest(protocolVersion, {url: nextUrl}, requestOptions).fail(d.reject).done(function(nextData) {
  6256. d.resolve(data.concat(nextData))
  6257. })
  6258. }
  6259. else {
  6260. if (isFinite(tuplet.count))
  6261. extra = {totalCount: tuplet.count};
  6262. d.resolve(data, extra)
  6263. }
  6264. });
  6265. return d.promise()
  6266. };
  6267. var formatDotNetError = function(errorObj) {
  6268. var message,
  6269. currentError = errorObj;
  6270. if ("message" in errorObj)
  6271. if (errorObj.message.value)
  6272. message = errorObj.message.value;
  6273. else
  6274. message = errorObj.message;
  6275. while (currentError = currentError.innererror || currentError.internalexception) {
  6276. message = currentError.message;
  6277. if (currentError.internalexception && message.indexOf("inner exception") === -1)
  6278. break
  6279. }
  6280. return message
  6281. };
  6282. var errorFromResponse = function(obj, textStatus) {
  6283. if (textStatus === "nocontent")
  6284. return null;
  6285. var httpStatus = 200,
  6286. message = "Unknown error",
  6287. response = obj;
  6288. if (textStatus !== "success") {
  6289. httpStatus = obj.status;
  6290. message = data.utils.errorMessageFromXhr(obj, textStatus);
  6291. try {
  6292. response = $.parseJSON(obj.responseText)
  6293. }
  6294. catch(x) {}
  6295. }
  6296. var errorObj = response && (response.error || response["@odata.error"]);
  6297. if (errorObj) {
  6298. message = formatDotNetError(errorObj) || message;
  6299. if (httpStatus === 200)
  6300. httpStatus = 500;
  6301. if (errorObj.code)
  6302. httpStatus = Number(errorObj.code);
  6303. return $.extend(Error(message), {
  6304. httpStatus: httpStatus,
  6305. errorDetails: errorObj
  6306. })
  6307. }
  6308. else if (httpStatus !== 200)
  6309. return $.extend(Error(message), {httpStatus: httpStatus})
  6310. };
  6311. var interpretJsonFormat = function(obj, textStatus) {
  6312. var error = errorFromResponse(obj, textStatus),
  6313. value;
  6314. if (error)
  6315. return {error: error};
  6316. if (!$.isPlainObject(obj))
  6317. return {data: obj};
  6318. if ("d" in obj && (utils.isArray(obj.d) || utils.isObject(obj.d)))
  6319. value = interpretVerboseJsonFormat(obj, textStatus);
  6320. else
  6321. value = interpretLightJsonFormat(obj, textStatus);
  6322. transformTypes(value);
  6323. return value
  6324. };
  6325. var interpretVerboseJsonFormat = function(obj) {
  6326. var data = obj.d;
  6327. if (!isDefined(data))
  6328. return {error: Error("Malformed or unsupported JSON response received")};
  6329. data = data;
  6330. if (isDefined(data.results))
  6331. data = data.results;
  6332. return {
  6333. data: data,
  6334. nextUrl: obj.d.__next,
  6335. count: parseInt(obj.d.__count, 10)
  6336. }
  6337. };
  6338. var interpretLightJsonFormat = function(obj) {
  6339. var data = obj;
  6340. if (isDefined(data.value))
  6341. data = data.value;
  6342. return {
  6343. data: data,
  6344. nextUrl: obj["@odata.nextLink"],
  6345. count: parseInt(obj["@odata.count"], 10)
  6346. }
  6347. };
  6348. var EdmLiteral = DX.Class.inherit({
  6349. ctor: function(value) {
  6350. this._value = value
  6351. },
  6352. valueOf: function() {
  6353. return this._value
  6354. }
  6355. });
  6356. var transformTypes = function(obj) {
  6357. $.each(obj, function(key, value) {
  6358. if (value !== null && typeof value === "object") {
  6359. if ("results" in value)
  6360. obj[key] = value.results;
  6361. transformTypes(obj[key])
  6362. }
  6363. else if (typeof value === "string")
  6364. if (GUID_REGEX.test(value))
  6365. obj[key] = new Guid(value);
  6366. else if (value.match(VERBOSE_DATE_REGEX)) {
  6367. var date = new Date(Number(RegExp.$1) + RegExp.$2 * 60 * 1000);
  6368. obj[key] = new Date(date.valueOf() + date.getTimezoneOffset() * 60 * 1000)
  6369. }
  6370. else if (ISO8601_DATE_REGEX.test(value))
  6371. obj[key] = new Date(parseISO8601(obj[key]).valueOf())
  6372. })
  6373. };
  6374. var serializeDate = function(date) {
  6375. return "datetime'" + formatISO8601(date, true, true) + "'"
  6376. };
  6377. var serializeString = function(value) {
  6378. return "'" + value.replace(/'/g, "''") + "'"
  6379. };
  6380. var serializePropName = function(propName) {
  6381. if (propName instanceof EdmLiteral)
  6382. return propName.valueOf();
  6383. return propName.replace(/\./g, "/")
  6384. };
  6385. var serializeValueV4 = function(value) {
  6386. if (value instanceof Date)
  6387. return formatISO8601(value, false, false);
  6388. if (value instanceof Guid)
  6389. return value.valueOf();
  6390. return serializeValueV2(value)
  6391. };
  6392. var serializeValueV2 = function(value) {
  6393. if (value instanceof Date)
  6394. return serializeDate(value);
  6395. if (value instanceof Guid)
  6396. return "guid'" + value + "'";
  6397. if (value instanceof EdmLiteral)
  6398. return value.valueOf();
  6399. if (typeof value === "string")
  6400. return serializeString(value);
  6401. return String(value)
  6402. };
  6403. var serializeValue = function(value, protocolVersion) {
  6404. switch (protocolVersion) {
  6405. case 2:
  6406. case 3:
  6407. return serializeValueV2(value);
  6408. case 4:
  6409. return serializeValueV4(value);
  6410. default:
  6411. throw DX.Error("E4002");
  6412. }
  6413. };
  6414. var serializeKey = function(key, protocolVersion) {
  6415. if ($.isPlainObject(key)) {
  6416. var parts = [];
  6417. $.each(key, function(k, v) {
  6418. parts.push(serializePropName(k) + "=" + serializeValue(v, protocolVersion))
  6419. });
  6420. return parts.join()
  6421. }
  6422. return serializeValue(key, protocolVersion)
  6423. };
  6424. var keyConverters = {
  6425. String: function(value) {
  6426. return value + ""
  6427. },
  6428. Int32: function(value) {
  6429. return Math.floor(value)
  6430. },
  6431. Int64: function(value) {
  6432. if (value instanceof EdmLiteral)
  6433. return value;
  6434. return new EdmLiteral(value + "L")
  6435. },
  6436. Guid: function(value) {
  6437. if (value instanceof Guid)
  6438. return value;
  6439. return new Guid(value)
  6440. },
  6441. Boolean: function(value) {
  6442. return !!value
  6443. },
  6444. Single: function(value) {
  6445. if (value instanceof EdmLiteral)
  6446. return value;
  6447. return new EdmLiteral(value + "f")
  6448. },
  6449. Decimal: function(value) {
  6450. if (value instanceof EdmLiteral)
  6451. return value;
  6452. return new EdmLiteral(value + "m")
  6453. }
  6454. };
  6455. var compileCriteria = function() {
  6456. var createBinaryOperationFormatter = function(op) {
  6457. return function(prop, val, bag) {
  6458. bag.push(prop, " ", op, " ", val)
  6459. }
  6460. };
  6461. var createStringFuncFormatter = function(op, reverse) {
  6462. return function(prop, val, bag) {
  6463. if (reverse)
  6464. bag.push(op, "(", val, ",", prop, ")");
  6465. else
  6466. bag.push(op, "(", prop, ",", val, ")")
  6467. }
  6468. };
  6469. var formatters = {
  6470. "=": createBinaryOperationFormatter("eq"),
  6471. "<>": createBinaryOperationFormatter("ne"),
  6472. ">": createBinaryOperationFormatter("gt"),
  6473. ">=": createBinaryOperationFormatter("ge"),
  6474. "<": createBinaryOperationFormatter("lt"),
  6475. "<=": createBinaryOperationFormatter("le"),
  6476. startswith: createStringFuncFormatter("startswith"),
  6477. endswith: createStringFuncFormatter("endswith")
  6478. };
  6479. var formattersV2 = $.extend({}, formatters, {
  6480. contains: createStringFuncFormatter("substringof", true),
  6481. notcontains: createStringFuncFormatter("not substringof", true)
  6482. });
  6483. var formattersV4 = $.extend({}, formatters, {
  6484. contains: createStringFuncFormatter("contains"),
  6485. notcontains: createStringFuncFormatter("not contains")
  6486. });
  6487. var compileBinary = function(criteria, bag, protocolVersion) {
  6488. criteria = data.utils.normalizeBinaryCriterion(criteria);
  6489. var op = criteria[1],
  6490. formatters = protocolVersion === 4 ? formattersV4 : formattersV2,
  6491. formatter = formatters[op.toLowerCase()];
  6492. if (!formatter)
  6493. throw DX.Error("E4003", op);
  6494. formatter(serializePropName(criteria[0]), serializeValue(criteria[2], protocolVersion), bag)
  6495. };
  6496. var compileGroup = function(criteria, bag, protocolVersion) {
  6497. var pushAnd = false;
  6498. $.each(criteria, function() {
  6499. if ($.isArray(this)) {
  6500. if (pushAnd)
  6501. bag.push(" and ");
  6502. bag.push("(");
  6503. compileCore(this, bag, protocolVersion);
  6504. bag.push(")");
  6505. pushAnd = true
  6506. }
  6507. else {
  6508. bag.push(/and|&/i.test(this) ? " and " : " or ");
  6509. pushAnd = false
  6510. }
  6511. })
  6512. };
  6513. var compileCore = function(criteria, bag, protocolVersion) {
  6514. if ($.isArray(criteria[0]))
  6515. compileGroup(criteria, bag, protocolVersion);
  6516. else
  6517. compileBinary(criteria, bag, protocolVersion)
  6518. };
  6519. return function(criteria, protocolVersion) {
  6520. var bag = [];
  6521. compileCore(criteria, bag, protocolVersion);
  6522. return bag.join("")
  6523. }
  6524. }();
  6525. var createODataQueryAdapter = function(queryOptions) {
  6526. var _sorting = [],
  6527. _criteria = [],
  6528. _select,
  6529. _skip,
  6530. _take,
  6531. _countQuery;
  6532. var hasSlice = function() {
  6533. return _skip || _take !== undefined
  6534. };
  6535. var hasFunction = function(criterion) {
  6536. for (var i = 0; i < criterion.length; i++) {
  6537. if ($.isFunction(criterion[i]))
  6538. return true;
  6539. if ($.isArray(criterion[i]) && hasFunction(criterion[i]))
  6540. return true
  6541. }
  6542. return false
  6543. };
  6544. var generateExpand = function() {
  6545. var hash = {};
  6546. if (queryOptions.expand)
  6547. $.each($.makeArray(queryOptions.expand), function() {
  6548. hash[serializePropName(this)] = 1
  6549. });
  6550. if (_select)
  6551. $.each(_select, function() {
  6552. var path = this.split(".");
  6553. if (path.length < 2)
  6554. return;
  6555. path.pop();
  6556. hash[serializePropName(path.join("."))] = 1
  6557. });
  6558. return $.map(hash, function(k, v) {
  6559. return v
  6560. }).join() || undefined
  6561. };
  6562. var requestData = function() {
  6563. var result = {};
  6564. if (!_countQuery) {
  6565. if (_sorting.length)
  6566. result["$orderby"] = _sorting.join(",");
  6567. if (_skip)
  6568. result["$skip"] = _skip;
  6569. if (_take !== undefined)
  6570. result["$top"] = _take;
  6571. if (_select)
  6572. result["$select"] = serializePropName(_select.join());
  6573. result["$expand"] = generateExpand()
  6574. }
  6575. if (_criteria.length)
  6576. result["$filter"] = compileCriteria(_criteria.length < 2 ? _criteria[0] : _criteria, queryOptions.version);
  6577. if (_countQuery)
  6578. result["$top"] = 0;
  6579. if (queryOptions.requireTotalCount || _countQuery)
  6580. if (queryOptions.version !== 4)
  6581. result["$inlinecount"] = "allpages";
  6582. else
  6583. result["$count"] = "true";
  6584. return result
  6585. };
  6586. queryOptions.version = queryOptions.version || DEFAULT_PROTOCOL_VERSION;
  6587. return {
  6588. exec: function(url) {
  6589. return sendRequest(queryOptions.version, {
  6590. url: url,
  6591. params: $.extend(requestData(), queryOptions && queryOptions.params)
  6592. }, {
  6593. beforeSend: queryOptions.beforeSend,
  6594. jsonp: queryOptions.jsonp,
  6595. withCredentials: queryOptions.withCredentials,
  6596. countOnly: _countQuery
  6597. })
  6598. },
  6599. multiSort: function(args) {
  6600. var rules;
  6601. if (hasSlice())
  6602. return false;
  6603. for (var i = 0; i < args.length; i++) {
  6604. var getter = args[i][0],
  6605. desc = !!args[i][1],
  6606. rule;
  6607. if (typeof getter !== "string")
  6608. return false;
  6609. rule = serializePropName(getter);
  6610. if (desc)
  6611. rule += " desc";
  6612. rules = rules || [];
  6613. rules.push(rule)
  6614. }
  6615. _sorting = rules
  6616. },
  6617. slice: function(skipCount, takeCount) {
  6618. if (hasSlice())
  6619. return false;
  6620. _skip = skipCount;
  6621. _take = takeCount
  6622. },
  6623. filter: function(criterion) {
  6624. if (hasSlice() || $.isFunction(criterion))
  6625. return false;
  6626. if (!$.isArray(criterion))
  6627. criterion = $.makeArray(arguments);
  6628. if (hasFunction(criterion))
  6629. return false;
  6630. if (_criteria.length)
  6631. _criteria.push("and");
  6632. _criteria.push(criterion)
  6633. },
  6634. select: function(expr) {
  6635. if (_select || $.isFunction(expr))
  6636. return false;
  6637. if (!$.isArray(expr))
  6638. expr = $.makeArray(arguments);
  6639. _select = expr
  6640. },
  6641. count: function() {
  6642. _countQuery = true
  6643. }
  6644. }
  6645. };
  6646. $.extend(true, data, {
  6647. EdmLiteral: EdmLiteral,
  6648. utils: {odata: {
  6649. sendRequest: sendRequest,
  6650. serializePropName: serializePropName,
  6651. serializeValue: serializeValue,
  6652. serializeKey: serializeKey,
  6653. keyConverters: keyConverters
  6654. }},
  6655. queryAdapters: {odata: createODataQueryAdapter}
  6656. });
  6657. data.OData__internals = {interpretJsonFormat: interpretJsonFormat}
  6658. })(jQuery, DevExpress);
  6659. /*! Module core, file data.store.abstract.js */
  6660. (function($, DX, undefined) {
  6661. var Class = DX.Class,
  6662. abstract = DX.abstract,
  6663. data = DX.data,
  6664. normalizeSortingInfo = data.utils.normalizeSortingInfo;
  6665. var STORE_CALLBACK_NAMES = ["loading", "loaded", "modifying", "modified", "inserting", "inserted", "updating", "updated", "removing", "removed"];
  6666. function multiLevelGroup(query, groupInfo) {
  6667. query = query.groupBy(groupInfo[0].selector);
  6668. if (groupInfo.length > 1)
  6669. query = query.select(function(g) {
  6670. return $.extend({}, g, {items: multiLevelGroup(data.query(g.items), groupInfo.slice(1)).toArray()})
  6671. });
  6672. return query
  6673. }
  6674. data.utils.multiLevelGroup = multiLevelGroup;
  6675. function arrangeSortingInfo(groupInfo, sortInfo) {
  6676. var filteredGroup = [];
  6677. $.each(groupInfo, function(_, group) {
  6678. var collision = $.grep(sortInfo, function(sort) {
  6679. return group.selector === sort.selector
  6680. });
  6681. if (collision.length < 1)
  6682. filteredGroup.push(group)
  6683. });
  6684. return filteredGroup.concat(sortInfo)
  6685. }
  6686. data.utils.arrangeSortingInfo = arrangeSortingInfo;
  6687. data.Store = Class.inherit({
  6688. ctor: function(options) {
  6689. var that = this;
  6690. options = options || {};
  6691. $.each(STORE_CALLBACK_NAMES, function() {
  6692. var eventName = this;
  6693. var callbacks = that[eventName] = $.Callbacks();
  6694. var originalAdd = callbacks.add;
  6695. callbacks.add = function() {
  6696. DX.log("W0003", "Store", eventName, "14.2", "Use the '" + eventName + "' event instead");
  6697. return originalAdd.apply(eventName, arguments)
  6698. };
  6699. if (eventName in options)
  6700. callbacks.add(options[eventName]);
  6701. var propertyName = "on" + eventName.charAt(0).toUpperCase() + eventName.slice(1);
  6702. if (propertyName in options)
  6703. that.on(eventName, options[propertyName])
  6704. });
  6705. this._key = options.key;
  6706. this._errorHandler = options.errorHandler;
  6707. this._useDefaultSearch = true
  6708. },
  6709. _customLoadOptions: function() {
  6710. return null
  6711. },
  6712. key: function() {
  6713. return this._key
  6714. },
  6715. keyOf: function(obj) {
  6716. if (!this._keyGetter)
  6717. this._keyGetter = data.utils.compileGetter(this.key());
  6718. return this._keyGetter(obj)
  6719. },
  6720. _requireKey: function() {
  6721. if (!this.key())
  6722. throw DX.Error("E4005");
  6723. },
  6724. load: function(options) {
  6725. var that = this;
  6726. options = options || {};
  6727. this.fireEvent("loading", [options]);
  6728. this.loading.fire(options);
  6729. return this._loadImpl(options).done(function(result, extra) {
  6730. that.fireEvent("loaded", [result, options]);
  6731. that.loaded.fire(result, extra)
  6732. })
  6733. },
  6734. _loadImpl: function(options) {
  6735. var filter = options.filter,
  6736. sort = options.sort,
  6737. select = options.select,
  6738. group = options.group,
  6739. skip = options.skip,
  6740. take = options.take,
  6741. q = this.createQuery(options);
  6742. if (filter)
  6743. q = q.filter(filter);
  6744. if (group)
  6745. group = normalizeSortingInfo(group);
  6746. if (sort || group) {
  6747. sort = normalizeSortingInfo(sort || []);
  6748. if (group)
  6749. sort = arrangeSortingInfo(group, sort);
  6750. $.each(sort, function(index) {
  6751. q = q[index ? "thenBy" : "sortBy"](this.selector, this.desc)
  6752. })
  6753. }
  6754. if (select)
  6755. q = q.select(select);
  6756. if (group)
  6757. q = multiLevelGroup(q, group);
  6758. if (take || skip)
  6759. q = q.slice(skip || 0, take);
  6760. return q.enumerate()
  6761. },
  6762. createQuery: abstract,
  6763. totalCount: function(options) {
  6764. return this._addFailHandlers(this._totalCountImpl(options))
  6765. },
  6766. _totalCountImpl: function(options) {
  6767. options = options || {};
  6768. var q = this.createQuery(),
  6769. group = options.group,
  6770. filter = options.filter;
  6771. if (filter)
  6772. q = q.filter(filter);
  6773. if (group) {
  6774. group = normalizeSortingInfo(group);
  6775. q = multiLevelGroup(q, group)
  6776. }
  6777. return q.count()
  6778. },
  6779. byKey: function(key, extraOptions) {
  6780. return this._addFailHandlers(this._byKeyImpl(key, extraOptions))
  6781. },
  6782. _byKeyImpl: abstract,
  6783. insert: function(values) {
  6784. var that = this;
  6785. that.fireEvent("modifying");
  6786. that.fireEvent("inserting", [values]);
  6787. that.modifying.fire();
  6788. that.inserting.fire(values);
  6789. return that._addFailHandlers(that._insertImpl(values).done(function(callbackValues, callbackKey) {
  6790. that.fireEvent("inserted", [callbackValues, callbackKey]);
  6791. that.fireEvent("modified");
  6792. that.inserted.fire(callbackValues, callbackKey);
  6793. that.modified.fire()
  6794. }))
  6795. },
  6796. _insertImpl: abstract,
  6797. update: function(key, values) {
  6798. var that = this;
  6799. that.fireEvent("modifying");
  6800. that.fireEvent("updating", [key, values]);
  6801. that.modifying.fire();
  6802. that.updating.fire(key, values);
  6803. return that._addFailHandlers(that._updateImpl(key, values).done(function(callbackKey, callbackValues) {
  6804. that.fireEvent("updated", [callbackKey, callbackValues]);
  6805. that.fireEvent("modified");
  6806. that.updated.fire(callbackKey, callbackValues);
  6807. that.modified.fire()
  6808. }))
  6809. },
  6810. _updateImpl: abstract,
  6811. remove: function(key) {
  6812. var that = this;
  6813. that.fireEvent("modifying");
  6814. that.fireEvent("removing", [key]);
  6815. that.modifying.fire();
  6816. that.removing.fire(key);
  6817. return that._addFailHandlers(that._removeImpl(key).done(function(callbackKey) {
  6818. that.fireEvent("removed", [callbackKey]);
  6819. that.fireEvent("modified");
  6820. that.removed.fire(callbackKey);
  6821. that.modified.fire()
  6822. }))
  6823. },
  6824. _removeImpl: abstract,
  6825. _addFailHandlers: function(deferred) {
  6826. return deferred.fail(this._errorHandler, data._errorHandler)
  6827. }
  6828. }).include(DX.EventsMixin)
  6829. })(jQuery, DevExpress);
  6830. /*! Module core, file data.store.array.js */
  6831. (function($, DX, undefined) {
  6832. var data = DX.data,
  6833. Guid = data.Guid;
  6834. var trivialPromise = function() {
  6835. var d = $.Deferred();
  6836. return d.resolve.apply(d, arguments).promise()
  6837. };
  6838. var rejectedPromise = function() {
  6839. var d = $.Deferred();
  6840. return d.reject.apply(d, arguments).promise()
  6841. };
  6842. data.ArrayStore = data.Store.inherit({
  6843. ctor: function(options) {
  6844. if ($.isArray(options))
  6845. options = {data: options};
  6846. else
  6847. options = options || {};
  6848. this.callBase(options);
  6849. var initialArray = options.data;
  6850. if (initialArray && !$.isArray(initialArray))
  6851. throw DX.Error("E4006");
  6852. this._array = initialArray || []
  6853. },
  6854. createQuery: function() {
  6855. return data.query(this._array, {errorHandler: this._errorHandler})
  6856. },
  6857. _byKeyImpl: function(key) {
  6858. var index = this._indexByKey(key);
  6859. if (index === -1)
  6860. return rejectedPromise(DX.Error("E4009"));
  6861. return trivialPromise(this._array[index])
  6862. },
  6863. _insertImpl: function(values) {
  6864. var keyExpr = this.key(),
  6865. keyValue,
  6866. obj;
  6867. if ($.isPlainObject(values))
  6868. obj = $.extend({}, values);
  6869. else
  6870. obj = values;
  6871. if (keyExpr) {
  6872. keyValue = this.keyOf(obj);
  6873. if (keyValue === undefined || typeof keyValue === "object" && $.isEmptyObject(keyValue)) {
  6874. if ($.isArray(keyExpr))
  6875. throw DX.Error("E4007");
  6876. keyValue = obj[keyExpr] = String(new Guid)
  6877. }
  6878. else if (this._array[this._indexByKey(keyValue)] !== undefined)
  6879. return rejectedPromise(DX.Error("E4008"))
  6880. }
  6881. else
  6882. keyValue = obj;
  6883. this._array.push(obj);
  6884. return trivialPromise(values, keyValue)
  6885. },
  6886. _updateImpl: function(key, values) {
  6887. var target,
  6888. index;
  6889. if (this.key()) {
  6890. if (this.keyOf(values))
  6891. if (!data.utils.keysEqual(this.key(), key, this.keyOf(values)))
  6892. return rejectedPromise(DX.Error("E4017"));
  6893. index = this._indexByKey(key);
  6894. if (index < 0)
  6895. return rejectedPromise(DX.Error("E4009"));
  6896. target = this._array[index]
  6897. }
  6898. else
  6899. target = key;
  6900. DX.utils.deepExtendArraySafe(target, values);
  6901. return trivialPromise(key, values)
  6902. },
  6903. _removeImpl: function(key) {
  6904. var index = this._indexByKey(key);
  6905. if (index > -1)
  6906. this._array.splice(index, 1);
  6907. return trivialPromise(key)
  6908. },
  6909. _indexByKey: function(key) {
  6910. for (var i = 0, arrayLength = this._array.length; i < arrayLength; i++)
  6911. if (data.utils.keysEqual(this.key(), this.keyOf(this._array[i]), key))
  6912. return i;
  6913. return -1
  6914. },
  6915. clear: function() {
  6916. this._array = []
  6917. }
  6918. })
  6919. })(jQuery, DevExpress);
  6920. /*! Module core, file data.store.local.js */
  6921. (function($, DX, undefined) {
  6922. var Class = DX.Class,
  6923. abstract = DX.abstract,
  6924. data = DX.data;
  6925. var LocalStoreBackend = Class.inherit({
  6926. ctor: function(store, storeOptions) {
  6927. this._store = store;
  6928. this._dirty = false;
  6929. var immediate = this._immediate = storeOptions.immediate;
  6930. var flushInterval = Math.max(100, storeOptions.flushInterval || 10 * 1000);
  6931. if (!immediate) {
  6932. var saveProxy = $.proxy(this.save, this);
  6933. setInterval(saveProxy, flushInterval);
  6934. $(window).on("beforeunload", saveProxy);
  6935. if (window.cordova)
  6936. document.addEventListener("pause", saveProxy, false)
  6937. }
  6938. },
  6939. notifyChanged: function() {
  6940. this._dirty = true;
  6941. if (this._immediate)
  6942. this.save()
  6943. },
  6944. load: function() {
  6945. this._store._array = this._loadImpl();
  6946. this._dirty = false
  6947. },
  6948. save: function() {
  6949. if (!this._dirty)
  6950. return;
  6951. this._saveImpl(this._store._array);
  6952. this._dirty = false
  6953. },
  6954. _loadImpl: abstract,
  6955. _saveImpl: abstract
  6956. });
  6957. var DomLocalStoreBackend = LocalStoreBackend.inherit({
  6958. ctor: function(store, storeOptions) {
  6959. this.callBase(store, storeOptions);
  6960. var name = storeOptions.name;
  6961. if (!name)
  6962. throw DX.Error("E4013");
  6963. this._key = "dx-data-localStore-" + name
  6964. },
  6965. _loadImpl: function() {
  6966. var raw = localStorage.getItem(this._key);
  6967. if (raw)
  6968. return JSON.parse(raw);
  6969. return []
  6970. },
  6971. _saveImpl: function(array) {
  6972. if (!array.length)
  6973. localStorage.removeItem(this._key);
  6974. else
  6975. localStorage.setItem(this._key, JSON.stringify(array))
  6976. }
  6977. });
  6978. var localStoreBackends = {dom: DomLocalStoreBackend};
  6979. data.LocalStore = data.ArrayStore.inherit({
  6980. ctor: function(options) {
  6981. if (typeof options === "string")
  6982. options = {name: options};
  6983. else
  6984. options = options || {};
  6985. this.callBase(options);
  6986. this._backend = new localStoreBackends[options.backend || "dom"](this, options);
  6987. this._backend.load()
  6988. },
  6989. clear: function() {
  6990. this.callBase();
  6991. this._backend.notifyChanged()
  6992. },
  6993. _insertImpl: function(values) {
  6994. var b = this._backend;
  6995. return this.callBase(values).done($.proxy(b.notifyChanged, b))
  6996. },
  6997. _updateImpl: function(key, values) {
  6998. var b = this._backend;
  6999. return this.callBase(key, values).done($.proxy(b.notifyChanged, b))
  7000. },
  7001. _removeImpl: function(key) {
  7002. var b = this._backend;
  7003. return this.callBase(key).done($.proxy(b.notifyChanged, b))
  7004. }
  7005. })
  7006. })(jQuery, DevExpress);
  7007. /*! Module core, file data.store.odata.js */
  7008. (function($, DX, undefined) {
  7009. var Class = DX.Class,
  7010. data = DX.data,
  7011. utils = DX.utils,
  7012. odataUtils = data.utils.odata;
  7013. var DEFAULT_PROTOCOL_VERSION = 2;
  7014. var formatFunctionInvocationUrl = function(baseUrl, args) {
  7015. return DX.stringFormat("{0}({1})", baseUrl, $.map(args || {}, function(value, key) {
  7016. return DX.stringFormat("{0}={1}", key, value)
  7017. }).join(","))
  7018. };
  7019. var escapeServiceOperationParams = function(params, version) {
  7020. if (!params)
  7021. return params;
  7022. var result = {};
  7023. $.each(params, function(k, v) {
  7024. result[k] = odataUtils.serializeValue(v, version)
  7025. });
  7026. return result
  7027. };
  7028. var convertSimpleKey = function(keyType, keyValue) {
  7029. var converter = odataUtils.keyConverters[keyType];
  7030. if (!converter)
  7031. throw DX.Error("E4014", keyType);
  7032. return converter(keyValue)
  7033. };
  7034. var SharedMethods = {
  7035. _extractServiceOptions: function(options) {
  7036. options = options || {};
  7037. this._url = String(options.url).replace(/\/+$/, "");
  7038. this._beforeSend = options.beforeSend;
  7039. this._jsonp = options.jsonp;
  7040. this._version = options.version || DEFAULT_PROTOCOL_VERSION;
  7041. this._withCredentials = options.withCredentials
  7042. },
  7043. _sendRequest: function(url, method, params, payload) {
  7044. return odataUtils.sendRequest(this.version(), {
  7045. url: url,
  7046. method: method,
  7047. params: params || {},
  7048. payload: payload
  7049. }, {
  7050. beforeSend: this._beforeSend,
  7051. jsonp: this._jsonp,
  7052. withCredentials: this._withCredentials
  7053. })
  7054. },
  7055. version: function() {
  7056. return this._version
  7057. }
  7058. };
  7059. var ODataStore = data.Store.inherit({
  7060. ctor: function(options) {
  7061. this.callBase(options);
  7062. this._extractServiceOptions(options);
  7063. this._keyType = options.keyType;
  7064. if (this.version() === 2)
  7065. this._updateMethod = "MERGE";
  7066. else
  7067. this._updateMethod = "PATCH"
  7068. },
  7069. _customLoadOptions: function() {
  7070. return ["expand", "customQueryParams"]
  7071. },
  7072. _byKeyImpl: function(key, extraOptions) {
  7073. var params = {};
  7074. if (extraOptions)
  7075. if (extraOptions.expand)
  7076. params["$expand"] = $.map($.makeArray(extraOptions.expand), odataUtils.serializePropName).join();
  7077. return this._sendRequest(this._byKeyUrl(key), "GET", params)
  7078. },
  7079. createQuery: function(loadOptions) {
  7080. var url,
  7081. queryOptions;
  7082. loadOptions = loadOptions || {};
  7083. queryOptions = {
  7084. beforeSend: this._beforeSend,
  7085. errorHandler: this._errorHandler,
  7086. jsonp: this._jsonp,
  7087. version: this._version,
  7088. withCredentials: this._withCredentials,
  7089. expand: loadOptions.expand,
  7090. requireTotalCount: loadOptions.requireTotalCount
  7091. };
  7092. if (utils.isDefined(loadOptions.urlOverride))
  7093. url = loadOptions.urlOverride;
  7094. else
  7095. url = this._url;
  7096. if ("customQueryParams" in loadOptions) {
  7097. var params = escapeServiceOperationParams(loadOptions.customQueryParams, this.version());
  7098. if (this.version() === 4)
  7099. url = formatFunctionInvocationUrl(url, params);
  7100. else
  7101. queryOptions.params = params
  7102. }
  7103. return data.query(url, queryOptions)
  7104. },
  7105. _insertImpl: function(values) {
  7106. this._requireKey();
  7107. var that = this,
  7108. d = $.Deferred();
  7109. $.when(this._sendRequest(this._url, "POST", null, values)).done(function(serverResponse) {
  7110. d.resolve(values, that.keyOf(serverResponse))
  7111. }).fail(d.reject);
  7112. return d.promise()
  7113. },
  7114. _updateImpl: function(key, values) {
  7115. var d = $.Deferred();
  7116. $.when(this._sendRequest(this._byKeyUrl(key), this._updateMethod, null, values)).done(function() {
  7117. d.resolve(key, values)
  7118. }).fail(d.reject, d);
  7119. return d.promise()
  7120. },
  7121. _removeImpl: function(key) {
  7122. var d = $.Deferred();
  7123. $.when(this._sendRequest(this._byKeyUrl(key), "DELETE")).done(function() {
  7124. d.resolve(key)
  7125. }).fail(d.reject, d);
  7126. return d.promise()
  7127. },
  7128. _byKeyUrl: function(key, useOriginalHost) {
  7129. var keyObj = key,
  7130. keyType = this._keyType,
  7131. baseUrl = useOriginalHost ? DX._proxyUrlFormatter.formatLocalUrl(this._url) : this._url;
  7132. if ($.isPlainObject(keyType)) {
  7133. keyObj = {};
  7134. $.each(keyType, function(subKeyName, subKeyType) {
  7135. keyObj[subKeyName] = convertSimpleKey(subKeyType, key[subKeyName])
  7136. })
  7137. }
  7138. else if (keyType)
  7139. keyObj = convertSimpleKey(keyType, key);
  7140. return baseUrl + "(" + encodeURIComponent(odataUtils.serializeKey(keyObj, this._version)) + ")"
  7141. }
  7142. }).include(SharedMethods);
  7143. var ODataContext = Class.inherit({
  7144. ctor: function(options) {
  7145. var that = this;
  7146. that._extractServiceOptions(options);
  7147. that._errorHandler = options.errorHandler;
  7148. $.each(options.entities || [], function(entityAlias, entityOptions) {
  7149. that[entityAlias] = new ODataStore($.extend({}, options, {url: that._url + "/" + encodeURIComponent(entityOptions.name || entityAlias)}, entityOptions))
  7150. })
  7151. },
  7152. get: function(operationName, params) {
  7153. return this.invoke(operationName, params, "GET")
  7154. },
  7155. invoke: function(operationName, params, httpMethod) {
  7156. params = params || {};
  7157. httpMethod = (httpMethod || "POST").toLowerCase();
  7158. var d = $.Deferred(),
  7159. url = this._url + "/" + encodeURIComponent(operationName),
  7160. payload;
  7161. if (this.version() === 4)
  7162. if (httpMethod === "get") {
  7163. url = formatFunctionInvocationUrl(url, escapeServiceOperationParams(params, this.version()));
  7164. params = null
  7165. }
  7166. else if (httpMethod === "post") {
  7167. payload = params;
  7168. params = null
  7169. }
  7170. $.when(this._sendRequest(url, httpMethod, escapeServiceOperationParams(params, this.version()), payload)).done(function(r) {
  7171. if ($.isPlainObject(r) && operationName in r)
  7172. r = r[operationName];
  7173. d.resolve(r)
  7174. }).fail([this._errorHandler, data._errorHandler, d.reject]);
  7175. return d.promise()
  7176. },
  7177. objectLink: function(entityAlias, key) {
  7178. var store = this[entityAlias];
  7179. if (!store)
  7180. throw DX.Error("E4015", entityAlias);
  7181. if (!utils.isDefined(key))
  7182. return null;
  7183. return {__metadata: {uri: store._byKeyUrl(key, true)}}
  7184. }
  7185. }).include(SharedMethods);
  7186. $.extend(data, {
  7187. ODataStore: ODataStore,
  7188. ODataContext: ODataContext
  7189. })
  7190. })(jQuery, DevExpress);
  7191. /*! Module core, file data.store.custom.js */
  7192. (function($, DX, undefined) {
  7193. var data = DX.data;
  7194. var TOTAL_COUNT = "totalCount",
  7195. LOAD = "load",
  7196. BY_KEY = "byKey",
  7197. INSERT = "insert",
  7198. UPDATE = "update",
  7199. REMOVE = "remove";
  7200. function isPromise(obj) {
  7201. return obj && $.isFunction(obj.then)
  7202. }
  7203. function trivialPromise(value) {
  7204. return $.Deferred().resolve(value).promise()
  7205. }
  7206. function ensureRequiredFuncOption(name, obj) {
  7207. if (!$.isFunction(obj))
  7208. throw DX.Error("E4011", name);
  7209. }
  7210. function throwInvalidUserFuncResult(name) {
  7211. throw DX.Error("E4012", name);
  7212. }
  7213. function createUserFuncFailureHandler(pendingDeferred) {
  7214. function errorMessageFromXhr(promiseArguments) {
  7215. var xhr = promiseArguments[0],
  7216. textStatus = promiseArguments[1];
  7217. if (!xhr || !xhr.getResponseHeader)
  7218. return null;
  7219. return data.utils.errorMessageFromXhr(xhr, textStatus)
  7220. }
  7221. return function(arg) {
  7222. var error;
  7223. if (arg instanceof Error)
  7224. error = arg;
  7225. else
  7226. error = new Error(errorMessageFromXhr(arguments) || arg && String(arg) || "Unknown error");
  7227. pendingDeferred.reject(error)
  7228. }
  7229. }
  7230. data.CustomStore = data.Store.inherit({
  7231. ctor: function(options) {
  7232. options = options || {};
  7233. this.callBase(options);
  7234. this._useDefaultSearch = false;
  7235. this._loadFunc = options[LOAD];
  7236. this._totalCountFunc = options[TOTAL_COUNT];
  7237. this._byKeyFunc = options[BY_KEY];
  7238. this._insertFunc = options[INSERT];
  7239. this._updateFunc = options[UPDATE];
  7240. this._removeFunc = options[REMOVE]
  7241. },
  7242. createQuery: function() {
  7243. throw DX.Error("E4010");
  7244. },
  7245. _totalCountImpl: function(options) {
  7246. var userFunc = this._totalCountFunc,
  7247. userResult,
  7248. d = $.Deferred();
  7249. ensureRequiredFuncOption(TOTAL_COUNT, userFunc);
  7250. userResult = userFunc(options);
  7251. if (!isPromise(userResult)) {
  7252. userResult = Number(userResult);
  7253. if (!isFinite(userResult))
  7254. throwInvalidUserFuncResult(TOTAL_COUNT);
  7255. userResult = trivialPromise(userResult)
  7256. }
  7257. userResult.then(function(count) {
  7258. d.resolve(Number(count))
  7259. }, createUserFuncFailureHandler(d));
  7260. return d.promise()
  7261. },
  7262. _loadImpl: function(options) {
  7263. var userFunc = this._loadFunc,
  7264. userResult,
  7265. d = $.Deferred();
  7266. ensureRequiredFuncOption(LOAD, userFunc);
  7267. userResult = userFunc(options);
  7268. if ($.isArray(userResult))
  7269. userResult = trivialPromise(userResult);
  7270. else if (userResult === null || userResult === undefined)
  7271. userResult = trivialPromise([]);
  7272. else if (!isPromise(userResult))
  7273. throwInvalidUserFuncResult(LOAD);
  7274. userResult.then(function(data, extra) {
  7275. d.resolve(data, extra)
  7276. }, createUserFuncFailureHandler(d));
  7277. return this._addFailHandlers(d.promise())
  7278. },
  7279. _byKeyImpl: function(key, extraOptions) {
  7280. var userFunc = this._byKeyFunc,
  7281. userResult,
  7282. d = $.Deferred();
  7283. ensureRequiredFuncOption(BY_KEY, userFunc);
  7284. userResult = userFunc(key, extraOptions);
  7285. if (!isPromise(userResult))
  7286. userResult = trivialPromise(userResult);
  7287. userResult.then(function(obj) {
  7288. d.resolve(obj)
  7289. }, createUserFuncFailureHandler(d));
  7290. return d.promise()
  7291. },
  7292. _insertImpl: function(values) {
  7293. var userFunc = this._insertFunc,
  7294. userResult,
  7295. d = $.Deferred();
  7296. ensureRequiredFuncOption(INSERT, userFunc);
  7297. userResult = userFunc(values);
  7298. if (!isPromise(userResult))
  7299. userResult = trivialPromise(userResult);
  7300. userResult.then(function(newKey) {
  7301. d.resolve(values, newKey)
  7302. }, createUserFuncFailureHandler(d));
  7303. return d.promise()
  7304. },
  7305. _updateImpl: function(key, values) {
  7306. var userFunc = this._updateFunc,
  7307. userResult,
  7308. d = $.Deferred();
  7309. ensureRequiredFuncOption(UPDATE, userFunc);
  7310. userResult = userFunc(key, values);
  7311. if (!isPromise(userResult))
  7312. userResult = trivialPromise();
  7313. userResult.then(function() {
  7314. d.resolve(key, values)
  7315. }, createUserFuncFailureHandler(d));
  7316. return d.promise()
  7317. },
  7318. _removeImpl: function(key) {
  7319. var userFunc = this._removeFunc,
  7320. userResult,
  7321. d = $.Deferred();
  7322. ensureRequiredFuncOption(REMOVE, userFunc);
  7323. userResult = userFunc(key);
  7324. if (!isPromise(userResult))
  7325. userResult = trivialPromise();
  7326. userResult.then(function() {
  7327. d.resolve(key)
  7328. }, createUserFuncFailureHandler(d));
  7329. return d.promise()
  7330. }
  7331. })
  7332. })(jQuery, DevExpress);
  7333. /*! Module core, file data.dataSource.js */
  7334. (function($, DX, undefined) {
  7335. var data = DX.data,
  7336. CustomStore = data.CustomStore,
  7337. Class = DX.Class;
  7338. var storeTypeRegistry = {
  7339. jaydata: "JayDataStore",
  7340. breeze: "BreezeStore",
  7341. odata: "ODataStore",
  7342. local: "LocalStore",
  7343. array: "ArrayStore"
  7344. };
  7345. var nextLoadOperationId = function() {
  7346. var id = -1;
  7347. return function() {
  7348. return ++id
  7349. }
  7350. }();
  7351. var canceledOperationsRegistry = function() {
  7352. var registry = {};
  7353. return {
  7354. add: function(operationId) {
  7355. registry[operationId] = true
  7356. },
  7357. has: function(operationId) {
  7358. return operationId in registry
  7359. },
  7360. remove: function(operationId) {
  7361. delete registry[operationId]
  7362. }
  7363. }
  7364. }();
  7365. var ensureIsNotRejected = function(loadOperationId, pendingDeferred) {
  7366. if (canceledOperationsRegistry.has(loadOperationId)) {
  7367. canceledOperationsRegistry.remove(loadOperationId);
  7368. pendingDeferred.reject("canceled");
  7369. return false
  7370. }
  7371. return true
  7372. };
  7373. function normalizeDataSourceOptions(options) {
  7374. var store;
  7375. function createCustomStoreFromLoadFunc() {
  7376. var storeConfig = {};
  7377. $.each(["key", "load", "byKey", "lookup", "totalCount", "insert", "update", "remove"], function() {
  7378. storeConfig[this] = options[this];
  7379. delete options[this]
  7380. });
  7381. return new CustomStore(storeConfig)
  7382. }
  7383. function createStoreFromConfig(storeConfig) {
  7384. var storeCtor = data[storeTypeRegistry[storeConfig.type]];
  7385. delete storeConfig.type;
  7386. return new storeCtor(storeConfig)
  7387. }
  7388. function createCustomStoreFromUrl(url) {
  7389. return new CustomStore({load: function() {
  7390. return $.getJSON(url)
  7391. }})
  7392. }
  7393. if (typeof options === "string")
  7394. options = createCustomStoreFromUrl(options);
  7395. if (options === undefined)
  7396. options = [];
  7397. if ($.isArray(options) || options instanceof data.Store)
  7398. options = {store: options};
  7399. else
  7400. options = $.extend({}, options);
  7401. if (options.store === undefined)
  7402. options.store = [];
  7403. store = options.store;
  7404. if ("load" in options)
  7405. store = createCustomStoreFromLoadFunc();
  7406. else if ($.isArray(store))
  7407. store = new data.ArrayStore(store);
  7408. else if ($.isPlainObject(store))
  7409. store = createStoreFromConfig($.extend({}, store));
  7410. options.store = store;
  7411. return options
  7412. }
  7413. function normalizeStoreLoadOptionAccessorArguments(originalArguments) {
  7414. switch (originalArguments.length) {
  7415. case 0:
  7416. return undefined;
  7417. case 1:
  7418. return originalArguments[0]
  7419. }
  7420. return $.makeArray(originalArguments)
  7421. }
  7422. function generateStoreLoadOptionAccessor(optionName) {
  7423. return function() {
  7424. var args = normalizeStoreLoadOptionAccessorArguments(arguments);
  7425. if (args !== undefined)
  7426. this._storeLoadOptions[optionName] = args;
  7427. return this._storeLoadOptions[optionName]
  7428. }
  7429. }
  7430. function mapDataRespectingGrouping(items, mapper, groupInfo) {
  7431. function mapRecursive(items, level) {
  7432. if (!DX.utils.isArray(items))
  7433. return items;
  7434. return level ? mapGroup(items, level) : $.map(items, mapper)
  7435. }
  7436. function mapGroup(group, level) {
  7437. return $.map(group, function(item) {
  7438. var result = {
  7439. key: item.key,
  7440. items: mapRecursive(item.items, level - 1)
  7441. };
  7442. if ("aggregates" in item)
  7443. result.aggregates = item.aggregates;
  7444. return result
  7445. })
  7446. }
  7447. return mapRecursive(items, groupInfo ? data.utils.normalizeSortingInfo(groupInfo).length : 0)
  7448. }
  7449. var DataSource = Class.inherit({
  7450. ctor: function(options) {
  7451. options = normalizeDataSourceOptions(options);
  7452. this._store = options.store;
  7453. this._storeLoadOptions = this._extractLoadOptions(options);
  7454. this._mapFunc = options.map;
  7455. this._postProcessFunc = options.postProcess;
  7456. this._pageIndex = options.pageIndex !== undefined ? options.pageIndex : 0;
  7457. this._pageSize = options.pageSize !== undefined ? options.pageSize : 20;
  7458. this._items = [];
  7459. this._totalCount = -1;
  7460. this._isLoaded = false;
  7461. this._loadingCount = 0;
  7462. this._loadQueue = this._createLoadQueue();
  7463. this._searchValue = "searchValue" in options ? options.searchValue : null;
  7464. this._searchOperation = options.searchOperation || "contains";
  7465. this._searchExpr = options.searchExpr;
  7466. this._paginate = options.paginate;
  7467. if (this._paginate === undefined)
  7468. this._paginate = !this.group();
  7469. this._isLastPage = !this._paginate;
  7470. this._userData = {};
  7471. $.each(["changed", "loadError", "loadingChanged"], $.proxy(function(_, eventName) {
  7472. var callbacks = this[eventName] = $.Callbacks();
  7473. var originalAdd = callbacks.add;
  7474. callbacks.add = function() {
  7475. DX.log("W0003", "DataSource", eventName, "14.2", "Use the '" + eventName + "' event instead");
  7476. return originalAdd.apply(eventName, arguments)
  7477. }
  7478. }, this));
  7479. $.each(["changed", "loadError", "loadingChanged", "customizeLoadResult", "customizeStoreLoadOptions"], $.proxy(function(_, eventName) {
  7480. var optionName = "on" + eventName[0].toUpperCase() + eventName.slice(1);
  7481. if (options.hasOwnProperty(optionName))
  7482. this.on(eventName, options[optionName])
  7483. }, this))
  7484. },
  7485. dispose: function() {
  7486. this.changed.empty();
  7487. this.loadError.empty();
  7488. this.loadingChanged.empty();
  7489. this._disposeEvents();
  7490. delete this._store;
  7491. if (this._delayedLoadTask)
  7492. this._delayedLoadTask.abort();
  7493. this._disposed = true
  7494. },
  7495. _extractLoadOptions: function(options) {
  7496. var result = {},
  7497. names = ["sort", "filter", "select", "group", "requireTotalCount"],
  7498. customNames = this._store._customLoadOptions();
  7499. if (customNames)
  7500. names = names.concat(customNames);
  7501. $.each(names, function() {
  7502. result[this] = options[this]
  7503. });
  7504. return result
  7505. },
  7506. loadOptions: function() {
  7507. return this._storeLoadOptions
  7508. },
  7509. items: function() {
  7510. return this._items
  7511. },
  7512. pageIndex: function(newIndex) {
  7513. if (newIndex !== undefined) {
  7514. this._pageIndex = newIndex;
  7515. this._isLastPage = !this._paginate
  7516. }
  7517. return this._pageIndex
  7518. },
  7519. paginate: function(value) {
  7520. if (arguments.length < 1)
  7521. return this._paginate;
  7522. value = !!value;
  7523. if (this._paginate !== value) {
  7524. this._paginate = value;
  7525. this.pageIndex(0)
  7526. }
  7527. },
  7528. pageSize: function(value) {
  7529. if (arguments.length < 1)
  7530. return this._pageSize;
  7531. this._pageSize = value
  7532. },
  7533. isLastPage: function() {
  7534. return this._isLastPage
  7535. },
  7536. sort: generateStoreLoadOptionAccessor("sort"),
  7537. filter: function() {
  7538. var newFilter = normalizeStoreLoadOptionAccessorArguments(arguments);
  7539. if (newFilter !== undefined) {
  7540. this._storeLoadOptions.filter = newFilter;
  7541. this.pageIndex(0)
  7542. }
  7543. return this._storeLoadOptions.filter
  7544. },
  7545. group: generateStoreLoadOptionAccessor("group"),
  7546. select: generateStoreLoadOptionAccessor("select"),
  7547. requireTotalCount: generateStoreLoadOptionAccessor("requireTotalCount"),
  7548. searchValue: function(value) {
  7549. if (value !== undefined) {
  7550. this.pageIndex(0);
  7551. this._searchValue = value
  7552. }
  7553. return this._searchValue
  7554. },
  7555. searchOperation: function(op) {
  7556. if (op !== undefined) {
  7557. this.pageIndex(0);
  7558. this._searchOperation = op
  7559. }
  7560. return this._searchOperation
  7561. },
  7562. searchExpr: function(expr) {
  7563. var argc = arguments.length;
  7564. if (argc) {
  7565. if (argc > 1)
  7566. expr = $.makeArray(arguments);
  7567. this.pageIndex(0);
  7568. this._searchExpr = expr
  7569. }
  7570. return this._searchExpr
  7571. },
  7572. store: function() {
  7573. return this._store
  7574. },
  7575. key: function() {
  7576. return this._store && this._store.key()
  7577. },
  7578. totalCount: function() {
  7579. return this._totalCount
  7580. },
  7581. isLoaded: function() {
  7582. return this._isLoaded
  7583. },
  7584. isLoading: function() {
  7585. return this._loadingCount > 0
  7586. },
  7587. _createLoadQueue: function() {
  7588. return DX.createQueue()
  7589. },
  7590. _changeLoadingCount: function(increment) {
  7591. var oldLoading = this.isLoading(),
  7592. newLoading;
  7593. this._loadingCount += increment;
  7594. newLoading = this.isLoading();
  7595. if (oldLoading ^ newLoading) {
  7596. this.fireEvent("loadingChanged", [newLoading]);
  7597. this.loadingChanged.fire(newLoading)
  7598. }
  7599. },
  7600. _scheduleLoadCallbacks: function(deferred) {
  7601. var that = this;
  7602. that._changeLoadingCount(1);
  7603. deferred.always(function() {
  7604. that._changeLoadingCount(-1)
  7605. })
  7606. },
  7607. _scheduleChangedCallbacks: function(deferred) {
  7608. var that = this;
  7609. deferred.done(function() {
  7610. that.fireEvent("changed");
  7611. that.changed.fire()
  7612. })
  7613. },
  7614. loadSingle: function(propName, propValue) {
  7615. var that = this;
  7616. var d = $.Deferred().fail(function() {
  7617. that.fireEvent("loadError", arguments);
  7618. that.loadError.fire.apply(that, arguments)
  7619. }),
  7620. key = this.key(),
  7621. store = this._store,
  7622. loadOptions = this._createStoreLoadOptions();
  7623. function handleSuccess(data) {
  7624. if (data === null || typeof data === "undefined" || $.isArray(data) && data.length < 1)
  7625. d.reject();
  7626. else
  7627. d.resolve(that._transformLoadedData(data)[0])
  7628. }
  7629. if (arguments.length < 2) {
  7630. propValue = propName;
  7631. propName = key
  7632. }
  7633. delete loadOptions.skip;
  7634. delete loadOptions.group;
  7635. delete loadOptions.refresh;
  7636. delete loadOptions.pageIndex;
  7637. delete loadOptions.searchString;
  7638. if (propName === key || store instanceof data.CustomStore)
  7639. store.byKey(propValue, loadOptions).done(handleSuccess).fail(d.reject);
  7640. else {
  7641. loadOptions.take = 1;
  7642. loadOptions.filter = loadOptions.filter ? [loadOptions.filter, [propName, propValue]] : [propName, propValue];
  7643. store.load(loadOptions).done(handleSuccess).fail(d.reject)
  7644. }
  7645. return d.promise()
  7646. },
  7647. load: function() {
  7648. var that = this,
  7649. d = $.Deferred(),
  7650. loadOptions;
  7651. this._scheduleLoadCallbacks(d);
  7652. this._scheduleChangedCallbacks(d);
  7653. loadOptions = this._createLoadOptions();
  7654. this.fireEvent("customizeStoreLoadOptions", [loadOptions]);
  7655. if (!ensureIsNotRejected(loadOptions.operationId, d))
  7656. return d.promise();
  7657. function errorCallback() {
  7658. if (arguments[0] !== "canceled") {
  7659. that.fireEvent("loadError", arguments);
  7660. that.loadError.fire.apply(that.loadError, arguments)
  7661. }
  7662. }
  7663. function loadTask() {
  7664. if (that._disposed)
  7665. return undefined;
  7666. return that._loadFromStore(loadOptions, d)
  7667. }
  7668. this._loadQueue.add(function() {
  7669. if (typeof loadOptions.delay === "number")
  7670. that._delayedLoadTask = DX.utils.executeAsync(loadTask, loadOptions.delay);
  7671. else
  7672. loadTask();
  7673. return d.promise()
  7674. });
  7675. return d.promise({loadOperationId: loadOptions.operationId}).fail(errorCallback)
  7676. },
  7677. reload: function() {
  7678. var prop,
  7679. userData = this._userData;
  7680. for (prop in userData)
  7681. if (userData.hasOwnProperty(prop))
  7682. delete userData[prop];
  7683. this._totalCount = -1;
  7684. this._isLoaded = false;
  7685. return this.load()
  7686. },
  7687. cancel: function(loadOperationId) {
  7688. canceledOperationsRegistry.add(loadOperationId)
  7689. },
  7690. _addSearchOptions: function(storeLoadOptions) {
  7691. if (this._disposed)
  7692. return;
  7693. if (this.store()._useDefaultSearch)
  7694. this._addSearchFilter(storeLoadOptions);
  7695. else {
  7696. storeLoadOptions.searchOperation = this._searchOperation;
  7697. storeLoadOptions.searchValue = this._searchValue;
  7698. storeLoadOptions.searchExpr = this._searchExpr
  7699. }
  7700. },
  7701. _createStoreLoadOptions: function() {
  7702. var result = $.extend({}, this._storeLoadOptions);
  7703. this._addSearchOptions(result);
  7704. if (this._paginate)
  7705. if (this._pageSize) {
  7706. result.skip = this._pageIndex * this._pageSize;
  7707. result.take = this._pageSize
  7708. }
  7709. result.userData = this._userData;
  7710. return result
  7711. },
  7712. _createLoadOptions: function() {
  7713. return {
  7714. operationId: nextLoadOperationId(),
  7715. storeLoadOptions: this._createStoreLoadOptions()
  7716. }
  7717. },
  7718. _addSearchFilter: function(storeLoadOptions) {
  7719. var value = this._searchValue,
  7720. op = this._searchOperation,
  7721. selector = this._searchExpr,
  7722. searchFilter = [];
  7723. if (!value)
  7724. return;
  7725. if (!selector)
  7726. selector = "this";
  7727. if (!$.isArray(selector))
  7728. selector = [selector];
  7729. $.each(selector, function(i, item) {
  7730. if (searchFilter.length)
  7731. searchFilter.push("or");
  7732. searchFilter.push([item, op, value])
  7733. });
  7734. if (storeLoadOptions.filter)
  7735. storeLoadOptions.filter = [searchFilter, storeLoadOptions.filter];
  7736. else
  7737. storeLoadOptions.filter = searchFilter
  7738. },
  7739. _loadFromStore: function(loadOptions, pendingDeferred) {
  7740. var that = this;
  7741. function handleSuccess(data, extra) {
  7742. function processResult() {
  7743. var loadResult;
  7744. loadResult = $.extend({
  7745. data: data,
  7746. extra: extra
  7747. }, loadOptions);
  7748. that.fireEvent("customizeLoadResult", [loadResult]);
  7749. if (ensureIsNotRejected(loadOptions.operationId, pendingDeferred))
  7750. that._processStoreLoadResult(loadResult, pendingDeferred)
  7751. }
  7752. if (that._disposed)
  7753. return;
  7754. processResult()
  7755. }
  7756. if (!ensureIsNotRejected(loadOptions.operationId, pendingDeferred))
  7757. return pendingDeferred.promise();
  7758. return this.store().load(loadOptions.storeLoadOptions).done(handleSuccess).fail(pendingDeferred.reject)
  7759. },
  7760. _processStoreLoadResult: function(loadResult, pendingDeferred) {
  7761. var that = this;
  7762. var data = loadResult.data,
  7763. extra = loadResult.extra,
  7764. storeLoadOptions = loadResult.storeLoadOptions;
  7765. function resolvePendingDeferred() {
  7766. if (!ensureIsNotRejected(loadResult.operationId, pendingDeferred))
  7767. return pendingDeferred;
  7768. that._isLoaded = true;
  7769. that._totalCount = isFinite(extra.totalCount) ? extra.totalCount : -1;
  7770. return pendingDeferred.resolve(data, extra)
  7771. }
  7772. function proceedLoadingTotalCount() {
  7773. that.store().totalCount(storeLoadOptions).done(function(count) {
  7774. extra.totalCount = count;
  7775. resolvePendingDeferred()
  7776. }).fail(function(){})
  7777. }
  7778. if (that._disposed)
  7779. return;
  7780. data = that._transformLoadedData(data);
  7781. if (!$.isPlainObject(extra))
  7782. extra = {};
  7783. that._items = data;
  7784. if (!data.length || !that._paginate || that._pageSize && data.length < that._pageSize)
  7785. that._isLastPage = true;
  7786. if (storeLoadOptions.requireTotalCount && !isFinite(extra.totalCount))
  7787. proceedLoadingTotalCount();
  7788. else
  7789. resolvePendingDeferred()
  7790. },
  7791. _transformLoadedData: function(data) {
  7792. var result = $.makeArray(data);
  7793. if (this._mapFunc)
  7794. result = mapDataRespectingGrouping(result, this._mapFunc, this.group());
  7795. if (this._postProcessFunc)
  7796. result = this._postProcessFunc(result);
  7797. return result
  7798. }
  7799. }).include(DX.EventsMixin);
  7800. $.extend(true, data, {
  7801. DataSource: DataSource,
  7802. utils: {
  7803. storeTypeRegistry: storeTypeRegistry,
  7804. normalizeDataSourceOptions: normalizeDataSourceOptions
  7805. }
  7806. })
  7807. })(jQuery, DevExpress);
  7808. /*! Module core, file ko.js */
  7809. (function($, DX) {
  7810. if (DX.support.hasKo && DX.compareVersions(ko.version, [2, 3]) < 0)
  7811. throw DX.Error("E0013");
  7812. })(jQuery, DevExpress);
  7813. /*! Module core, file ng.js */
  7814. (function($, DX, undefined) {
  7815. if (!DX.support.hasNg)
  7816. return;
  7817. DX.ng = {module: window.angular.module("dx", ["ngSanitize"])}
  7818. })(jQuery, DevExpress);
  7819. /*! Module core, file component.js */
  7820. (function($, DX, undefined) {
  7821. var utils = DX.utils,
  7822. dataUtils = DX.data.utils,
  7823. inflector = DX.inflector;
  7824. var Component = DX.Class.inherit({
  7825. NAME: "Component",
  7826. _setDeprecatedOptions: function() {
  7827. this._deprecatedOptions = {}
  7828. },
  7829. _getDeprecatedOptions: function() {
  7830. return this._deprecatedOptions
  7831. },
  7832. _setOptionAliases: function() {
  7833. var aliases = this._optionAliases = {};
  7834. $.each(this._getDeprecatedOptions(), function(optionName, info) {
  7835. var optionAlias = info.alias;
  7836. if (optionAlias)
  7837. aliases[optionName] = optionAlias
  7838. })
  7839. },
  7840. _getOptionAliases: function() {
  7841. return this._optionAliases
  7842. },
  7843. _getOptionAliasesByName: function(optionName) {
  7844. return $.map(this._getOptionAliases(), function(aliasedOption, aliasName) {
  7845. return optionName === aliasedOption ? aliasName : undefined
  7846. })
  7847. },
  7848. _setDefaultOptions: function() {
  7849. this.option({
  7850. onInitialized: null,
  7851. onOptionChanged: null,
  7852. onDisposing: null,
  7853. defaultOptionsRules: null
  7854. })
  7855. },
  7856. _defaultOptionsRules: function() {
  7857. return []
  7858. },
  7859. _setOptionsByDevice: function(userRules) {
  7860. var rules = this._defaultOptionsRules();
  7861. if (this._customRules)
  7862. rules = rules.concat(this._customRules);
  7863. if ($.isArray(userRules))
  7864. rules = rules.concat(userRules);
  7865. this.option(this._convertRulesToOptions(rules))
  7866. },
  7867. _convertRulesToOptions: function(rules) {
  7868. var options = {};
  7869. var currentDevice = DX.devices.current();
  7870. var deviceMatch = function(device, filter) {
  7871. filter = $.makeArray(filter);
  7872. return filter.length === 1 && $.isEmptyObject(filter[0]) || utils.findBestMatches(device, filter).length > 0
  7873. };
  7874. $.each(rules, function(index, rule) {
  7875. var deviceFilter = rule.device || {},
  7876. match;
  7877. if ($.isFunction(deviceFilter))
  7878. match = deviceFilter(currentDevice);
  7879. else
  7880. match = deviceMatch(currentDevice, deviceFilter);
  7881. if (match)
  7882. $.extend(options, rule.options)
  7883. });
  7884. return options
  7885. },
  7886. _isInitialOptionValue: function(name) {
  7887. var isCustomOption = this._customRules && this._convertRulesToOptions(this._customRules).hasOwnProperty(name);
  7888. var isInitialOption = this.option(name) === this._initialOptions[name];
  7889. return !isCustomOption && isInitialOption
  7890. },
  7891. _setOptionsByReference: function() {
  7892. this._optionsByReference = {}
  7893. },
  7894. _getOptionsByReference: function() {
  7895. return this._optionsByReference
  7896. },
  7897. ctor: function(options) {
  7898. if (!this.NAME)
  7899. throw DX.Error("E0004");
  7900. options = options || {};
  7901. this._options = {};
  7902. this._cachedGetters = {};
  7903. this._updateLockCount = 0;
  7904. this._optionChangedCallbacks = options._optionChangedCallbacks || $.Callbacks();
  7905. this._disposingCallbacks = options._disposingCallbacks || $.Callbacks();
  7906. this.optionChanged = $.Callbacks();
  7907. this.disposing = $.Callbacks();
  7908. $.each(["optionChanged", "disposing"], $.proxy(function(_, propertyName) {
  7909. var that = this,
  7910. originalAdd = this[propertyName].add;
  7911. this[propertyName].add = function() {
  7912. DX.log("W0003", that.NAME, propertyName, "14.2", "Use the '" + propertyName + "' event instead");
  7913. return originalAdd.apply(this, arguments)
  7914. }
  7915. }, this));
  7916. this.beginUpdate();
  7917. try {
  7918. this._suppressDeprecatedWarnings();
  7919. this._setOptionsByReference();
  7920. this._setDeprecatedOptions();
  7921. this._setOptionAliases();
  7922. this._setDefaultOptions();
  7923. this._setOptionsByDevice(options.defaultOptionsRules);
  7924. this._resumeDeprecatedWarnings();
  7925. this._initialOptions = $.extend({}, this.option());
  7926. this._initOptions(options)
  7927. }
  7928. finally {
  7929. this.endUpdate()
  7930. }
  7931. },
  7932. _initOptions: function(options) {
  7933. this.option(options)
  7934. },
  7935. _optionValuesEqual: function(name, oldValue, newValue) {
  7936. oldValue = dataUtils.toComparable(oldValue, true);
  7937. newValue = dataUtils.toComparable(newValue, true);
  7938. if (oldValue && newValue && oldValue.jquery && newValue.jquery)
  7939. return newValue.is(oldValue);
  7940. var oldValueIsNaN = oldValue !== oldValue,
  7941. newValueIsNaN = newValue !== newValue;
  7942. if (oldValueIsNaN && newValueIsNaN)
  7943. return true;
  7944. if (oldValue === null || typeof oldValue !== "object")
  7945. return oldValue === newValue;
  7946. return false
  7947. },
  7948. _init: function() {
  7949. this._createOptionChangedAction();
  7950. this._createDisposingAction();
  7951. this.on("optionChanged", function(args) {
  7952. this._optionChangedCallbacks.fireWith(this, [args])
  7953. });
  7954. this.on("disposing", function(args) {
  7955. this._disposingCallbacks.fireWith(this, [args])
  7956. })
  7957. },
  7958. _createOptionChangedAction: function() {
  7959. this._optionChangedAction = this._createActionByOption("onOptionChanged", {excludeValidators: ["disabled", "readOnly"]})
  7960. },
  7961. _createDisposingAction: function() {
  7962. this._disposingAction = this._createActionByOption("onDisposing", {excludeValidators: ["disabled", "readOnly"]})
  7963. },
  7964. _optionChanged: function(args) {
  7965. switch (args.name) {
  7966. case"onInitialized":
  7967. break;
  7968. case"onOptionChanged":
  7969. this._createOptionChangedAction();
  7970. break;
  7971. case"onDisposing":
  7972. this._createDisposingAction();
  7973. break;
  7974. case"defaultOptionsRules":
  7975. break
  7976. }
  7977. },
  7978. _dispose: function() {
  7979. this.optionChanged.empty();
  7980. this.disposing.fireWith(this).empty();
  7981. this._disposingAction();
  7982. this._disposeEvents();
  7983. this._disposed = true
  7984. },
  7985. instance: function() {
  7986. return this
  7987. },
  7988. beginUpdate: function() {
  7989. this._updateLockCount++
  7990. },
  7991. endUpdate: function() {
  7992. this._updateLockCount--;
  7993. if (!this._updateLockCount)
  7994. if (!this._initializing && !this._initialized) {
  7995. this._initializing = true;
  7996. try {
  7997. this._init()
  7998. }
  7999. finally {
  8000. this._initializing = false;
  8001. this._initialized = true;
  8002. this._createActionByOption("onInitialized")()
  8003. }
  8004. }
  8005. },
  8006. _logWarningIfDeprecated: function(option) {
  8007. var info = this._getDeprecatedOptions()[option];
  8008. if (info && !this._deprecatedOptionsSuppressed)
  8009. this._logDeprecatedWarning(option, info)
  8010. },
  8011. _logDeprecatedWarningCount: 0,
  8012. _logDeprecatedWarning: function(option, info) {
  8013. var message = info.message || "Use the '" + info.alias + "' option instead";
  8014. DX.log("W0001", this.NAME, option, info.since, message);
  8015. ++this._logDeprecatedWarningCount
  8016. },
  8017. _suppressDeprecatedWarnings: function() {
  8018. this._deprecatedOptionsSuppressed = true
  8019. },
  8020. _resumeDeprecatedWarnings: function() {
  8021. this._deprecatedOptionsSuppressed = false
  8022. },
  8023. _notifyOptionChanged: function(option, value, previousValue) {
  8024. var that = this;
  8025. if (this._initialized)
  8026. $.each(that._getOptionAliasesByName(option).concat([option]), function(index, name) {
  8027. var args = {
  8028. name: name.split(/[.\[]/)[0],
  8029. fullName: name,
  8030. value: value,
  8031. previousValue: previousValue
  8032. };
  8033. that.optionChanged.fireWith(that, [args.name, value, previousValue]);
  8034. that._optionChangedAction($.extend({}, args));
  8035. if (!that._disposed)
  8036. that._optionChanged(args)
  8037. })
  8038. },
  8039. initialOption: function(optionName) {
  8040. var options = this._initialOptions;
  8041. return options[optionName]
  8042. },
  8043. _defaultActionConfig: function() {
  8044. return {
  8045. context: this,
  8046. component: this
  8047. }
  8048. },
  8049. _defaultActionArgs: function() {
  8050. return {component: this}
  8051. },
  8052. _createAction: function(actionSource, config) {
  8053. var that = this,
  8054. action = new DX.Action(actionSource, $.extend(config, that._defaultActionConfig()));
  8055. return function(e) {
  8056. if (!arguments.length)
  8057. e = {};
  8058. if (e instanceof $.Event)
  8059. throw Error("Action must be executed with jQuery.Event like action({ jQueryEvent: event })");
  8060. if (!$.isPlainObject(e))
  8061. e = {actionValue: e};
  8062. return action.execute.call(action, $.extend(e, that._defaultActionArgs()))
  8063. }
  8064. },
  8065. _createActionByOption: function(optionName, config) {
  8066. config = config || {};
  8067. if (typeof optionName !== "string")
  8068. throw DX.Error("E0008");
  8069. var matches = /^on(\w+)/.exec(optionName);
  8070. if (matches) {
  8071. var eventName = inflector.camelize(matches[1]),
  8072. afterExecute = config.afterExecute || $.noop,
  8073. that = this;
  8074. config.afterExecute = function(args) {
  8075. that.fireEvent(eventName, args.args);
  8076. return afterExecute.apply(this, arguments)
  8077. }
  8078. }
  8079. else {
  8080. var optionAlias = this._getOptionAliasesByName(optionName),
  8081. isOptionDeprecated = Boolean(this._getDeprecatedOptions()[optionName]);
  8082. if (isOptionDeprecated) {
  8083. if (optionAlias.length)
  8084. throw Error("The '" + optionName + "' is deprecated and has alias '" + optionAlias + "'");
  8085. }
  8086. else
  8087. throw Error("The '" + optionName + "' option name should start with 'on' prefix");
  8088. }
  8089. this._suppressDeprecatedWarnings();
  8090. var action = this._createAction(this.option(optionName), config);
  8091. this._resumeDeprecatedWarnings();
  8092. return action
  8093. },
  8094. option: function(options) {
  8095. var that = this,
  8096. name = options,
  8097. value = arguments[1],
  8098. optionAliases = this._getOptionAliases();
  8099. var normalizeOptionName = function(name) {
  8100. if (name) {
  8101. that._logWarningIfDeprecated(name);
  8102. if (optionAliases[name])
  8103. name = optionAliases[name]
  8104. }
  8105. return name
  8106. };
  8107. var getOptionValue = function(name, unwrapObservables) {
  8108. if (!that._cachedGetters[name])
  8109. that._cachedGetters[name] = dataUtils.compileGetter(name);
  8110. return that._cachedGetters[name](that._options, {
  8111. functionsAsIs: true,
  8112. unwrapObservables: unwrapObservables
  8113. })
  8114. };
  8115. if (arguments.length < 2 && $.type(name) !== "object") {
  8116. name = normalizeOptionName(name);
  8117. return getOptionValue(name)
  8118. }
  8119. if (typeof name === "string") {
  8120. options = {};
  8121. options[name] = value
  8122. }
  8123. that.beginUpdate();
  8124. try {
  8125. $.each(options, function(name, value) {
  8126. name = normalizeOptionName(name);
  8127. var prevValue = getOptionValue(name, false);
  8128. if (that._optionValuesEqual(name, prevValue, value))
  8129. return;
  8130. dataUtils.compileSetter(name)(that._options, value, {
  8131. functionsAsIs: true,
  8132. merge: !that._getOptionsByReference()[name],
  8133. unwrapObservables: false
  8134. });
  8135. that._notifyOptionChanged(name, value, prevValue)
  8136. })
  8137. }
  8138. finally {
  8139. that.endUpdate()
  8140. }
  8141. }
  8142. }).include(DX.EventsMixin);
  8143. $.extend(DX, {Component: Component})
  8144. })(jQuery, DevExpress);
  8145. /*! Module core, file transitionExecutor.js */
  8146. (function($, DX) {
  8147. var directionPostfixes = {
  8148. forward: " dx-forward",
  8149. backward: " dx-backward",
  8150. none: " dx-no-direction",
  8151. undefined: " dx-no-direction"
  8152. };
  8153. var addToAnimate = function(targetArray, $elements, animationConfig, type) {
  8154. $elements.each(function() {
  8155. var resultAnimationConfig = prepareElementAnimationConfig(animationConfig, type);
  8156. if (resultAnimationConfig)
  8157. targetArray.push({
  8158. $element: $(this),
  8159. animationConfig: resultAnimationConfig
  8160. })
  8161. })
  8162. };
  8163. var prepareElementAnimationConfig = function(config, type) {
  8164. var result;
  8165. if (typeof config === "string") {
  8166. var presetName = config;
  8167. config = DX.animationPresets.getPreset(presetName)
  8168. }
  8169. if (!config)
  8170. result = undefined;
  8171. else if ($.isFunction(config[type]))
  8172. result = config[type];
  8173. else {
  8174. var cssClass = "dx-" + type;
  8175. result = $.extend({skipElementInitialStyles: true}, config);
  8176. if (!result.type || result.type === "css") {
  8177. var extraCssClasses = result.extraCssClasses ? " " + result.extraCssClasses : "";
  8178. result.type = "css";
  8179. result.from = result.from || cssClass + extraCssClasses;
  8180. result.to = result.to || cssClass + "-active"
  8181. }
  8182. }
  8183. return result
  8184. };
  8185. var setupAnimations = function(items, config) {
  8186. var result = [];
  8187. $.each(items, function(index, item) {
  8188. var animationConfig = item.animationConfig,
  8189. $element = item.$element,
  8190. animationInstance;
  8191. if ($.isPlainObject(animationConfig)) {
  8192. var fxConfig = getFXConfig(animationConfig, config);
  8193. fxConfig.staggerDelay = fxConfig.staggerDelay || 0;
  8194. fxConfig.delay = index * fxConfig.staggerDelay + fxConfig.delay;
  8195. animationInstance = DX.fx.createAnimation($element, fxConfig)
  8196. }
  8197. else if ($.isFunction(animationConfig))
  8198. animationInstance = animationConfig($element, config);
  8199. animationInstance.setup();
  8200. result.push({
  8201. $element: $element,
  8202. animationInstance: animationInstance
  8203. })
  8204. });
  8205. return result
  8206. };
  8207. var startAnimations = function(items) {
  8208. for (var i = 0; i < items.length; i++)
  8209. items[i].animationInstance.start()
  8210. };
  8211. var getFXConfig = function(animation, config) {
  8212. var result = animation;
  8213. result.cleanupWhen = config.cleanupWhen;
  8214. result.delay = result.delay || 0;
  8215. if (result.type === "css") {
  8216. var direction = animation.direction || config.direction,
  8217. directionPostfix = directionPostfixes[direction];
  8218. result.from += directionPostfix
  8219. }
  8220. return result
  8221. };
  8222. var TransitionExecutor = DevExpress.Class.inherit({
  8223. ctor: function() {
  8224. this.toEnterItems = [];
  8225. this.toLeaveItems = [];
  8226. this.reset()
  8227. },
  8228. reset: function() {
  8229. this.toEnterItems.length = 0;
  8230. this.toLeaveItems.length = 0
  8231. },
  8232. enter: function($elements, animation) {
  8233. animation = animation || {};
  8234. addToAnimate(this.toEnterItems, $elements, animation, "enter")
  8235. },
  8236. leave: function($elements, animation) {
  8237. animation = animation || {};
  8238. addToAnimate(this.toLeaveItems, $elements, animation, "leave")
  8239. },
  8240. start: function(config) {
  8241. config = $.extend({}, config);
  8242. var that = this,
  8243. result;
  8244. if (!this.toEnterItems.length && !this.toLeaveItems.length) {
  8245. that.reset();
  8246. result = $.Deferred().resolve().promise()
  8247. }
  8248. else {
  8249. var animationItems = [],
  8250. animationDeferreds,
  8251. completeDeferred = $.Deferred();
  8252. config.cleanupWhen = completeDeferred.promise();
  8253. animationItems.push.apply(animationItems, setupAnimations(this.toEnterItems, config));
  8254. animationItems.push.apply(animationItems, setupAnimations(this.toLeaveItems, config));
  8255. animationDeferreds = $.map(animationItems, function(item) {
  8256. return item.animationInstance.deferred
  8257. });
  8258. result = $.when.apply($, animationDeferreds).always(function() {
  8259. completeDeferred.resolve();
  8260. that.reset()
  8261. });
  8262. DX.utils.executeAsync(function() {
  8263. startAnimations(animationItems)
  8264. })
  8265. }
  8266. return result
  8267. }
  8268. });
  8269. var optionPrefix = "preset_";
  8270. var AnimationPresetCollection = DevExpress.Component.inherit({
  8271. ctor: function() {
  8272. this.callBase.apply(this, arguments);
  8273. this._customRules = [];
  8274. this._registeredPresets = [];
  8275. this.resetToDefaults()
  8276. },
  8277. _setDefaultOptions: function() {
  8278. this.callBase();
  8279. this.option({
  8280. defaultAnimationDuration: 400,
  8281. defaultAnimationDelay: 0,
  8282. defaultStaggerAnimationDuration: 300,
  8283. defaultStaggerAnimationDelay: 40,
  8284. defaultStaggerAnimationStartDelay: 500
  8285. })
  8286. },
  8287. _defaultOptionsRules: function() {
  8288. return this.callBase().concat([{
  8289. device: function(device) {
  8290. return device.phone
  8291. },
  8292. options: {
  8293. defaultStaggerAnimationDuration: 350,
  8294. defaultStaggerAnimationDelay: 50,
  8295. defaultStaggerAnimationStartDelay: 0
  8296. }
  8297. }, {
  8298. device: function(device) {
  8299. return device.android
  8300. },
  8301. options: {defaultAnimationDelay: 100}
  8302. }])
  8303. },
  8304. _getPresetOptionName: function(animationName) {
  8305. return optionPrefix + animationName
  8306. },
  8307. resetToDefaults: function() {
  8308. this.clear();
  8309. this.registerDefaultPresets();
  8310. this.applyChanges()
  8311. },
  8312. clear: function(name) {
  8313. var that = this,
  8314. newRegisteredPresets = [];
  8315. $.each(this._registeredPresets, function(index, preset) {
  8316. if (!name || name === preset.name)
  8317. that.option(that._getPresetOptionName(preset.name), undefined);
  8318. else
  8319. newRegisteredPresets.push(preset)
  8320. });
  8321. this._registeredPresets = newRegisteredPresets;
  8322. this.applyChanges()
  8323. },
  8324. registerPreset: function(name, config) {
  8325. this._registeredPresets.push({
  8326. name: name,
  8327. config: config
  8328. })
  8329. },
  8330. applyChanges: function() {
  8331. var that = this;
  8332. this._customRules.length = 0;
  8333. $.each(this._registeredPresets, function(index, preset) {
  8334. var rule = {
  8335. device: preset.config.device,
  8336. options: {}
  8337. };
  8338. rule.options[that._getPresetOptionName(preset.name)] = preset.config.animation;
  8339. that._customRules.push(rule)
  8340. });
  8341. this._setOptionsByDevice()
  8342. },
  8343. getPreset: function(name) {
  8344. var result = name;
  8345. while (typeof result === "string")
  8346. result = this.option(this._getPresetOptionName(result));
  8347. return result
  8348. },
  8349. registerDefaultPresets: function() {
  8350. this.registerPreset("fade", {animation: {
  8351. extraCssClasses: "dx-fade-animation",
  8352. delay: this.option("defaultAnimationDelay"),
  8353. duration: this.option("defaultAnimationDuration")
  8354. }});
  8355. this.registerPreset("slide", {animation: {
  8356. extraCssClasses: "dx-slide-animation",
  8357. delay: this.option("defaultAnimationDelay"),
  8358. duration: this.option("defaultAnimationDuration")
  8359. }});
  8360. this.registerPreset("ios7-slide", {animation: {
  8361. extraCssClasses: "dx-ios7-slide-animation",
  8362. delay: this.option("defaultAnimationDelay"),
  8363. duration: this.option("defaultAnimationDuration")
  8364. }});
  8365. this.registerPreset("overflow", {animation: {
  8366. extraCssClasses: "dx-overflow-animation",
  8367. delay: this.option("defaultAnimationDelay"),
  8368. duration: this.option("defaultAnimationDuration")
  8369. }});
  8370. this.registerPreset("ios7-toolbar", {animation: {
  8371. extraCssClasses: "dx-ios7-toolbar-animation",
  8372. delay: this.option("defaultAnimationDelay"),
  8373. duration: this.option("defaultAnimationDuration")
  8374. }});
  8375. this.registerPreset("stagger-fade", {animation: {
  8376. extraCssClasses: "dx-fade-animation",
  8377. staggerDelay: this.option("defaultStaggerAnimationDelay"),
  8378. duration: this.option("defaultStaggerAnimationDuration"),
  8379. delay: this.option("defaultStaggerAnimationStartDelay")
  8380. }});
  8381. this.registerPreset("stagger-slide", {animation: {
  8382. extraCssClasses: "dx-slide-animation",
  8383. staggerDelay: this.option("defaultStaggerAnimationDelay"),
  8384. duration: this.option("defaultStaggerAnimationDuration"),
  8385. delay: this.option("defaultStaggerAnimationStartDelay")
  8386. }});
  8387. this.registerPreset("stagger-fade-slide", {animation: {
  8388. extraCssClasses: "dx-fade-slide-animation",
  8389. staggerDelay: this.option("defaultStaggerAnimationDelay"),
  8390. duration: this.option("defaultStaggerAnimationDuration"),
  8391. delay: this.option("defaultStaggerAnimationStartDelay")
  8392. }});
  8393. this.registerPreset("stagger-drop", {animation: {
  8394. extraCssClasses: "dx-drop-animation",
  8395. staggerDelay: this.option("defaultStaggerAnimationDelay"),
  8396. duration: this.option("defaultStaggerAnimationDuration"),
  8397. delay: this.option("defaultStaggerAnimationStartDelay")
  8398. }});
  8399. this.registerPreset("stagger-fade-drop", {animation: {
  8400. extraCssClasses: "dx-fade-drop-animation",
  8401. staggerDelay: this.option("defaultStaggerAnimationDelay"),
  8402. duration: this.option("defaultStaggerAnimationDuration"),
  8403. delay: this.option("defaultStaggerAnimationStartDelay")
  8404. }});
  8405. this.registerPreset("stagger-3d-drop", {animation: {
  8406. extraCssClasses: "dx-3d-drop-animation",
  8407. staggerDelay: this.option("defaultStaggerAnimationDelay"),
  8408. duration: this.option("defaultStaggerAnimationDuration"),
  8409. delay: this.option("defaultStaggerAnimationStartDelay")
  8410. }});
  8411. this.registerPreset("stagger-fade-zoom", {animation: {
  8412. extraCssClasses: "dx-fade-zoom-animation",
  8413. staggerDelay: this.option("defaultStaggerAnimationDelay"),
  8414. duration: this.option("defaultStaggerAnimationDuration"),
  8415. delay: this.option("defaultStaggerAnimationStartDelay")
  8416. }})
  8417. }
  8418. });
  8419. DX.TransitionExecutor = TransitionExecutor;
  8420. DX.AnimationPresetCollection = AnimationPresetCollection;
  8421. DX.animationPresets = new AnimationPresetCollection
  8422. })(jQuery, DevExpress);
  8423. /*! Module core, file DOMComponent.js */
  8424. (function($, DX, undefined) {
  8425. var windowResizeCallbacks = DX.utils.windowResizeCallbacks;
  8426. var RTL_DIRECTION_CLASS = "dx-rtl",
  8427. COMPONENT_NAMES_DATA_KEY = "dxComponents",
  8428. VISIBILITY_CHANGE_CLASS = "dx-visibility-change-handler",
  8429. VISIBILITY_CHANGE_EVENTNAMESPACE = "dxVisibilityChange";
  8430. var DOMComponent = DX.Component.inherit({
  8431. NAME: "DOMComponent",
  8432. _setDefaultOptions: function() {
  8433. this.callBase();
  8434. this.option({
  8435. width: undefined,
  8436. height: undefined,
  8437. rtlEnabled: DX.rtlEnabled
  8438. })
  8439. },
  8440. ctor: function(element, options) {
  8441. this._$element = $(element);
  8442. this.element().data(this.NAME, this);
  8443. this._attachInstanceToElement(this._$element);
  8444. this.callBase(options)
  8445. },
  8446. _attachInstanceToElement: $.noop,
  8447. _visibilityChanged: DX.abstract,
  8448. _dimensionChanged: DX.abstract,
  8449. _init: function() {
  8450. this.callBase();
  8451. this._attachWindowResizeCallback()
  8452. },
  8453. _attachWindowResizeCallback: function() {
  8454. if (this._isDimensionChangeSupported()) {
  8455. var windowResizeCallBack = this._windowResizeCallBack = $.proxy(this._dimensionChanged, this);
  8456. windowResizeCallbacks.add(windowResizeCallBack)
  8457. }
  8458. },
  8459. _isDimensionChangeSupported: function() {
  8460. return this._dimensionChanged !== DX.abstract
  8461. },
  8462. _render: function() {
  8463. this._toggleRTLDirection(this.option("rtlEnabled"));
  8464. this._renderVisibilityChange();
  8465. this._renderDimensions()
  8466. },
  8467. _renderVisibilityChange: function() {
  8468. if (!this._isVisibilityChangeSupported())
  8469. return;
  8470. this.element().addClass(VISIBILITY_CHANGE_CLASS);
  8471. this._attachVisiblityChangeHandlers()
  8472. },
  8473. _renderDimensions: function() {
  8474. var width = this.option("width"),
  8475. height = this.option("height"),
  8476. $element = this.element();
  8477. $element.outerWidth(width);
  8478. $element.outerHeight(height)
  8479. },
  8480. _attachVisiblityChangeHandlers: function() {
  8481. var that = this;
  8482. that.element().off("." + VISIBILITY_CHANGE_EVENTNAMESPACE).on("dxhiding." + VISIBILITY_CHANGE_EVENTNAMESPACE, function() {
  8483. that._visibilityChanged(false)
  8484. }).on("dxshown." + VISIBILITY_CHANGE_EVENTNAMESPACE, function() {
  8485. that._visibilityChanged(true)
  8486. })
  8487. },
  8488. _isVisibilityChangeSupported: function() {
  8489. return this._visibilityChanged !== DX.abstract
  8490. },
  8491. _clean: $.noop,
  8492. _modelByElement: $.noop,
  8493. _invalidate: function() {
  8494. if (!this._updateLockCount)
  8495. throw DX.Error("E0007");
  8496. this._requireRefresh = true
  8497. },
  8498. _refresh: function() {
  8499. this._clean();
  8500. this._render()
  8501. },
  8502. _dispose: function() {
  8503. this.callBase();
  8504. this._clean();
  8505. this._detachWindowResizeCallback()
  8506. },
  8507. _detachWindowResizeCallback: function() {
  8508. if (this._isDimensionChangeSupported())
  8509. windowResizeCallbacks.remove(this._windowResizeCallBack)
  8510. },
  8511. _toggleRTLDirection: function(rtl) {
  8512. this.element().toggleClass(RTL_DIRECTION_CLASS, rtl)
  8513. },
  8514. _createComponent: function(element, name, config) {
  8515. config = config || {};
  8516. this._extendConfig(config, {rtlEnabled: this.option("rtlEnabled")});
  8517. var $element = $(element)[name](config);
  8518. return $element[name]("instance")
  8519. },
  8520. _extendConfig: function(config, extendConfig) {
  8521. $.each(extendConfig, function(key, value) {
  8522. config[key] = config.hasOwnProperty(key) ? config[key] : value
  8523. })
  8524. },
  8525. _defaultActionConfig: function() {
  8526. return $.extend(this.callBase(), {context: this._modelByElement(this.element())})
  8527. },
  8528. _defaultActionArgs: function() {
  8529. var element = this.element(),
  8530. model = this._modelByElement(this.element());
  8531. return $.extend(this.callBase(), {
  8532. element: element,
  8533. model: model
  8534. })
  8535. },
  8536. _optionChanged: function(args) {
  8537. switch (args.name) {
  8538. case"width":
  8539. case"height":
  8540. this._renderDimensions();
  8541. break;
  8542. case"rtlEnabled":
  8543. this._invalidate();
  8544. break;
  8545. default:
  8546. this.callBase(args);
  8547. break
  8548. }
  8549. },
  8550. endUpdate: function() {
  8551. var requireRender = !this._initializing && !this._initialized;
  8552. this.callBase.apply(this, arguments);
  8553. if (!this._updateLockCount)
  8554. if (requireRender)
  8555. this._render();
  8556. else if (this._requireRefresh) {
  8557. this._requireRefresh = false;
  8558. this._refresh()
  8559. }
  8560. },
  8561. element: function() {
  8562. return this._$element
  8563. }
  8564. });
  8565. var registerComponent = function(name, namespace, componentClass) {
  8566. if (!componentClass) {
  8567. componentClass = namespace;
  8568. namespace = DX
  8569. }
  8570. componentClass.redefine({_attachInstanceToElement: function($element) {
  8571. $element.data(name, this);
  8572. if (!$element.data(COMPONENT_NAMES_DATA_KEY))
  8573. $element.data(COMPONENT_NAMES_DATA_KEY, []);
  8574. $element.data(COMPONENT_NAMES_DATA_KEY).push(name)
  8575. }});
  8576. namespace[name] = componentClass;
  8577. componentClass.prototype.NAME = name;
  8578. componentClass.defaultOptions = function(rule) {
  8579. componentClass.prototype._customRules = componentClass.prototype._customRules || [];
  8580. componentClass.prototype._customRules.push(rule)
  8581. };
  8582. $.fn[name] = function(options) {
  8583. var isMemberInvoke = typeof options === "string",
  8584. result;
  8585. if (isMemberInvoke) {
  8586. var memberName = options,
  8587. memberArgs = $.makeArray(arguments).slice(1);
  8588. this.each(function() {
  8589. var instance = $(this).data(name);
  8590. if (!instance)
  8591. throw DX.Error("E0009", name);
  8592. var member = instance[memberName],
  8593. memberValue = member.apply(instance, memberArgs);
  8594. if (result === undefined)
  8595. result = memberValue
  8596. })
  8597. }
  8598. else {
  8599. this.each(function() {
  8600. var instance = $(this).data(name);
  8601. if (instance)
  8602. instance.option(options);
  8603. else
  8604. new componentClass(this, options)
  8605. });
  8606. result = this
  8607. }
  8608. return result
  8609. }
  8610. };
  8611. var getComponents = function(element) {
  8612. element = $(element);
  8613. var names = element.data(COMPONENT_NAMES_DATA_KEY);
  8614. if (!names)
  8615. return [];
  8616. return $.map(names, function(name) {
  8617. return element.data(name)
  8618. })
  8619. };
  8620. var disposeComponents = function() {
  8621. $.each(getComponents(this), function() {
  8622. this._dispose()
  8623. })
  8624. };
  8625. var originalCleanData = $.cleanData;
  8626. $.cleanData = function(element) {
  8627. $.each(element, disposeComponents);
  8628. return originalCleanData.apply(this, arguments)
  8629. };
  8630. registerComponent("DOMComponent", DOMComponent);
  8631. DX.registerComponent = registerComponent
  8632. })(jQuery, DevExpress);
  8633. /*! Module core, file ui.js */
  8634. (function($, DX, undefined) {
  8635. DX.ui = {};
  8636. var createValidatorByTargetElement = function(condition) {
  8637. return function(e) {
  8638. if (!e.args.length)
  8639. return;
  8640. var args = e.args[0],
  8641. element = args[e.validatingTargetName] || args.element;
  8642. if (element && condition(element))
  8643. e.cancel = true
  8644. }
  8645. };
  8646. DX.registerActionExecutor({
  8647. designMode: {validate: function(e) {
  8648. if (DX.designMode)
  8649. e.cancel = true
  8650. }},
  8651. disabled: {validate: createValidatorByTargetElement(function($target) {
  8652. return $target.is(".dx-state-disabled, .dx-state-disabled *")
  8653. })},
  8654. readOnly: {validate: createValidatorByTargetElement(function($target) {
  8655. return $target.is(".dx-state-readonly, .dx-state-readonly *")
  8656. })}
  8657. })
  8658. })(jQuery, DevExpress);
  8659. /*! Module core, file ui.templates.js */
  8660. (function($, DX, undefined) {
  8661. var ui = DX.ui,
  8662. triggerShownEvent = DX.utils.triggerShownEvent;
  8663. var getWidgetName = function(widgetConstructor) {
  8664. return widgetConstructor.prototype.NAME
  8665. };
  8666. var TemplateProviderBase = DX.Class.inherit({
  8667. ctor: function() {
  8668. this.widgetTemplatesCache = {}
  8669. },
  8670. createTemplate: DX.abstract,
  8671. getTemplates: function(widget) {
  8672. return this._getWidgetTemplates(widget.constructor)
  8673. },
  8674. _getWidgetTemplates: function(widgetConstructor) {
  8675. if (!getWidgetName(widgetConstructor))
  8676. return {};
  8677. return this._getCachedWidgetTemplates(widgetConstructor)
  8678. },
  8679. _getCachedWidgetTemplates: function(widgetConstructor) {
  8680. var widgetName = getWidgetName(widgetConstructor),
  8681. templatesCache = this.widgetTemplatesCache;
  8682. if (!templatesCache[widgetName])
  8683. templatesCache[widgetName] = $.extend({}, this._getWidgetTemplates(widgetConstructor.parent), this._templatesForWidget(widgetName));
  8684. return templatesCache[widgetName]
  8685. },
  8686. _templatesForWidget: DX.abstract
  8687. });
  8688. var TemplateBase = DX.Class.inherit({
  8689. ctor: function(element, owner) {
  8690. this._element = $(element);
  8691. this._owner = owner
  8692. },
  8693. owner: function() {
  8694. return this._owner
  8695. },
  8696. render: function(data, $container, index) {
  8697. if (data instanceof jQuery) {
  8698. $container = data;
  8699. data = undefined
  8700. }
  8701. if ($container)
  8702. data = this._prepareDataForContainer(data, $container);
  8703. var $result = this._renderCore(data, index, $container);
  8704. if (this._shouldAppend && $container) {
  8705. $container.append($result);
  8706. if ($.contains(document.body, $container.get(0)))
  8707. triggerShownEvent($result)
  8708. }
  8709. return $result
  8710. },
  8711. source: function() {
  8712. return this._element.clone()
  8713. },
  8714. _prepareDataForContainer: function(data) {
  8715. return data
  8716. },
  8717. _renderCore: DX.abstract,
  8718. _shouldAppend: true,
  8719. dispose: function() {
  8720. this._owner = null
  8721. }
  8722. });
  8723. $.extend(ui, {
  8724. TemplateProviderBase: TemplateProviderBase,
  8725. TemplateBase: TemplateBase
  8726. })
  8727. })(jQuery, DevExpress);
  8728. /*! Module core, file jquery.templates.js */
  8729. (function($, DX, undefined) {
  8730. var ui = DX.ui,
  8731. utils = DX.utils,
  8732. isString = DX.utils.isString,
  8733. currentTemplateEngine,
  8734. templateEngines = {};
  8735. var Template = ui.TemplateBase.inherit({
  8736. ctor: function(element, owner) {
  8737. this.callBase(element, owner);
  8738. this._compiledTemplate = currentTemplateEngine.compile(element)
  8739. },
  8740. _renderCore: function(data) {
  8741. return $("<div>").append(currentTemplateEngine.render(this._compiledTemplate, data)).contents()
  8742. }
  8743. });
  8744. var setTemplateEngine = function(templateEngine) {
  8745. if (isString(templateEngine)) {
  8746. currentTemplateEngine = templateEngines[templateEngine];
  8747. if (!currentTemplateEngine)
  8748. throw DX.Error("E0020", templateEngine);
  8749. }
  8750. else
  8751. currentTemplateEngine = templateEngine
  8752. };
  8753. var registerTemplateEngine = function(name, templateEngine) {
  8754. templateEngines[name] = templateEngine
  8755. };
  8756. var outerHtml = function(element) {
  8757. element = $(element);
  8758. if (!element.length || element[0].nodeName.toLowerCase() !== "script")
  8759. element = $("<div>").append(element);
  8760. return element.html()
  8761. };
  8762. registerTemplateEngine("default", {
  8763. compile: function(element) {
  8764. return DX.utils.normalizeTemplateElement(element)
  8765. },
  8766. render: function(template, data) {
  8767. return template.clone()
  8768. }
  8769. });
  8770. registerTemplateEngine("jquery-tmpl", {
  8771. compile: function(element) {
  8772. return $("<div>").append(DX.utils.normalizeTemplateElement(element))
  8773. },
  8774. render: function(template, data) {
  8775. return template.tmpl(data)
  8776. }
  8777. });
  8778. registerTemplateEngine("jsrender", {
  8779. compile: function(element) {
  8780. return $.templates(outerHtml(element))
  8781. },
  8782. render: function(template, data) {
  8783. return template.render(data)
  8784. }
  8785. });
  8786. registerTemplateEngine("mustache", {
  8787. compile: function(element) {
  8788. return Mustache.compile(outerHtml(element))
  8789. },
  8790. render: function(template, data) {
  8791. return template(data)
  8792. }
  8793. });
  8794. registerTemplateEngine("hogan", {
  8795. compile: function(element) {
  8796. return Hogan.compile(outerHtml(element))
  8797. },
  8798. render: function(template, data) {
  8799. return template.render(data)
  8800. }
  8801. });
  8802. registerTemplateEngine("underscore", {
  8803. compile: function(element) {
  8804. return _.template(outerHtml(element))
  8805. },
  8806. render: function(template, data) {
  8807. return template(data)
  8808. }
  8809. });
  8810. registerTemplateEngine("handlebars", {
  8811. compile: function(element) {
  8812. return Handlebars.compile(outerHtml(element))
  8813. },
  8814. render: function(template, data) {
  8815. return template(data)
  8816. }
  8817. });
  8818. registerTemplateEngine("doT", {
  8819. compile: function(element) {
  8820. return doT.template(outerHtml(element))
  8821. },
  8822. render: function(template, data) {
  8823. return template(data)
  8824. }
  8825. });
  8826. setTemplateEngine("default");
  8827. var DefaultTemplate = ui.TemplateBase.inherit({
  8828. ctor: function(render, owner) {
  8829. this.callBase($("<div>"), owner);
  8830. this._render = render
  8831. },
  8832. _renderCore: function(data, index, container) {
  8833. return DX.utils.normalizeTemplateElement(this._render(data, index, container))
  8834. }
  8835. });
  8836. var TemplateProvider = new(ui.TemplateProviderBase.inherit({
  8837. createTemplate: function(element, owner) {
  8838. return new ui.Template(element, owner)
  8839. },
  8840. _templatesForWidget: function(widgetName) {
  8841. var templateGenerators = TEMPLATE_GENERATORS[widgetName] || {},
  8842. templates = {};
  8843. $.each(templateGenerators, function(name, generator) {
  8844. templates[name] = new ui.DefaultTemplate(function() {
  8845. var $markup = generator.apply(this, arguments);
  8846. if (name !== "itemFrame")
  8847. $markup = $markup.contents();
  8848. return $markup
  8849. }, TemplateProvider)
  8850. });
  8851. return templates
  8852. }
  8853. }));
  8854. var TEMPLATE_GENERATORS = {};
  8855. var emptyTemplate = function() {
  8856. return $()
  8857. };
  8858. var ITEM_CONTENT_PLACEHOLDER_CLASS = "dx-item-content-placeholder";
  8859. TEMPLATE_GENERATORS.CollectionWidget = {
  8860. item: function(itemData) {
  8861. var $itemContent = $("<div>");
  8862. if ($.isPlainObject(itemData)) {
  8863. if (itemData.text)
  8864. $itemContent.text(itemData.text);
  8865. if (itemData.html)
  8866. $itemContent.html(itemData.html)
  8867. }
  8868. else
  8869. $itemContent.html(String(itemData));
  8870. return $itemContent
  8871. },
  8872. itemFrame: function(itemData) {
  8873. var $itemFrame = $("<div>");
  8874. $itemFrame.toggleClass("dx-state-invisible", itemData.visible !== undefined && !itemData.visible);
  8875. $itemFrame.toggleClass("dx-state-disabled", !!itemData.disabled);
  8876. var $placeholder = $("<div>").addClass(ITEM_CONTENT_PLACEHOLDER_CLASS);
  8877. $itemFrame.append($placeholder);
  8878. return $itemFrame
  8879. }
  8880. };
  8881. var BUTTON_TEXT_CLASS = "dx-button-text";
  8882. TEMPLATE_GENERATORS.dxButton = {content: function(itemData) {
  8883. var $itemContent = $("<div>"),
  8884. $iconElement = utils.getImageContainer(itemData.icon),
  8885. $textContainer = itemData.text ? $("<span>").text(itemData.text).addClass(BUTTON_TEXT_CLASS) : undefined;
  8886. $itemContent.append($iconElement).append($textContainer);
  8887. return $itemContent
  8888. }};
  8889. var LIST_ITEM_BADGE_CONTAINER_CLASS = "dx-list-item-badge-container",
  8890. LIST_ITEM_BADGE_CLASS = "dx-list-item-badge",
  8891. BADGE_CLASS = "dx-badge",
  8892. LIST_ITEM_CHEVRON_CONTAINER_CLASS = "dx-list-item-chevron-container",
  8893. LIST_ITEM_CHEVRON_CLASS = "dx-list-item-chevron";
  8894. TEMPLATE_GENERATORS.dxList = {
  8895. item: function(itemData) {
  8896. var $itemContent = TEMPLATE_GENERATORS.CollectionWidget.item(itemData);
  8897. if (itemData.key) {
  8898. var $key = $("<div>").text(itemData.key);
  8899. $key.appendTo($itemContent)
  8900. }
  8901. return $itemContent
  8902. },
  8903. itemFrame: function(itemData) {
  8904. var $itemFrame = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(itemData);
  8905. if (itemData.badge) {
  8906. var $badgeContainer = $("<div>").addClass(LIST_ITEM_BADGE_CONTAINER_CLASS),
  8907. $badge = $("<div>").addClass(LIST_ITEM_BADGE_CLASS).addClass(BADGE_CLASS);
  8908. $badge.text(itemData.badge);
  8909. $badgeContainer.append($badge).appendTo($itemFrame)
  8910. }
  8911. if (itemData.showChevron) {
  8912. var $chevronContainer = $("<div>").addClass(LIST_ITEM_CHEVRON_CONTAINER_CLASS),
  8913. $chevron = $("<div>").addClass(LIST_ITEM_CHEVRON_CLASS);
  8914. $chevronContainer.append($chevron).appendTo($itemFrame)
  8915. }
  8916. return $itemFrame
  8917. },
  8918. group: function(groupData) {
  8919. var $groupContent = $("<div>");
  8920. if ($.isPlainObject(groupData)) {
  8921. if (groupData.key)
  8922. $groupContent.text(groupData.key)
  8923. }
  8924. else
  8925. $groupContent.html(String(groupData));
  8926. return $groupContent
  8927. }
  8928. };
  8929. TEMPLATE_GENERATORS.dxDropDownMenu = {item: TEMPLATE_GENERATORS.dxList.item};
  8930. TEMPLATE_GENERATORS.dxDropDownList = {item: TEMPLATE_GENERATORS.dxList.item};
  8931. TEMPLATE_GENERATORS.dxRadioGroup = {item: TEMPLATE_GENERATORS.CollectionWidget.item};
  8932. TEMPLATE_GENERATORS.dxScheduler = {item: function(itemData) {
  8933. var $itemContent = TEMPLATE_GENERATORS.CollectionWidget.item(itemData);
  8934. var $details = $("<div>").addClass("dx-scheduler-appointment-content-details");
  8935. if (itemData.startDate)
  8936. $("<strong>").text(Globalize.format(DX.utils.makeDate(itemData.startDate), "t")).appendTo($details);
  8937. if (itemData.endDate)
  8938. $("<strong>").text(" - " + Globalize.format(DX.utils.makeDate(itemData.endDate), "t")).appendTo($details);
  8939. $details.appendTo($itemContent);
  8940. if (itemData.recurrenceRule)
  8941. $("<span>").addClass("dx-scheduler-appointment-recurrence-icon").appendTo($itemContent);
  8942. return $itemContent
  8943. }};
  8944. TEMPLATE_GENERATORS.dxOverlay = {content: emptyTemplate};
  8945. TEMPLATE_GENERATORS.dxSlideOutView = {
  8946. menu: emptyTemplate,
  8947. content: emptyTemplate
  8948. };
  8949. TEMPLATE_GENERATORS.dxSlideOut = {
  8950. menuItem: TEMPLATE_GENERATORS.dxList.item,
  8951. menuGroup: TEMPLATE_GENERATORS.dxList.group,
  8952. content: emptyTemplate
  8953. };
  8954. TEMPLATE_GENERATORS.dxAccordion = {
  8955. title: function(titleData) {
  8956. var $titleContent = $("<div>"),
  8957. icon = titleData.icon,
  8958. iconSrc = titleData.iconSrc,
  8959. $iconElement = utils.getImageContainer(icon || iconSrc);
  8960. if ($.isPlainObject(titleData)) {
  8961. if (titleData.title)
  8962. $titleContent.text(titleData.title)
  8963. }
  8964. else
  8965. $titleContent.html(String(titleData));
  8966. $iconElement && $iconElement.prependTo($titleContent);
  8967. return $titleContent
  8968. },
  8969. item: TEMPLATE_GENERATORS.CollectionWidget.item
  8970. };
  8971. TEMPLATE_GENERATORS.dxActionSheet = {item: function(itemData) {
  8972. return $("<div>").append($("<div>").dxButton($.extend({onClick: itemData.click}, itemData)))
  8973. }};
  8974. TEMPLATE_GENERATORS.dxGallery = {item: function(itemData) {
  8975. var $itemContent = $("<div>");
  8976. if (itemData.imageSrc)
  8977. $('<img>').attr('src', itemData.imageSrc).appendTo($itemContent);
  8978. else
  8979. $('<img>').attr('src', String(itemData)).appendTo($itemContent);
  8980. return $itemContent
  8981. }};
  8982. var DX_MENU_ITEM_CAPTION_CLASS = 'dx-menu-item-text',
  8983. DX_MENU_ITEM_POPOUT_CLASS = 'dx-menu-item-popout',
  8984. DX_MENU_ITEM_POPOUT_CONTAINER_CLASS = 'dx-menu-item-popout-container';
  8985. TEMPLATE_GENERATORS.dxMenuBase = {item: function(itemData) {
  8986. var $itemContent = $("<div>"),
  8987. icon = itemData.icon,
  8988. iconSrc = itemData.iconSrc,
  8989. $iconElement = utils.getImageContainer(icon || iconSrc);
  8990. $iconElement && $iconElement.appendTo($itemContent);
  8991. var $itemCaption;
  8992. if ($.isPlainObject(itemData) && itemData.text)
  8993. $itemCaption = $('<span>').addClass(DX_MENU_ITEM_CAPTION_CLASS).text(itemData.text);
  8994. else if (!$.isPlainObject(itemData))
  8995. $itemCaption = $('<span>').addClass(DX_MENU_ITEM_CAPTION_CLASS).html(String(itemData));
  8996. $itemContent.append($itemCaption);
  8997. var $popOutImage,
  8998. $popOutContainer;
  8999. if (itemData.items && itemData.items.length > 0) {
  9000. $popOutContainer = $('<span>').addClass(DX_MENU_ITEM_POPOUT_CONTAINER_CLASS).appendTo($itemContent);
  9001. $popOutImage = $('<div>').addClass(DX_MENU_ITEM_POPOUT_CLASS).appendTo($popOutContainer)
  9002. }
  9003. return $itemContent
  9004. }};
  9005. var PANORAMA_ITEM_TITLE_CLASS = "dx-panorama-item-title";
  9006. TEMPLATE_GENERATORS.dxPanorama = {itemFrame: function(itemData) {
  9007. var $itemContent = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(itemData);
  9008. if (itemData.title) {
  9009. var $itemHeader = $("<div>").addClass(PANORAMA_ITEM_TITLE_CLASS).text(itemData.title);
  9010. $itemContent.prepend($itemHeader)
  9011. }
  9012. return $itemContent
  9013. }};
  9014. TEMPLATE_GENERATORS.dxPivotTabs = {item: function(itemData) {
  9015. var $itemContent = $("<div>");
  9016. var $itemText;
  9017. if ($.isPlainObject(itemData))
  9018. $itemText = $("<span>").text(itemData.title);
  9019. else
  9020. $itemText = $("<span>").text(String(itemData));
  9021. $itemContent.html($itemText);
  9022. return $itemContent
  9023. }};
  9024. TEMPLATE_GENERATORS.dxPivot = {
  9025. title: TEMPLATE_GENERATORS.dxPivotTabs.item,
  9026. content: emptyTemplate
  9027. };
  9028. var TABS_ITEM_TEXT_CLASS = "dx-tab-text";
  9029. TEMPLATE_GENERATORS.dxTabs = {
  9030. item: function(itemData) {
  9031. var $itemContent = TEMPLATE_GENERATORS.CollectionWidget.item(itemData);
  9032. if (itemData.html)
  9033. return $itemContent;
  9034. var icon = itemData.icon,
  9035. iconSrc = itemData.iconSrc,
  9036. $iconElement = utils.getImageContainer(icon || iconSrc);
  9037. if (!itemData.html)
  9038. $itemContent.wrapInner($("<span>").addClass(TABS_ITEM_TEXT_CLASS));
  9039. $iconElement && $iconElement.prependTo($itemContent);
  9040. return $itemContent
  9041. },
  9042. itemFrame: function(itemData) {
  9043. var $badge = $(),
  9044. $itemFrame = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(itemData);
  9045. if (itemData.badge)
  9046. $badge = $("<div>", {"class": "dx-tabs-item-badge dx-badge"}).text(itemData.badge);
  9047. $itemFrame.append($badge);
  9048. return $itemFrame
  9049. }
  9050. };
  9051. TEMPLATE_GENERATORS.dxTabPanel = {
  9052. item: TEMPLATE_GENERATORS.CollectionWidget.item,
  9053. title: function(itemData) {
  9054. var itemTitleData = itemData;
  9055. if ($.isPlainObject(itemData))
  9056. itemTitleData = $.extend({}, itemData, {text: itemData.title});
  9057. var $title = TEMPLATE_GENERATORS.dxTabs.item(itemTitleData);
  9058. return $title
  9059. }
  9060. };
  9061. var NAVBAR_ITEM_BADGE_CLASS = "dx-navbar-item-badge";
  9062. TEMPLATE_GENERATORS.dxNavBar = {itemFrame: function(itemData) {
  9063. var $itemFrame = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(itemData);
  9064. if (itemData.badge) {
  9065. var $badge = $("<div>").addClass(NAVBAR_ITEM_BADGE_CLASS).addClass(BADGE_CLASS);
  9066. $badge.text(itemData.badge);
  9067. $badge.appendTo($itemFrame)
  9068. }
  9069. return $itemFrame
  9070. }};
  9071. TEMPLATE_GENERATORS.dxToolbar = {
  9072. item: function(itemData) {
  9073. var $itemContent = TEMPLATE_GENERATORS.CollectionWidget.item(itemData);
  9074. var widget = itemData.widget;
  9075. if (widget) {
  9076. var widgetElement = $("<div>").appendTo($itemContent),
  9077. widgetName = DX.inflector.camelize("dx-" + widget),
  9078. options = itemData.options || {};
  9079. widgetElement[widgetName](options)
  9080. }
  9081. else if (itemData.text)
  9082. $itemContent.wrapInner("<div>");
  9083. return $itemContent
  9084. },
  9085. menuItem: TEMPLATE_GENERATORS.dxList.item,
  9086. actionSheetItem: TEMPLATE_GENERATORS.dxActionSheet.item
  9087. };
  9088. TEMPLATE_GENERATORS.dxTreeView = {item: function(itemData) {
  9089. var $itemContent = $("<div>"),
  9090. icon = itemData.icon,
  9091. iconSrc = itemData.iconSrc,
  9092. $iconElement = utils.getImageContainer(icon || iconSrc);
  9093. if (itemData.html)
  9094. $itemContent.html(itemData.html);
  9095. else {
  9096. $iconElement && $iconElement.appendTo($itemContent);
  9097. $("<span>").text(itemData.text).appendTo($itemContent)
  9098. }
  9099. return $itemContent
  9100. }};
  9101. var popupTitleAndBottom = function(itemData) {
  9102. return $("<div>").append($("<div>").dxToolbar({items: itemData}))
  9103. };
  9104. TEMPLATE_GENERATORS.dxPopup = {
  9105. title: popupTitleAndBottom,
  9106. bottom: popupTitleAndBottom
  9107. };
  9108. TEMPLATE_GENERATORS.dxLookup = {
  9109. title: TEMPLATE_GENERATORS.dxPopup.title,
  9110. group: TEMPLATE_GENERATORS.dxList.group
  9111. };
  9112. TEMPLATE_GENERATORS.dxTagBox = {tag: function(itemData) {
  9113. return $("<div>").append($("<span>").text(itemData))
  9114. }};
  9115. TEMPLATE_GENERATORS.dxCalendar = {cell: function(itemData) {
  9116. return $("<div>").text(itemData.text || String(itemData))
  9117. }};
  9118. $.extend(ui, {
  9119. TemplateProvider: TemplateProvider,
  9120. Template: Template,
  9121. DefaultTemplate: DefaultTemplate,
  9122. setTemplateEngine: setTemplateEngine
  9123. })
  9124. })(jQuery, DevExpress);
  9125. /*! Module core, file ko.components.js */
  9126. (function($, DX, undefined) {
  9127. if (!DX.support.hasKo)
  9128. return;
  9129. var ko = window.ko,
  9130. ui = DX.ui,
  9131. LOCKS_DATA_KEY = "dxKoLocks",
  9132. CREATED_WITH_KO_DATA_KEY = "dxKoCreation";
  9133. var Locks = function() {
  9134. var info = {};
  9135. var currentCount = function(lockName) {
  9136. return info[lockName] || 0
  9137. };
  9138. return {
  9139. obtain: function(lockName) {
  9140. info[lockName] = currentCount(lockName) + 1
  9141. },
  9142. release: function(lockName) {
  9143. var count = currentCount(lockName);
  9144. if (count < 1)
  9145. throw DX.Error("E0014");
  9146. if (count === 1)
  9147. delete info[lockName];
  9148. else
  9149. info[lockName] = count - 1
  9150. },
  9151. locked: function(lockName) {
  9152. return currentCount(lockName) > 0
  9153. }
  9154. }
  9155. };
  9156. var editorsBingindHandlers = [];
  9157. var registerComponentKoBinding = function(componentName, componentClass) {
  9158. if (componentClass.subclassOf(ui.Editor))
  9159. editorsBingindHandlers.push(componentName);
  9160. ko.bindingHandlers[componentName] = {init: function(domNode, valueAccessor) {
  9161. var $element = $(domNode),
  9162. optionChangedCallbacks = $.Callbacks(),
  9163. ctorOptions = {
  9164. templateProvider: ui.KoTemplateProvider,
  9165. _optionChangedCallbacks: optionChangedCallbacks
  9166. },
  9167. optionNameToModelMap = {};
  9168. var applyModelValueToOption = function(optionName, modelValue) {
  9169. var component = $element.data(componentName),
  9170. locks = $element.data(LOCKS_DATA_KEY),
  9171. optionValue = ko.unwrap(modelValue);
  9172. if (ko.isWriteableObservable(modelValue))
  9173. optionNameToModelMap[optionName] = modelValue;
  9174. if (component) {
  9175. if (locks.locked(optionName))
  9176. return;
  9177. locks.obtain(optionName);
  9178. try {
  9179. component.option(optionName, optionValue)
  9180. }
  9181. finally {
  9182. locks.release(optionName)
  9183. }
  9184. }
  9185. else
  9186. ctorOptions[optionName] = optionValue
  9187. };
  9188. var handleOptionChanged = function(args) {
  9189. var optionName = args.fullName,
  9190. optionValue = args.value;
  9191. if (!(optionName in optionNameToModelMap))
  9192. return;
  9193. var $element = this._$element,
  9194. locks = $element.data(LOCKS_DATA_KEY);
  9195. if (locks.locked(optionName))
  9196. return;
  9197. locks.obtain(optionName);
  9198. try {
  9199. optionNameToModelMap[optionName](optionValue)
  9200. }
  9201. finally {
  9202. locks.release(optionName)
  9203. }
  9204. };
  9205. var createComponent = function() {
  9206. optionChangedCallbacks.add(handleOptionChanged);
  9207. $element.data(CREATED_WITH_KO_DATA_KEY, true).data(LOCKS_DATA_KEY, new Locks)[componentName](ctorOptions);
  9208. ctorOptions = null
  9209. };
  9210. var unwrapModelValue = function(option, model) {
  9211. var modelUnwrapped;
  9212. ko.computed(function() {
  9213. applyModelValueToOption(option, model);
  9214. modelUnwrapped = ko.unwrap(model)
  9215. }, null, {disposeWhenNodeIsRemoved: domNode});
  9216. if ($.isPlainObject(modelUnwrapped))
  9217. $.each(modelUnwrapped, function(optionName, modelValue) {
  9218. unwrapModelValue(option + "." + optionName, modelValue)
  9219. })
  9220. };
  9221. ko.computed(function() {
  9222. var component = $element.data(componentName);
  9223. if (component)
  9224. component.beginUpdate();
  9225. $.each(ko.unwrap(valueAccessor()), function(optionName, modelValue) {
  9226. unwrapModelValue(optionName, modelValue)
  9227. });
  9228. if (component)
  9229. component.endUpdate();
  9230. else
  9231. createComponent()
  9232. }, null, {disposeWhenNodeIsRemoved: domNode});
  9233. return {controlsDescendantBindings: componentClass.subclassOf(ui.Widget)}
  9234. }};
  9235. if (componentName === "dxValidator")
  9236. ko.bindingHandlers["dxValidator"].after = editorsBingindHandlers
  9237. };
  9238. DX.DOMComponent.redefine({_modelByElement: function(element) {
  9239. if (element.length)
  9240. return ko.dataFor(element.get(0))
  9241. }});
  9242. var originalRegisterComponent = DX.registerComponent;
  9243. var registerKoComponent = function(componentName, _, componentClass) {
  9244. componentClass = componentClass || _;
  9245. originalRegisterComponent.apply(this, arguments);
  9246. registerComponentKoBinding(componentName, componentClass)
  9247. };
  9248. DX.registerComponent = registerKoComponent;
  9249. var cleanKoData = function(element, andSelf) {
  9250. var cleanNode = function() {
  9251. ko.cleanNode(this)
  9252. };
  9253. if (andSelf)
  9254. element.each(cleanNode);
  9255. else
  9256. element.find("*").each(cleanNode)
  9257. };
  9258. var originalEmpty = $.fn.empty;
  9259. $.fn.empty = function() {
  9260. cleanKoData(this, false);
  9261. return originalEmpty.apply(this, arguments)
  9262. };
  9263. var originalRemove = $.fn.remove;
  9264. $.fn.remove = function(selector, keepData) {
  9265. if (!keepData) {
  9266. var subject = this;
  9267. if (selector)
  9268. subject = subject.filter(selector);
  9269. cleanKoData(subject, true)
  9270. }
  9271. return originalRemove.call(this, selector, keepData)
  9272. };
  9273. var originalHtml = $.fn.html;
  9274. $.fn.html = function(value) {
  9275. if (typeof value === "string")
  9276. cleanKoData(this, false);
  9277. return originalHtml.apply(this, arguments)
  9278. };
  9279. ko.bindingHandlers.dxAction = {update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
  9280. var $element = $(element);
  9281. var unwrappedValue = ko.utils.unwrapObservable(valueAccessor()),
  9282. actionSource = unwrappedValue,
  9283. actionOptions = {context: element};
  9284. if (unwrappedValue.execute) {
  9285. actionSource = unwrappedValue.execute;
  9286. $.extend(actionOptions, unwrappedValue)
  9287. }
  9288. var action = new DX.Action(actionSource, actionOptions);
  9289. $element.off(".dxActionBinding").on("dxclick.dxActionBinding", function(e) {
  9290. action.execute({
  9291. element: $element,
  9292. model: viewModel,
  9293. evaluate: function(expression) {
  9294. var context = viewModel;
  9295. if (expression.length > 0 && expression[0] === "$")
  9296. context = ko.contextFor(element);
  9297. var getter = DX.data.utils.compileGetter(expression);
  9298. return getter(context)
  9299. },
  9300. jQueryEvent: e
  9301. });
  9302. if (!actionOptions.bubbling)
  9303. e.stopPropagation()
  9304. })
  9305. }};
  9306. ko.bindingHandlers.dxControlsDescendantBindings = {init: function(_, valueAccessor) {
  9307. return {controlsDescendantBindings: ko.unwrap(valueAccessor())}
  9308. }};
  9309. var render = function($element, options, viewModel, bindingContext) {
  9310. var result = $.Deferred();
  9311. $element.removeClass("dx-pending-rendering-manual");
  9312. $element.addClass("dx-pending-rendering-active");
  9313. if (options.showLoadIndicator && options.showLoadIndicatorImmediately !== true)
  9314. showLoadIndicator($element);
  9315. DX.utils.executeAsync(function() {
  9316. renderImpl($element, options, viewModel, bindingContext).done(function() {
  9317. var shownArgs = {element: $element};
  9318. if (options.onShown)
  9319. options.onShown.apply(viewModel, [shownArgs]);
  9320. result.resolve(shownArgs)
  9321. }).fail(function() {
  9322. result.rejectWith(result, arguments)
  9323. })
  9324. });
  9325. return result.promise()
  9326. };
  9327. var showLoadIndicator = function($container) {
  9328. var $indicator = $('<div/>').dxLoadIndicator({visible: true}).addClass("dx-defered-rendering-load-indicator");
  9329. $container.append($indicator)
  9330. };
  9331. var isElementInViewport = function(element) {
  9332. var rect = element.getBoundingClientRect();
  9333. return rect.bottom >= 0 && rect.right >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.left <= (window.innerWidth || document.documentElement.clientWidth)
  9334. };
  9335. var renderImpl = function($element, options, viewModel, bindingContext) {
  9336. var animatePromise,
  9337. childBindingContext = bindingContext.createChildContext(viewModel),
  9338. renderedArgs = {element: $element};
  9339. $element.find(".dx-defered-rendering-load-indicator").remove();
  9340. ko.applyBindingsToDescendants(childBindingContext, $element[0]);
  9341. options._renderedDeferred.resolve(renderedArgs);
  9342. if (options.onRendered)
  9343. options.onRendered.apply(viewModel, [renderedArgs]);
  9344. $element.children().removeClass("dx-invisible-while-pending-rendering");
  9345. DX.utils.triggerShownEvent($element.children());
  9346. $element.removeClass("dx-pending-rendering");
  9347. $element.removeClass("dx-pending-rendering-active");
  9348. if (options.animation) {
  9349. var transitionExecutor = new DX.TransitionExecutor;
  9350. if (options.staggerItemSelector) {
  9351. $element.find(options.staggerItemSelector).each(function() {
  9352. if (isElementInViewport(this))
  9353. transitionExecutor.enter($(this), options.animation)
  9354. });
  9355. animatePromise = $.when(animatePromise, transitionExecutor.start())
  9356. }
  9357. else {
  9358. transitionExecutor.enter($element, options.animation || "content-rendered");
  9359. animatePromise = transitionExecutor.start()
  9360. }
  9361. }
  9362. else
  9363. animatePromise = $.Deferred().resolve().promise();
  9364. return animatePromise
  9365. };
  9366. var initElement = function($element, options) {
  9367. $element.addClass("dx-defer-rendering dx-pending-rendering dx-loadindicator-container");
  9368. $element.data("dx-rendered-promise", options._renderedDeferred.promise());
  9369. if (options.hiddenUntilRendered)
  9370. $element.children().addClass("dx-invisible-while-pending-rendering");
  9371. if (options.showLoadIndicator && options.showLoadIndicatorImmediately)
  9372. showLoadIndicator($element)
  9373. };
  9374. var initRender = function($element, options, viewModel, bindingContext) {
  9375. var doRender = function() {
  9376. return render($element, options, viewModel, bindingContext)
  9377. };
  9378. if (options.renderWhen)
  9379. options.renderWhen.done(doRender);
  9380. else {
  9381. $element.data("dx-render-delegate", doRender);
  9382. $element.addClass("dx-pending-rendering-manual")
  9383. }
  9384. };
  9385. ko.bindingHandlers.dxDeferRendering = {init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
  9386. var $element = $(element),
  9387. passedOptions = ko.unwrap(valueAccessor()),
  9388. showLoadIndicatorImmediately = ko.unwrap(passedOptions.showLoadIndicatorImmediately),
  9389. hiddenUntilRendered = ko.unwrap(passedOptions.hiddenUntilRendered),
  9390. options = {
  9391. showLoadIndicator: ko.unwrap(passedOptions.showLoadIndicator) || false,
  9392. showLoadIndicatorImmediately: showLoadIndicatorImmediately !== undefined ? showLoadIndicatorImmediately : true,
  9393. hiddenUntilRendered: hiddenUntilRendered !== undefined ? hiddenUntilRendered : true,
  9394. renderWhen: ko.unwrap(passedOptions.renderWhen),
  9395. animation: ko.unwrap(passedOptions.animation),
  9396. staggerItemSelector: ko.unwrap(passedOptions.staggerItemSelector),
  9397. onRendered: ko.unwrap(passedOptions.onRendered),
  9398. onShown: ko.unwrap(passedOptions.onShown),
  9399. _renderedDeferred: $.Deferred()
  9400. };
  9401. initElement($element, options);
  9402. initRender($element, options, viewModel, bindingContext);
  9403. return {controlsDescendantBindings: true}
  9404. }};
  9405. ko.bindingHandlers.dxIcon = {
  9406. init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
  9407. var options = ko.utils.unwrapObservable(valueAccessor()) || {},
  9408. iconElement = DevExpress.utils.getImageContainer(options);
  9409. ko.virtualElements.emptyNode(element);
  9410. if (iconElement)
  9411. ko.virtualElements.prepend(element, iconElement.get(0))
  9412. },
  9413. update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
  9414. var options = ko.utils.unwrapObservable(valueAccessor()) || {},
  9415. iconElement = DevExpress.utils.getImageContainer(options);
  9416. ko.virtualElements.emptyNode(element);
  9417. if (iconElement)
  9418. ko.virtualElements.prepend(element, iconElement.get(0))
  9419. }
  9420. };
  9421. ko.virtualElements.allowedBindings.dxIcon = true
  9422. })(jQuery, DevExpress);
  9423. /*! Module core, file ng.components.js */
  9424. (function($, DX, undefined) {
  9425. if (!DX.support.hasNg)
  9426. return;
  9427. var ui = DX.ui,
  9428. compileSetter = DX.data.utils.compileSetter,
  9429. compileGetter = DX.data.utils.compileGetter;
  9430. var ITEM_ALIAS_ATTRIBUTE_NAME = "dxItemAlias",
  9431. DEFAULT_MODEL_ALIAS = "scopeValue";
  9432. var SKIP_APPLY_ACTION_CATEGORIES = ["rendering"];
  9433. var phoneJsModule = DX.ng.module;
  9434. var safeApply = function(func, scope) {
  9435. if (scope.$root.$$phase)
  9436. func(scope);
  9437. else
  9438. scope.$apply(function() {
  9439. func(scope)
  9440. })
  9441. };
  9442. var ComponentBuilder = DX.Class.inherit({
  9443. ctor: function(options) {
  9444. this._$element = options.$element;
  9445. this._$templates = options.$templates;
  9446. this._componentClass = options.componentClass;
  9447. this._scope = options.scope;
  9448. this._parse = options.parse;
  9449. this._compile = options.compile;
  9450. this._ngOptions = this._normalizeOptions(options.ngOptions);
  9451. this._itemAlias = options.itemAlias;
  9452. this._componentDisposing = $.Callbacks();
  9453. if (options.ngOptions.data)
  9454. this._initDataScope(options.ngOptions.data)
  9455. },
  9456. _normalizeOptions: function(options) {
  9457. var result = $.extend({}, options);
  9458. if (options.bindingOptions)
  9459. $.each(options.bindingOptions, function(key, value) {
  9460. if ($.type(value) === 'string')
  9461. result.bindingOptions[key] = {dataPath: value}
  9462. });
  9463. return result
  9464. },
  9465. initComponentWithBindings: function() {
  9466. this._initComponentBindings();
  9467. this._initComponent(this._scope);
  9468. this._shownEventTimer = setTimeout($.proxy(function() {
  9469. DX.utils.triggerShownEvent(this._$element)
  9470. }, this))
  9471. },
  9472. _initDataScope: function(data) {
  9473. if (typeof data === "string") {
  9474. var dataStr = data,
  9475. rootScope = this._scope;
  9476. data = rootScope.$eval(data);
  9477. this._scope = rootScope.$new();
  9478. this._synchronizeDataScopes(rootScope, this._scope, data, dataStr)
  9479. }
  9480. $.extend(this._scope, data)
  9481. },
  9482. _synchronizeDataScopes: function(parentScope, childScope, data, parentPrefix) {
  9483. var that = this;
  9484. $.each(data, function(fieldPath) {
  9485. that._synchronizeScopeField({
  9486. parentScope: parentScope,
  9487. childScope: childScope,
  9488. fieldPath: fieldPath,
  9489. parentPrefix: parentPrefix
  9490. })
  9491. })
  9492. },
  9493. _initComponent: function(scope) {
  9494. this._component = new this._componentClass(this._$element, this._evalOptions(scope))
  9495. },
  9496. _initComponentBindings: function() {
  9497. var that = this,
  9498. optionDependencies = {};
  9499. that._disposingCallbacks = $.Callbacks();
  9500. if (that._ngOptions.bindingOptions)
  9501. $.each(that._ngOptions.bindingOptions, function(optionPath, value) {
  9502. var separatorIndex = optionPath.search(/\[|\./),
  9503. optionForSubscribe = separatorIndex > -1 ? optionPath.substring(0, separatorIndex) : optionPath,
  9504. prevWatchMethod,
  9505. clearWatcher,
  9506. valuePath = value.dataPath,
  9507. deepWatch = true,
  9508. forcePlainWatchMethod = false;
  9509. if (value.deep !== undefined)
  9510. forcePlainWatchMethod = deepWatch = !!value.deep;
  9511. if (!optionDependencies[optionForSubscribe])
  9512. optionDependencies[optionForSubscribe] = {};
  9513. optionDependencies[optionForSubscribe][optionPath] = valuePath;
  9514. var watchCallback = function(newValue, oldValue) {
  9515. if (newValue !== oldValue) {
  9516. that._component.option(optionPath, newValue);
  9517. updateWatcher()
  9518. }
  9519. };
  9520. var updateWatcher = function() {
  9521. var watchMethod = $.isArray(that._scope.$eval(valuePath)) && !forcePlainWatchMethod ? "$watchCollection" : "$watch";
  9522. if (prevWatchMethod !== watchMethod) {
  9523. if (clearWatcher)
  9524. clearWatcher();
  9525. clearWatcher = that._scope[watchMethod](valuePath, watchCallback, deepWatch);
  9526. prevWatchMethod = watchMethod
  9527. }
  9528. };
  9529. updateWatcher();
  9530. that._disposingCallbacks.add(function() {
  9531. clearWatcher();
  9532. that._componentDisposing.fire()
  9533. })
  9534. });
  9535. that._optionChangedCallbacks = $.Callbacks().add(function(args) {
  9536. var optionName = args.name,
  9537. optionValue = args.value;
  9538. if (that._scope.$root.$$phase === "$digest" || !optionDependencies || !optionDependencies[optionName])
  9539. return;
  9540. safeApply(function(scope) {
  9541. $.each(optionDependencies[optionName], function(optionPath, valuePath) {
  9542. var getter = compileGetter(optionPath);
  9543. var tmpData = {};
  9544. tmpData[optionName] = optionValue;
  9545. that._parse(valuePath).assign(that._scope, getter(tmpData))
  9546. })
  9547. }, that._scope)
  9548. });
  9549. that._disposingCallbacks.add(function() {
  9550. clearTimeout(that._shownEventTimer)
  9551. })
  9552. },
  9553. _compilerByTemplate: function(template) {
  9554. var that = this,
  9555. scopeItemsPath = this._getScopeItemsPath();
  9556. return function(data, index) {
  9557. var $resultMarkup = $(template).clone(),
  9558. templateScope;
  9559. if (data !== undefined) {
  9560. var dataIsScope = data.$id;
  9561. templateScope = dataIsScope ? data : that._createScopeWithData(data);
  9562. $resultMarkup.on("$destroy", function() {
  9563. var destroyAlreadyCalled = !templateScope.$parent;
  9564. if (destroyAlreadyCalled)
  9565. return;
  9566. templateScope.$destroy()
  9567. })
  9568. }
  9569. else
  9570. templateScope = that._scope;
  9571. if (scopeItemsPath)
  9572. that._synchronizeScopes(templateScope, scopeItemsPath, index);
  9573. safeApply(that._compile($resultMarkup), templateScope);
  9574. return $resultMarkup
  9575. }
  9576. },
  9577. _getScopeItemsPath: function() {
  9578. if (this._componentClass.subclassOf(ui.CollectionWidget) && this._ngOptions.bindingOptions && this._ngOptions.bindingOptions.items)
  9579. return this._ngOptions.bindingOptions.items.dataPath
  9580. },
  9581. _createScopeWithData: function(data) {
  9582. var newScope = this._scope.$new(true);
  9583. data = this._enshureDataIsPlainObject(data);
  9584. $.extend(newScope, data);
  9585. return newScope
  9586. },
  9587. _synchronizeScopes: function(itemScope, parentPrefix, itemIndex) {
  9588. var that = this,
  9589. item = compileGetter(parentPrefix + "[" + itemIndex + "]")(this._scope);
  9590. item = that._enshureDataIsPlainObject(item);
  9591. $.each(item, function(itemPath) {
  9592. that._synchronizeScopeField({
  9593. parentScope: that._scope,
  9594. childScope: itemScope,
  9595. fieldPath: itemPath,
  9596. parentPrefix: parentPrefix,
  9597. itemIndex: itemIndex
  9598. })
  9599. })
  9600. },
  9601. _synchronizeScopeField: function(args) {
  9602. var parentScope = args.parentScope,
  9603. childScope = args.childScope,
  9604. fieldPath = args.fieldPath,
  9605. parentPrefix = args.parentPrefix,
  9606. itemIndex = args.itemIndex;
  9607. var innerPathSuffix = fieldPath === (this._itemAlias || DEFAULT_MODEL_ALIAS) ? "" : "." + fieldPath,
  9608. collectionField = itemIndex !== undefined,
  9609. optionOuterBag = [parentPrefix],
  9610. optionOuterPath;
  9611. if (collectionField)
  9612. optionOuterBag.push("[", itemIndex, "]");
  9613. optionOuterBag.push(innerPathSuffix);
  9614. optionOuterPath = optionOuterBag.join("");
  9615. var clearParentWatcher = parentScope.$watch(optionOuterPath, function(newValue, oldValue) {
  9616. if (newValue !== oldValue)
  9617. compileSetter(fieldPath)(childScope, newValue)
  9618. });
  9619. var clearItemWatcher = childScope.$watch(fieldPath, function(newValue, oldValue) {
  9620. if (newValue !== oldValue) {
  9621. if (collectionField && !compileGetter(parentPrefix)(parentScope)[itemIndex]) {
  9622. clearItemWatcher();
  9623. return
  9624. }
  9625. compileSetter(optionOuterPath)(parentScope, newValue)
  9626. }
  9627. });
  9628. this._componentDisposing.add([clearParentWatcher, clearItemWatcher])
  9629. },
  9630. _evalOptions: function(scope) {
  9631. var result = $.extend({}, this._ngOptions);
  9632. delete result.data;
  9633. delete result.bindingOptions;
  9634. if (this._ngOptions.bindingOptions)
  9635. $.each(this._ngOptions.bindingOptions, function(key, value) {
  9636. result[key] = scope.$eval(value.dataPath)
  9637. });
  9638. result._optionChangedCallbacks = this._optionChangedCallbacks;
  9639. result._disposingCallbacks = this._disposingCallbacks;
  9640. result.templateProvider = ui.NgTemplateProvider;
  9641. result.templateCompiler = $.proxy(function($template) {
  9642. return this._compilerByTemplate($template)
  9643. }, this);
  9644. return result
  9645. },
  9646. _enshureDataIsPlainObject: function(object) {
  9647. var result;
  9648. if ($.isPlainObject(object))
  9649. result = object;
  9650. else {
  9651. result = {};
  9652. result[DEFAULT_MODEL_ALIAS] = object
  9653. }
  9654. if (this._itemAlias)
  9655. result[this._itemAlias] = object;
  9656. return result
  9657. }
  9658. });
  9659. ComponentBuilder = ComponentBuilder.inherit({
  9660. ctor: function(options) {
  9661. this.callBase.apply(this, arguments);
  9662. this._componentName = options.componentName;
  9663. this._ngModel = options.ngModel;
  9664. this._ngModelController = options.ngModelController
  9665. },
  9666. _isNgModelRequired: function() {
  9667. return this._componentClass.subclassOf(ui.Editor) && this._ngModel
  9668. },
  9669. _initComponentBindings: function() {
  9670. this.callBase.apply(this, arguments);
  9671. this._initNgModelBinding()
  9672. },
  9673. _initNgModelBinding: function() {
  9674. if (!this._isNgModelRequired())
  9675. return;
  9676. var that = this;
  9677. var ngModelWatcher = this._scope.$watch(this._ngModel, function(newValue, oldValue) {
  9678. if (newValue === oldValue)
  9679. return;
  9680. that._component.option(that._ngModelOption(), newValue)
  9681. });
  9682. that._optionChangedCallbacks.add(function(args) {
  9683. if (args.name !== that._ngModelOption())
  9684. return;
  9685. that._ngModelController.$setViewValue(args.value)
  9686. });
  9687. this._disposingCallbacks.add(function() {
  9688. ngModelWatcher()
  9689. })
  9690. },
  9691. _ngModelOption: function() {
  9692. if ($.inArray(this._componentName, ["dxFileUploader", "dxTagBox"]) > -1)
  9693. return "values";
  9694. return "value"
  9695. },
  9696. _evalOptions: function() {
  9697. if (!this._isNgModelRequired())
  9698. return this.callBase.apply(this, arguments);
  9699. var result = this.callBase.apply(this, arguments);
  9700. result[this._ngModelOption()] = this._parse(this._ngModel)(this._scope);
  9701. return result
  9702. }
  9703. });
  9704. var NgComponent = DX.DOMComponent.inherit({
  9705. _modelByElement: function(element) {
  9706. if (element.length)
  9707. return element.scope()
  9708. },
  9709. _createActionByOption: function(optionName, config) {
  9710. var action = this.callBase.apply(this, arguments);
  9711. if (config && $.inArray(config.category, SKIP_APPLY_ACTION_CATEGORIES) > -1)
  9712. return action;
  9713. var component = this,
  9714. wrappedAction = function() {
  9715. var that = this,
  9716. scope = component._modelByElement(component.element()),
  9717. args = arguments;
  9718. if (!scope || !scope.$root || scope.$root.$$phase)
  9719. return action.apply(that, args);
  9720. return scope.$apply(function() {
  9721. return action.apply(that, args)
  9722. })
  9723. };
  9724. return wrappedAction
  9725. },
  9726. _createComponent: function(element, name, config) {
  9727. return this.callBase(element, name, $.extend({templateCompiler: this.option("templateCompiler")}, config))
  9728. }
  9729. });
  9730. var registeredComponents = {};
  9731. var originalRegisterComponent = DX.registerComponent;
  9732. var registerNgComponent = function(componentName, _, componentClass) {
  9733. componentClass = componentClass || _;
  9734. originalRegisterComponent.apply(this, arguments);
  9735. if (!registeredComponents[componentName])
  9736. registerComponentDirective(componentName);
  9737. registeredComponents[componentName] = componentClass
  9738. };
  9739. var registerComponentDirective = function(componentName) {
  9740. var priority = componentName !== "dxValidator" ? 1 : 10;
  9741. phoneJsModule.directive(componentName, ["$compile", "$parse", function($compile, $parse) {
  9742. return {
  9743. restrict: "A",
  9744. require: "^?ngModel",
  9745. priority: priority,
  9746. compile: function($element) {
  9747. var componentClass = registeredComponents[componentName],
  9748. $content = componentClass.subclassOf(ui.Widget) ? $element.contents().detach() : null;
  9749. return function(scope, $element, attrs, ngModelController) {
  9750. $element.append($content);
  9751. var componentBuilder = new ComponentBuilder({
  9752. componentClass: componentClass,
  9753. componentName: componentName,
  9754. compile: $compile,
  9755. parse: $parse,
  9756. $element: $element,
  9757. scope: scope,
  9758. ngOptions: attrs[componentName] ? scope.$eval(attrs[componentName]) : {},
  9759. ngModel: attrs.ngModel,
  9760. ngModelController: ngModelController,
  9761. itemAlias: attrs[ITEM_ALIAS_ATTRIBUTE_NAME]
  9762. });
  9763. componentBuilder.initComponentWithBindings()
  9764. }
  9765. }
  9766. }
  9767. }])
  9768. };
  9769. phoneJsModule.filter('dxGlobalize', function() {
  9770. return function(input, param) {
  9771. return Globalize.format(input, param)
  9772. }
  9773. });
  9774. phoneJsModule.directive("dxIcon", ["$compile", function($compile) {
  9775. return {
  9776. restrict: 'E',
  9777. link: function($scope, $element, $attrs) {
  9778. var html = DX.utils.getImageContainer($scope.icon || $scope.iconSrc);
  9779. if (html) {
  9780. var e = $compile(html.get(0))($scope);
  9781. $element.replaceWith(e)
  9782. }
  9783. }
  9784. }
  9785. }]);
  9786. DX.registerComponent = registerNgComponent;
  9787. registerNgComponent("DOMComponent", NgComponent)
  9788. })(jQuery, DevExpress);
  9789. /*! Module core, file ko.templates.js */
  9790. (function($, DX, undefined) {
  9791. if (!DX.support.hasKo)
  9792. return;
  9793. var ko = window.ko,
  9794. ui = DX.ui;
  9795. var KoTemplate = ui.TemplateBase.inherit({
  9796. ctor: function(element) {
  9797. this.callBase.apply(this, arguments);
  9798. this._template = $("<div>").append(DX.utils.normalizeTemplateElement(element));
  9799. this._registerKoTemplate()
  9800. },
  9801. _registerKoTemplate: function() {
  9802. var template = this._template.get(0);
  9803. new ko.templateSources.anonymousTemplate(template)['nodes'](template)
  9804. },
  9805. _prepareDataForContainer: function(data, container) {
  9806. var result = data,
  9807. containerElement,
  9808. containerContext;
  9809. if (container.length) {
  9810. containerElement = container.get(0);
  9811. data = data !== undefined ? data : ko.dataFor(containerElement) || {};
  9812. containerContext = ko.contextFor(containerElement);
  9813. if (containerContext)
  9814. result = data === containerContext.$data ? containerContext : containerContext.createChildContext(data);
  9815. else
  9816. result = data
  9817. }
  9818. return result
  9819. },
  9820. _renderCore: function(data) {
  9821. var $renderBag = $("<div>");
  9822. ko.renderTemplate(this._template.get(0), data, null, $renderBag.get(0));
  9823. var $result = $renderBag.contents().detach();
  9824. $renderBag.remove();
  9825. return $result
  9826. },
  9827. dispose: function() {
  9828. this.callBase();
  9829. this._template.remove()
  9830. }
  9831. });
  9832. var KoTemplateProvider = new(ui.TemplateProviderBase.inherit({
  9833. createTemplate: function(element, owner) {
  9834. return new KoTemplate(element, owner)
  9835. },
  9836. applyTemplate: function(element, model) {
  9837. ko.applyBindings(model, element)
  9838. },
  9839. _templatesForWidget: function(widgetName) {
  9840. var templateGenerators = TEMPLATE_GENERATORS[widgetName] || {},
  9841. templates = {};
  9842. $.each(templateGenerators, function(name, generator) {
  9843. var $markup = DX.utils.createMarkupFromString(generator());
  9844. if (name !== "itemFrame")
  9845. $markup = $markup.contents();
  9846. templates[name] = new KoTemplate($markup, KoTemplateProvider)
  9847. });
  9848. return templates
  9849. }
  9850. }));
  9851. var createElementWithBindAttr = function(tagName, bindings, closeTag, additionalProperties) {
  9852. closeTag = closeTag === undefined ? true : closeTag;
  9853. var bindAttr = $.map(bindings, function(value, key) {
  9854. return key + ":" + value
  9855. }).join(",");
  9856. additionalProperties = additionalProperties || "";
  9857. return "<" + tagName + " data-bind=\"" + bindAttr + "\" " + additionalProperties + ">" + (closeTag ? "</" + tagName + ">" : "")
  9858. };
  9859. var defaultKoTemplateBasicBindings = {css: "{ 'dx-state-disabled': $data.disabled, 'dx-state-invisible': !($data.visible === undefined || ko.unwrap($data.visible)) }"};
  9860. var TEMPLATE_GENERATORS = {};
  9861. var emptyTemplate = function() {
  9862. return ""
  9863. };
  9864. TEMPLATE_GENERATORS.CollectionWidget = {
  9865. itemFrame: function() {
  9866. var markup = [createElementWithBindAttr("div", defaultKoTemplateBasicBindings, false), "<div class='dx-item-content-placeholder'></div>", "</div>"];
  9867. return markup.join("")
  9868. },
  9869. item: function() {
  9870. var htmlBinding = createElementWithBindAttr("div", {html: "html"}),
  9871. textBinding = createElementWithBindAttr("div", {text: "text"}),
  9872. primitiveBinding = createElementWithBindAttr("div", {text: "String($data)"});
  9873. var markup = ["<div>", "<!-- ko if: $data.html && !$data.text -->", htmlBinding, "<!-- /ko -->", "<!-- ko if: !$data.html && $data.text -->", textBinding, "<!-- /ko -->", "<!-- ko ifnot: $.isPlainObject($data) -->", primitiveBinding, "<!-- /ko -->", "</div>"];
  9874. return markup.join("")
  9875. }
  9876. };
  9877. var BUTTON_TEXT_CLASS = "dx-button-text";
  9878. TEMPLATE_GENERATORS.dxButton = {content: function() {
  9879. var textBinding = createElementWithBindAttr("span", {
  9880. text: "$data.text",
  9881. css: "{ '" + BUTTON_TEXT_CLASS + "' : !!$data.text }"
  9882. });
  9883. var markup = ["<div>", "<!-- ko dxIcon: $data.icon || $data.iconSrc --><!-- /ko -->", textBinding, "</div>"];
  9884. return markup.join("")
  9885. }};
  9886. var LIST_ITEM_BADGE_CONTAINER_CLASS = "dx-list-item-badge-container",
  9887. LIST_ITEM_BADGE_CLASS = "dx-list-item-badge",
  9888. BADGE_CLASS = "dx-badge",
  9889. LIST_ITEM_CHEVRON_CONTAINER_CLASS = "dx-list-item-chevron-container",
  9890. LIST_ITEM_CHEVRON_CLASS = "dx-list-item-chevron";
  9891. TEMPLATE_GENERATORS.dxList = {
  9892. item: function() {
  9893. var template = TEMPLATE_GENERATORS.CollectionWidget.item(),
  9894. keyBinding = createElementWithBindAttr("div", {text: "key"});
  9895. template = [template.substring(0, template.length - 6), "<!-- ko if: $data.key -->" + keyBinding + "<!-- /ko -->", "</div>"];
  9896. return template.join("")
  9897. },
  9898. itemFrame: function() {
  9899. var template = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(),
  9900. badgeBinding = createElementWithBindAttr("div", {text: "badge"}, true, 'class="' + LIST_ITEM_BADGE_CLASS + " " + BADGE_CLASS + '"');
  9901. var markup = [template.substring(0, template.length - 6), "<!-- ko if: $data.badge -->", "<div class=\"" + LIST_ITEM_BADGE_CONTAINER_CLASS + "\">", badgeBinding, "</div>", "<!-- /ko -->", "<!-- ko if: $data.showChevron -->", "<div class=\"" + LIST_ITEM_CHEVRON_CONTAINER_CLASS + "\">", "<div class=\"" + LIST_ITEM_CHEVRON_CLASS + "\"></div>", "</div>", "<!-- /ko -->", "</div>"];
  9902. return markup.join("")
  9903. },
  9904. group: function() {
  9905. var keyBinding = createElementWithBindAttr("div", {text: "key"}),
  9906. primitiveBinding = createElementWithBindAttr("div", {text: "String($data)"});
  9907. var markup = ["<div>", "<!-- ko if: $data.key -->", keyBinding, "<!-- /ko -->", "<!-- ko ifnot: $.isPlainObject($data) -->", primitiveBinding, "<!-- /ko -->", "</div>"];
  9908. return markup.join("")
  9909. }
  9910. };
  9911. TEMPLATE_GENERATORS.dxDropDownMenu = {item: TEMPLATE_GENERATORS.dxList.item};
  9912. TEMPLATE_GENERATORS.dxDropDownList = {item: TEMPLATE_GENERATORS.dxList.item};
  9913. TEMPLATE_GENERATORS.dxRadioGroup = {item: TEMPLATE_GENERATORS.CollectionWidget.item};
  9914. TEMPLATE_GENERATORS.dxScheduler = {item: function() {
  9915. var template = TEMPLATE_GENERATORS.CollectionWidget.item(),
  9916. startDateBinding = createElementWithBindAttr("strong", {text: "Globalize.format(DevExpress.utils.makeDate($data.startDate), 't')"}),
  9917. endDateBinding = createElementWithBindAttr("strong", {text: "' - ' + Globalize.format(DevExpress.utils.makeDate($data.endDate), 't')"});
  9918. template = [template.substring(0, template.length - 6), "<div class='dx-scheduler-appointment-content-details'>", "<!-- ko if: $data.startDate -->" + startDateBinding + "<!-- /ko -->", "<!-- ko if: $data.endDate -->" + endDateBinding + "<!-- /ko -->", "</div>", "<!-- ko if: $data.recurrenceRule --><span class='dx-scheduler-appointment-recurrence-icon'></span><!-- /ko -->", "</div>"];
  9919. return template.join("")
  9920. }};
  9921. TEMPLATE_GENERATORS.dxOverlay = {content: emptyTemplate};
  9922. TEMPLATE_GENERATORS.dxSlideOutView = {
  9923. menu: emptyTemplate,
  9924. content: emptyTemplate
  9925. };
  9926. TEMPLATE_GENERATORS.dxSlideOut = {
  9927. menuItem: TEMPLATE_GENERATORS.dxList.item,
  9928. menuGroup: TEMPLATE_GENERATORS.dxList.group,
  9929. content: emptyTemplate
  9930. };
  9931. TEMPLATE_GENERATORS.dxAccordion = {
  9932. title: function() {
  9933. var titleBinding = createElementWithBindAttr("span", {text: "$.isPlainObject($data) ? $data.title : String($data)"});
  9934. var markup = ["<div>", "<!-- ko dxIcon: $data.icon || $data.iconSrc --><!-- /ko -->", titleBinding, "</div>"];
  9935. return markup.join("")
  9936. },
  9937. item: TEMPLATE_GENERATORS.CollectionWidget.item
  9938. };
  9939. TEMPLATE_GENERATORS.dxResponsiveBox = {item: TEMPLATE_GENERATORS.CollectionWidget.item},
  9940. TEMPLATE_GENERATORS.dxPivotTabs = {item: function() {
  9941. var titleBinding = createElementWithBindAttr("span", {text: "title"}),
  9942. primitiveBinding = createElementWithBindAttr("div", {text: "String($data)"});
  9943. var markup = ["<div>", "<!-- ko if: $data.title -->", titleBinding, "<!-- /ko -->", "<!-- ko ifnot: $.isPlainObject($data) -->", primitiveBinding, "<!-- /ko -->", "</div>"];
  9944. return markup.join("")
  9945. }};
  9946. TEMPLATE_GENERATORS.dxPivot = {
  9947. title: TEMPLATE_GENERATORS.dxPivotTabs.item,
  9948. content: emptyTemplate
  9949. };
  9950. var PANORAMA_ITEM_TITLE_CLASS = "dx-panorama-item-title";
  9951. TEMPLATE_GENERATORS.dxPanorama = {itemFrame: function() {
  9952. var template = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(),
  9953. headerBinding = createElementWithBindAttr("div", {text: "title"}, true, 'class="' + PANORAMA_ITEM_TITLE_CLASS + '"');
  9954. var divInnerStart = template.indexOf(">") + 1;
  9955. template = [template.substring(0, divInnerStart), "<!-- ko if: $data.title -->", headerBinding, "<!-- /ko -->", template.substring(divInnerStart, template.length)];
  9956. return template.join("")
  9957. }};
  9958. TEMPLATE_GENERATORS.dxActionSheet = {item: function() {
  9959. return ["<div>", createElementWithBindAttr("div", {dxButton: "{ text: $data.text, onClick: $data.clickAction || $data.onClick, type: $data.type, disabled: !!ko.unwrap($data.disabled) }"}), "</div>"].join("")
  9960. }};
  9961. TEMPLATE_GENERATORS.dxToolbar = {
  9962. item: function() {
  9963. var template = TEMPLATE_GENERATORS.CollectionWidget.item();
  9964. template = [template.substring(0, template.length - 6), "<!-- ko if: $data.widget -->"];
  9965. $.each(["button", "tabs", "dropDownMenu"], function() {
  9966. var bindingName = DX.inflector.camelize(["dx", "-", this].join("")),
  9967. bindingObj = {};
  9968. bindingObj[bindingName] = "$data.options";
  9969. template.push("<!-- ko if: $data.widget === '", this, "' -->", createElementWithBindAttr("div", bindingObj), "<!-- /ko -->")
  9970. });
  9971. template.push("<!-- /ko -->");
  9972. return template.join("")
  9973. },
  9974. menuItem: TEMPLATE_GENERATORS.dxList.item,
  9975. actionSheetItem: TEMPLATE_GENERATORS.dxActionSheet.item
  9976. };
  9977. TEMPLATE_GENERATORS.dxGallery = {item: function() {
  9978. var template = TEMPLATE_GENERATORS.CollectionWidget.item(),
  9979. primitiveBinding = createElementWithBindAttr("div", {text: "String($data)"}),
  9980. imgBinding = createElementWithBindAttr("img", {attr: "{ src: String($data) }"}, false);
  9981. template = [template.substring(0, template.length - 6).replace(primitiveBinding, imgBinding), "<!-- ko if: $data.imageSrc -->", createElementWithBindAttr("img", {attr: "{ src: $data.imageSrc }"}, false), "<!-- /ko -->"].join("");
  9982. return template
  9983. }};
  9984. TEMPLATE_GENERATORS.dxTabs = {
  9985. item: function() {
  9986. var template = TEMPLATE_GENERATORS.CollectionWidget.item(),
  9987. basePrimitiveBinding = createElementWithBindAttr("div", {text: "String($data)"}),
  9988. primitiveBinding = "<span class=\"dx-tab-text\" data-bind=\"text: String($data)\"></span>",
  9989. baseTextBinding = createElementWithBindAttr("div", {text: "text"}),
  9990. textBinding = "<!-- ko dxIcon: $data.icon || $data.iconSrc --><!-- /ko -->" + "<span class=\"dx-tab-text\" data-bind=\"text: $data.text\"></span>";
  9991. template = template.replace("<!-- ko if: !$data.html && $data.text -->", "<!-- ko if: !$data.html && ($data.text || $data.icon || $data.iconSrc) -->").replace(basePrimitiveBinding, primitiveBinding).replace(baseTextBinding, textBinding);
  9992. return template
  9993. },
  9994. itemFrame: function() {
  9995. var template = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(),
  9996. badgeBinding = createElementWithBindAttr("div", {
  9997. attr: "{ 'class': 'dx-tabs-item-badge dx-badge' }",
  9998. text: "badge"
  9999. });
  10000. var markup = [template.substring(0, template.length - 6), "<!-- ko if: $data.badge -->", badgeBinding, "<!-- /ko -->", "</div>"];
  10001. return markup.join("")
  10002. }
  10003. };
  10004. TEMPLATE_GENERATORS.dxTabPanel = {
  10005. item: TEMPLATE_GENERATORS.CollectionWidget.item,
  10006. title: function() {
  10007. var template = TEMPLATE_GENERATORS.dxTabs.item();
  10008. return template.replace(/\$data\.text/g, '$data.title')
  10009. }
  10010. };
  10011. var NAVBAR_ITEM_BADGE_CLASS = "dx-navbar-item-badge";
  10012. TEMPLATE_GENERATORS.dxNavBar = {itemFrame: function() {
  10013. var template = TEMPLATE_GENERATORS.CollectionWidget.itemFrame(),
  10014. badgeBinding = createElementWithBindAttr("div", {text: "badge"}, true, 'class="' + NAVBAR_ITEM_BADGE_CLASS + " " + BADGE_CLASS + '"');
  10015. var markup = [template.substring(0, template.length - 6), "<!-- ko if: $data.badge -->", badgeBinding, "<!-- /ko -->", "</div>"];
  10016. return markup.join("")
  10017. }};
  10018. TEMPLATE_GENERATORS.dxMenuBase = {item: function() {
  10019. var template = [createElementWithBindAttr("div", defaultKoTemplateBasicBindings, false)],
  10020. textBinding = createElementWithBindAttr("span", {
  10021. text: "text",
  10022. css: "{ 'dx-menu-item-text': true }"
  10023. }),
  10024. primitiveBinding = createElementWithBindAttr("span", {
  10025. text: "String($data)",
  10026. css: "{ 'dx-menu-item-text': true }"
  10027. }),
  10028. popout = "<span class='dx-menu-item-popout-container'><div class='dx-menu-item-popout'></div></span>";
  10029. template.push("<!-- ko dxIcon: $data.icon || $data.iconSrc --><!-- /ko -->", "<!-- ko if: $.isPlainObject($data) && $data.text -->", textBinding, "<!-- /ko -->", "<!-- ko ifnot: $.isPlainObject($data) -->", primitiveBinding, "<!-- /ko -->", "<!-- ko if: $data.items -->", popout, "<!-- /ko -->", "</div>");
  10030. return template.join("")
  10031. }};
  10032. TEMPLATE_GENERATORS.dxTreeView = {item: function() {
  10033. var node = [],
  10034. link = createElementWithBindAttr("span", {text: "text"}, true),
  10035. htmlBinding = createElementWithBindAttr("div", {html: "html"});
  10036. node.push("<div>", "<!-- ko if: $data.html && !$data.text -->", htmlBinding, "<!-- /ko -->", "<!-- ko dxIcon: $data.icon || $data.iconSrc --><!-- /ko -->", "<!-- ko if: !$data.html && $data.text -->" + link + "<!-- /ko -->", "</div>");
  10037. return node.join("")
  10038. }};
  10039. TEMPLATE_GENERATORS.dxCalendar = {cell: function() {
  10040. var textBinding = createElementWithBindAttr("span", {text: "text"}),
  10041. primitiveBinding = createElementWithBindAttr("span", {text: "String($data)"});
  10042. var markup = ["<div>", "<!-- ko if: !$data.html && $data.text -->", textBinding, "<!-- /ko -->", "<!-- ko ifnot: $.isPlainObject($data) -->", primitiveBinding, "<!-- /ko -->", "</div>"];
  10043. return markup.join("")
  10044. }};
  10045. var popupTitleAndBottom = function() {
  10046. return ["<div>", createElementWithBindAttr("div", {dxToolbar: "{ items: $data }"}), "</div>"].join("")
  10047. };
  10048. TEMPLATE_GENERATORS.dxPopup = {
  10049. title: popupTitleAndBottom,
  10050. bottom: popupTitleAndBottom
  10051. };
  10052. TEMPLATE_GENERATORS.dxLookup = {
  10053. title: TEMPLATE_GENERATORS.dxPopup.title,
  10054. group: TEMPLATE_GENERATORS.dxList.group
  10055. };
  10056. TEMPLATE_GENERATORS.dxTagBox = {tag: function() {
  10057. return ["<div>", createElementWithBindAttr("span", {text: "$data"})].join("")
  10058. }};
  10059. $.extend(ui, {
  10060. KoTemplateProvider: KoTemplateProvider,
  10061. KoTemplate: KoTemplate
  10062. })
  10063. })(jQuery, DevExpress);
  10064. /*! Module core, file ng.templates.js */
  10065. (function($, DX, undefined) {
  10066. if (!DX.support.hasNg)
  10067. return;
  10068. var ui = DX.ui;
  10069. var TEMPLATE_WRAPPER_CLASS = "dx-template-wrapper";
  10070. var NgTemplate = ui.TemplateBase.inherit({
  10071. ctor: function() {
  10072. this.callBase.apply(this, arguments);
  10073. this.setCompiler(this._getParentTemplateCompiler())
  10074. },
  10075. _getParentTemplateCompiler: function() {
  10076. var templateCompiler = null,
  10077. owner = this.owner();
  10078. while (!templateCompiler && owner) {
  10079. templateCompiler = $.isFunction(owner.option) ? owner.option("templateCompiler") : null;
  10080. owner = $.isFunction(owner.owner) ? owner.owner() : null
  10081. }
  10082. return templateCompiler
  10083. },
  10084. _renderCore: function(data, index, $container) {
  10085. var compiledTemplate = this._compiledTemplate,
  10086. result = $.isFunction(compiledTemplate) ? compiledTemplate(data, index, $container) : compiledTemplate;
  10087. return result
  10088. },
  10089. setCompiler: function(templateCompiler) {
  10090. if (!templateCompiler)
  10091. return;
  10092. this._compiledTemplate = templateCompiler(DX.utils.normalizeTemplateElement(this._element))
  10093. }
  10094. });
  10095. var NgTemplateProvider = new(ui.TemplateProviderBase.inherit({
  10096. createTemplate: function(element, owner) {
  10097. return new NgTemplate(element, owner)
  10098. },
  10099. getTemplates: function(widget) {
  10100. var templateCompiler = widget.option("templateCompiler"),
  10101. templates = this.callBase.apply(this, arguments);
  10102. $.each(templates, function(_, template) {
  10103. template.setCompiler(templateCompiler)
  10104. });
  10105. return templates
  10106. },
  10107. _templatesForWidget: function(widgetName) {
  10108. var templateGenerators = TEMPLATE_GENERATORS[widgetName] || {},
  10109. templates = {};
  10110. $.each(templateGenerators, function(name, generator) {
  10111. var $markup = DX.utils.createMarkupFromString(generator());
  10112. templates[name] = new NgTemplate($markup.wrap(), NgTemplateProvider)
  10113. });
  10114. return templates
  10115. }
  10116. }));
  10117. var baseElements = {
  10118. container: function() {
  10119. return $("<div>").addClass(TEMPLATE_WRAPPER_CLASS)
  10120. },
  10121. html: function() {
  10122. return $("<div>").attr("ng-if", "html").attr("ng-bind-html", "html")
  10123. },
  10124. text: function() {
  10125. return $("<div>").attr("ng-if", "text").attr("ng-bind", "text")
  10126. },
  10127. primitive: function() {
  10128. return $("<div>").attr("ng-if", "scopeValue").attr("ng-bind-html", "'' + scopeValue")
  10129. }
  10130. };
  10131. var TEMPLATE_GENERATORS = {};
  10132. var emptyTemplate = function() {
  10133. return $()
  10134. };
  10135. TEMPLATE_GENERATORS.CollectionWidget = {
  10136. item: function() {
  10137. return baseElements.container().append(baseElements.html()).append(baseElements.text()).append(baseElements.primitive())
  10138. },
  10139. itemFrame: function() {
  10140. var $container = $("<div>").attr("ng-class", "{ 'dx-state-invisible': !visible && visible != undefined, 'dx-state-disabled': !!disabled }"),
  10141. $placeholder = $("<div>").addClass("dx-item-content-placeholder");
  10142. $container.append($placeholder);
  10143. return $container
  10144. }
  10145. };
  10146. var BUTTON_TEXT_CLASS = "dx-button-text";
  10147. TEMPLATE_GENERATORS.dxButton = {content: function() {
  10148. var $titleBinding = $("<span>").attr("ng-bind", "text").attr("ng-class", "{ '" + BUTTON_TEXT_CLASS + "' : !!text }"),
  10149. icon = $("<dx-icon>");
  10150. return baseElements.container().append(icon).append($titleBinding).append(baseElements.primitive())
  10151. }};
  10152. var LIST_ITEM_BADGE_CONTAINER_CLASS = "dx-list-item-badge-container",
  10153. LIST_ITEM_BADGE_CLASS = "dx-list-item-badge",
  10154. BADGE_CLASS = "dx-badge",
  10155. LIST_ITEM_CHEVRON_CONTAINER_CLASS = "dx-list-item-chevron-container",
  10156. LIST_ITEM_CHEVRON_CLASS = "dx-list-item-chevron";
  10157. TEMPLATE_GENERATORS.dxList = {
  10158. item: function() {
  10159. return TEMPLATE_GENERATORS.CollectionWidget.item().append($("<div>").attr("ng-if", "key").attr("ng-bind", "key"))
  10160. },
  10161. itemFrame: function() {
  10162. var $badgeContainer = $("<div>").addClass(LIST_ITEM_BADGE_CONTAINER_CLASS).attr("ng-if", "badge"),
  10163. $badge = $("<div>").addClass(LIST_ITEM_BADGE_CLASS).addClass(BADGE_CLASS).attr("ng-bind", "badge");
  10164. var $chevronContainer = $("<div>").addClass(LIST_ITEM_CHEVRON_CONTAINER_CLASS).attr("ng-if", "showChevron"),
  10165. $chevron = $("<div>").addClass(LIST_ITEM_CHEVRON_CLASS);
  10166. return TEMPLATE_GENERATORS.CollectionWidget.itemFrame().append($badgeContainer.append($badge)).append($chevronContainer.append($chevron))
  10167. },
  10168. group: function() {
  10169. var $keyBinding = $("<div>").attr("ng-if", "key").attr("ng-bind", "key");
  10170. return baseElements.container().append($keyBinding).append(baseElements.primitive())
  10171. }
  10172. };
  10173. TEMPLATE_GENERATORS.dxDropDownMenu = {item: TEMPLATE_GENERATORS.dxList.item};
  10174. TEMPLATE_GENERATORS.dxDropDownList = {item: TEMPLATE_GENERATORS.dxList.item};
  10175. TEMPLATE_GENERATORS.dxRadioGroup = {item: TEMPLATE_GENERATORS.CollectionWidget.item};
  10176. TEMPLATE_GENERATORS.dxScheduler = {item: function() {
  10177. var $itemContent = TEMPLATE_GENERATORS.CollectionWidget.item();
  10178. var $details = $("<div>").addClass("dx-scheduler-appointment-content-details");
  10179. $("<strong>").attr("ng-if", "startDate").text("{{startDate | date : 'shortTime' }}").appendTo($details);
  10180. $("<strong>").attr("ng-if", "endDate").text(" - {{endDate | date : 'shortTime' }}").appendTo($details);
  10181. $details.appendTo($itemContent);
  10182. $("<span>").attr("ng-if", "recurrenceRule").addClass("dx-scheduler-appointment-recurrence-icon").appendTo($itemContent);
  10183. return $itemContent
  10184. }};
  10185. TEMPLATE_GENERATORS.dxOverlay = {content: emptyTemplate};
  10186. TEMPLATE_GENERATORS.dxSlideOutView = {
  10187. menu: emptyTemplate,
  10188. content: emptyTemplate
  10189. };
  10190. TEMPLATE_GENERATORS.dxSlideOut = {
  10191. menuItem: TEMPLATE_GENERATORS.dxList.item,
  10192. menuGroup: TEMPLATE_GENERATORS.dxList.group,
  10193. content: emptyTemplate
  10194. };
  10195. TEMPLATE_GENERATORS.dxAccordion = {
  10196. title: function() {
  10197. var $titleBinding = $("<span>").attr("ng-if", "title").attr("ng-bind", "title"),
  10198. icon = $("<dx-icon>");
  10199. return baseElements.container().append(icon).append($titleBinding).append(baseElements.primitive())
  10200. },
  10201. content: TEMPLATE_GENERATORS.CollectionWidget.item
  10202. };
  10203. TEMPLATE_GENERATORS.dxPivotTabs = {item: function() {
  10204. return baseElements.container().append($("<span>").attr("ng-if", "title").attr("ng-bind", "title")).append(baseElements.primitive())
  10205. }};
  10206. TEMPLATE_GENERATORS.dxPivot = {
  10207. title: TEMPLATE_GENERATORS.dxPivotTabs.item,
  10208. content: emptyTemplate
  10209. };
  10210. var PANORAMA_ITEM_TITLE_CLASS = "dx-panorama-item-title";
  10211. TEMPLATE_GENERATORS.dxPanorama = {itemFrame: function() {
  10212. return TEMPLATE_GENERATORS.CollectionWidget.itemFrame().prepend($("<div>").addClass(PANORAMA_ITEM_TITLE_CLASS).attr("ng-if", "title").attr("ng-bind", "title"))
  10213. }};
  10214. TEMPLATE_GENERATORS.dxActionSheet = {item: function() {
  10215. return baseElements.container().append($("<div>").attr("dx-button", "{ bindingOptions: { text: 'text', onClick: 'onClick', type: 'type', disabled: 'disabled' } }"))
  10216. }};
  10217. TEMPLATE_GENERATORS.dxToolbar = {
  10218. item: function() {
  10219. var template = TEMPLATE_GENERATORS.CollectionWidget.item();
  10220. $.each(["button", "tabs", "dropDownMenu"], function(i, widgetName) {
  10221. var bindingName = "dx-" + DX.inflector.dasherize(this);
  10222. $("<div>").attr("ng-if", "widget === '" + widgetName + "'").attr(bindingName, "options").appendTo(template)
  10223. });
  10224. return template
  10225. },
  10226. menuItem: TEMPLATE_GENERATORS.dxList.item,
  10227. actionSheetItem: TEMPLATE_GENERATORS.dxActionSheet.item
  10228. };
  10229. TEMPLATE_GENERATORS.dxGallery = {item: function() {
  10230. return baseElements.container().append(baseElements.html()).append(baseElements.text()).append($("<img>").attr("ng-if", "scopeValue").attr("ng-src", "{{'' + scopeValue}}")).append($("<img>").attr("ng-if", "imageSrc").attr("ng-src", "{{imageSrc}}"))
  10231. }};
  10232. var TABS_ITEM_TEXT_CLASS = "dx-tab-text";
  10233. TEMPLATE_GENERATORS.dxTabs = {
  10234. item: function() {
  10235. var container = baseElements.container();
  10236. var text = $("<span>").addClass(TABS_ITEM_TEXT_CLASS).attr("ng-bind", "text").attr("ng-if", "text"),
  10237. icon = $("<dx-icon>");
  10238. return container.append(baseElements.html()).append(icon).append(text).append(baseElements.primitive().addClass(TABS_ITEM_TEXT_CLASS))
  10239. },
  10240. itemFrame: function() {
  10241. var $badge = $("<div>").addClass("dx-tabs-item-badge dx-badge").attr("ng-bind", "badge").attr("ng-if", "badge");
  10242. return TEMPLATE_GENERATORS.CollectionWidget.itemFrame().append($badge)
  10243. }
  10244. };
  10245. var NAVBAR_ITEM_BADGE_CLASS = "dx-navbar-item-badge";
  10246. TEMPLATE_GENERATORS.dxNavBar = {itemFrame: function() {
  10247. var $badge = $("<div>").addClass(NAVBAR_ITEM_BADGE_CLASS).addClass(BADGE_CLASS).attr("ng-if", "badge").attr("ng-bind", "badge");
  10248. return TEMPLATE_GENERATORS.CollectionWidget.itemFrame().append($badge)
  10249. }};
  10250. TEMPLATE_GENERATORS.dxMenuBase = {item: function() {
  10251. var container = baseElements.container();
  10252. var text = $("<span>").attr("ng-if", "text").addClass("dx-menu-item-text").attr("ng-bind", "text"),
  10253. icon = $("<dx-icon>"),
  10254. popout = $("<span>").addClass("dx-menu-item-popout-container").attr("ng-if", "items").append($("<div>").addClass("dx-menu-item-popout"));
  10255. container.append(baseElements.html()).append(icon).append(text).append(popout).append(baseElements.primitive()).appendTo(container);
  10256. return container
  10257. }};
  10258. TEMPLATE_GENERATORS.dxTreeView = {item: function() {
  10259. var content = baseElements.container(),
  10260. link = $("<span/>").attr("ng-bind", "text"),
  10261. icon = $("<dx-icon>");
  10262. content.append(baseElements.html()).append(icon).append(link).append(baseElements.primitive());
  10263. return content
  10264. }};
  10265. TEMPLATE_GENERATORS.dxTabPanel = {
  10266. item: TEMPLATE_GENERATORS.CollectionWidget.item,
  10267. title: function() {
  10268. var content = TEMPLATE_GENERATORS.dxTabs.item();
  10269. content.find(".dx-tab-text").eq(0).attr("ng-bind", "title").attr("ng-if", "title");
  10270. return content
  10271. }
  10272. };
  10273. var popupTitleAndBottom = function() {
  10274. return $("<div>").attr("dx-toolbar", "{ bindingOptions: { items: 'scopeValue' } }")
  10275. };
  10276. TEMPLATE_GENERATORS.dxPopup = {
  10277. title: popupTitleAndBottom,
  10278. bottom: popupTitleAndBottom
  10279. };
  10280. TEMPLATE_GENERATORS.dxLookup = {
  10281. title: TEMPLATE_GENERATORS.dxPopup.title,
  10282. group: TEMPLATE_GENERATORS.dxList.group
  10283. };
  10284. TEMPLATE_GENERATORS.dxTagBox = {tag: function() {
  10285. return $("<div>").append($("<span>").attr("ng-bind", "scopeValue"))
  10286. }};
  10287. TEMPLATE_GENERATORS.dxCalendar = {cell: function() {
  10288. var $cell = $("<span>").attr("ng-if", "text").attr("ng-bind", "text");
  10289. return baseElements.container().append($cell).append(baseElements.primitive())
  10290. }};
  10291. $.extend(ui, {
  10292. NgTemplate: NgTemplate,
  10293. NgTemplateProvider: NgTemplateProvider
  10294. })
  10295. })(jQuery, DevExpress);
  10296. /*! Module core, file ko.validation.js */
  10297. (function($, DX, undefined) {
  10298. if (!DX.support.hasKo)
  10299. return;
  10300. var ko = window.ko;
  10301. var koDxValidator = DX.Class.inherit({
  10302. ctor: function(target, option) {
  10303. var that = this;
  10304. that.target = target;
  10305. that.validationRules = option.validationRules;
  10306. that.name = option.name;
  10307. that.isValid = ko.observable(true);
  10308. that.validationError = ko.observable();
  10309. $.each(this.validationRules, function(_, rule) {
  10310. rule.validator = that
  10311. })
  10312. },
  10313. validate: function() {
  10314. var result = DevExpress.validationEngine.validate(this.target(), this.validationRules, this.name);
  10315. this._applyValidationResult(result);
  10316. return result
  10317. },
  10318. reset: function() {
  10319. this.target(null);
  10320. var result = {
  10321. isValid: true,
  10322. brokenRule: null
  10323. };
  10324. this._applyValidationResult(result);
  10325. return result
  10326. },
  10327. _applyValidationResult: function(result) {
  10328. result.validator = this;
  10329. this.target.dxValidator.isValid(result.isValid);
  10330. this.target.dxValidator.validationError(result.brokenRule);
  10331. this.fireEvent("validated", [result])
  10332. }
  10333. }).include(DX.EventsMixin);
  10334. ko.extenders.dxValidator = function(target, option) {
  10335. target.dxValidator = new koDxValidator(target, option);
  10336. target.subscribe($.proxy(target.dxValidator.validate, target.dxValidator));
  10337. return target
  10338. };
  10339. DevExpress.validationEngine.registerModelForValidation = function(model) {
  10340. $.each(model, function(name, member) {
  10341. if (ko.isObservable(member) && member.dxValidator)
  10342. DevExpress.validationEngine.registerValidatorInGroup(model, member.dxValidator)
  10343. })
  10344. };
  10345. DevExpress.validationEngine.validateModel = DevExpress.validationEngine.validateGroup
  10346. })(jQuery, DevExpress);
  10347. /*! Module core, file ui.themes.js */
  10348. (function($, DX, undefined) {
  10349. var DX_LINK_SELECTOR = "link[rel=dx-theme]",
  10350. THEME_ATTR = "data-theme",
  10351. ACTIVE_ATTR = "data-active";
  10352. var context,
  10353. $activeThemeLink,
  10354. knownThemes,
  10355. currentThemeName,
  10356. pendingThemeName;
  10357. var THEME_MARKER_PREFIX = "dx.";
  10358. function readThemeMarker() {
  10359. var element = $("<div></div>", context).addClass("dx-theme-marker").appendTo(context.documentElement),
  10360. result;
  10361. try {
  10362. result = element.css("font-family");
  10363. if (!result)
  10364. return null;
  10365. result = result.replace(/["']/g, "");
  10366. if (result.substr(0, THEME_MARKER_PREFIX.length) !== THEME_MARKER_PREFIX)
  10367. return null;
  10368. return result.substr(THEME_MARKER_PREFIX.length)
  10369. }
  10370. finally {
  10371. element.remove()
  10372. }
  10373. }
  10374. function waitForThemeLoad(themeName, callback) {
  10375. var timerId,
  10376. waitStartTime;
  10377. pendingThemeName = themeName;
  10378. function handleLoaded() {
  10379. pendingThemeName = null;
  10380. callback()
  10381. }
  10382. if (isPendingThemeLoaded())
  10383. handleLoaded();
  10384. else {
  10385. waitStartTime = $.now();
  10386. timerId = setInterval(function() {
  10387. var isLoaded = isPendingThemeLoaded(),
  10388. isTimeout = !isLoaded && $.now() - waitStartTime > 15 * 1000;
  10389. if (isTimeout)
  10390. DX.log("W0004", pendingThemeName);
  10391. if (isLoaded || isTimeout) {
  10392. clearInterval(timerId);
  10393. handleLoaded()
  10394. }
  10395. }, 10)
  10396. }
  10397. }
  10398. function isPendingThemeLoaded() {
  10399. return !pendingThemeName || readThemeMarker() === pendingThemeName
  10400. }
  10401. function processMarkup() {
  10402. var $allThemeLinks = $(DX_LINK_SELECTOR, context);
  10403. if (!$allThemeLinks.length)
  10404. return;
  10405. knownThemes = {};
  10406. $activeThemeLink = $(DX.utils.createMarkupFromString("<link rel=stylesheet>"), context);
  10407. $allThemeLinks.each(function() {
  10408. var link = $(this, context),
  10409. fullThemeName = link.attr(THEME_ATTR),
  10410. url = link.attr("href"),
  10411. isActive = link.attr(ACTIVE_ATTR) === "true";
  10412. knownThemes[fullThemeName] = {
  10413. url: url,
  10414. isActive: isActive
  10415. }
  10416. });
  10417. $allThemeLinks.last().after($activeThemeLink);
  10418. $allThemeLinks.remove()
  10419. }
  10420. function resolveFullThemeName(desiredThemeName) {
  10421. var desiredThemeParts = desiredThemeName.split("."),
  10422. result = null;
  10423. if (knownThemes)
  10424. $.each(knownThemes, function(knownThemeName, themeData) {
  10425. var knownThemeParts = knownThemeName.split(".");
  10426. if (knownThemeParts[0] !== desiredThemeParts[0])
  10427. return;
  10428. if (desiredThemeParts[1] && desiredThemeParts[1] !== knownThemeParts[1])
  10429. return;
  10430. if (desiredThemeParts[2] && desiredThemeParts[2] !== knownThemeParts[2])
  10431. return;
  10432. if (!result || themeData.isActive)
  10433. result = knownThemeName;
  10434. if (themeData.isActive)
  10435. return false
  10436. });
  10437. return result
  10438. }
  10439. function initContext(newContext) {
  10440. try {
  10441. if (newContext !== context)
  10442. knownThemes = null
  10443. }
  10444. catch(x) {
  10445. knownThemes = null
  10446. }
  10447. context = newContext
  10448. }
  10449. function init(options) {
  10450. options = options || {};
  10451. initContext(options.context || document);
  10452. processMarkup();
  10453. currentThemeName = undefined;
  10454. current(options)
  10455. }
  10456. function current(options) {
  10457. if (!arguments.length)
  10458. return currentThemeName || readThemeMarker();
  10459. detachCssClasses(DX.viewPort(), currentThemeName);
  10460. options = options || {};
  10461. if (typeof options === "string")
  10462. options = {theme: options};
  10463. var isAutoInit = options._autoInit,
  10464. loadCallback = options.loadCallback,
  10465. currentThemeData;
  10466. currentThemeName = options.theme || currentThemeName;
  10467. if (isAutoInit && !currentThemeName)
  10468. currentThemeName = themeNameFromDevice(DX.devices.current());
  10469. currentThemeName = resolveFullThemeName(currentThemeName);
  10470. if (currentThemeName)
  10471. currentThemeData = knownThemes[currentThemeName];
  10472. if (currentThemeData) {
  10473. $activeThemeLink.attr("href", knownThemes[currentThemeName].url);
  10474. if (loadCallback)
  10475. waitForThemeLoad(currentThemeName, loadCallback);
  10476. else if (pendingThemeName)
  10477. pendingThemeName = currentThemeName
  10478. }
  10479. else if (isAutoInit) {
  10480. if (loadCallback)
  10481. loadCallback()
  10482. }
  10483. else
  10484. throw DX.Error("E0021", currentThemeName);
  10485. attachCssClasses(DX.viewPort(), currentThemeName)
  10486. }
  10487. function themeNameFromDevice(device) {
  10488. var themeName = device.platform;
  10489. if (themeName === "ios")
  10490. themeName += "7";
  10491. if (themeName === "android")
  10492. themeName += "5";
  10493. return themeName
  10494. }
  10495. function getCssClasses(themeName) {
  10496. themeName = themeName || current();
  10497. var result = [],
  10498. themeNameParts = themeName && themeName.split(".");
  10499. if (themeNameParts) {
  10500. result.push("dx-theme-" + themeNameParts[0], "dx-theme-" + themeNameParts[0] + "-typography");
  10501. if (themeNameParts.length > 1)
  10502. result.push("dx-color-scheme-" + themeNameParts[1])
  10503. }
  10504. return result
  10505. }
  10506. var themeClasses;
  10507. function attachCssClasses(element, themeName) {
  10508. themeClasses = getCssClasses(themeName).join(" ");
  10509. $(element).addClass(themeClasses)
  10510. }
  10511. function detachCssClasses(element, themeName) {
  10512. $(element).removeClass(themeClasses)
  10513. }
  10514. $.holdReady(true);
  10515. init({
  10516. _autoInit: true,
  10517. loadCallback: function() {
  10518. $.holdReady(false)
  10519. }
  10520. });
  10521. $(function() {
  10522. if ($(DX_LINK_SELECTOR, context).length)
  10523. throw DX.Error("E0022");
  10524. });
  10525. DX.viewPortChanged.add(function(viewPort, prevViewPort) {
  10526. detachCssClasses(prevViewPort);
  10527. attachCssClasses(viewPort)
  10528. });
  10529. DX.ui.themes = {
  10530. init: init,
  10531. current: current,
  10532. attachCssClasses: attachCssClasses,
  10533. detachCssClasses: detachCssClasses
  10534. };
  10535. DX.ui.themes.__internals = {
  10536. themeNameFromDevice: themeNameFromDevice,
  10537. waitForThemeLoad: waitForThemeLoad,
  10538. resetTheme: function() {
  10539. $activeThemeLink.attr("href", "about:blank");
  10540. currentThemeName = null;
  10541. pendingThemeName = null
  10542. }
  10543. }
  10544. })(jQuery, DevExpress);
  10545. /*! Module core, file ui.events.js */
  10546. (function($, DX, undefined) {
  10547. var ui = DX.ui,
  10548. eventNS = $.event,
  10549. hooksNS = eventNS.fixHooks,
  10550. specialNS = eventNS.special,
  10551. EVENT_SOURCES_REGEX = {
  10552. dx: /^dx/i,
  10553. mouse: /(mouse|wheel)/i,
  10554. touch: /^touch/i,
  10555. keyboard: /^key/i,
  10556. pointer: /^(ms)?pointer/i
  10557. };
  10558. var eventSource = function(e) {
  10559. var result = "other";
  10560. $.each(EVENT_SOURCES_REGEX, function(key) {
  10561. if (this.test(e.type)) {
  10562. result = key;
  10563. return false
  10564. }
  10565. });
  10566. return result
  10567. };
  10568. var isDxEvent = function(e) {
  10569. return eventSource(e) === "dx"
  10570. };
  10571. var isNativeMouseEvent = function(e) {
  10572. return eventSource(e) === "mouse"
  10573. };
  10574. var isNativeTouchEvent = function(e) {
  10575. return eventSource(e) === "touch"
  10576. };
  10577. var isPointerEvent = function(e) {
  10578. return eventSource(e) === "pointer"
  10579. };
  10580. var isMouseEvent = function(e) {
  10581. return isNativeMouseEvent(e) || (isPointerEvent(e) || isDxEvent(e)) && e.pointerType === "mouse"
  10582. };
  10583. var isTouchEvent = function(e) {
  10584. return isNativeTouchEvent(e) || (isPointerEvent(e) || isDxEvent(e)) && e.pointerType === "touch"
  10585. };
  10586. var isKeyboardEvent = function(e) {
  10587. return eventSource(e) === "keyboard"
  10588. };
  10589. var eventData = function(e) {
  10590. return {
  10591. x: e.pageX,
  10592. y: e.pageY,
  10593. time: e.timeStamp
  10594. }
  10595. };
  10596. var eventDelta = function(from, to) {
  10597. return {
  10598. x: to.x - from.x,
  10599. y: to.y - from.y,
  10600. time: to.time - from.time || 1
  10601. }
  10602. };
  10603. var hasTouches = function(e) {
  10604. if (isNativeTouchEvent(e))
  10605. return (e.originalEvent.touches || []).length;
  10606. if (isDxEvent(e))
  10607. return (e.pointers || []).length;
  10608. return 0
  10609. };
  10610. var needSkipEvent = function(e) {
  10611. var $target = $(e.target),
  10612. touchInInput = $target.is("input, textarea, select");
  10613. if (e.type === 'dxmousewheel')
  10614. return $target.is("input[type='number'], textarea, select") && $target.is(':focus');
  10615. if (isMouseEvent(e))
  10616. return touchInInput || e.which > 1;
  10617. if (isTouchEvent(e))
  10618. return touchInInput && $target.is(":focus")
  10619. };
  10620. var createEvent = function(originalEvent, args) {
  10621. var event = $.Event(originalEvent),
  10622. fixHook = hooksNS[originalEvent.type] || eventNS.mouseHooks;
  10623. var props = fixHook.props ? eventNS.props.concat(fixHook.props) : eventNS.props,
  10624. propIndex = props.length;
  10625. while (propIndex--) {
  10626. var prop = props[propIndex];
  10627. event[prop] = originalEvent[prop]
  10628. }
  10629. if (args)
  10630. $.extend(event, args);
  10631. return fixHook.filter ? fixHook.filter(event, originalEvent) : event
  10632. };
  10633. var fireEvent = function(props) {
  10634. var event = createEvent(props.originalEvent, props);
  10635. eventNS.trigger(event, null, props.delegateTarget || event.target);
  10636. return event
  10637. };
  10638. var addNamespace = function(eventNames, namespace) {
  10639. if (!namespace)
  10640. throw DX.Error("E0017");
  10641. if (typeof eventNames === "string")
  10642. return addNamespace(eventNames.split(/\s+/g), namespace);
  10643. $.each(eventNames, function(index, eventName) {
  10644. eventNames[index] = eventName + "." + namespace
  10645. });
  10646. return eventNames.join(" ")
  10647. };
  10648. var dxEventHook = {props: eventNS.mouseHooks.props.concat(["pointerType", "pointerId", "pointers"])};
  10649. var registerEvent = function(eventName, eventObject) {
  10650. var strategy = {};
  10651. if ("noBubble" in eventObject)
  10652. strategy.noBubble = eventObject.noBubble;
  10653. if ("bindType" in eventObject)
  10654. strategy.bindType = eventObject.bindType;
  10655. if ("delegateType" in eventObject)
  10656. strategy.delegateType = eventObject.delegateType;
  10657. $.each(["setup", "teardown", "add", "remove", "trigger", "handle", "_default", "dispose"], function(_, methodName) {
  10658. if (!eventObject[methodName])
  10659. return;
  10660. strategy[methodName] = function() {
  10661. var args = $.makeArray(arguments);
  10662. args.unshift(this);
  10663. return eventObject[methodName].apply(eventObject, args)
  10664. }
  10665. });
  10666. hooksNS[eventName] = dxEventHook;
  10667. specialNS[eventName] = strategy
  10668. };
  10669. ui.events = {
  10670. eventSource: eventSource,
  10671. isPointerEvent: isPointerEvent,
  10672. isMouseEvent: isMouseEvent,
  10673. isTouchEvent: isTouchEvent,
  10674. isKeyboardEvent: isKeyboardEvent,
  10675. hasTouches: hasTouches,
  10676. eventData: eventData,
  10677. eventDelta: eventDelta,
  10678. needSkipEvent: needSkipEvent,
  10679. createEvent: createEvent,
  10680. fireEvent: fireEvent,
  10681. addNamespace: addNamespace,
  10682. registerEvent: registerEvent
  10683. }
  10684. })(jQuery, DevExpress);
  10685. /*! Module core, file ko.events.js */
  10686. (function($, DX, undefined) {
  10687. if (!DX.support.hasKo)
  10688. return;
  10689. var ko = window.ko,
  10690. events = DX.ui.events;
  10691. var originalRegisterEvent = events.registerEvent;
  10692. var registerKoEvent = function(eventName, eventObject) {
  10693. originalRegisterEvent(eventName, eventObject);
  10694. var koBindingEventName = events.addNamespace(eventName, eventName + "Binding");
  10695. ko.bindingHandlers[eventName] = {update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
  10696. var $element = $(element),
  10697. unwrappedValue = ko.utils.unwrapObservable(valueAccessor()),
  10698. eventSource = unwrappedValue.execute ? unwrappedValue.execute : unwrappedValue;
  10699. $element.off(koBindingEventName).on(koBindingEventName, $.isPlainObject(unwrappedValue) ? unwrappedValue : {}, function(e) {
  10700. eventSource.call(viewModel, viewModel, e)
  10701. })
  10702. }}
  10703. };
  10704. $.extend(events, {registerEvent: registerKoEvent})
  10705. })(jQuery, DevExpress);
  10706. /*! Module core, file ng.events.js */
  10707. (function($, DX, undefined) {
  10708. if (!DX.support.hasNg)
  10709. return;
  10710. var events = DX.ui.events;
  10711. var originalRegisterEvent = events.registerEvent;
  10712. var registerNgEvent = function(eventName, eventObject) {
  10713. originalRegisterEvent(eventName, eventObject);
  10714. var ngEventName = eventName.slice(0, 2) + eventName.charAt(2).toUpperCase() + eventName.slice(3);
  10715. DX.ng.module.directive(ngEventName, ['$parse', function($parse) {
  10716. return function(scope, element, attr) {
  10717. var attrValue = $.trim(attr[ngEventName]),
  10718. handler,
  10719. eventOptions = {};
  10720. if (attrValue.charAt(0) === "{") {
  10721. eventOptions = scope.$eval(attrValue);
  10722. handler = $parse(eventOptions.execute)
  10723. }
  10724. else
  10725. handler = $parse(attr[ngEventName]);
  10726. element.on(eventName, eventOptions, function(e) {
  10727. scope.$apply(function() {
  10728. handler(scope, {$event: e})
  10729. })
  10730. })
  10731. }
  10732. }])
  10733. };
  10734. $.extend(events, {registerEvent: registerNgEvent})
  10735. })(jQuery, DevExpress);
  10736. /*! Module core, file ui.keyboardProcessor.js */
  10737. (function($, DX, undefined) {
  10738. var ui = DX.ui,
  10739. events = ui.events;
  10740. ui.KeyboardProcessor = DX.Class.inherit({
  10741. _keydown: events.addNamespace("keydown", "KeyboardProcessor"),
  10742. codes: {
  10743. "8": "backspace",
  10744. "9": "tab",
  10745. "13": "enter",
  10746. "27": "escape",
  10747. "33": "pageUp",
  10748. "34": "pageDown",
  10749. "35": "end",
  10750. "36": "home",
  10751. "37": "leftArrow",
  10752. "38": "upArrow",
  10753. "39": "rightArrow",
  10754. "40": "downArrow",
  10755. "46": "del",
  10756. "32": "space",
  10757. "70": "F",
  10758. "65": "A",
  10759. "106": "asterisk",
  10760. "109": "minus"
  10761. },
  10762. ctor: function(options) {
  10763. var _this = this;
  10764. options = options || {};
  10765. if (options.element)
  10766. this._element = $(options.element);
  10767. if (options.focusTarget)
  10768. this._focusTarget = options.focusTarget;
  10769. this._handler = options.handler;
  10770. this._context = options.context;
  10771. this._childProcessors = [];
  10772. if (this._element)
  10773. this._element.on(this._keydown, function(e) {
  10774. _this.process(e)
  10775. })
  10776. },
  10777. dispose: function() {
  10778. if (this._element)
  10779. this._element.off(this._keydown);
  10780. this._element = undefined;
  10781. this._handler = undefined;
  10782. this._context = undefined;
  10783. this._childProcessors = undefined
  10784. },
  10785. clearChildren: function() {
  10786. this._childProcessors = []
  10787. },
  10788. push: function(child) {
  10789. if (!this._childProcessors)
  10790. this.clearChildren();
  10791. this._childProcessors.push(child);
  10792. return child
  10793. },
  10794. attachChildProcessor: function() {
  10795. var childProcessor = new ui.KeyboardProcessor;
  10796. this._childProcessors.push(childProcessor);
  10797. return childProcessor
  10798. },
  10799. reinitialize: function(childHandler, childContext) {
  10800. this._context = childContext;
  10801. this._handler = childHandler;
  10802. return this
  10803. },
  10804. process: function(e) {
  10805. if (this._focusTarget && this._focusTarget !== e.target && $.inArray(e.target, this._focusTarget) < 0)
  10806. return false;
  10807. var args = {
  10808. key: this.codes[e.which] || e.which,
  10809. ctrl: e.ctrlKey,
  10810. shift: e.shiftKey,
  10811. alt: e.altKey,
  10812. originalEvent: e
  10813. };
  10814. var handlerResult = this._handler && this._handler.call(this._context, args);
  10815. if (handlerResult && this._childProcessors)
  10816. $.each(this._childProcessors, function(index, childProcessor) {
  10817. childProcessor.process(e)
  10818. })
  10819. }
  10820. })
  10821. })(jQuery, DevExpress);
  10822. /*! Module core, file ui.dialog.js */
  10823. (function($, DX, undefined) {
  10824. var ui = DX.ui,
  10825. utils = DX.utils;
  10826. var DEFAULT_BUTTON = {
  10827. text: "OK",
  10828. onClick: function() {
  10829. return true
  10830. }
  10831. };
  10832. var DX_DIALOG_CLASSNAME = "dx-dialog",
  10833. DX_DIALOG_WRAPPER_CLASSNAME = DX_DIALOG_CLASSNAME + "-wrapper",
  10834. DX_DIALOG_ROOT_CLASSNAME = DX_DIALOG_CLASSNAME + "-root",
  10835. DX_DIALOG_CONTENT_CLASSNAME = DX_DIALOG_CLASSNAME + "-content",
  10836. DX_DIALOG_MESSAGE_CLASSNAME = DX_DIALOG_CLASSNAME + "-message",
  10837. DX_DIALOG_BUTTONS_CLASSNAME = DX_DIALOG_CLASSNAME + "-buttons",
  10838. DX_DIALOG_BUTTON_CLASSNAME = DX_DIALOG_CLASSNAME + "-button";
  10839. var FakeDialogComponent = DX.Component.inherit({
  10840. NAME: "dxDialog",
  10841. ctor: function(element, options) {
  10842. this.callBase(options)
  10843. },
  10844. _defaultOptionsRules: function() {
  10845. return this.callBase().concat([{
  10846. device: {platform: "ios"},
  10847. options: {width: 276}
  10848. }, {
  10849. device: {platform: "android"},
  10850. options: {
  10851. lWidth: "60%",
  10852. pWidth: "80%"
  10853. }
  10854. }, {
  10855. device: {
  10856. platform: "win8",
  10857. phone: false
  10858. },
  10859. options: {width: function() {
  10860. return $(window).width()
  10861. }}
  10862. }, {
  10863. device: {
  10864. platform: "win8",
  10865. phone: true
  10866. },
  10867. options: {position: {
  10868. my: "top center",
  10869. at: "top center",
  10870. of: window,
  10871. offset: "0 0"
  10872. }}
  10873. }])
  10874. }
  10875. });
  10876. var dialog = function(options) {
  10877. if (!ui.dxPopup)
  10878. throw DX.Error("E0018");
  10879. var deferred = $.Deferred();
  10880. var defaultOptions = (new FakeDialogComponent).option();
  10881. options = $.extend(defaultOptions, options);
  10882. var $element = $("<div>").addClass(DX_DIALOG_CLASSNAME).appendTo(DX.viewPort());
  10883. var $message = $("<div>").addClass(DX_DIALOG_MESSAGE_CLASSNAME).html(String(options.message));
  10884. var popupButtons = [];
  10885. $.each(options.buttons || [DEFAULT_BUTTON], function() {
  10886. if (this.clickAction) {
  10887. DX.log("W0001", "Dialog", "clickAction", "14.2", "Use 'onClick' option instead");
  10888. this.onClick = this.clickAction
  10889. }
  10890. var action = new DX.Action(this.onClick || this.clickAction, {context: popupInstance});
  10891. popupButtons.push({
  10892. toolbar: 'bottom',
  10893. location: 'center',
  10894. widget: 'button',
  10895. options: {
  10896. text: this.text,
  10897. onClick: function() {
  10898. var result = action.execute(arguments);
  10899. hide(result)
  10900. }
  10901. }
  10902. })
  10903. });
  10904. var popupInstance = $element.dxPopup({
  10905. title: options.title || this.title,
  10906. showTitle: function() {
  10907. var isTitle = options.showTitle === undefined ? true : options.showTitle;
  10908. return isTitle
  10909. }(),
  10910. height: "auto",
  10911. width: function() {
  10912. var isPortrait = $(window).height() > $(window).width(),
  10913. key = (isPortrait ? "p" : "l") + "Width",
  10914. widthOption = options.hasOwnProperty(key) ? options[key] : options["width"];
  10915. return $.isFunction(widthOption) ? widthOption() : widthOption
  10916. },
  10917. showCloseButton: false,
  10918. focusStateEnabled: false,
  10919. onContentReady: function(args) {
  10920. args.component.content().addClass(DX_DIALOG_CONTENT_CLASSNAME).append($message)
  10921. },
  10922. onShowing: function(e) {
  10923. e.component.bottomToolbar().addClass(DX_DIALOG_BUTTONS_CLASSNAME).find(".dx-button").addClass(DX_DIALOG_BUTTON_CLASSNAME).first().focus()
  10924. },
  10925. buttons: popupButtons,
  10926. animation: {
  10927. show: {
  10928. type: "pop",
  10929. duration: 400
  10930. },
  10931. hide: {
  10932. type: "pop",
  10933. duration: 400,
  10934. to: {
  10935. opacity: 0,
  10936. scale: 0
  10937. },
  10938. from: {
  10939. opacity: 1,
  10940. scale: 1
  10941. }
  10942. }
  10943. },
  10944. rtlEnabled: DX.rtlEnabled,
  10945. boundaryOffset: {
  10946. h: 10,
  10947. v: 0
  10948. }
  10949. }).dxPopup("instance");
  10950. popupInstance._wrapper().addClass(DX_DIALOG_WRAPPER_CLASSNAME);
  10951. if (options.position)
  10952. popupInstance.option("position", options.position);
  10953. popupInstance._wrapper().addClass(DX_DIALOG_ROOT_CLASSNAME);
  10954. function show() {
  10955. popupInstance.show();
  10956. utils.resetActiveElement();
  10957. return deferred.promise()
  10958. }
  10959. function hide(value) {
  10960. popupInstance.hide().done(function() {
  10961. popupInstance.element().remove()
  10962. });
  10963. deferred.resolve(value)
  10964. }
  10965. return {
  10966. show: show,
  10967. hide: hide
  10968. }
  10969. };
  10970. var alert = function(message, title, showTitle) {
  10971. var dialogInstance,
  10972. options = $.isPlainObject(message) ? message : {
  10973. title: title,
  10974. message: message,
  10975. showTitle: showTitle
  10976. };
  10977. dialogInstance = ui.dialog.custom(options);
  10978. return dialogInstance.show()
  10979. };
  10980. var confirm = function(message, title, showTitle) {
  10981. var dialogInstance,
  10982. options = $.isPlainObject(message) ? message : {
  10983. title: title,
  10984. message: message,
  10985. showTitle: showTitle,
  10986. buttons: [{
  10987. text: Globalize.localize("Yes"),
  10988. onClick: function() {
  10989. return true
  10990. }
  10991. }, {
  10992. text: Globalize.localize("No"),
  10993. onClick: function() {
  10994. return false
  10995. }
  10996. }]
  10997. };
  10998. dialogInstance = ui.dialog.custom(options);
  10999. return dialogInstance.show()
  11000. };
  11001. var $notify = null;
  11002. var notify = function(message, type, displayTime) {
  11003. var options = $.isPlainObject(message) ? message : {message: message};
  11004. if (!ui.dxToast) {
  11005. alert(options.message);
  11006. return
  11007. }
  11008. if (options.hiddenAction) {
  11009. DX.log("W0001", "Dialog", "hiddenAction", "14.2", "Use 'onHidden' option instead");
  11010. options.onHidden = options.hiddenAction
  11011. }
  11012. var userHiddenAction = options.onHidden;
  11013. $.extend(options, {
  11014. type: type,
  11015. displayTime: displayTime,
  11016. onHidden: function(args) {
  11017. args.element.remove();
  11018. new DX.Action(userHiddenAction, {context: args.model}).execute(arguments)
  11019. }
  11020. });
  11021. $notify = $("<div>").appendTo(DX.viewPort()).dxToast(options);
  11022. $notify.dxToast("instance").show()
  11023. };
  11024. $.extend(ui, {
  11025. notify: notify,
  11026. dialog: {
  11027. custom: dialog,
  11028. alert: alert,
  11029. confirm: confirm
  11030. }
  11031. });
  11032. ui.dialog.FakeDialogComponent = FakeDialogComponent
  11033. })(jQuery, DevExpress);
  11034. /*! Module core, file ui.dataHelper.js */
  11035. (function($, DX, undefined) {
  11036. var data = DX.data;
  11037. var DATA_SOURCE_OPTIONS_METHOD = "_dataSourceOptions",
  11038. DATA_SOURCE_CHANGED_METHOD = "_dataSourceChangedHandler",
  11039. DATA_SOURCE_LOAD_ERROR_METHOD = "_dataSourceLoadErrorHandler",
  11040. DATA_SOURCE_LOADING_CHANGED_METHOD = "_dataSourceLoadingChangedHandler";
  11041. DX.ui.DataHelperMixin = {
  11042. postCtor: function() {
  11043. this.on("disposing", function() {
  11044. this._disposeDataSource()
  11045. })
  11046. },
  11047. _isDataSourceReady: function() {
  11048. return !this._dataSource || this._dataSource.isLoaded()
  11049. },
  11050. _refreshDataSource: function() {
  11051. this._initDataSource();
  11052. this._loadDataSource()
  11053. },
  11054. _initDataSource: function() {
  11055. var dataSourceOptions = this.option("dataSource"),
  11056. widgetDataSourceOptions,
  11057. dataSourceType;
  11058. this._disposeDataSource();
  11059. if (dataSourceOptions) {
  11060. if (dataSourceOptions instanceof data.DataSource) {
  11061. this._isSharedDataSource = true;
  11062. this._dataSource = dataSourceOptions
  11063. }
  11064. else {
  11065. widgetDataSourceOptions = DATA_SOURCE_OPTIONS_METHOD in this ? this[DATA_SOURCE_OPTIONS_METHOD]() : {};
  11066. dataSourceType = this._dataSourceType ? this._dataSourceType() : data.DataSource;
  11067. this._dataSource = new dataSourceType($.extend(true, {}, widgetDataSourceOptions, data.utils.normalizeDataSourceOptions(dataSourceOptions)))
  11068. }
  11069. this._addDataSourceHandlers()
  11070. }
  11071. },
  11072. _addDataSourceHandlers: function() {
  11073. if (DATA_SOURCE_CHANGED_METHOD in this)
  11074. this._addDataSourceChangeHandler();
  11075. if (DATA_SOURCE_LOAD_ERROR_METHOD in this)
  11076. this._addDataSourceLoadErrorHandler();
  11077. if (DATA_SOURCE_LOADING_CHANGED_METHOD in this)
  11078. this._addDataSourceLoadingChangedHandler();
  11079. this._addReadyWatcher()
  11080. },
  11081. _addReadyWatcher: function() {
  11082. this._dataSource.on("loadingChanged", $.proxy(function(isLoading) {
  11083. this._ready && this._ready(!isLoading)
  11084. }, this))
  11085. },
  11086. _addDataSourceChangeHandler: function() {
  11087. var dataSource = this._dataSource;
  11088. this._proxiedDataSourceChangedHandler = $.proxy(function() {
  11089. this[DATA_SOURCE_CHANGED_METHOD](dataSource.items())
  11090. }, this);
  11091. dataSource.on("changed", this._proxiedDataSourceChangedHandler)
  11092. },
  11093. _addDataSourceLoadErrorHandler: function() {
  11094. this._proxiedDataSourceLoadErrorHandler = $.proxy(this[DATA_SOURCE_LOAD_ERROR_METHOD], this);
  11095. this._dataSource.on("loadError", this._proxiedDataSourceLoadErrorHandler)
  11096. },
  11097. _addDataSourceLoadingChangedHandler: function() {
  11098. this._proxiedDataSourceLoadingChangedHandler = $.proxy(this[DATA_SOURCE_LOADING_CHANGED_METHOD], this);
  11099. this._dataSource.on("loadingChanged", this._proxiedDataSourceLoadingChangedHandler)
  11100. },
  11101. _loadDataSource: function() {
  11102. if (this._dataSource) {
  11103. var dataSource = this._dataSource;
  11104. if (dataSource.isLoaded())
  11105. this._proxiedDataSourceChangedHandler && this._proxiedDataSourceChangedHandler();
  11106. else
  11107. dataSource.load()
  11108. }
  11109. },
  11110. _loadSingle: function(key, value) {
  11111. key = key === "this" ? this._dataSource.key() || "this" : key;
  11112. return this._dataSource.loadSingle(key, value)
  11113. },
  11114. _isLastPage: function() {
  11115. return !this._dataSource || this._dataSource.isLastPage() || !this._dataSource._pageSize
  11116. },
  11117. _isDataSourceLoading: function() {
  11118. return this._dataSource && this._dataSource.isLoading()
  11119. },
  11120. _disposeDataSource: function() {
  11121. if (this._dataSource) {
  11122. if (this._isSharedDataSource) {
  11123. delete this._isSharedDataSource;
  11124. this._proxiedDataSourceChangedHandler && this._dataSource.off("changed", this._proxiedDataSourceChangedHandler);
  11125. this._proxiedDataSourceLoadErrorHandler && this._dataSource.off("loadError", this._proxiedDataSourceLoadErrorHandler);
  11126. this._proxiedDataSourceLoadingChangedHandler && this._dataSource.off("loadingChanged", this._proxiedDataSourceLoadingChangedHandler)
  11127. }
  11128. else
  11129. this._dataSource.dispose();
  11130. delete this._dataSource;
  11131. delete this._proxiedDataSourceChangedHandler;
  11132. delete this._proxiedDataSourceLoadErrorHandler;
  11133. delete this._proxiedDataSourceLoadingChangedHandler
  11134. }
  11135. }
  11136. }
  11137. })(jQuery, DevExpress);
  11138. /*! Module core, file ui.dataExpression.js */
  11139. (function($, DX, undefined) {
  11140. var ui = DX.ui,
  11141. utils = DX.utils,
  11142. dataUtils = DX.data.utils;
  11143. ui.DataExpressionMixin = $.extend(ui.DataHelperMixin, {
  11144. _dataExpressionDeprecatedOptions: function() {
  11145. return {itemRender: {
  11146. since: "14.2",
  11147. alias: "itemTemplate"
  11148. }}
  11149. },
  11150. _dataExpressionDefaultOptions: function() {
  11151. return {
  11152. items: [],
  11153. dataSource: null,
  11154. itemTemplate: "item",
  11155. value: null,
  11156. valueExpr: "this",
  11157. displayExpr: undefined
  11158. }
  11159. },
  11160. _initDataExpressions: function() {
  11161. this._compileValueGetter();
  11162. this._compileDisplayGetter();
  11163. this._initDynamicTemplates();
  11164. this._initDataSource();
  11165. this._itemsToDataSource()
  11166. },
  11167. _itemsToDataSource: function() {
  11168. if (!this.option("dataSource"))
  11169. this._dataSource = new DevExpress.data.DataSource({
  11170. store: new DevExpress.data.ArrayStore(this.option("items")),
  11171. pageSize: 0
  11172. })
  11173. },
  11174. _compileDisplayGetter: function() {
  11175. this._displayGetter = dataUtils.compileGetter(this._displayGetterExpr())
  11176. },
  11177. _displayGetterExpr: function() {
  11178. return this.option("displayExpr")
  11179. },
  11180. _compileValueGetter: function() {
  11181. this._valueGetter = dataUtils.compileGetter(this._valueGetterExpr())
  11182. },
  11183. _valueGetterExpr: function() {
  11184. return this.option("valueExpr") || "this"
  11185. },
  11186. _loadValue: function(value) {
  11187. var deferred = $.Deferred();
  11188. value = this._unwrappedValue(value);
  11189. if (!utils.isDefined(value))
  11190. return deferred.reject().promise();
  11191. this._loadSingle(this._valueGetterExpr(), value).done($.proxy(function(item) {
  11192. this._isValueEquals(this._valueGetter(item), value) ? deferred.resolve(item) : deferred.reject()
  11193. }, this)).fail(function() {
  11194. deferred.reject()
  11195. });
  11196. return deferred.promise()
  11197. },
  11198. _unwrappedValue: function(value) {
  11199. value = DX.utils.isDefined(value) ? value : this.option("value");
  11200. if (value && this._dataSource && this._valueGetterExpr() === "this") {
  11201. var key = this._dataSource.key();
  11202. if (key && typeof value === "object")
  11203. value = value[key]
  11204. }
  11205. return utils.unwrapObservable(value)
  11206. },
  11207. _isValueEquals: function(value1, value2) {
  11208. var isDefined = utils.isDefined;
  11209. var ensureDefined = utils.ensureDefined;
  11210. var unwrapObservable = utils.unwrapObservable;
  11211. var dataSourceKey = this._dataSource && this._dataSource.key();
  11212. var result = this._compareValues(value1, value2);
  11213. if (!result && isDefined(value1) && isDefined(value2) && dataSourceKey) {
  11214. var valueKey1 = ensureDefined(unwrapObservable(value1[dataSourceKey]), value1);
  11215. var valueKey2 = ensureDefined(unwrapObservable(value2[dataSourceKey]), value2);
  11216. result = this._compareValues(valueKey1, valueKey2)
  11217. }
  11218. return result
  11219. },
  11220. _compareValues: function(value1, value2) {
  11221. return dataUtils.toComparable(value1) === dataUtils.toComparable(value2)
  11222. },
  11223. _initDynamicTemplates: function() {
  11224. if (this._displayGetterExpr())
  11225. this._dynamicTemplates["item"] = new ui.DefaultTemplate($.proxy(function(data) {
  11226. return this._displayGetter(data)
  11227. }, this));
  11228. else
  11229. delete this._dynamicTemplates["item"]
  11230. },
  11231. _setCollectionWidgetItemTemplate: function() {
  11232. this._initDynamicTemplates();
  11233. this._setCollectionWidgetOption("itemTemplate", this._getTemplateByOption("itemTemplate"))
  11234. },
  11235. _dataExpressionOptionChanged: function(args) {
  11236. switch (args.name) {
  11237. case"items":
  11238. this._itemsToDataSource();
  11239. this._setCollectionWidgetOption("items");
  11240. break;
  11241. case"dataSource":
  11242. this._initDataSource();
  11243. break;
  11244. case"itemTemplate":
  11245. this._setCollectionWidgetItemTemplate();
  11246. break;
  11247. case"valueExpr":
  11248. this._compileValueGetter();
  11249. break;
  11250. case"displayExpr":
  11251. this._compileDisplayGetter();
  11252. this._setCollectionWidgetItemTemplate();
  11253. break
  11254. }
  11255. }
  11256. })
  11257. })(jQuery, DevExpress);
  11258. /*! Module core, file ui.events.pointer.touchHooks.js */
  11259. (function($, DX, undefined) {
  11260. var touchEventHook = {
  11261. filter: function(event, originalEvent) {
  11262. var touches = originalEvent.touches.length ? originalEvent.touches : originalEvent.changedTouches;
  11263. $.each(["pageX", "pageY", "screenX", "screenY", "clientX", "clientY"], function() {
  11264. event[this] = touches[0][this]
  11265. });
  11266. return event
  11267. },
  11268. props: $.event.mouseHooks.props.concat(["touches", "changedTouches", "targetTouches", "detail", "result", "originalTarget", "charCode", "prevValue"])
  11269. };
  11270. $.each(["touchstart", "touchmove", "touchend", "touchcancel"], function() {
  11271. $.event.fixHooks[this] = touchEventHook
  11272. })
  11273. })(jQuery, DevExpress);
  11274. /*! Module core, file ui.events.pointer.mspointerHooks.js */
  11275. (function($, DX, undefined) {
  11276. var POINTER_TYPE_MAP = {
  11277. 2: "touch",
  11278. 3: "pen",
  11279. 4: "mouse"
  11280. };
  11281. var pointerEventHook = {
  11282. filter: function(event, originalEvent) {
  11283. var pointerType = originalEvent.pointerType;
  11284. if ($.isNumeric(pointerType))
  11285. event.pointerType = POINTER_TYPE_MAP[pointerType];
  11286. return event
  11287. },
  11288. props: $.event.mouseHooks.props.concat(["pointerId", "pointerType", "originalTarget", "width", "height", "pressure", "result", "tiltX", "charCode", "tiltY", "detail", "isPrimary", "prevValue"])
  11289. };
  11290. $.each(["MSPointerDown", "MSPointerMove", "MSPointerUp", "MSPointerCancel", "MSPointerOver", "MSPointerOut", "mouseenter", "mouseleave", "pointerdown", "pointermove", "pointerup", "pointercancel", "pointerover", "pointerout", "pointerenter", "pointerleave"], function() {
  11291. $.event.fixHooks[this] = pointerEventHook
  11292. })
  11293. })(jQuery, DevExpress);
  11294. /*! Module core, file ui.events.pointer.base.js */
  11295. (function($, DX, undefined) {
  11296. var ui = DX.ui,
  11297. events = ui.events;
  11298. var POINTER_EVENTS_NAMESPACE = "dxPointerEvents";
  11299. var BaseStrategy = DX.Class.inherit({
  11300. ctor: function(eventName, originalEvents) {
  11301. this._eventName = eventName;
  11302. this._eventNamespace = [POINTER_EVENTS_NAMESPACE, ".", this._eventName].join("");
  11303. this._originalEvents = originalEvents;
  11304. this._handlerCount = 0;
  11305. this.noBubble = this._isNoBubble()
  11306. },
  11307. _isNoBubble: function() {
  11308. var eventName = this._eventName;
  11309. return eventName === "dxpointerenter" || eventName === "dxpointerleave"
  11310. },
  11311. _handler: function(e) {
  11312. var delegateTarget = this._getDelegateTarget(e);
  11313. return this._fireEvent({
  11314. type: this._eventName,
  11315. pointerType: e.pointerType || events.eventSource(e),
  11316. originalEvent: e,
  11317. delegateTarget: delegateTarget
  11318. })
  11319. },
  11320. _getDelegateTarget: function(e) {
  11321. var delegateTarget;
  11322. if (this.noBubble)
  11323. delegateTarget = e.delegateTarget;
  11324. return delegateTarget
  11325. },
  11326. _fireEvent: function(args) {
  11327. return events.fireEvent(args)
  11328. },
  11329. setup: function() {
  11330. return true
  11331. },
  11332. add: function(element, handleObj) {
  11333. if (this._handlerCount <= 0 || this.noBubble) {
  11334. this._selector = handleObj.selector;
  11335. element = this.noBubble ? element : document;
  11336. $(element).on(events.addNamespace(this._originalEvents, this._eventNamespace), this._selector, $.proxy(this._handler, this))
  11337. }
  11338. if (!this.noBubble)
  11339. this._handlerCount++
  11340. },
  11341. remove: function(element) {
  11342. if (!this.noBubble)
  11343. this._handlerCount--
  11344. },
  11345. teardown: function(element) {
  11346. if (this._handlerCount && !this.noBubble)
  11347. return;
  11348. element = this.noBubble ? element : document;
  11349. $(element).off("." + this._eventNamespace, this._selector)
  11350. },
  11351. dispose: function(element) {
  11352. element = this.noBubble ? element : document;
  11353. $(element).off("." + this._eventNamespace)
  11354. }
  11355. });
  11356. events.pointer = {};
  11357. events.pointer.BaseStrategy = BaseStrategy
  11358. })(jQuery, DevExpress);
  11359. /*! Module core, file ui.events.pointer.mouse.js */
  11360. (function($, DX, undefined) {
  11361. var ui = DX.ui,
  11362. events = ui.events,
  11363. pointer = events.pointer;
  11364. var MouseStrategyEventMap = {
  11365. dxpointerdown: "mousedown",
  11366. dxpointermove: "mousemove",
  11367. dxpointerup: "mouseup",
  11368. dxpointercancel: "",
  11369. dxpointerover: "mouseover",
  11370. dxpointerout: "mouseout",
  11371. dxpointerenter: "mouseenter",
  11372. dxpointerleave: "mouseleave"
  11373. };
  11374. var normalizeMouseEvent = function(e) {
  11375. var pointers = [];
  11376. e.pointerId = 1;
  11377. if (e.type !== "mouseup")
  11378. pointers.push(e);
  11379. return {
  11380. pointers: pointers,
  11381. pointerId: 1
  11382. }
  11383. };
  11384. var MouseStrategy = pointer.BaseStrategy.inherit({_fireEvent: function(args) {
  11385. return this.callBase($.extend(normalizeMouseEvent(args.originalEvent), args))
  11386. }});
  11387. pointer.mouse = {
  11388. strategy: MouseStrategy,
  11389. map: MouseStrategyEventMap,
  11390. normalize: normalizeMouseEvent
  11391. }
  11392. })(jQuery, DevExpress);
  11393. /*! Module core, file ui.events.pointer.touch.js */
  11394. (function($, DX, undefined) {
  11395. var ui = DX.ui,
  11396. device = $.proxy(DX.devices.real, DX.devices),
  11397. events = ui.events,
  11398. pointer = events.pointer;
  11399. var TouchStrategyEventMap = {
  11400. dxpointerdown: "touchstart",
  11401. dxpointermove: "touchmove",
  11402. dxpointerup: "touchend",
  11403. dxpointercancel: "touchcancel"
  11404. };
  11405. var normalizeTouchEvent = function(e) {
  11406. var pointers = [];
  11407. $.each(e.touches, function(_, touch) {
  11408. pointers.push($.extend({pointerId: touch.identifier}, touch))
  11409. });
  11410. return {
  11411. pointers: pointers,
  11412. pointerId: e.changedTouches[0].identifier
  11413. }
  11414. };
  11415. var skipTouchWithSameIdentifier = function(pointerEvent) {
  11416. return device().platform === "ios" && (pointerEvent === "dxpointerdown" || pointerEvent === "dxpointerup")
  11417. };
  11418. var TouchStrategy = pointer.BaseStrategy.inherit({
  11419. ctor: function() {
  11420. this.callBase.apply(this, arguments);
  11421. this._pointerId = 0
  11422. },
  11423. _handler: function(e) {
  11424. if (skipTouchWithSameIdentifier(this._eventName)) {
  11425. var touch = e.changedTouches[0];
  11426. if (this._pointerId === touch.identifier && this._pointerId !== 0)
  11427. return;
  11428. this._pointerId = touch.identifier
  11429. }
  11430. return this.callBase.apply(this, arguments)
  11431. },
  11432. _fireEvent: function(args) {
  11433. return this.callBase($.extend(normalizeTouchEvent(args.originalEvent), args))
  11434. }
  11435. });
  11436. pointer.touch = {
  11437. strategy: TouchStrategy,
  11438. map: TouchStrategyEventMap,
  11439. normalize: normalizeTouchEvent
  11440. }
  11441. })(jQuery, DevExpress);
  11442. /*! Module core, file ui.events.pointer.mouseAndTouch.js */
  11443. (function($, DX, undefined) {
  11444. var ui = DX.ui,
  11445. events = ui.events,
  11446. pointer = events.pointer;
  11447. var MouseAndTouchStrategyEventMap = {
  11448. dxpointerdown: "touchstart mousedown",
  11449. dxpointermove: "touchmove mousemove",
  11450. dxpointerup: "touchend mouseup",
  11451. dxpointercancel: "touchcancel",
  11452. dxpointerover: "mouseover",
  11453. dxpointerout: "mouseout",
  11454. dxpointerenter: "mouseenter",
  11455. dxpointerleave: "mouseleave"
  11456. };
  11457. var MouseAndTouchStrategy = pointer.BaseStrategy.inherit({
  11458. EVENT_LOCK_TIMEOUT: 100,
  11459. _handler: function(e) {
  11460. var isMouseEvent = events.isMouseEvent(e);
  11461. if (!isMouseEvent)
  11462. this._skipNextEvents = true;
  11463. if (isMouseEvent && this._mouseLocked)
  11464. return;
  11465. if (isMouseEvent && this._skipNextEvents) {
  11466. this._skipNextEvents = false;
  11467. this._mouseLocked = true;
  11468. clearTimeout(this._unlockMouseTimer);
  11469. this._unlockMouseTimer = setTimeout($.proxy(function() {
  11470. this._mouseLocked = false
  11471. }, this), this.EVENT_LOCK_TIMEOUT);
  11472. return
  11473. }
  11474. return this.callBase(e)
  11475. },
  11476. _fireEvent: function(args) {
  11477. var isMouseEvent = events.isMouseEvent(args.originalEvent),
  11478. normalizer = isMouseEvent ? pointer.mouse.normalize : pointer.touch.normalize;
  11479. return this.callBase($.extend(normalizer(args.originalEvent), args))
  11480. },
  11481. dispose: function() {
  11482. this.callBase();
  11483. this._skipNextEvents = false;
  11484. this._mouseLocked = false;
  11485. clearTimeout(this._unlockMouseTimer)
  11486. }
  11487. });
  11488. pointer.mouseAndTouch = {
  11489. strategy: MouseAndTouchStrategy,
  11490. map: MouseAndTouchStrategyEventMap
  11491. }
  11492. })(jQuery, DevExpress);
  11493. /*! Module core, file ui.events.pointer.mspointer.js */
  11494. (function($, DX, undefined) {
  11495. var ui = DX.ui,
  11496. events = ui.events,
  11497. pointer = events.pointer;
  11498. var MsPointerStrategyEventMap = {
  11499. dxpointerdown: "MSPointerDown pointerdown",
  11500. dxpointermove: "MSPointerMove pointermove",
  11501. dxpointerup: "MSPointerUp pointerup",
  11502. dxpointercancel: "MSPointerCancel pointercancel",
  11503. dxpointerover: "MSPointerOver pointerover",
  11504. dxpointerout: "MSPointerOut pointerout",
  11505. dxpointerenter: "mouseenter",
  11506. dxpointerleave: "mouseleave"
  11507. };
  11508. var pointers = [];
  11509. var getPointerIndex = function(e) {
  11510. var index = -1;
  11511. $.each(pointers, function(i, pointer) {
  11512. if (e.pointerId === pointer.pointerId) {
  11513. index = i;
  11514. return true
  11515. }
  11516. });
  11517. return index
  11518. };
  11519. var addPointer = function(e) {
  11520. if (getPointerIndex(e) === -1)
  11521. pointers.push(e)
  11522. };
  11523. var removePointer = function(e) {
  11524. pointers.splice(getPointerIndex(e), 1)
  11525. };
  11526. var updatePointer = function(e) {
  11527. pointers[getPointerIndex(e)] = e
  11528. };
  11529. var addEventsListner = function(events, handler) {
  11530. events = events.split(" ");
  11531. $.each(events, function(_, event) {
  11532. document.addEventListener(event, handler, true)
  11533. })
  11534. };
  11535. var activateMspointerStrategy = function() {
  11536. var eventMap = MsPointerStrategyEventMap;
  11537. addEventsListner(eventMap.dxpointerdown, addPointer);
  11538. addEventsListner(eventMap.dxpointermove, updatePointer);
  11539. addEventsListner(eventMap.dxpointerup, removePointer);
  11540. addEventsListner(eventMap.dxpointercancel, removePointer);
  11541. activateMspointerStrategy = $.noop
  11542. };
  11543. var MsPointerStrategy = pointer.BaseStrategy.inherit({
  11544. ctor: function() {
  11545. this.callBase.apply(this, arguments);
  11546. activateMspointerStrategy()
  11547. },
  11548. _fireEvent: function(args) {
  11549. return this.callBase($.extend({
  11550. pointers: pointers,
  11551. pointerId: args.originalEvent.pointerId
  11552. }, args))
  11553. }
  11554. });
  11555. pointer.msPointer = {
  11556. strategy: MsPointerStrategy,
  11557. map: MsPointerStrategyEventMap
  11558. };
  11559. DX.ui.events.__internals = DX.ui.events.__internals || {};
  11560. $.extend(DX.ui.events.__internals, {cleanMsPointers: function() {
  11561. pointers = []
  11562. }})
  11563. })(jQuery, DevExpress);
  11564. /*! Module core, file ui.events.pointer.js */
  11565. (function($, DX, undefined) {
  11566. var ui = DX.ui,
  11567. support = DX.support,
  11568. device = $.proxy(DX.devices.real, DX.devices),
  11569. events = ui.events,
  11570. pointer = events.pointer;
  11571. var eventType = function() {
  11572. if (support.pointer)
  11573. return pointer.msPointer;
  11574. if (support.touch && !(device().tablet || device().phone))
  11575. return pointer.mouseAndTouch;
  11576. if (support.touch)
  11577. return pointer.touch;
  11578. return pointer.mouse
  11579. }();
  11580. $.each(eventType.map, function(pointerEvent, originalEvents) {
  11581. events.registerEvent(pointerEvent, new eventType.strategy(pointerEvent, originalEvents))
  11582. })
  11583. })(jQuery, DevExpress);
  11584. /*! Module core, file ui.events.wheel.js */
  11585. (function($, DX, undefined) {
  11586. var ui = DX.ui,
  11587. events = ui.events;
  11588. var EVENT_NAME = "dxmousewheel",
  11589. EVENT_NAMESPACE = "dxWheel";
  11590. $.event.fixHooks["wheel"] = $.event.mouseHooks;
  11591. var wheelEvent = document.onmousewheel !== undefined ? "mousewheel" : "wheel";
  11592. var wheel = {
  11593. setup: function(element, data) {
  11594. var $element = $(element);
  11595. $element.on(events.addNamespace(wheelEvent, EVENT_NAMESPACE), $.proxy(wheel._wheelHandler, wheel))
  11596. },
  11597. teardown: function(element) {
  11598. var $element = $(element);
  11599. $element.off("." + EVENT_NAMESPACE)
  11600. },
  11601. _wheelHandler: function(e) {
  11602. var delta = this._getWheelDelta(e.originalEvent);
  11603. events.fireEvent({
  11604. type: EVENT_NAME,
  11605. originalEvent: e,
  11606. delta: delta,
  11607. pointerType: "mouse"
  11608. });
  11609. e.stopPropagation()
  11610. },
  11611. _getWheelDelta: function(event) {
  11612. return event.wheelDelta ? event.wheelDelta : -event.deltaY * 30
  11613. }
  11614. };
  11615. events.registerEvent(EVENT_NAME, wheel)
  11616. })(jQuery, DevExpress);
  11617. /*! Module core, file ui.events.hover.js */
  11618. (function($, DX, undefined) {
  11619. var ui = DX.ui,
  11620. events = ui.events;
  11621. var HOVERSTART_NAMESPACE = "dxHoverStart",
  11622. HOVERSTART = "dxhoverstart",
  11623. POINTERENTER_NAMESPACED_EVENT_NAME = events.addNamespace("dxpointerenter", HOVERSTART_NAMESPACE),
  11624. POINTERDOWN_NAMESPACED_EVENT_NAME = events.addNamespace("dxpointerdown", HOVERSTART_NAMESPACE),
  11625. POINTERUP_NAMESPACED_EVENT_NAME = events.addNamespace("dxpointerup", HOVERSTART_NAMESPACE),
  11626. HOVEREND_NAMESPACE = "dxHoverEnd",
  11627. HOVEREND = "dxhoverend",
  11628. POINTERLEAVE_NAMESPACED_EVENT_NAME = events.addNamespace("dxpointerleave", HOVEREND_NAMESPACE);
  11629. var Hover = DX.Class.inherit({
  11630. noBubble: true,
  11631. add: function(element, handleObj) {
  11632. var $element = $(element);
  11633. $element.off("." + this._namespace).on(this._originalEventName, handleObj.selector, $.proxy(this._handler, this))
  11634. },
  11635. _handler: function(e) {
  11636. if (events.isTouchEvent(e))
  11637. return;
  11638. events.fireEvent({
  11639. type: this._eventName,
  11640. originalEvent: e,
  11641. delegateTarget: e.delegateTarget
  11642. })
  11643. },
  11644. teardown: function(element) {
  11645. $(element).off("." + this._namespace)
  11646. }
  11647. });
  11648. var HoverStart = Hover.inherit({
  11649. ctor: function() {
  11650. this._eventName = HOVERSTART;
  11651. this._originalEventName = POINTERENTER_NAMESPACED_EVENT_NAME;
  11652. this._namespace = HOVERSTART_NAMESPACE;
  11653. this._isMouseDown = false;
  11654. this._eventsAttached = 0
  11655. },
  11656. _handler: function(e) {
  11657. if (!this._isMouseDown)
  11658. this.callBase.apply(this, arguments)
  11659. },
  11660. setup: function() {
  11661. $(document).off("." + HOVERSTART_NAMESPACE).on(POINTERDOWN_NAMESPACED_EVENT_NAME, $.proxy(function() {
  11662. this._isMouseDown = true
  11663. }, this)).on(POINTERUP_NAMESPACED_EVENT_NAME, $.proxy(function() {
  11664. this._isMouseDown = false
  11665. }, this));
  11666. this._eventsAttached++
  11667. },
  11668. teardown: function() {
  11669. this._eventsAttached--;
  11670. if (this._eventsAttached === 0)
  11671. $(document).off("." + HOVERSTART_NAMESPACE)
  11672. }
  11673. });
  11674. var HoverEnd = Hover.inherit({ctor: function() {
  11675. this._eventName = HOVEREND;
  11676. this._originalEventName = POINTERLEAVE_NAMESPACED_EVENT_NAME;
  11677. this._namespace = HOVEREND_NAMESPACE
  11678. }});
  11679. events.registerEvent(HOVERSTART, new HoverStart);
  11680. events.registerEvent(HOVEREND, new HoverEnd)
  11681. })(jQuery, DevExpress);
  11682. /*! Module core, file ui.events.manager.js */
  11683. (function($, DX, undefined) {
  11684. var ui = DX.ui,
  11685. events = ui.events;
  11686. var MANAGER_EVENT = "dxEventManager",
  11687. EMITTER_DATA = "dxEmitter";
  11688. var EventManager = DX.Class.inherit({
  11689. ctor: function() {
  11690. this._attachHandlers();
  11691. this.reset();
  11692. this._proxiedCancelHandler = $.proxy(this._cancelHandler, this);
  11693. this._proxiedAcceptHandler = $.proxy(this._acceptHandler, this)
  11694. },
  11695. _attachHandlers: function() {
  11696. $(document).on(events.addNamespace("dxpointerdown", MANAGER_EVENT), $.proxy(this._pointerDownHandler, this)).on(events.addNamespace("dxpointermove", MANAGER_EVENT), $.proxy(this._pointerMoveHandler, this)).on(events.addNamespace("dxpointerup dxpointercancel", MANAGER_EVENT), $.proxy(this._pointerUpHandler, this)).on(events.addNamespace("dxmousewheel", MANAGER_EVENT), $.proxy(this._mouseWheelHandler, this))
  11697. },
  11698. _eachEmitter: function(callback) {
  11699. var activeEmitters = this._activeEmitters || [];
  11700. var i = 0;
  11701. while (activeEmitters.length > i) {
  11702. var emitter = activeEmitters[i];
  11703. if (callback(emitter) === false)
  11704. break;
  11705. if (activeEmitters[i] === emitter)
  11706. i++
  11707. }
  11708. },
  11709. _applyToEmitters: function(method, arg) {
  11710. this._eachEmitter(function(emitter) {
  11711. emitter[method].call(emitter, arg)
  11712. })
  11713. },
  11714. reset: function() {
  11715. this._eachEmitter(this._proxiedCancelHandler);
  11716. this._activeEmitters = []
  11717. },
  11718. resetEmitter: function(emitter) {
  11719. this._proxiedCancelHandler(emitter)
  11720. },
  11721. _pointerDownHandler: function(e) {
  11722. if (events.isMouseEvent(e) && e.which > 1)
  11723. return;
  11724. this._updateEmitters(e)
  11725. },
  11726. _updateEmitters: function(e) {
  11727. if (!this._isSetChanged(e))
  11728. return;
  11729. this._cleanEmitters(e);
  11730. this._fetchEmitters(e)
  11731. },
  11732. _isSetChanged: function(e) {
  11733. var currentSet = this._closestEmitter(e);
  11734. var previousSet = this._emittersSet || [];
  11735. var setChanged = currentSet.length !== previousSet.length;
  11736. $.each(currentSet, function(index, emitter) {
  11737. setChanged = setChanged || previousSet[index] !== emitter;
  11738. return !setChanged
  11739. });
  11740. this._emittersSet = currentSet;
  11741. return setChanged
  11742. },
  11743. _closestEmitter: function(e) {
  11744. var that = this,
  11745. result = [],
  11746. $element = $(e.target);
  11747. function handleEmitter(_, emitter) {
  11748. if (!!emitter && emitter.validatePointers(e) && emitter.validate(e)) {
  11749. emitter.addCancelCallback(that._proxiedCancelHandler);
  11750. emitter.addAcceptCallback(that._proxiedAcceptHandler);
  11751. result.push(emitter)
  11752. }
  11753. }
  11754. while ($element.length) {
  11755. var emitters = $.data($element.get(0), EMITTER_DATA) || [];
  11756. $.each(emitters, handleEmitter);
  11757. $element = $element.parent()
  11758. }
  11759. return result
  11760. },
  11761. _acceptHandler: function(acceptedEmitter, e) {
  11762. var that = this;
  11763. this._eachEmitter(function(emitter) {
  11764. if (emitter !== acceptedEmitter)
  11765. that._cancelEmitter(emitter, e)
  11766. })
  11767. },
  11768. _cancelHandler: function(canceledEmitter, e) {
  11769. this._cancelEmitter(canceledEmitter, e)
  11770. },
  11771. _cancelEmitter: function(emitter, e) {
  11772. var activeEmitters = this._activeEmitters;
  11773. if (e)
  11774. emitter.cancel(e);
  11775. else
  11776. emitter.reset();
  11777. emitter.removeCancelCallback();
  11778. emitter.removeAcceptCallback();
  11779. var emitterIndex = $.inArray(emitter, activeEmitters);
  11780. if (emitterIndex > -1)
  11781. activeEmitters.splice(emitterIndex, 1)
  11782. },
  11783. _cleanEmitters: function(e) {
  11784. this._applyToEmitters("end", e);
  11785. this.reset(e)
  11786. },
  11787. _fetchEmitters: function(e) {
  11788. this._activeEmitters = this._emittersSet.slice();
  11789. this._applyToEmitters("start", e)
  11790. },
  11791. _pointerMoveHandler: function(e) {
  11792. this._applyToEmitters("move", e)
  11793. },
  11794. _pointerUpHandler: function(e) {
  11795. this._updateEmitters(e)
  11796. },
  11797. _mouseWheelHandler: function(e) {
  11798. var allowInterruption = true;
  11799. this._eachEmitter(function(emitter) {
  11800. allowInterruption = emitter.allowInterruptionByMousewheel() && allowInterruption;
  11801. return allowInterruption
  11802. });
  11803. if (!allowInterruption)
  11804. return;
  11805. e.pointers = [null];
  11806. this._pointerDownHandler(e);
  11807. this._eachEmitter(function(emitter) {
  11808. var direction = emitter.getDirection ? emitter.getDirection(e) : "",
  11809. prop = direction !== "horizontal" ? "pageY" : "pageX";
  11810. if (direction)
  11811. e[prop] += e.delta;
  11812. return !direction
  11813. });
  11814. this._pointerMoveHandler(e);
  11815. e.pointers = [];
  11816. this._pointerUpHandler(e)
  11817. },
  11818. isActive: function(element) {
  11819. var result = false;
  11820. this._eachEmitter(function(emitter) {
  11821. result = result || emitter.getElement().is(element)
  11822. });
  11823. return result
  11824. }
  11825. });
  11826. var eventManager = new EventManager;
  11827. var EMITTER_SUBSCRIPTION_DATA = "dxEmitterSubscription";
  11828. var registerEmitter = function(emitterConfig) {
  11829. var emitterClass = emitterConfig.emitter,
  11830. emitterName = emitterConfig.events[0],
  11831. emitterEvents = emitterConfig.events;
  11832. $.each(emitterEvents, function(_, eventName) {
  11833. events.registerEvent(eventName, {
  11834. noBubble: !emitterConfig.bubble,
  11835. setup: function(element, data) {
  11836. var subscriptions = $.data(element, EMITTER_SUBSCRIPTION_DATA) || {},
  11837. emitters = $.data(element, EMITTER_DATA) || {},
  11838. emitter = emitters[emitterName] || new emitterClass(element);
  11839. subscriptions[eventName] = true;
  11840. emitters[emitterName] = emitter;
  11841. $.data(element, EMITTER_DATA, emitters);
  11842. $.data(element, EMITTER_SUBSCRIPTION_DATA, subscriptions)
  11843. },
  11844. add: function(element, handleObj) {
  11845. var emitters = $.data(element, EMITTER_DATA),
  11846. emitter = emitters[emitterName];
  11847. emitter.configurate($.extend({delegateSelector: handleObj.selector}, handleObj.data), handleObj.type)
  11848. },
  11849. teardown: function(element) {
  11850. var subscriptions = $.data(element, EMITTER_SUBSCRIPTION_DATA),
  11851. emitters = $.data(element, EMITTER_DATA),
  11852. emitter = emitters[emitterName];
  11853. delete subscriptions[eventName];
  11854. var disposeEmitter = true;
  11855. $.each(emitterEvents, function(_, eventName) {
  11856. disposeEmitter = disposeEmitter && !subscriptions[eventName];
  11857. return disposeEmitter
  11858. });
  11859. if (disposeEmitter) {
  11860. if (eventManager.isActive(element))
  11861. eventManager.resetEmitter(emitter);
  11862. emitter && emitter.dispose();
  11863. delete emitters[emitterName]
  11864. }
  11865. }
  11866. })
  11867. })
  11868. };
  11869. $.extend(events, {registerEmitter: registerEmitter})
  11870. })(jQuery, DevExpress);
  11871. /*! Module core, file ui.events.emitter.js */
  11872. (function($, DX, undefined) {
  11873. var ui = DX.ui,
  11874. events = ui.events;
  11875. var Emitter = DX.Class.inherit({
  11876. ctor: function(element) {
  11877. this._$element = $(element);
  11878. this._cancelCallback = $.Callbacks();
  11879. this._acceptCallback = $.Callbacks()
  11880. },
  11881. getElement: function() {
  11882. return this._$element
  11883. },
  11884. validate: function(e) {
  11885. return e.type !== "dxmousewheel"
  11886. },
  11887. validatePointers: function(e) {
  11888. return events.hasTouches(e) === 1
  11889. },
  11890. allowInterruptionByMousewheel: function() {
  11891. return true
  11892. },
  11893. configurate: function(data) {
  11894. $.extend(this, data)
  11895. },
  11896. addCancelCallback: function(callback) {
  11897. this._cancelCallback.add(callback)
  11898. },
  11899. removeCancelCallback: function() {
  11900. this._cancelCallback.empty()
  11901. },
  11902. _cancel: function(e) {
  11903. this._cancelCallback.fire(this, e)
  11904. },
  11905. addAcceptCallback: function(callback) {
  11906. this._acceptCallback.add(callback)
  11907. },
  11908. removeAcceptCallback: function() {
  11909. this._acceptCallback.empty()
  11910. },
  11911. _accept: function(e) {
  11912. this._acceptCallback.fire(this, e)
  11913. },
  11914. _requestAccept: function(e) {
  11915. this._acceptRequestEvent = e
  11916. },
  11917. _forgetAccept: function() {
  11918. this._accept(this._acceptRequestEvent);
  11919. this._acceptRequestEvent = null
  11920. },
  11921. start: $.noop,
  11922. move: $.noop,
  11923. end: $.noop,
  11924. cancel: $.noop,
  11925. reset: function() {
  11926. if (this._acceptRequestEvent)
  11927. this._accept(this._acceptRequestEvent)
  11928. },
  11929. _fireEvent: function(eventName, e, params) {
  11930. var eventData = $.extend({
  11931. type: eventName,
  11932. originalEvent: e,
  11933. target: this._getEmitterTarget(e),
  11934. delegateTarget: this.getElement().get(0)
  11935. }, params);
  11936. e = events.fireEvent(eventData);
  11937. if (e.cancel)
  11938. this._cancel(e);
  11939. return e
  11940. },
  11941. _getEmitterTarget: function(e) {
  11942. return (this.delegateSelector ? $(e.target).closest(this.delegateSelector) : this.getElement()).get(0)
  11943. },
  11944. dispose: $.noop
  11945. });
  11946. $.extend(events, {Emitter: Emitter})
  11947. })(jQuery, DevExpress);
  11948. /*! Module core, file ui.events.emitter.feedback.js */
  11949. (function($, DX, undefined) {
  11950. var ui = DX.ui,
  11951. events = ui.events,
  11952. ACTIVE_EVENT_NAME = "dxactive",
  11953. INACTIVE_EVENT_NAME = "dxinactive",
  11954. ACTIVE_TIMEOUT = 30,
  11955. INACTIVE_TIMEOUT = 400;
  11956. var activeEmitter;
  11957. var FeedbackEmitter = events.Emitter.inherit({
  11958. configurate: function(data, eventName) {
  11959. switch (eventName) {
  11960. case ACTIVE_EVENT_NAME:
  11961. data.activeTimeout = data.timeout;
  11962. break;
  11963. case INACTIVE_EVENT_NAME:
  11964. data.inactiveTimeout = data.timeout;
  11965. break
  11966. }
  11967. this.callBase(data)
  11968. },
  11969. start: function(e) {
  11970. var element = this.getElement().get(0);
  11971. var activeElement = activeEmitter && activeEmitter.getElement().get(0);
  11972. var activeChildExists = $.contains(element, activeElement);
  11973. var childJustActivated = activeEmitter && activeEmitter._activeTimer !== null;
  11974. if (activeChildExists && childJustActivated)
  11975. this._cancel();
  11976. else {
  11977. if (activeEmitter)
  11978. activeEmitter._forceInactiveTimer();
  11979. activeEmitter = this;
  11980. var eventTarget = this._getEmitterTarget(e);
  11981. this._forceActiveTimer = $.proxy(this._fireActive, this, e, eventTarget);
  11982. this._forceInactiveTimer = $.proxy(this._fireInctive, this, e, eventTarget);
  11983. this._startActiveTimer(e)
  11984. }
  11985. },
  11986. cancel: function(e) {
  11987. this.end(e)
  11988. },
  11989. end: function(e) {
  11990. var skipTimers = e.type !== "dxpointerup";
  11991. if (skipTimers)
  11992. this._stopActiveTimer();
  11993. else
  11994. this._forceActiveTimer();
  11995. this._startInactiveTimer(e);
  11996. if (skipTimers)
  11997. this._forceInactiveTimer()
  11998. },
  11999. dispose: function() {
  12000. this._stopActiveTimer();
  12001. this._stopInactiveTimer();
  12002. this.callBase()
  12003. },
  12004. _startActiveTimer: function(e) {
  12005. var activeTimeout = "activeTimeout" in this ? this.activeTimeout : ACTIVE_TIMEOUT;
  12006. this._activeTimer = window.setTimeout(this._forceActiveTimer, activeTimeout)
  12007. },
  12008. _fireActive: function(e, eventTarget) {
  12009. this._stopActiveTimer();
  12010. this._fireEvent(ACTIVE_EVENT_NAME, e, {target: eventTarget})
  12011. },
  12012. _stopActiveTimer: function() {
  12013. clearTimeout(this._activeTimer);
  12014. this._activeTimer = null
  12015. },
  12016. _forceActiveTimer: $.noop,
  12017. _startInactiveTimer: function(e) {
  12018. var inactiveTimeout = "inactiveTimeout" in this ? this.inactiveTimeout : INACTIVE_TIMEOUT;
  12019. this._inactiveTimer = window.setTimeout(this._forceInactiveTimer, inactiveTimeout)
  12020. },
  12021. _fireInctive: function(e, eventTarget) {
  12022. this._stopInactiveTimer();
  12023. activeEmitter = null;
  12024. this._fireEvent(INACTIVE_EVENT_NAME, e, {target: eventTarget})
  12025. },
  12026. _stopInactiveTimer: function() {
  12027. clearTimeout(this._inactiveTimer);
  12028. this._inactiveTimer = null
  12029. },
  12030. _forceInactiveTimer: $.noop,
  12031. lockInactive: function() {
  12032. this._forceActiveTimer();
  12033. this._stopInactiveTimer();
  12034. activeEmitter = null;
  12035. this._cancel();
  12036. return this._forceInactiveTimer
  12037. }
  12038. });
  12039. ui.events = $.extend(ui.events, {lockFeedback: function(deferred) {
  12040. var lockInactive = activeEmitter ? activeEmitter.lockInactive() : $.noop;
  12041. $.when(deferred).always(lockInactive)
  12042. }});
  12043. events.registerEmitter({
  12044. emitter: FeedbackEmitter,
  12045. events: [ACTIVE_EVENT_NAME, INACTIVE_EVENT_NAME]
  12046. })
  12047. })(jQuery, DevExpress);
  12048. /*! Module core, file ui.events.emitter.click.js */
  12049. (function($, DX, wnd, undefined) {
  12050. var ui = DX.ui,
  12051. utils = DX.utils,
  12052. events = ui.events,
  12053. abs = Math.abs,
  12054. CLICK_EVENT_NAME = "dxclick",
  12055. TOUCH_BOUNDARY = 10;
  12056. var isInput = function(element) {
  12057. return $(element).is("input, textarea, select, button ,:focus, :focus *")
  12058. };
  12059. var misc = {requestAnimationFrame: DX.requestAnimationFrame};
  12060. var ClickEmitter = events.Emitter.inherit({
  12061. ctor: function(element) {
  12062. this.callBase(element);
  12063. this._makeElementClickable($(element))
  12064. },
  12065. _makeElementClickable: function($element) {
  12066. if (!$element.attr("onclick"))
  12067. $element.attr("onclick", "void(0)")
  12068. },
  12069. start: function(e) {
  12070. this._blurPrevented = e.dxPreventBlur;
  12071. this._startTarget = e.target;
  12072. this._startEventData = events.eventData(e)
  12073. },
  12074. end: function(e) {
  12075. if (this._eventOutOfElement(e, this.getElement().get(0)) || e.type === "dxpointercancel") {
  12076. this._cancel(e);
  12077. return
  12078. }
  12079. if (!isInput(e.target) && !this._blurPrevented)
  12080. utils.resetActiveElement();
  12081. this._accept(e);
  12082. misc.requestAnimationFrame($.proxy(function() {
  12083. this._fireClickEvent(e)
  12084. }, this))
  12085. },
  12086. _eventOutOfElement: function(e, element) {
  12087. var target = e.target,
  12088. targetChanged = !$.contains(element, target) && element !== target,
  12089. gestureDelta = events.eventDelta(events.eventData(e), this._startEventData),
  12090. boundsExceeded = abs(gestureDelta.x) > TOUCH_BOUNDARY || abs(gestureDelta.y) > TOUCH_BOUNDARY;
  12091. return targetChanged || boundsExceeded
  12092. },
  12093. _fireClickEvent: function(e) {
  12094. this._fireEvent(CLICK_EVENT_NAME, e, {target: utils.closestCommonParent(this._startTarget, e.target)})
  12095. }
  12096. });
  12097. (function() {
  12098. var useNativeClick = DX.devices.real().generic;
  12099. if (useNativeClick) {
  12100. var prevented = null;
  12101. ClickEmitter = ClickEmitter.inherit({
  12102. start: function() {
  12103. prevented = null
  12104. },
  12105. end: $.noop,
  12106. cancel: function() {
  12107. prevented = true
  12108. }
  12109. });
  12110. var clickHandler = function(e) {
  12111. if ((!e.which || e.which === 1) && !prevented)
  12112. events.fireEvent({
  12113. type: CLICK_EVENT_NAME,
  12114. originalEvent: e
  12115. })
  12116. };
  12117. $(document).on(events.addNamespace("click", "NATIVE_DXCLICK_STRATEGY"), clickHandler)
  12118. }
  12119. $.extend(events.__internals, {useNativeClick: useNativeClick})
  12120. })();
  12121. (function() {
  12122. var fixBuggyInertia = DX.devices.real().ios;
  12123. if (fixBuggyInertia) {
  12124. var GESTURE_LOCK_KEY = "dxGestureLock";
  12125. ClickEmitter = ClickEmitter.inherit({_fireClickEvent: function(e) {
  12126. var $element = $(e.target);
  12127. while ($element.length) {
  12128. if ($.data($element.get(0), GESTURE_LOCK_KEY))
  12129. return;
  12130. $element = $element.parent()
  12131. }
  12132. this.callBase.apply(this, arguments)
  12133. }})
  12134. }
  12135. $.extend(events.__internals, {fixBuggyInertia: fixBuggyInertia})
  12136. })();
  12137. (function() {
  12138. var desktopDevice = DX.devices.real().generic;
  12139. if (!desktopDevice) {
  12140. var startTarget = null,
  12141. blurPrevented = false;
  12142. var pointerDownHandler = function(e) {
  12143. startTarget = e.target;
  12144. blurPrevented = e.dxPreventBlur
  12145. };
  12146. var clickHandler = function(e) {
  12147. var $target = $(e.target);
  12148. if (!blurPrevented && startTarget && !$target.is(startTarget) && !$(startTarget).is("label") && isInput($target))
  12149. utils.resetActiveElement();
  12150. startTarget = null;
  12151. blurPrevented = false
  12152. };
  12153. var NATIVE_CLICK_FIXER_NAMESPACE = "NATIVE_CLICK_FIXER";
  12154. $(document).on(events.addNamespace("dxpointerdown", NATIVE_CLICK_FIXER_NAMESPACE), pointerDownHandler).on(events.addNamespace("click", NATIVE_CLICK_FIXER_NAMESPACE), clickHandler)
  12155. }
  12156. })();
  12157. events.registerEmitter({
  12158. emitter: ClickEmitter,
  12159. bubble: true,
  12160. events: [CLICK_EVENT_NAME]
  12161. });
  12162. $.extend(events.__internals, {
  12163. useFastClick: !events.__internals.useNativeClick && !events.__internals.fixBuggyInertia,
  12164. misc: misc
  12165. })
  12166. })(jQuery, DevExpress, window);
  12167. /*! Module core, file ui.events.emitter.hold.js */
  12168. (function($, DX, undefined) {
  12169. var ui = DX.ui,
  12170. events = ui.events,
  12171. abs = Math.abs,
  12172. HOLD_EVENT_NAME = "dxhold",
  12173. HOLD_TIMEOUT = 750,
  12174. TOUCH_BOUNDARY = 5;
  12175. var HoldEmitter = events.Emitter.inherit({
  12176. start: function(e) {
  12177. this._startEventData = events.eventData(e);
  12178. this._startTimer(e)
  12179. },
  12180. _startTimer: function(e) {
  12181. var holdTimeout = "timeout" in this ? this.timeout : HOLD_TIMEOUT;
  12182. this._holdTimer = setTimeout($.proxy(function() {
  12183. this._requestAccept(e);
  12184. this._fireEvent(HOLD_EVENT_NAME, e, {target: e.target});
  12185. this._forgetAccept()
  12186. }, this), holdTimeout)
  12187. },
  12188. move: function(e) {
  12189. if (this._touchWasMoved(e))
  12190. this._cancel(e)
  12191. },
  12192. _touchWasMoved: function(e) {
  12193. var delta = events.eventDelta(this._startEventData, events.eventData(e));
  12194. return abs(delta.x) > TOUCH_BOUNDARY || abs(delta.y) > TOUCH_BOUNDARY
  12195. },
  12196. end: function() {
  12197. this._stopTimer()
  12198. },
  12199. _stopTimer: function() {
  12200. clearTimeout(this._holdTimer)
  12201. },
  12202. cancel: function() {
  12203. this._stopTimer()
  12204. }
  12205. });
  12206. events.registerEmitter({
  12207. emitter: HoldEmitter,
  12208. bubble: true,
  12209. events: [HOLD_EVENT_NAME]
  12210. })
  12211. })(jQuery, DevExpress);
  12212. /*! Module core, file ui.events.emitter.gesture.js */
  12213. (function($, DX, undefined) {
  12214. var ui = DX.ui,
  12215. utils = DX.utils,
  12216. events = ui.events,
  12217. devices = DX.devices,
  12218. support = DX.support,
  12219. abs = Math.abs;
  12220. var SLEEP = 0,
  12221. INITED = 1,
  12222. STARTED = 2,
  12223. TOUCH_BOUNDARY = 10,
  12224. IMMEDIATE_TOUCH_BOUNDARY = 0,
  12225. IMMEDIATE_TIMEOUT = 180;
  12226. var isMousewheelEvent = function(e) {
  12227. return e && e.type === "dxmousewheel"
  12228. };
  12229. var GestureEmitter = events.Emitter.inherit({
  12230. configurate: function(data) {
  12231. this.getElement().css("msTouchAction", data.immediate ? "pinch-zoom" : "");
  12232. this.callBase(data)
  12233. },
  12234. allowInterruptionByMousewheel: function() {
  12235. return this._stage !== STARTED
  12236. },
  12237. getDirection: function() {
  12238. return this.direction
  12239. },
  12240. _cancel: function(e) {
  12241. this.callBase.apply(this, arguments);
  12242. this._togglePointerAddons(true);
  12243. this._stage = SLEEP
  12244. },
  12245. start: function(e) {
  12246. if (events.needSkipEvent(e)) {
  12247. this._cancel(e);
  12248. return
  12249. }
  12250. this._startEvent = events.createEvent(e);
  12251. this._startEventData = events.eventData(e);
  12252. this._prevEventData = this._startEventData;
  12253. this._stage = INITED;
  12254. this._init(e);
  12255. this._setupImmediateTimer()
  12256. },
  12257. _setupImmediateTimer: function() {
  12258. clearTimeout(this._immediateTimer);
  12259. this._immedeateAccepted = false;
  12260. if (!this.immediate)
  12261. return;
  12262. this._immediateTimer = setTimeout($.proxy(function() {
  12263. this._immedeateAccepted = true
  12264. }, this), IMMEDIATE_TIMEOUT)
  12265. },
  12266. move: function(e) {
  12267. if (this._stage === INITED && this._directionConfirmed(e)) {
  12268. this._stage = STARTED;
  12269. this._resetActiveElement();
  12270. this._togglePointerAddons(false, e);
  12271. this._clearSelection(e);
  12272. this._adjustStartEvent(e);
  12273. this._start(this._startEvent);
  12274. this._prevEventData = events.eventData(this._startEvent);
  12275. if (this._stage === SLEEP)
  12276. return;
  12277. this._requestAccept(e);
  12278. this._move(e);
  12279. this._forgetAccept()
  12280. }
  12281. else if (this._stage === STARTED)
  12282. this._move(e);
  12283. this._prevEventData = events.eventData(e)
  12284. },
  12285. _directionConfirmed: function(e) {
  12286. var touchBoundary = this._getTouchBoundary(e),
  12287. delta = events.eventDelta(this._startEventData, events.eventData(e)),
  12288. deltaX = abs(delta.x),
  12289. deltaY = abs(delta.y);
  12290. var horizontalMove = this._validateMove(touchBoundary, deltaX, deltaY),
  12291. verticalMove = this._validateMove(touchBoundary, deltaY, deltaX);
  12292. var direction = this.getDirection(e),
  12293. bothAccepted = direction === "both" && (horizontalMove || verticalMove),
  12294. horizontalAccepted = direction === "horizontal" && horizontalMove,
  12295. verticalAccepted = direction === "vertical" && verticalMove;
  12296. return bothAccepted || horizontalAccepted || verticalAccepted || this._immedeateAccepted
  12297. },
  12298. _validateMove: function(touchBoundary, mainAxis, crossAxis) {
  12299. return mainAxis && mainAxis >= touchBoundary && (this.immediate ? mainAxis >= crossAxis : true)
  12300. },
  12301. _getTouchBoundary: function(e) {
  12302. return this.immediate || isMousewheelEvent(e) ? IMMEDIATE_TOUCH_BOUNDARY : TOUCH_BOUNDARY
  12303. },
  12304. _adjustStartEvent: function(e) {
  12305. var touchBoundary = this._getTouchBoundary(e),
  12306. delta = events.eventDelta(this._startEventData, events.eventData(e));
  12307. this._startEvent.pageX += utils.sign(delta.x) * touchBoundary;
  12308. this._startEvent.pageY += utils.sign(delta.y) * touchBoundary
  12309. },
  12310. _resetActiveElement: function() {
  12311. if (devices.real().platform === "ios" && $(":focus", this.getElement()).length)
  12312. utils.resetActiveElement()
  12313. },
  12314. _togglePointerAddons: function(toggle, e) {
  12315. var isStarted = this._stage === STARTED;
  12316. if (isStarted) {
  12317. this._togglePointerInteration(toggle);
  12318. if (!isMousewheelEvent(e))
  12319. this._togglePointerCursor(toggle)
  12320. }
  12321. },
  12322. _togglePointerInteration: function(toggle) {
  12323. var isDesktop = devices.real().platform === "generic";
  12324. if (isDesktop) {
  12325. $("body").css("pointer-events", toggle ? "" : "none");
  12326. if (support.supportProp("user-select"))
  12327. $("body").css(support.styleProp("user-select"), toggle ? "" : "none")
  12328. }
  12329. },
  12330. _togglePointerCursor: function(toggle) {
  12331. if (toggle)
  12332. $("html").css("cursor", this._originalCursor);
  12333. else {
  12334. this._originalCursor = $("html").css("cursor");
  12335. $("html").css("cursor", this.getElement().css("cursor"))
  12336. }
  12337. },
  12338. _clearSelection: function(e) {
  12339. if (isMousewheelEvent(e) || events.isTouchEvent(e))
  12340. return;
  12341. utils.clearSelection()
  12342. },
  12343. end: function(e) {
  12344. this._togglePointerAddons(true, e);
  12345. if (this._stage === STARTED)
  12346. this._end(e);
  12347. else if (this._stage === INITED)
  12348. this._stop(e);
  12349. this._stage = SLEEP
  12350. },
  12351. dispose: function() {
  12352. clearTimeout(this._immediateTimer);
  12353. this.callBase.apply(this, arguments);
  12354. this._togglePointerAddons(true)
  12355. },
  12356. _init: $.noop,
  12357. _start: $.noop,
  12358. _move: $.noop,
  12359. _stop: $.noop,
  12360. _end: $.noop
  12361. });
  12362. $.extend(events, {GestureEmitter: GestureEmitter});
  12363. var ORIG_TOUCH_BOUNDARY = TOUCH_BOUNDARY;
  12364. $.extend(DX.ui.events.__internals, {
  12365. GESTURE_TOUCH_BOUNDARY: ORIG_TOUCH_BOUNDARY,
  12366. resetTouchBoundary: function() {
  12367. TOUCH_BOUNDARY = ORIG_TOUCH_BOUNDARY;
  12368. events.__internals.GESTURE_TOUCH_BOUNDARY = ORIG_TOUCH_BOUNDARY
  12369. },
  12370. cleanTouchBoundary: function() {
  12371. TOUCH_BOUNDARY = 0
  12372. }
  12373. })
  12374. })(jQuery, DevExpress);
  12375. /*! Module core, file ui.events.emitter.gesture.scroll.js */
  12376. (function($, DX, undefined) {
  12377. var ui = DX.ui,
  12378. events = ui.events;
  12379. var SCROLL_INIT_EVENT = "dxscrollinit",
  12380. SCROLL_START_EVENT = "dxscrollstart",
  12381. SCROLL_MOVE_EVENT = "dxscroll",
  12382. SCROLL_END_EVENT = "dxscrollend",
  12383. SCROLL_STOP_EVENT = "dxscrollstop",
  12384. SCROLL_CANCEL_EVENT = "dxscrollcancel",
  12385. INERTIA_TIMEOUT = 100,
  12386. VELOCITY_CALC_TIMEOUT = 200,
  12387. FRAME_DURATION = Math.round(1000 / 60),
  12388. GESTURE_LOCK_KEY = "dxGestureLock",
  12389. GESTURE_LOCK_TIMEOUT = 200,
  12390. NAMESPACED_SCROLL_EVENT = events.addNamespace("scroll", "dxScrollEmitter");
  12391. var ScrollEmitter = events.GestureEmitter.inherit({
  12392. ctor: function(element) {
  12393. this.callBase.apply(this, arguments);
  12394. this.direction = "both";
  12395. $.data(element, "scroll", $.proxy(this._treatScroll, this));
  12396. $(element).on(NAMESPACED_SCROLL_EVENT, $.proxy(this._treatScroll, this))
  12397. },
  12398. validate: function() {
  12399. return true
  12400. },
  12401. _domElement: function() {
  12402. return this.getElement().get(0)
  12403. },
  12404. _treatScroll: function() {
  12405. this._prepareGesture();
  12406. this._forgetGesture()
  12407. },
  12408. _prepareGesture: function() {
  12409. if (this._gestureEndTimer)
  12410. this._clearGestureTimer();
  12411. else
  12412. $.data(this._domElement(), GESTURE_LOCK_KEY, true)
  12413. },
  12414. _forgetGesture: function() {
  12415. var that = this;
  12416. this._gestureEndTimer = setTimeout(function() {
  12417. $.data(that._domElement(), GESTURE_LOCK_KEY, false);
  12418. that._gestureEndTimer = null
  12419. }, GESTURE_LOCK_TIMEOUT)
  12420. },
  12421. _init: function(e) {
  12422. if ($.data(this._domElement(), GESTURE_LOCK_KEY))
  12423. this._accept(e);
  12424. this._fireEvent(SCROLL_INIT_EVENT, e)
  12425. },
  12426. move: function(e) {
  12427. this.callBase.apply(this, arguments);
  12428. e.isScrollingEvent = this.isNative || e.isScrollingEvent
  12429. },
  12430. _start: function(e) {
  12431. this._savedEventData = events.eventData(e);
  12432. this._fireEvent(SCROLL_START_EVENT, e, {delta: events.eventDelta(this._savedEventData, events.eventData(e))})
  12433. },
  12434. _move: function(e) {
  12435. var currentEventData = events.eventData(e);
  12436. this._fireEvent(SCROLL_MOVE_EVENT, e, {delta: events.eventDelta(this._prevEventData, currentEventData)});
  12437. var eventDelta = events.eventDelta(this._savedEventData, currentEventData);
  12438. if (eventDelta.time > VELOCITY_CALC_TIMEOUT)
  12439. this._savedEventData = this._prevEventData
  12440. },
  12441. _end: function(e) {
  12442. var endEventDelta = events.eventDelta(this._prevEventData, events.eventData(e));
  12443. var velocity = {
  12444. x: 0,
  12445. y: 0
  12446. };
  12447. var isWheelEvent = e.type === "dxmousewheel";
  12448. if (endEventDelta.time < INERTIA_TIMEOUT) {
  12449. var deltaEventData = events.eventDelta(this._savedEventData, this._prevEventData);
  12450. velocity = {
  12451. x: isWheelEvent ? 0 : deltaEventData.x * FRAME_DURATION / deltaEventData.time,
  12452. y: isWheelEvent ? 0 : deltaEventData.y * FRAME_DURATION / deltaEventData.time
  12453. }
  12454. }
  12455. this._fireEvent(SCROLL_END_EVENT, e, {velocity: velocity})
  12456. },
  12457. _stop: function(e) {
  12458. this._fireEvent(SCROLL_STOP_EVENT, e)
  12459. },
  12460. cancel: function(e) {
  12461. this.callBase.apply(this, arguments);
  12462. this._fireEvent(SCROLL_CANCEL_EVENT, e)
  12463. },
  12464. dispose: function() {
  12465. this.callBase.apply(this, arguments);
  12466. $.data(this._domElement(), GESTURE_LOCK_KEY, false);
  12467. this._clearGestureTimer();
  12468. this.getElement().off(NAMESPACED_SCROLL_EVENT)
  12469. },
  12470. _clearGestureTimer: function() {
  12471. clearTimeout(this._gestureEndTimer);
  12472. this._gestureEndTimer = null
  12473. }
  12474. });
  12475. events.registerEmitter({
  12476. emitter: ScrollEmitter,
  12477. events: [SCROLL_INIT_EVENT, SCROLL_START_EVENT, SCROLL_MOVE_EVENT, SCROLL_END_EVENT, SCROLL_STOP_EVENT, SCROLL_CANCEL_EVENT]
  12478. })
  12479. })(jQuery, DevExpress);
  12480. /*! Module core, file ui.events.emitter.gesture.swipe.js */
  12481. (function($, DX, undefined) {
  12482. var ui = DX.ui,
  12483. events = ui.events,
  12484. SWIPE_START_EVENT = "dxswipestart",
  12485. SWIPE_EVENT = "dxswipe",
  12486. SWIPE_END_EVENT = "dxswipeend";
  12487. var HorizontalStrategy = {
  12488. defaultItemSizeFunc: function() {
  12489. return this.getElement().width()
  12490. },
  12491. getBounds: function() {
  12492. return [this._maxLeftOffset, this._maxRightOffset]
  12493. },
  12494. calcOffsetRatio: function(e) {
  12495. var endEventData = events.eventData(e);
  12496. return (endEventData.x - (this._savedEventData && this._savedEventData.x || 0)) / this._itemSizeFunc().call(this, e)
  12497. },
  12498. isFastSwipe: function(e) {
  12499. var endEventData = events.eventData(e);
  12500. return this.FAST_SWIPE_SPEED_LIMIT * Math.abs(endEventData.x - this._tickData.x) >= endEventData.time - this._tickData.time
  12501. }
  12502. };
  12503. var VerticalStrategy = {
  12504. defaultItemSizeFunc: function() {
  12505. return this.getElement().height()
  12506. },
  12507. getBounds: function() {
  12508. return [this._maxTopOffset, this._maxBottomOffset]
  12509. },
  12510. calcOffsetRatio: function(e) {
  12511. var endEventData = events.eventData(e);
  12512. return (endEventData.y - (this._savedEventData && this._savedEventData.y || 0)) / this._itemSizeFunc().call(this, e)
  12513. },
  12514. isFastSwipe: function(e) {
  12515. var endEventData = events.eventData(e);
  12516. return this.FAST_SWIPE_SPEED_LIMIT * Math.abs(endEventData.y - this._tickData.y) >= endEventData.time - this._tickData.time
  12517. }
  12518. };
  12519. var STRATEGIES = {
  12520. horizontal: HorizontalStrategy,
  12521. vertical: VerticalStrategy
  12522. };
  12523. var SwipeEmitter = events.GestureEmitter.inherit({
  12524. TICK_INTERVAL: 300,
  12525. FAST_SWIPE_SPEED_LIMIT: 5,
  12526. ctor: function(element) {
  12527. this.callBase(element);
  12528. this.direction = "horizontal";
  12529. this.elastic = true
  12530. },
  12531. _getStrategy: function() {
  12532. return STRATEGIES[this.direction]
  12533. },
  12534. _defaultItemSizeFunc: function() {
  12535. return this._getStrategy().defaultItemSizeFunc.call(this)
  12536. },
  12537. _itemSizeFunc: function() {
  12538. return this.itemSizeFunc || this._defaultItemSizeFunc
  12539. },
  12540. _start: function(e) {
  12541. this._savedEventData = events.eventData(e);
  12542. this._tickData = {time: 0};
  12543. e = this._fireEvent(SWIPE_START_EVENT, e);
  12544. if (!e.cancel) {
  12545. this._maxLeftOffset = e.maxLeftOffset;
  12546. this._maxRightOffset = e.maxRightOffset;
  12547. this._maxTopOffset = e.maxTopOffset;
  12548. this._maxBottomOffset = e.maxBottomOffset
  12549. }
  12550. },
  12551. _move: function(e) {
  12552. var strategy = this._getStrategy(),
  12553. moveEventData = events.eventData(e),
  12554. offset = strategy.calcOffsetRatio.call(this, e);
  12555. offset = this._fitOffset(offset, this.elastic);
  12556. if (moveEventData.time - this._tickData.time > this.TICK_INTERVAL)
  12557. this._tickData = moveEventData;
  12558. this._fireEvent(SWIPE_EVENT, e, {offset: offset});
  12559. e.preventDefault()
  12560. },
  12561. _end: function(e) {
  12562. var strategy = this._getStrategy(),
  12563. offsetRatio = strategy.calcOffsetRatio.call(this, e),
  12564. isFast = strategy.isFastSwipe.call(this, e),
  12565. startOffset = offsetRatio,
  12566. targetOffset = this._calcTargetOffset(offsetRatio, isFast);
  12567. startOffset = this._fitOffset(startOffset, this.elastic);
  12568. targetOffset = this._fitOffset(targetOffset, false);
  12569. this._fireEvent(SWIPE_END_EVENT, e, {
  12570. offset: startOffset,
  12571. targetOffset: targetOffset
  12572. })
  12573. },
  12574. _fitOffset: function(offset, elastic) {
  12575. var strategy = this._getStrategy(),
  12576. bounds = strategy.getBounds.call(this);
  12577. if (offset < -bounds[0])
  12578. return elastic ? (-2 * bounds[0] + offset) / 3 : -bounds[0];
  12579. if (offset > bounds[1])
  12580. return elastic ? (2 * bounds[1] + offset) / 3 : bounds[1];
  12581. return offset
  12582. },
  12583. _calcTargetOffset: function(offsetRatio, isFast) {
  12584. var result;
  12585. if (isFast) {
  12586. result = Math.ceil(Math.abs(offsetRatio));
  12587. if (offsetRatio < 0)
  12588. result = -result
  12589. }
  12590. else
  12591. result = Math.round(offsetRatio);
  12592. return result
  12593. }
  12594. });
  12595. events.registerEmitter({
  12596. emitter: SwipeEmitter,
  12597. events: [SWIPE_START_EVENT, SWIPE_EVENT, SWIPE_END_EVENT]
  12598. })
  12599. })(jQuery, DevExpress);
  12600. /*! Module core, file ui.events.emitter.gesture.drag.js */
  12601. (function($, DX, undefined) {
  12602. var ui = DX.ui,
  12603. utils = DX.utils,
  12604. events = ui.events,
  12605. wrapToArray = utils.wrapToArray;
  12606. var DRAG_START_EVENT = "dxdragstart",
  12607. DRAG_EVENT = "dxdrag",
  12608. DRAG_END_EVENT = "dxdragend",
  12609. DRAG_ENTER_EVENT = "dxdragenter",
  12610. DRAG_LEAVE_EVENT = "dxdragleave",
  12611. DROP_EVENT = "dxdrop";
  12612. var knownDropTargets = [],
  12613. knownDropTargetSelectors = [],
  12614. knownDropTargetConfigs = [];
  12615. var dropTargetRegistration = {
  12616. setup: function(element, data) {
  12617. var knownDropTarget = $.inArray(element, knownDropTargets) !== -1;
  12618. if (!knownDropTarget) {
  12619. knownDropTargets.push(element);
  12620. knownDropTargetSelectors.push([]);
  12621. knownDropTargetConfigs.push(data || {})
  12622. }
  12623. },
  12624. add: function(element, handleObj) {
  12625. var index = $.inArray(element, knownDropTargets);
  12626. var selector = handleObj.selector;
  12627. if ($.inArray(selector, knownDropTargetSelectors[index]) === -1)
  12628. knownDropTargetSelectors[index].push(selector)
  12629. },
  12630. teardown: function(element, data) {
  12631. var elementEvents = $._data(element, "events"),
  12632. handlersCount = 0;
  12633. $.each([DRAG_ENTER_EVENT, DRAG_LEAVE_EVENT, DROP_EVENT], function(_, eventName) {
  12634. var eventHandlers = elementEvents[eventName];
  12635. if (eventHandlers)
  12636. handlersCount += eventHandlers.length
  12637. });
  12638. if (!handlersCount) {
  12639. var index = $.inArray(element, knownDropTargets);
  12640. knownDropTargets.splice(index, 1);
  12641. knownDropTargetSelectors.splice(index, 1);
  12642. knownDropTargetConfigs.splice(index, 1)
  12643. }
  12644. }
  12645. };
  12646. events.registerEvent(DRAG_ENTER_EVENT, dropTargetRegistration);
  12647. events.registerEvent(DRAG_LEAVE_EVENT, dropTargetRegistration);
  12648. events.registerEvent(DROP_EVENT, dropTargetRegistration);
  12649. var getItemDelegatedTargets = function($element) {
  12650. var dropTargetIndex = $.inArray($element.get(0), knownDropTargets),
  12651. dropTargetSelectors = knownDropTargetSelectors[dropTargetIndex];
  12652. var $delegatedTargets = $element.find(dropTargetSelectors.join(", "));
  12653. if ($.inArray(undefined, dropTargetSelectors) !== -1)
  12654. $delegatedTargets = $delegatedTargets.addBack();
  12655. return $delegatedTargets
  12656. };
  12657. var getItemConfig = function($element) {
  12658. var dropTargetIndex = $.inArray($element.get(0), knownDropTargets);
  12659. return knownDropTargetConfigs[dropTargetIndex]
  12660. };
  12661. var getItemPosition = function(dropTargetConfig, $element) {
  12662. if (dropTargetConfig.itemPositionFunc)
  12663. return dropTargetConfig.itemPositionFunc($element);
  12664. else
  12665. return $element.offset()
  12666. };
  12667. var getItemSize = function(dropTargetConfig, $element) {
  12668. if (dropTargetConfig.itemSizeFunc)
  12669. return dropTargetConfig.itemSizeFunc($element);
  12670. return {
  12671. width: $element.width(),
  12672. height: $element.height()
  12673. }
  12674. };
  12675. var DragEmitter = events.GestureEmitter.inherit({
  12676. ctor: function(element) {
  12677. this.callBase(element);
  12678. this.direction = "both"
  12679. },
  12680. _init: function(e) {
  12681. this._initEvent = e
  12682. },
  12683. _start: function(e) {
  12684. e = this._fireEvent(DRAG_START_EVENT, this._initEvent);
  12685. this._maxLeftOffset = e.maxLeftOffset;
  12686. this._maxRightOffset = e.maxRightOffset;
  12687. this._maxTopOffset = e.maxTopOffset;
  12688. this._maxBottomOffset = e.maxBottomOffset;
  12689. var dropTargets = wrapToArray(e.targetElements || (e.targetElements === null ? [] : knownDropTargets));
  12690. this._dropTargets = $.map(dropTargets, function(element) {
  12691. return $(element).get(0)
  12692. })
  12693. },
  12694. _move: function(e) {
  12695. var eventData = events.eventData(e),
  12696. dragOffset = this._calculateOffset(eventData);
  12697. this._fireEvent(DRAG_EVENT, e, {offset: dragOffset});
  12698. this._processDropTargets(e, dragOffset);
  12699. e.preventDefault()
  12700. },
  12701. _calculateOffset: function(eventData) {
  12702. return {
  12703. x: this._calculateXOffset(eventData),
  12704. y: this._calculateYOffset(eventData)
  12705. }
  12706. },
  12707. _calculateXOffset: function(eventData) {
  12708. if (this.direction !== "vertical") {
  12709. var offset = eventData.x - this._startEventData.x;
  12710. return this._fitOffset(offset, this._maxLeftOffset, this._maxRightOffset)
  12711. }
  12712. return 0
  12713. },
  12714. _calculateYOffset: function(eventData) {
  12715. if (this.direction !== "horizontal") {
  12716. var offset = eventData.y - this._startEventData.y;
  12717. return this._fitOffset(offset, this._maxTopOffset, this._maxBottomOffset)
  12718. }
  12719. return 0
  12720. },
  12721. _fitOffset: function(offset, minOffset, maxOffset) {
  12722. if (minOffset != null)
  12723. offset = Math.max(offset, -minOffset);
  12724. if (maxOffset != null)
  12725. offset = Math.min(offset, maxOffset);
  12726. return offset
  12727. },
  12728. _processDropTargets: function(e, dragOffset) {
  12729. var target = this._findDropTarget(e),
  12730. sameTarget = target === this._currentDropTarget;
  12731. if (!sameTarget) {
  12732. this._fireDropTargetEvent(e, DRAG_LEAVE_EVENT);
  12733. this._currentDropTarget = target;
  12734. this._fireDropTargetEvent(e, DRAG_ENTER_EVENT)
  12735. }
  12736. },
  12737. _fireDropTargetEvent: function(event, eventName) {
  12738. if (!this._currentDropTarget)
  12739. return;
  12740. var eventData = {
  12741. type: eventName,
  12742. originalEvent: event,
  12743. draggingElement: this._$element.get(0),
  12744. target: this._currentDropTarget
  12745. };
  12746. events.fireEvent(eventData)
  12747. },
  12748. _findDropTarget: function(e) {
  12749. var that = this,
  12750. result;
  12751. $.each(knownDropTargets, function(_, target) {
  12752. if (!that._checkDropTargetActive(target))
  12753. return;
  12754. var $target = $(target);
  12755. $.each(getItemDelegatedTargets($target), function(_, delegatedTarget) {
  12756. var $delegatedTarget = $(delegatedTarget);
  12757. if (that._checkDropTarget(getItemConfig($target), $delegatedTarget, e))
  12758. result = delegatedTarget
  12759. })
  12760. });
  12761. return result
  12762. },
  12763. _checkDropTargetActive: function(target) {
  12764. var active = false;
  12765. $.each(this._dropTargets, function(_, activeTarget) {
  12766. active = active || activeTarget === target || $.contains(activeTarget, target);
  12767. return !active
  12768. });
  12769. return active
  12770. },
  12771. _checkDropTarget: function(config, $target, e) {
  12772. var isDraggingElement = $target.get(0) === this._$element.get(0);
  12773. if (isDraggingElement)
  12774. return false;
  12775. var targetPosition = getItemPosition(config, $target);
  12776. if (e.pageX < targetPosition.left)
  12777. return false;
  12778. if (e.pageY < targetPosition.top)
  12779. return false;
  12780. var targetSize = getItemSize(config, $target);
  12781. if (e.pageX > targetPosition.left + targetSize.width)
  12782. return false;
  12783. if (e.pageY > targetPosition.top + targetSize.height)
  12784. return false;
  12785. return $target
  12786. },
  12787. _end: function(e) {
  12788. var eventData = events.eventData(e);
  12789. this._fireEvent(DRAG_END_EVENT, e, {offset: this._calculateOffset(eventData)});
  12790. this._fireDropTargetEvent(e, DROP_EVENT);
  12791. delete this._currentDropTarget
  12792. }
  12793. });
  12794. events.registerEmitter({
  12795. emitter: DragEmitter,
  12796. events: [DRAG_START_EVENT, DRAG_EVENT, DRAG_END_EVENT]
  12797. });
  12798. DX.ui.events.__internals = DX.ui.events.__internals || {};
  12799. $.extend(DX.ui.events.__internals, {dropTargets: knownDropTargets})
  12800. })(jQuery, DevExpress);
  12801. /*! Module core, file ui.events.emitter.transform.js */
  12802. (function($, DX, undefined) {
  12803. var ui = DX.ui,
  12804. utils = DX.utils,
  12805. events = ui.events,
  12806. fitIntoRange = utils.fitIntoRange;
  12807. var DX_PREFIX = "dx",
  12808. TRANSFORM = "transform",
  12809. TRANSLATE = "translate",
  12810. ZOOM = "zoom",
  12811. PINCH = "pinch",
  12812. ROTATE = "rotate",
  12813. START_POSTFIX = "start",
  12814. UPDATE_POSTFIX = "",
  12815. END_POSTFIX = "end";
  12816. var eventAliases = [];
  12817. var addAlias = function(eventName, eventArgs) {
  12818. eventAliases.push({
  12819. name: eventName,
  12820. args: eventArgs
  12821. })
  12822. };
  12823. addAlias(TRANSFORM, {
  12824. scale: true,
  12825. deltaScale: true,
  12826. rotation: true,
  12827. deltaRotation: true,
  12828. translation: true,
  12829. deltaTranslation: true
  12830. });
  12831. addAlias(TRANSLATE, {
  12832. translation: true,
  12833. deltaTranslation: true
  12834. });
  12835. addAlias(ZOOM, {
  12836. scale: true,
  12837. deltaScale: true
  12838. });
  12839. addAlias(PINCH, {
  12840. scale: true,
  12841. deltaScale: true
  12842. });
  12843. addAlias(ROTATE, {
  12844. rotation: true,
  12845. deltaRotation: true
  12846. });
  12847. var getVector = function(first, second) {
  12848. return {
  12849. x: second.pageX - first.pageX,
  12850. y: -second.pageY + first.pageY,
  12851. centerX: (second.pageX + first.pageX) * 0.5,
  12852. centerY: (second.pageY + first.pageY) * 0.5
  12853. }
  12854. };
  12855. var getEventVector = function(e) {
  12856. var pointers = e.pointers;
  12857. return getVector(pointers[0], pointers[1])
  12858. };
  12859. var getDistance = function(vector) {
  12860. return Math.sqrt(vector.x * vector.x + vector.y * vector.y)
  12861. };
  12862. var getScale = function(firstVector, secondVector) {
  12863. return getDistance(firstVector) / getDistance(secondVector)
  12864. };
  12865. var getRotation = function(firstVector, secondVector) {
  12866. var scalarProduct = firstVector.x * secondVector.x + firstVector.y * secondVector.y;
  12867. var distanceProduct = getDistance(firstVector) * getDistance(secondVector);
  12868. if (distanceProduct === 0)
  12869. return 0;
  12870. var sign = utils.sign(firstVector.x * secondVector.y - secondVector.x * firstVector.y);
  12871. var angle = Math.acos(fitIntoRange(scalarProduct / distanceProduct, -1, 1));
  12872. return sign * angle
  12873. };
  12874. var getTranslation = function(firstVector, secondVector) {
  12875. return {
  12876. x: firstVector.centerX - secondVector.centerX,
  12877. y: firstVector.centerY - secondVector.centerY
  12878. }
  12879. };
  12880. var TransformEmitter = events.Emitter.inherit({
  12881. configurate: function(data, eventName) {
  12882. if (eventName.indexOf(ZOOM) > -1)
  12883. DX.log("W0005", eventName, "15.1", "Use '" + eventName.replace(ZOOM, PINCH) + "' event instead");
  12884. this.callBase(data)
  12885. },
  12886. validatePointers: function(e) {
  12887. return events.hasTouches(e) > 1
  12888. },
  12889. start: function(e) {
  12890. this._accept(e);
  12891. var startVector = getEventVector(e);
  12892. this._startVector = startVector;
  12893. this._prevVector = startVector;
  12894. this._fireEventAliases(START_POSTFIX, e)
  12895. },
  12896. move: function(e) {
  12897. var currentVector = getEventVector(e),
  12898. eventArgs = this._getEventArgs(currentVector);
  12899. this._fireEventAliases(UPDATE_POSTFIX, e, eventArgs);
  12900. this._prevVector = currentVector
  12901. },
  12902. end: function(e) {
  12903. var eventArgs = this._getEventArgs(this._prevVector);
  12904. this._fireEventAliases(END_POSTFIX, e, eventArgs)
  12905. },
  12906. _getEventArgs: function(vector) {
  12907. return {
  12908. scale: getScale(vector, this._startVector),
  12909. deltaScale: getScale(vector, this._prevVector),
  12910. rotation: getRotation(vector, this._startVector),
  12911. deltaRotation: getRotation(vector, this._prevVector),
  12912. translation: getTranslation(vector, this._startVector),
  12913. deltaTranslation: getTranslation(vector, this._prevVector)
  12914. }
  12915. },
  12916. _fireEventAliases: function(eventPostfix, originalEvent, eventArgs) {
  12917. eventArgs = eventArgs || {};
  12918. $.each(eventAliases, $.proxy(function(_, eventAlias) {
  12919. var args = {};
  12920. $.each(eventAlias.args, function(name) {
  12921. if (name in eventArgs)
  12922. args[name] = eventArgs[name]
  12923. });
  12924. this._fireEvent(DX_PREFIX + eventAlias.name + eventPostfix, originalEvent, args)
  12925. }, this))
  12926. }
  12927. });
  12928. events.registerEmitter({
  12929. emitter: TransformEmitter,
  12930. events: $.map(eventAliases, function(eventAlias) {
  12931. var eventNames = [];
  12932. $.each([START_POSTFIX, UPDATE_POSTFIX, END_POSTFIX], function(_, eventPostfix) {
  12933. eventNames.push(DX_PREFIX + eventAlias.name + eventPostfix)
  12934. });
  12935. return eventNames
  12936. })
  12937. })
  12938. })(jQuery, DevExpress);
  12939. /*! Module core, file ui.events.dblclick.js */
  12940. (function($, DX, undefined) {
  12941. var ui = DX.ui,
  12942. events = ui.events,
  12943. utils = DX.utils,
  12944. DBLCLICK_EVENT_NAME = "dxdblclick",
  12945. DBLCLICK_NAMESPACE = "dxDblClick",
  12946. NAMESPACED_CLICK_EVENT = events.addNamespace("dxclick", DBLCLICK_NAMESPACE),
  12947. DBLCLICK_TIMEOUT = 300;
  12948. var DblClick = DX.Class.inherit({
  12949. ctor: function() {
  12950. this._handlerCount = 0;
  12951. this._forgetLastClick()
  12952. },
  12953. _forgetLastClick: function() {
  12954. this._firstClickTarget = null;
  12955. this._lastClickTimeStamp = -DBLCLICK_TIMEOUT
  12956. },
  12957. add: function() {
  12958. if (this._handlerCount <= 0)
  12959. $(document).on(NAMESPACED_CLICK_EVENT, $.proxy(this._clickHandler, this));
  12960. this._handlerCount++
  12961. },
  12962. _clickHandler: function(e) {
  12963. var timeStamp = e.timeStamp || $.now();
  12964. if (timeStamp - this._lastClickTimeStamp < DBLCLICK_TIMEOUT) {
  12965. events.fireEvent({
  12966. type: DBLCLICK_EVENT_NAME,
  12967. target: utils.closestCommonParent(this._firstClickTarget, e.target),
  12968. originalEvent: e
  12969. });
  12970. this._forgetLastClick()
  12971. }
  12972. else {
  12973. this._firstClickTarget = e.target;
  12974. this._lastClickTimeStamp = timeStamp
  12975. }
  12976. },
  12977. remove: function() {
  12978. this._handlerCount--;
  12979. if (this._handlerCount <= 0) {
  12980. this._forgetLastClick();
  12981. $(document).off(NAMESPACED_CLICK_EVENT)
  12982. }
  12983. }
  12984. });
  12985. events.registerEvent(DBLCLICK_EVENT_NAME, new DblClick)
  12986. })(jQuery, DevExpress);
  12987. /*! Module core, file ui.events.remove.js */
  12988. (function($) {
  12989. (function(cleanData) {
  12990. $.cleanData = function(elements) {
  12991. $.each(elements, function() {
  12992. $(this).triggerHandler("dxremove")
  12993. });
  12994. return cleanData.apply(this, arguments)
  12995. }
  12996. })($.cleanData)
  12997. })(jQuery);
  12998. /*! Module core, file ui.events.contextmenu.js */
  12999. (function($, DX, undefined) {
  13000. var ui = DX.ui,
  13001. events = ui.events,
  13002. support = DX.support,
  13003. CONTEXTMENU_NAMESPACE = "dxContexMenu",
  13004. CONTEXTMENU_NAMESPACED_EVENT_NAME = events.addNamespace("contextmenu", CONTEXTMENU_NAMESPACE),
  13005. HOLD_NAMESPACED_EVENT_NAME = events.addNamespace("dxhold", CONTEXTMENU_NAMESPACE),
  13006. CONTEXTMENU_EVENT_NAME = "dxcontextmenu";
  13007. var ContextMenu = DX.Class.inherit({
  13008. setup: function(element, data) {
  13009. var $element = $(element);
  13010. $element.on(CONTEXTMENU_NAMESPACED_EVENT_NAME, $.proxy(this._contextMenuHandler, this));
  13011. if (support.touch || DX.devices.isSimulator())
  13012. $element.on(HOLD_NAMESPACED_EVENT_NAME, $.proxy(this._holdHandler, this))
  13013. },
  13014. _holdHandler: function(e) {
  13015. if (events.isMouseEvent(e) && !DX.devices.isSimulator())
  13016. return;
  13017. this._fireContextMenu(e)
  13018. },
  13019. _contextMenuHandler: function(e) {
  13020. e = this._fireContextMenu(e);
  13021. if (!e.cancel)
  13022. e.preventDefault()
  13023. },
  13024. _fireContextMenu: function(e) {
  13025. return events.fireEvent({
  13026. type: CONTEXTMENU_EVENT_NAME,
  13027. originalEvent: e
  13028. })
  13029. },
  13030. teardown: function(element) {
  13031. $(element).off("." + CONTEXTMENU_NAMESPACE)
  13032. }
  13033. });
  13034. events.registerEvent(CONTEXTMENU_EVENT_NAME, new ContextMenu)
  13035. })(jQuery, DevExpress);
  13036. /*! Module core, file ui.widget.js */
  13037. (function($, DX, undefined) {
  13038. var ui = DX.ui,
  13039. utils = DX.utils,
  13040. events = ui.events,
  13041. UI_FEEDBACK = "UIFeedback",
  13042. WIDGET_CLASS = "dx-widget",
  13043. ACTIVE_STATE_CLASS = "dx-state-active",
  13044. DISABLED_STATE_CLASS = "dx-state-disabled",
  13045. INVISIBLE_STATE_CLASS = "dx-state-invisible",
  13046. HOVER_STATE_CLASS = "dx-state-hover",
  13047. FOCUSED_STATE_CLASS = "dx-state-focused",
  13048. FEEDBACK_SHOW_TIMEOUT = 30,
  13049. FEEDBACK_HIDE_TIMEOUT = 400,
  13050. HOVER_START = "dxhoverstart",
  13051. HOVER_END = "dxhoverend",
  13052. FOCUS_NAMESPACE = "Focus",
  13053. ANONYMOUS_TEMPLATE_NAME = "template",
  13054. TEXT_NODE = 3,
  13055. TEMPLATE_SELECTOR = "[data-options*='dxTemplate']",
  13056. TEMPLATE_WRAPPER_CLASS = "dx-template-wrapper";
  13057. var DynamicTemplate = ui.TemplateBase.inherit({
  13058. ctor: function(compileFunction, owner) {
  13059. this.callBase($(), owner);
  13060. this._compileFunction = compileFunction
  13061. },
  13062. _renderCore: function(data, index, container) {
  13063. if (data === undefined && index === undefined) {
  13064. data = container;
  13065. container = undefined
  13066. }
  13067. var compiledTemplate = index === undefined ? this._compileFunction(data, container) : this._compileFunction(data, index, container);
  13068. var renderResult = compiledTemplate.render(data, container, index);
  13069. if (compiledTemplate.owner() === this)
  13070. compiledTemplate.dispose();
  13071. return renderResult
  13072. }
  13073. });
  13074. var EmptyTemplate = ui.TemplateBase.inherit({
  13075. ctor: function(owner) {
  13076. this.callBase($(), owner)
  13077. },
  13078. _renderCore: function(data, index, container) {
  13079. return $()
  13080. }
  13081. });
  13082. var RendererTemplate = ui.TemplateBase.inherit({_renderCore: function() {
  13083. return this._element
  13084. }});
  13085. ui.Widget = DX.DOMComponent.inherit({
  13086. NAME: "Widget",
  13087. _supportedKeys: function() {
  13088. return {}
  13089. },
  13090. _setDeprecatedOptions: function() {
  13091. this.callBase();
  13092. $.extend(this._deprecatedOptions, {contentReadyAction: {
  13093. since: "14.2",
  13094. alias: "onContentReady"
  13095. }})
  13096. },
  13097. _setDefaultOptions: function() {
  13098. this.callBase();
  13099. this.option({
  13100. disabled: false,
  13101. visible: true,
  13102. hint: undefined,
  13103. activeStateEnabled: false,
  13104. onContentReady: null,
  13105. hoverStateEnabled: false,
  13106. focusStateEnabled: false,
  13107. tabIndex: 0,
  13108. accessKey: null,
  13109. onFocusIn: null,
  13110. onFocusOut: null,
  13111. templateProvider: ui.TemplateProvider,
  13112. _keyboardProcessor: undefined,
  13113. _templates: {}
  13114. })
  13115. },
  13116. _init: function() {
  13117. this.callBase();
  13118. this._feedbackShowTimeout = FEEDBACK_SHOW_TIMEOUT;
  13119. this._feedbackHideTimeout = FEEDBACK_HIDE_TIMEOUT;
  13120. this._tempTemplates = [];
  13121. this._dynamicTemplates = {};
  13122. this._initTemplates();
  13123. this._initContentReadyAction();
  13124. this._initFocusActions()
  13125. },
  13126. _initTemplates: function() {
  13127. this._extractTemplates();
  13128. this._extractAnonimousTemplate()
  13129. },
  13130. _extractTemplates: function() {
  13131. var templates = this.option("_templates"),
  13132. templateElements = this.element().contents().filter(TEMPLATE_SELECTOR);
  13133. var templatesMap = {};
  13134. templateElements.each(function(_, template) {
  13135. var templateOptions = utils.getElementOptions(template).dxTemplate;
  13136. if (!templateOptions)
  13137. return;
  13138. if (!templateOptions.name)
  13139. throw DX.Error("E0023");
  13140. $(template).addClass(TEMPLATE_WRAPPER_CLASS).detach();
  13141. templatesMap[templateOptions.name] = templatesMap[templateOptions.name] || [];
  13142. templatesMap[templateOptions.name].push(template)
  13143. });
  13144. $.each(templatesMap, $.proxy(function(templateName, value) {
  13145. var deviceTemplate = this._findTemplateByDevice(value);
  13146. if (deviceTemplate)
  13147. templates[templateName] = this._createTemplate(deviceTemplate, this)
  13148. }, this))
  13149. },
  13150. _findTemplateByDevice: function(templates) {
  13151. var suitableTemplate = DX.utils.findBestMatches(DX.devices.current(), templates, function(template) {
  13152. return utils.getElementOptions(template).dxTemplate
  13153. })[0];
  13154. $.each(templates, function(index, template) {
  13155. if (template !== suitableTemplate)
  13156. $(template).remove()
  13157. });
  13158. return suitableTemplate
  13159. },
  13160. _extractAnonimousTemplate: function() {
  13161. var templates = this.option("_templates"),
  13162. anonimiousTemplateName = this._getAnonimousTemplateName(),
  13163. $anonimiousTemplate = this.element().contents().detach();
  13164. var $notJunkTemplateContent = $anonimiousTemplate.filter(function(_, element) {
  13165. var isTextNode = element.nodeType === TEXT_NODE,
  13166. isEmptyText = $.trim($(element).text()).length < 1;
  13167. return !(isTextNode && isEmptyText)
  13168. }),
  13169. onlyJunkTemplateContent = $notJunkTemplateContent.length < 1;
  13170. if (!templates[anonimiousTemplateName] && !onlyJunkTemplateContent)
  13171. templates[anonimiousTemplateName] = this._createTemplate($anonimiousTemplate, this)
  13172. },
  13173. _getAriaTarget: function() {
  13174. return this.element()
  13175. },
  13176. _getAnonimousTemplateName: function() {
  13177. return ANONYMOUS_TEMPLATE_NAME
  13178. },
  13179. _getTemplateByOption: function(optionName) {
  13180. return this._getTemplate(this.option(optionName))
  13181. },
  13182. _getTemplate: function(templateSource) {
  13183. if ($.isFunction(templateSource)) {
  13184. var that = this;
  13185. return new DynamicTemplate(function() {
  13186. var templateSourceResult = templateSource.apply(that, arguments);
  13187. if (utils.isDefined(templateSourceResult))
  13188. return that._acquireTemplate(templateSourceResult, this, true);
  13189. else
  13190. return new EmptyTemplate
  13191. }, this)
  13192. }
  13193. return this._acquireTemplate(templateSource, this)
  13194. },
  13195. _acquireTemplate: function(templateSource, owner, preferRenderer) {
  13196. if (templateSource == null)
  13197. return this._createTemplate(utils.normalizeTemplateElement(templateSource), owner);
  13198. if (templateSource instanceof ui.TemplateBase)
  13199. return templateSource;
  13200. if (templateSource.nodeType || templateSource.jquery) {
  13201. templateSource = $(templateSource);
  13202. if (preferRenderer && !templateSource.is("script"))
  13203. return new RendererTemplate(templateSource, owner);
  13204. return this._createTemplate(templateSource, owner)
  13205. }
  13206. if (typeof templateSource === "string") {
  13207. var userTemplate = this.option("_templates")[templateSource];
  13208. if (userTemplate)
  13209. return userTemplate;
  13210. var dynamicTemplate = this._dynamicTemplates[templateSource];
  13211. if (dynamicTemplate)
  13212. return dynamicTemplate;
  13213. var defaultTemplate = this.option("templateProvider").getTemplates(this)[templateSource];
  13214. if (defaultTemplate)
  13215. return defaultTemplate;
  13216. return this._createTemplate(utils.normalizeTemplateElement(templateSource), owner)
  13217. }
  13218. return this._acquireTemplate(templateSource.toString(), owner)
  13219. },
  13220. _createTemplate: function(element, owner) {
  13221. var template = this.option("templateProvider").createTemplate(element, owner);
  13222. this._tempTemplates.push(template);
  13223. return template
  13224. },
  13225. _cleanTemplates: function() {
  13226. var that = this;
  13227. $.each(this.option("_templates"), function(_, template) {
  13228. if (that === template.owner())
  13229. template.dispose()
  13230. });
  13231. $.each(this._tempTemplates, function(_, template) {
  13232. template.dispose()
  13233. })
  13234. },
  13235. _initContentReadyAction: function() {
  13236. this._contentReadyAction = this._createActionByOption("onContentReady", {excludeValidators: ["designMode", "disabled", "readOnly"]})
  13237. },
  13238. _initFocusActions: function() {
  13239. var focusInAction = this._createActionByOption("onFocusIn", {excludeValidators: ["readOnly"]});
  13240. var focusOutAction = this._createActionByOption("onFocusOut", {excludeValidators: ["readOnly"]});
  13241. this._focusInAction = this._createAction(function(e) {
  13242. e.component._focusInHandler(e.jQueryEvent);
  13243. focusInAction(e)
  13244. }, {excludeValidators: ["readOnly"]});
  13245. this._focusOutAction = this._createAction(function(e) {
  13246. e.component._focusOutHandler(e.jQueryEvent);
  13247. focusOutAction(e)
  13248. }, {excludeValidators: ["readOnly"]})
  13249. },
  13250. _render: function() {
  13251. this.element().addClass(WIDGET_CLASS);
  13252. this.callBase();
  13253. this._toggleDisabledState(this.option("disabled"));
  13254. this._toggleVisibility(this.option("visible"));
  13255. this._renderHint();
  13256. this._renderContent();
  13257. this._renderFocusState();
  13258. this._attachFeedbackEvents();
  13259. this._attachHoverEvents()
  13260. },
  13261. _renderHint: function() {
  13262. utils.toggleAttr(this.element(), "title", this.option("hint"))
  13263. },
  13264. _renderContent: function() {
  13265. this._renderContentImpl();
  13266. this._fireContentReadyAction()
  13267. },
  13268. _renderContentImpl: $.noop,
  13269. _fireContentReadyAction: function() {
  13270. this._contentReadyAction()
  13271. },
  13272. _dispose: function() {
  13273. this._cleanTemplates();
  13274. this._contentReadyAction = null;
  13275. this.callBase()
  13276. },
  13277. _clean: function() {
  13278. this._cleanFocusState();
  13279. this.callBase();
  13280. this.element().empty()
  13281. },
  13282. _toggleVisibility: function(visible) {
  13283. this.element().toggleClass(INVISIBLE_STATE_CLASS, !visible);
  13284. this.setAria("hidden", !visible || undefined)
  13285. },
  13286. _renderFocusState: function() {
  13287. if (!this.option("focusStateEnabled") || this.option("disabled"))
  13288. return;
  13289. this._renderFocusTarget();
  13290. this._attachFocusEvents();
  13291. this._attachKeyboardEvents();
  13292. this._renderAccessKey()
  13293. },
  13294. _renderAccessKey: function() {
  13295. var focusTarget = this._focusTarget();
  13296. focusTarget.attr("accesskey", this.option("accessKey"));
  13297. var clickNamespace = events.addNamespace("dxclick", UI_FEEDBACK);
  13298. focusTarget.off(clickNamespace);
  13299. this.option("accessKey") && focusTarget.on(clickNamespace, $.proxy(function(e) {
  13300. if (e.screenX === 0 && !e.offsetX && e.pageX === 0) {
  13301. e.stopImmediatePropagation();
  13302. this.focus()
  13303. }
  13304. }, this))
  13305. },
  13306. _eventBindingTarget: function() {
  13307. return this.element()
  13308. },
  13309. _focusTarget: function() {
  13310. return this._getActiveElement()
  13311. },
  13312. _getActiveElement: function() {
  13313. var activeElement = this._eventBindingTarget();
  13314. if (this._activeStateUnit)
  13315. activeElement = activeElement.find(this._activeStateUnit).not("." + DISABLED_STATE_CLASS);
  13316. return activeElement
  13317. },
  13318. _renderFocusTarget: function() {
  13319. this._focusTarget().attr("tabindex", this.option("tabIndex"))
  13320. },
  13321. _keyboardEventBindingTarget: function() {
  13322. return this._eventBindingTarget()
  13323. },
  13324. _attachFocusEvents: function() {
  13325. var focusInEvent = events.addNamespace("focusin", this.NAME + FOCUS_NAMESPACE);
  13326. var focusOutEvent = events.addNamespace("focusout", this.NAME + FOCUS_NAMESPACE);
  13327. var beforeactivateEventNamespace = events.addNamespace("beforeactivate", this.NAME + FOCUS_NAMESPACE);
  13328. this._focusTarget().off("." + this.NAME + FOCUS_NAMESPACE).on(focusInEvent, $.proxy(function(e) {
  13329. this._focusInAction({jQueryEvent: e})
  13330. }, this)).on(focusOutEvent, $.proxy(function(e) {
  13331. this._focusOutAction({jQueryEvent: e})
  13332. }, this)).on(beforeactivateEventNamespace, function(e) {
  13333. if (!$(e.target).is(":dx-focusable"))
  13334. e.preventDefault()
  13335. })
  13336. },
  13337. _focusInHandler: function(e) {
  13338. this._updateFocusState(e, true)
  13339. },
  13340. _focusOutHandler: function(e) {
  13341. this._updateFocusState(e, false)
  13342. },
  13343. _updateFocusState: function(e, isFocused) {
  13344. var currentTarget = e.currentTarget,
  13345. focusTargets = this._focusTarget();
  13346. if ($.inArray(currentTarget, focusTargets) !== -1)
  13347. $(e.currentTarget).toggleClass(FOCUSED_STATE_CLASS, isFocused)
  13348. },
  13349. _attachKeyboardEvents: function() {
  13350. var processor = this.option("_keyboardProcessor") || new ui.KeyboardProcessor({
  13351. element: this._keyboardEventBindingTarget(),
  13352. focusTarget: this._focusTarget()
  13353. });
  13354. this._keyboardProcessor = processor.reinitialize(this._keyboardHandler, this)
  13355. },
  13356. _keyboardHandler: function(options) {
  13357. var e = options.originalEvent,
  13358. key = options.key;
  13359. var keys = this._supportedKeys(),
  13360. func = keys[key];
  13361. if (func !== undefined) {
  13362. var handler = $.proxy(func, this);
  13363. return handler(e) || false
  13364. }
  13365. else
  13366. return true
  13367. },
  13368. _refreshFocusState: function() {
  13369. this._cleanFocusState();
  13370. this._renderFocusState()
  13371. },
  13372. _cleanFocusState: function() {
  13373. var $element = this._focusTarget();
  13374. $element.off("." + this.NAME + FOCUS_NAMESPACE);
  13375. $element.removeClass(FOCUSED_STATE_CLASS);
  13376. $element.removeAttr("tabindex");
  13377. if (this._keyboardProcessor)
  13378. this._keyboardProcessor.dispose()
  13379. },
  13380. _attachHoverEvents: function() {
  13381. var that = this,
  13382. hoverableSelector = that._activeStateUnit,
  13383. nameStart = events.addNamespace(HOVER_START, UI_FEEDBACK),
  13384. nameEnd = events.addNamespace(HOVER_END, UI_FEEDBACK);
  13385. that._eventBindingTarget().off(nameStart, hoverableSelector).off(nameEnd, hoverableSelector);
  13386. if (that.option("hoverStateEnabled")) {
  13387. var startAction = new DX.Action(function(args) {
  13388. that._hoverStartHandler(args.event);
  13389. var $target = args.element;
  13390. that._refreshHoveredElement($target)
  13391. });
  13392. that._eventBindingTarget().on(nameStart, hoverableSelector, function(e) {
  13393. startAction.execute({
  13394. element: $(e.target),
  13395. event: e
  13396. })
  13397. }).on(nameEnd, hoverableSelector, function(e) {
  13398. that._hoverEndHandler(e);
  13399. that._forgetHoveredElement()
  13400. })
  13401. }
  13402. else
  13403. that._toggleHoverClass(false)
  13404. },
  13405. _hoverStartHandler: $.noop,
  13406. _hoverEndHandler: $.noop,
  13407. _attachFeedbackEvents: function() {
  13408. var that = this,
  13409. feedbackSelector = that._activeStateUnit,
  13410. activeEventName = events.addNamespace("dxactive", UI_FEEDBACK),
  13411. inactiveEventName = events.addNamespace("dxinactive", UI_FEEDBACK);
  13412. that._eventBindingTarget().off(activeEventName, feedbackSelector).off(inactiveEventName, feedbackSelector);
  13413. if (that.option("activeStateEnabled")) {
  13414. var feedbackActionHandler = function(args) {
  13415. var $element = args.element,
  13416. value = args.value;
  13417. that._toggleActiveState($element, value)
  13418. };
  13419. var feedbackAction = new DX.Action(function(args) {
  13420. feedbackActionHandler(args)
  13421. }),
  13422. feedbackActionDisabled = new DX.Action(function(args) {
  13423. feedbackActionHandler(args)
  13424. }, {excludeValidators: ["disabled", "readOnly"]});
  13425. that._eventBindingTarget().on(activeEventName, feedbackSelector, {timeout: that._feedbackShowTimeout}, function(e) {
  13426. feedbackAction.execute({
  13427. element: $(e.currentTarget),
  13428. value: true
  13429. })
  13430. }).on(inactiveEventName, feedbackSelector, {timeout: that._feedbackHideTimeout}, function(e) {
  13431. feedbackActionDisabled.execute({
  13432. element: $(e.currentTarget),
  13433. value: false
  13434. })
  13435. })
  13436. }
  13437. },
  13438. _toggleActiveState: function($element, value) {
  13439. this._toggleHoverClass(!value);
  13440. $element.toggleClass(ACTIVE_STATE_CLASS, value)
  13441. },
  13442. _refreshHoveredElement: function(hoveredElement) {
  13443. var selector = this._activeStateUnit || this.element();
  13444. this._forgetHoveredElement();
  13445. this._hoveredElement = hoveredElement.closest(selector);
  13446. this._toggleHoverClass(true)
  13447. },
  13448. _forgetHoveredElement: function() {
  13449. this._toggleHoverClass(false);
  13450. delete this._hoveredElement
  13451. },
  13452. _toggleHoverClass: function(value) {
  13453. if (this._hoveredElement)
  13454. this._hoveredElement.toggleClass(HOVER_STATE_CLASS, value && this.option("hoverStateEnabled"))
  13455. },
  13456. _toggleDisabledState: function(value) {
  13457. this.element().toggleClass(DISABLED_STATE_CLASS, Boolean(value));
  13458. this._toggleHoverClass(!value);
  13459. this.setAria("disabled", value || undefined)
  13460. },
  13461. _setWidgetOption: function(widgetName, args) {
  13462. if (!this[widgetName])
  13463. return;
  13464. if ($.isPlainObject(args[0])) {
  13465. $.each(args[0], $.proxy(function(option, value) {
  13466. this._setWidgetOption(widgetName, [option, value])
  13467. }, this));
  13468. return
  13469. }
  13470. var optionName = args[0];
  13471. var value = args[1];
  13472. if (args.length === 1)
  13473. value = this.option(optionName);
  13474. var widgetOptionMap = this[widgetName + "OptionMap"];
  13475. this[widgetName].option(widgetOptionMap ? widgetOptionMap(optionName) : optionName, value)
  13476. },
  13477. _createComponent: function(element, name, config) {
  13478. config = config || {};
  13479. this._extendConfig(config, {
  13480. templateProvider: this.option("templateProvider"),
  13481. _templates: this.option("_templates")
  13482. });
  13483. return this.callBase(element, name, config)
  13484. },
  13485. _optionChanged: function(args) {
  13486. switch (args.name) {
  13487. case"disabled":
  13488. this._toggleDisabledState(args.value);
  13489. this._refreshFocusState();
  13490. break;
  13491. case"hint":
  13492. this._renderHint();
  13493. break;
  13494. case"activeStateEnabled":
  13495. this._attachFeedbackEvents();
  13496. break;
  13497. case"hoverStateEnabled":
  13498. this._attachHoverEvents();
  13499. break;
  13500. case"tabIndex":
  13501. case"_keyboardProcessor":
  13502. case"focusStateEnabled":
  13503. this._refreshFocusState();
  13504. break;
  13505. case"onFocusIn":
  13506. case"onFocusOut":
  13507. this._initFocusActions();
  13508. break;
  13509. case"accessKey":
  13510. this._renderAccessKey();
  13511. break;
  13512. case"visible":
  13513. var visible = args.value;
  13514. this._toggleVisibility(visible);
  13515. if (this._isVisibilityChangeSupported())
  13516. this._visibilityChanged(visible);
  13517. break;
  13518. case"onContentReady":
  13519. this._initContentReadyAction();
  13520. break;
  13521. case"_templates":
  13522. case"templateProvider":
  13523. this._refresh();
  13524. break;
  13525. default:
  13526. this.callBase(args)
  13527. }
  13528. },
  13529. beginUpdate: function() {
  13530. this._ready(false);
  13531. this.callBase()
  13532. },
  13533. endUpdate: function() {
  13534. this.callBase();
  13535. if (this._initialized)
  13536. this._ready(true)
  13537. },
  13538. _ready: function(value) {
  13539. if (arguments.length === 0)
  13540. return this._isReady;
  13541. this._isReady = value
  13542. },
  13543. setAria: function() {
  13544. var setAttribute = function(option) {
  13545. var attrName = $.inArray(option.name, ["role", "id"]) + 1 ? option.name : "aria-" + option.name,
  13546. attrValue = option.value;
  13547. if (attrValue === null || attrValue === undefined)
  13548. attrValue = undefined;
  13549. else
  13550. attrValue = attrValue.toString();
  13551. utils.toggleAttr(option.target, attrName, attrValue)
  13552. };
  13553. if (!$.isPlainObject(arguments[0]))
  13554. setAttribute({
  13555. name: arguments[0],
  13556. value: arguments[1],
  13557. target: arguments[2] || this._getAriaTarget()
  13558. });
  13559. else {
  13560. var $target = arguments[1] || this._getAriaTarget();
  13561. $.each(arguments[0], function(key, value) {
  13562. setAttribute({
  13563. name: key,
  13564. value: value,
  13565. target: $target
  13566. })
  13567. })
  13568. }
  13569. },
  13570. isReady: function() {
  13571. return this._ready()
  13572. },
  13573. repaint: function() {
  13574. this._refresh()
  13575. },
  13576. focus: function() {
  13577. this._focusTarget().focus()
  13578. },
  13579. registerKeyHandler: function(key, handler) {
  13580. var currentKeys = this._supportedKeys(),
  13581. addingKeys = {};
  13582. addingKeys[key] = handler;
  13583. this._supportedKeys = function() {
  13584. return $.extend(currentKeys, addingKeys)
  13585. }
  13586. }
  13587. })
  13588. })(jQuery, DevExpress);
  13589. /*! Module core, file ui.editor.js */
  13590. (function($, DX, undefined) {
  13591. var ui = DX.ui,
  13592. READONLY_STATE_CLASS = "dx-state-readonly",
  13593. INVALID_CLASS = "dx-invalid",
  13594. INVALID_MESSAGE = "dx-invalid-message",
  13595. INVALID_MESSAGE_AUTO = "dx-invalid-message-auto",
  13596. INVALID_MESSAGE_ALWAYS = "dx-invalid-message-always";
  13597. ui.validation = ui.validation || {};
  13598. ui.validation.findGroup = function() {
  13599. var group = this.option("validationGroup"),
  13600. $dxGroup;
  13601. if (!group) {
  13602. $dxGroup = this.element().parents(".dx-validationgroup:first");
  13603. if ($dxGroup.length)
  13604. group = $dxGroup.dxValidationGroup("instance");
  13605. else
  13606. group = this._modelByElement(this.element())
  13607. }
  13608. return group
  13609. };
  13610. ui.Editor = ui.Widget.inherit({
  13611. _init: function() {
  13612. this.callBase();
  13613. this.validationRequest = $.Callbacks();
  13614. var $element = this.element();
  13615. if ($element) {
  13616. $element.data("dx-validation-target", this);
  13617. this.on("disposing", function() {
  13618. $element.data("dx-validation-target", null)
  13619. })
  13620. }
  13621. this._createValueChangeAction()
  13622. },
  13623. _setDeprecatedOptions: function() {
  13624. this.callBase();
  13625. $.extend(this._deprecatedOptions, {valueChangeAction: {
  13626. since: "14.2",
  13627. alias: "onValueChanged",
  13628. message: "'onValueChanged' option instead"
  13629. }})
  13630. },
  13631. _setDefaultOptions: function() {
  13632. this.callBase();
  13633. this.option({
  13634. value: null,
  13635. onValueChanged: null,
  13636. activeStateEnabled: true,
  13637. readOnly: false,
  13638. isValid: true,
  13639. validationError: null,
  13640. validationMessageMode: "auto",
  13641. validationTooltipOffset: {
  13642. h: 0,
  13643. v: -10
  13644. }
  13645. })
  13646. },
  13647. _defaultOptionsRules: function() {
  13648. return this.callBase().concat([{
  13649. device: function(device) {
  13650. return device.platform === "android"
  13651. },
  13652. options: {invalidTooltipOffset: {
  13653. h: 9,
  13654. v: -7
  13655. }}
  13656. }, {
  13657. device: {platform: "win8"},
  13658. options: {invalidTooltipOffset: {
  13659. h: 9,
  13660. v: -4
  13661. }}
  13662. }])
  13663. },
  13664. _attachKeyboardEvents: function() {
  13665. if (this.option("readOnly"))
  13666. return;
  13667. this.callBase.apply(this, arguments);
  13668. this._attachChildKeyboardEvents()
  13669. },
  13670. _attachChildKeyboardEvents: $.noop,
  13671. _setOptionsByReference: function() {
  13672. this.callBase();
  13673. $.extend(this._optionsByReference, {validationError: true})
  13674. },
  13675. _createValueChangeAction: function() {
  13676. this._valueChangeAction = this._createActionByOption("onValueChanged", {excludeValidators: ["disabled", "readOnly"]})
  13677. },
  13678. _suppressValueChangeAction: function() {
  13679. this._valueChangeActionSuppressed = true
  13680. },
  13681. _resumeValueChangeAction: function() {
  13682. this._valueChangeActionSuppressed = false
  13683. },
  13684. _render: function() {
  13685. this._renderValidationState();
  13686. this._toggleReadOnlyState();
  13687. this.callBase()
  13688. },
  13689. _raiseValueChangeAction: function(value, previousValue, extraArguments) {
  13690. this._valueChangeAction(this._valueChangeArgs(value, previousValue))
  13691. },
  13692. _valueChangeArgs: function(value, previousValue) {
  13693. return {
  13694. value: value,
  13695. previousValue: previousValue,
  13696. jQueryEvent: this._valueChangeEventInstance
  13697. }
  13698. },
  13699. _saveValueChangeEvent: function(e) {
  13700. this._valueChangeEventInstance = e
  13701. },
  13702. _renderValidationState: function() {
  13703. var isValid = this.option("isValid"),
  13704. validationError = this.option("validationError"),
  13705. validationMessageMode = this.option("validationMessageMode"),
  13706. $element = this.element();
  13707. $element.toggleClass(INVALID_CLASS, !isValid);
  13708. this.setAria("invalid", !isValid || undefined);
  13709. if (this._$validationMessage) {
  13710. this._$validationMessage.remove();
  13711. this._$validationMessage = null
  13712. }
  13713. if (!isValid && validationError && validationError.message) {
  13714. this._$validationMessage = $("<div/>", {"class": INVALID_MESSAGE}).text(validationError.message).appendTo($element);
  13715. this._createComponent(this._$validationMessage, "dxTooltip", {
  13716. target: $element,
  13717. container: $element,
  13718. position: this._getValidationTooltipPosition("below"),
  13719. closeOnOutsideClick: false,
  13720. closeOnTargetScroll: false,
  13721. animation: null,
  13722. visible: true
  13723. });
  13724. this._$validationMessage.toggleClass(INVALID_MESSAGE_AUTO, validationMessageMode === "auto").toggleClass(INVALID_MESSAGE_ALWAYS, validationMessageMode === "always")
  13725. }
  13726. },
  13727. _getValidationTooltipPosition: function(positionRequest) {
  13728. var rtlEnabled = this.option("rtlEnabled"),
  13729. tooltipPositionSide = rtlEnabled ? "right" : "left",
  13730. tooltipOriginalOffset = this.option("validationTooltipOffset"),
  13731. tooltipOffset = {
  13732. h: tooltipOriginalOffset.h,
  13733. v: tooltipOriginalOffset.v
  13734. },
  13735. verticalPositions = positionRequest === "below" ? [" top", " bottom"] : [" bottom", " top"];
  13736. if (rtlEnabled)
  13737. tooltipOffset.h = -tooltipOffset.h;
  13738. if (positionRequest !== "below")
  13739. tooltipOffset.v = -tooltipOffset.v;
  13740. return {
  13741. offset: tooltipOffset,
  13742. my: tooltipPositionSide + verticalPositions[0],
  13743. at: tooltipPositionSide + verticalPositions[1],
  13744. collision: "none"
  13745. }
  13746. },
  13747. _toggleReadOnlyState: function() {
  13748. this.element().toggleClass(READONLY_STATE_CLASS, this.option("readOnly"));
  13749. this.setAria("readonly", this.option("readOnly") || undefined)
  13750. },
  13751. _optionChanged: function(args) {
  13752. switch (args.name) {
  13753. case"onValueChanged":
  13754. this._createValueChangeAction();
  13755. break;
  13756. case"isValid":
  13757. case"validationError":
  13758. case"validationMessageMode":
  13759. this._renderValidationState();
  13760. break;
  13761. case"readOnly":
  13762. this._toggleReadOnlyState();
  13763. this._refreshFocusState();
  13764. break;
  13765. case"value":
  13766. if (!this._valueChangeActionSuppressed) {
  13767. this._raiseValueChangeAction(args.value, args.previousValue);
  13768. this._saveValueChangeEvent(undefined)
  13769. }
  13770. if (args.value != args.previousValue)
  13771. this.validationRequest.fire({
  13772. value: args.value,
  13773. editor: this
  13774. });
  13775. break;
  13776. default:
  13777. this.callBase(args)
  13778. }
  13779. },
  13780. reset: function() {
  13781. this.option("value", null)
  13782. }
  13783. })
  13784. })(jQuery, DevExpress);
  13785. /*! Module core, file ui.CollectionWidget.js */
  13786. (function($, DX, undefined) {
  13787. var ui = DX.ui,
  13788. utils = DX.utils,
  13789. events = ui.events;
  13790. var COLLECTION_CLASS = "dx-collection",
  13791. ITEM_CLASS = "dx-item",
  13792. CONTENT_CLASS_POSTFIX = "-content",
  13793. ITEM_CONTENT_PLACEHOLDER_CLASS = "dx-item-content-placeholder",
  13794. ITEM_DATA_KEY = "dxItemData",
  13795. ITEM_TEMPLATE_ID_PREFIX = "tmpl-",
  13796. ITEMS_SELECTOR = "[data-options*='dxItem']",
  13797. SELECTED_ITEM_CLASS = "dx-item-selected",
  13798. FOCUSED_STATE_CLASS = "dx-state-focused",
  13799. ITEM_RESPONSE_WAIT_CLASS = "dx-item-response-wait",
  13800. EMPTY_COLLECTION = "dx-empty-collection",
  13801. TEMPLATE_WRAPPER_CLASS = "dx-template-wrapper";
  13802. var FOCUS_UP = "up",
  13803. FOCUS_DOWN = "down",
  13804. FOCUS_LEFT = "left",
  13805. FOCUS_RIGHT = "right",
  13806. FOCUS_PAGE_UP = "pageup",
  13807. FOCUS_PAGE_DOWN = "pagedown",
  13808. FOCUS_LAST = "last",
  13809. FOCUS_FIRST = "first";
  13810. var CollectionWidget = ui.Widget.inherit({
  13811. NAME: "CollectionWidget",
  13812. _activeStateUnit: "." + ITEM_CLASS,
  13813. _supportedKeys: function() {
  13814. var click = function(e) {
  13815. var $itemElement = this.option("focusedElement");
  13816. if (!$itemElement)
  13817. return;
  13818. e.target = $itemElement;
  13819. e.currentTarget = $itemElement;
  13820. this._itemClickHandler(e)
  13821. },
  13822. move = function(location, e) {
  13823. e.preventDefault();
  13824. e.stopPropagation();
  13825. this._moveFocus(location, e)
  13826. };
  13827. return $.extend(this.callBase(), {
  13828. space: click,
  13829. enter: click,
  13830. leftArrow: $.proxy(move, this, FOCUS_LEFT),
  13831. rightArrow: $.proxy(move, this, FOCUS_RIGHT),
  13832. upArrow: $.proxy(move, this, FOCUS_UP),
  13833. downArrow: $.proxy(move, this, FOCUS_DOWN),
  13834. pageUp: $.proxy(move, this, FOCUS_UP),
  13835. pageDown: $.proxy(move, this, FOCUS_DOWN),
  13836. home: $.proxy(move, this, FOCUS_FIRST),
  13837. end: $.proxy(move, this, FOCUS_LAST)
  13838. })
  13839. },
  13840. _setDeprecatedOptions: function() {
  13841. this.callBase();
  13842. $.extend(this._deprecatedOptions, {
  13843. itemClickAction: {
  13844. since: "14.2",
  13845. alias: "onItemClick"
  13846. },
  13847. itemHoldAction: {
  13848. since: "14.2",
  13849. alias: "onItemHold"
  13850. },
  13851. itemRenderedAction: {
  13852. since: "14.2",
  13853. alias: "onItemRendered"
  13854. },
  13855. itemRender: {
  13856. since: "14.2",
  13857. alias: "itemTemplate"
  13858. }
  13859. })
  13860. },
  13861. _setDefaultOptions: function() {
  13862. this.callBase();
  13863. this.option({
  13864. selectOnFocus: false,
  13865. loopItemFocus: true,
  13866. items: [],
  13867. itemTemplate: "item",
  13868. onItemRendered: null,
  13869. onItemClick: null,
  13870. onItemHold: null,
  13871. itemHoldTimeout: 750,
  13872. onItemContextMenu: null,
  13873. onFocusedItemChanged: null,
  13874. noDataText: Globalize.localize("dxCollectionWidget-noDataText"),
  13875. dataSource: null,
  13876. _itemAttributes: {},
  13877. itemTemplateProperty: "template",
  13878. focusOnSelectedItem: true,
  13879. focusedElement: null
  13880. })
  13881. },
  13882. _getAnonimousTemplateName: function() {
  13883. return "item"
  13884. },
  13885. _init: function() {
  13886. this.callBase();
  13887. this._cleanRenderedItems();
  13888. this._refreshDataSource()
  13889. },
  13890. _initTemplates: function() {
  13891. this._initItemsFromMarkup();
  13892. this.callBase()
  13893. },
  13894. _initItemsFromMarkup: function() {
  13895. var $items = this.element().contents().filter(ITEMS_SELECTOR);
  13896. if (!$items.length || this.option("items").length)
  13897. return;
  13898. var items = $.map($items, $.proxy(function(item) {
  13899. var $item = $(item);
  13900. var result = utils.getElementOptions(item).dxItem;
  13901. var isTemplateRequired = $.trim($item.html()) && !result.template;
  13902. if (isTemplateRequired)
  13903. result.template = this._prepareItemTemplate($item);
  13904. else
  13905. $item.remove();
  13906. return result
  13907. }, this));
  13908. this.option("items", items)
  13909. },
  13910. _prepareItemTemplate: function($item) {
  13911. var templateId = ITEM_TEMPLATE_ID_PREFIX + new DX.data.Guid;
  13912. var templateOptions = "dxTemplate: { name: \"" + templateId + "\" }";
  13913. $item.attr("data-options", templateOptions).data("options", templateOptions);
  13914. return templateId
  13915. },
  13916. _dataSourceOptions: function() {
  13917. return {paginate: false}
  13918. },
  13919. _cleanRenderedItems: function() {
  13920. this._renderedItemsCount = 0
  13921. },
  13922. _focusTarget: function() {
  13923. return this.element()
  13924. },
  13925. _focusInHandler: function(e) {
  13926. this.callBase.apply(this, arguments);
  13927. var $focusedElement = this.option("focusedElement");
  13928. if ($focusedElement && $focusedElement.length)
  13929. this._setFocusedItem($focusedElement);
  13930. else {
  13931. var $activeItem = this._getActiveItem();
  13932. this.option("focusedElement", $activeItem)
  13933. }
  13934. },
  13935. _focusOutHandler: function(e) {
  13936. this.callBase.apply(this, arguments);
  13937. var $target = this.option("focusedElement");
  13938. if ($target)
  13939. $target.removeClass(FOCUSED_STATE_CLASS)
  13940. },
  13941. _getActiveItem: function(last) {
  13942. var $focusedElement = this.option("focusedElement");
  13943. if ($focusedElement && $focusedElement.length)
  13944. return $focusedElement;
  13945. var index = this.option("focusOnSelectedItem") ? this.option("selectedIndex") : 0,
  13946. activeElements = this._getActiveElement(),
  13947. lastIndex = activeElements.length - 1;
  13948. if (index < 0)
  13949. index = last ? lastIndex : 0;
  13950. return activeElements.eq(index)
  13951. },
  13952. _renderFocusTarget: function() {
  13953. this.callBase.apply(this, arguments);
  13954. this._refreshActiveDescendant()
  13955. },
  13956. _moveFocus: function(location) {
  13957. var $items = this._itemElements().filter(":visible").not(".dx-state-disabled"),
  13958. $newTarget;
  13959. switch (location) {
  13960. case FOCUS_PAGE_UP:
  13961. case FOCUS_UP:
  13962. $newTarget = this._prevItem($items);
  13963. break;
  13964. case FOCUS_PAGE_DOWN:
  13965. case FOCUS_DOWN:
  13966. $newTarget = this._nextItem($items);
  13967. break;
  13968. case FOCUS_RIGHT:
  13969. $newTarget = this.option("rtlEnabled") ? this._prevItem($items) : this._nextItem($items);
  13970. break;
  13971. case FOCUS_LEFT:
  13972. $newTarget = this.option("rtlEnabled") ? this._nextItem($items) : this._prevItem($items);
  13973. break;
  13974. case FOCUS_FIRST:
  13975. $newTarget = $items.first();
  13976. break;
  13977. case FOCUS_LAST:
  13978. $newTarget = $items.last();
  13979. break;
  13980. default:
  13981. return false
  13982. }
  13983. if ($newTarget.length !== 0)
  13984. this.option("focusedElement", $newTarget)
  13985. },
  13986. _prevItem: function($items) {
  13987. var $target = this._getActiveItem(),
  13988. targetIndex = $items.index($target),
  13989. $last = $items.last(),
  13990. $item = $($items[targetIndex - 1]),
  13991. loop = this.option("loopItemFocus");
  13992. if ($item.length === 0 && loop)
  13993. $item = $last;
  13994. return $item
  13995. },
  13996. _nextItem: function($items) {
  13997. var $target = this._getActiveItem(true),
  13998. targetIndex = $items.index($target),
  13999. $first = $items.first(),
  14000. $item = $($items[targetIndex + 1]),
  14001. loop = this.option("loopItemFocus");
  14002. if ($item.length === 0 && loop)
  14003. $item = $first;
  14004. return $item
  14005. },
  14006. _selectFocusedItem: function($target) {
  14007. this.selectItem($target)
  14008. },
  14009. _removeFocusedItem: function($target) {
  14010. if ($target && $target.length) {
  14011. $target.removeClass(FOCUSED_STATE_CLASS);
  14012. $target.removeAttr("id")
  14013. }
  14014. },
  14015. _refreshActiveDescendant: function() {
  14016. this.setAria("activedescendant", "");
  14017. this.setAria("activedescendant", this.getFocusedItemId())
  14018. },
  14019. _setFocusedItem: function($target) {
  14020. if (!$target || !$target.length)
  14021. return;
  14022. $target.attr("id", this.getFocusedItemId());
  14023. $target.addClass(FOCUSED_STATE_CLASS);
  14024. this.onFocusedItemChanged(this.getFocusedItemId());
  14025. this._refreshActiveDescendant();
  14026. if (this.option("selectOnFocus"))
  14027. this._selectFocusedItem($target)
  14028. },
  14029. _optionChanged: function(args) {
  14030. switch (args.name) {
  14031. case"items":
  14032. case"_itemAttributes":
  14033. case"itemTemplateProperty":
  14034. this._cleanRenderedItems();
  14035. this._invalidate();
  14036. break;
  14037. case"dataSource":
  14038. this._refreshDataSource();
  14039. if (!this._dataSource)
  14040. this.option("items", []);
  14041. this._renderEmptyMessage();
  14042. break;
  14043. case"noDataText":
  14044. this._renderEmptyMessage();
  14045. break;
  14046. case"itemTemplate":
  14047. this._invalidate();
  14048. break;
  14049. case"onItemRendered":
  14050. this._createItemRenderAction();
  14051. break;
  14052. case"onItemClick":
  14053. break;
  14054. case"onItemHold":
  14055. case"itemHoldTimeout":
  14056. this._attachHoldEvent();
  14057. break;
  14058. case"onItemContextMenu":
  14059. this._attachContextMenuEvent();
  14060. break;
  14061. case"onFocusedItemChanged":
  14062. this.onFocusedItemChanged = this._createActionByOption("onFocusedItemChanged");
  14063. break;
  14064. case"selectOnFocus":
  14065. case"loopItemFocus":
  14066. case"focusOnSelectedItem":
  14067. break;
  14068. case"focusedElement":
  14069. this._removeFocusedItem(args.previousValue);
  14070. this._setFocusedItem(args.value);
  14071. break;
  14072. default:
  14073. this.callBase(args)
  14074. }
  14075. },
  14076. _loadNextPage: function() {
  14077. var dataSource = this._dataSource;
  14078. this._expectNextPageLoading();
  14079. dataSource.pageIndex(1 + dataSource.pageIndex());
  14080. return dataSource.load()
  14081. },
  14082. _expectNextPageLoading: function() {
  14083. this._startIndexForAppendedItems = 0
  14084. },
  14085. _expectLastItemLoading: function() {
  14086. this._startIndexForAppendedItems = -1
  14087. },
  14088. _forgetNextPageLoading: function() {
  14089. this._startIndexForAppendedItems = null
  14090. },
  14091. _dataSourceChangedHandler: function(newItems) {
  14092. var items = this.option("items");
  14093. if (this._initialized && items && this._shouldAppendItems()) {
  14094. this._renderedItemsCount = items.length;
  14095. if (!this._isLastPage() || this._startIndexForAppendedItems !== -1)
  14096. this.option().items = items.concat(newItems.slice(this._startIndexForAppendedItems));
  14097. this._forgetNextPageLoading();
  14098. this._renderContent();
  14099. this._renderFocusTarget()
  14100. }
  14101. else
  14102. this.option("items", newItems)
  14103. },
  14104. _dataSourceLoadErrorHandler: function() {
  14105. this._forgetNextPageLoading();
  14106. this.option("items", this.option("items"))
  14107. },
  14108. _shouldAppendItems: function() {
  14109. return this._startIndexForAppendedItems != null && this._allowDinamicItemsAppend()
  14110. },
  14111. _allowDinamicItemsAppend: function() {
  14112. return false
  14113. },
  14114. _clean: function() {
  14115. this._cleanFocusState();
  14116. this._cleanItemContainer()
  14117. },
  14118. _cleanItemContainer: function() {
  14119. this._itemContainer().empty()
  14120. },
  14121. _refresh: function() {
  14122. this._cleanRenderedItems();
  14123. this.callBase.apply(this, arguments)
  14124. },
  14125. _itemContainer: function() {
  14126. return this.element()
  14127. },
  14128. _itemClass: function() {
  14129. return ITEM_CLASS
  14130. },
  14131. _itemContentClass: function() {
  14132. return this._itemClass() + CONTENT_CLASS_POSTFIX
  14133. },
  14134. _selectedItemClass: function() {
  14135. return SELECTED_ITEM_CLASS
  14136. },
  14137. _itemResponseWaitClass: function() {
  14138. return ITEM_RESPONSE_WAIT_CLASS
  14139. },
  14140. _itemSelector: function() {
  14141. return "." + this._itemClass()
  14142. },
  14143. _itemDataKey: function() {
  14144. return ITEM_DATA_KEY
  14145. },
  14146. _itemElements: function() {
  14147. return this._itemContainer().find(this._itemSelector())
  14148. },
  14149. _render: function() {
  14150. this.callBase();
  14151. this.element().addClass(COLLECTION_CLASS);
  14152. this._attachClickEvent();
  14153. this._attachHoldEvent();
  14154. this._attachContextMenuEvent();
  14155. this.onFocusedItemChanged = this._createActionByOption("onFocusedItemChanged")
  14156. },
  14157. _attachClickEvent: function() {
  14158. var itemSelector = this._itemSelector(),
  14159. clickEventNamespace = events.addNamespace("dxclick", this.NAME),
  14160. pointerDownEventNamespace = events.addNamespace("dxpointerdown", this.NAME),
  14161. that = this;
  14162. var pointerDownAction = new DX.Action(function(args) {
  14163. var event = args.event;
  14164. that._itemPointerDownHandler(event)
  14165. });
  14166. this._itemContainer().off(clickEventNamespace, itemSelector).off(pointerDownEventNamespace, itemSelector).on(clickEventNamespace, itemSelector, $.proxy(this._itemClickHandler, this)).on(pointerDownEventNamespace, itemSelector, function(e) {
  14167. pointerDownAction.execute({
  14168. element: $(e.target),
  14169. event: e
  14170. })
  14171. })
  14172. },
  14173. _itemClickHandler: function(e) {
  14174. this._itemJQueryEventHandler(e, "onItemClick")
  14175. },
  14176. _itemPointerDownHandler: function(e) {
  14177. if (!this.option("focusStateEnabled"))
  14178. return;
  14179. var elementClass = this._itemClass(),
  14180. $target = $(e.target).closest("." + elementClass);
  14181. if ($target.hasClass(elementClass))
  14182. this.option("focusedElement", $target)
  14183. },
  14184. _attachHoldEvent: function() {
  14185. var $itemContainer = this._itemContainer(),
  14186. itemSelector = this._itemSelector(),
  14187. eventName = events.addNamespace("dxhold", this.NAME);
  14188. $itemContainer.off(eventName, itemSelector);
  14189. if (this._shouldAttachHoldEvent())
  14190. $itemContainer.on(eventName, itemSelector, {timeout: this._getHoldTimeout()}, $.proxy(this._itemHoldHandler, this))
  14191. },
  14192. _getHoldTimeout: function() {
  14193. return this.option("itemHoldTimeout")
  14194. },
  14195. _shouldAttachHoldEvent: function() {
  14196. return this.option("onItemHold")
  14197. },
  14198. _itemHoldHandler: function(e) {
  14199. this._itemJQueryEventHandler(e, "onItemHold")
  14200. },
  14201. _attachContextMenuEvent: function() {
  14202. var $itemContainer = this._itemContainer(),
  14203. itemSelector = this._itemSelector(),
  14204. eventName = events.addNamespace("dxcontextmenu", this.NAME);
  14205. $itemContainer.off(eventName, itemSelector);
  14206. if (this._shouldAttachContextMenuEvent())
  14207. $itemContainer.on(eventName, itemSelector, $.proxy(this._itemContextMenuHandler, this))
  14208. },
  14209. _shouldAttachContextMenuEvent: function() {
  14210. return this.option("onItemContextMenu")
  14211. },
  14212. _itemContextMenuHandler: function(e) {
  14213. this._itemJQueryEventHandler(e, "onItemContextMenu")
  14214. },
  14215. _renderContentImpl: function() {
  14216. var items = this.option("items") || [];
  14217. if (this._renderedItemsCount)
  14218. this._renderItems(items.slice(this._renderedItemsCount));
  14219. else
  14220. this._renderItems(items)
  14221. },
  14222. _renderItems: function(items) {
  14223. if (items.length)
  14224. $.each(items, $.proxy(this._renderItem, this));
  14225. this._renderEmptyMessage()
  14226. },
  14227. _renderItem: function(index, itemData, $container) {
  14228. $container = $container || this._itemContainer();
  14229. var $itemFrame = this._renderItemFrame(index, itemData, $container);
  14230. this._setElementData($itemFrame, itemData);
  14231. var $itemContent = $itemFrame.find("." + ITEM_CONTENT_PLACEHOLDER_CLASS);
  14232. $itemContent.removeClass(ITEM_CONTENT_PLACEHOLDER_CLASS);
  14233. $itemContent = this._renderItemContent(index, itemData, $itemContent);
  14234. this._postprocessRenderItem({
  14235. itemElement: $itemFrame,
  14236. itemContent: $itemContent,
  14237. itemData: itemData,
  14238. itemIndex: index
  14239. });
  14240. this._executeItemRenderAction(index, itemData, $itemFrame);
  14241. this._attachItemClickEvent(itemData, $itemFrame);
  14242. return $itemFrame.attr(this.option("_itemAttributes"))
  14243. },
  14244. _attachItemClickEvent: function(itemData, $itemElement) {
  14245. if (!itemData || !itemData.onClick)
  14246. return;
  14247. $itemElement.on("dxclick", $.proxy(function(e) {
  14248. this._itemEventHandlerByHandler($itemElement, itemData.onClick, {jQueryEvent: e})
  14249. }, this))
  14250. },
  14251. _renderItemContent: function(index, itemData, $container) {
  14252. var $itemNode = itemData && itemData.node;
  14253. var itemTemplateName = this._getItemTemplateName(itemData);
  14254. var itemTemplate = this._getTemplate(itemTemplateName, itemData, index, $container);
  14255. var renderArgs = {
  14256. index: index,
  14257. item: itemData,
  14258. container: $container
  14259. };
  14260. if ($itemNode) {
  14261. $container.replaceWith($itemNode);
  14262. $container = $itemNode;
  14263. this._addItemContentClasses($container, itemData)
  14264. }
  14265. else {
  14266. this._addItemContentClasses($container, itemData);
  14267. var $result = this._createItemByTemplate(itemTemplate, renderArgs);
  14268. if ($result.hasClass(TEMPLATE_WRAPPER_CLASS)) {
  14269. $container.replaceWith($result);
  14270. $container = $result;
  14271. this._addItemContentClasses($container, itemData)
  14272. }
  14273. }
  14274. return $container
  14275. },
  14276. _addItemContentClasses: function($container) {
  14277. $container.addClass([ITEM_CLASS + CONTENT_CLASS_POSTFIX, this._itemContentClass()].join(" "))
  14278. },
  14279. _renderItemFrame: function(index, itemData, $container) {
  14280. var itemFrameTemplate = this.option("templateProvider").getTemplates(this)["itemFrame"],
  14281. $itemFrame = itemFrameTemplate.render(utils.isDefined(itemData) ? itemData : {}, $container, index);
  14282. $itemFrame.appendTo($container);
  14283. return $itemFrame
  14284. },
  14285. _postprocessRenderItem: $.noop,
  14286. _executeItemRenderAction: function(index, itemData, itemElement) {
  14287. this._getItemRenderAction()({
  14288. itemElement: itemElement,
  14289. itemIndex: index,
  14290. itemData: itemData
  14291. })
  14292. },
  14293. _setElementData: function(element, data) {
  14294. element.addClass([ITEM_CLASS, this._itemClass()].join(" ")).data(this._itemDataKey(), data)
  14295. },
  14296. _createItemRenderAction: function() {
  14297. return this._itemRenderAction = this._createActionByOption("onItemRendered", {
  14298. element: this.element(),
  14299. excludeValidators: ["designMode", "disabled", "readOnly"],
  14300. category: "rendering"
  14301. })
  14302. },
  14303. _getItemRenderAction: function() {
  14304. return this._itemRenderAction || this._createItemRenderAction()
  14305. },
  14306. _getItemTemplateName: function(itemData) {
  14307. var templateProperty = this.option("itemTemplateProperty");
  14308. return itemData && itemData[templateProperty] || this.option("itemTemplate")
  14309. },
  14310. _createItemByTemplate: function(itemTemplate, renderArgs) {
  14311. return itemTemplate.render(renderArgs.item, renderArgs.container, renderArgs.index, "ignoreTarget")
  14312. },
  14313. _renderEmptyMessage: function() {
  14314. var noDataText = this.option("noDataText"),
  14315. items = this.option("items"),
  14316. hideNoData = !noDataText || items && items.length || this._isDataSourceLoading();
  14317. if (hideNoData && this._$nodata) {
  14318. this._$nodata.remove();
  14319. this._$nodata = null;
  14320. this.setAria("label", undefined)
  14321. }
  14322. if (!hideNoData) {
  14323. this._$nodata = this._$nodata || $("<div>").addClass("dx-empty-message");
  14324. this._$nodata.appendTo(this._itemContainer()).html(noDataText);
  14325. this.setAria("label", noDataText)
  14326. }
  14327. this.element().toggleClass(EMPTY_COLLECTION, !hideNoData)
  14328. },
  14329. _itemJQueryEventHandler: function(jQueryEvent, handlerOptionName, actionArgs, actionConfig) {
  14330. this._itemEventHandler(jQueryEvent.target, handlerOptionName, $.extend(actionArgs, {jQueryEvent: jQueryEvent}), actionConfig)
  14331. },
  14332. _itemEventHandler: function(initiator, handlerOptionName, actionArgs, actionConfig) {
  14333. var action = this._createActionByOption(handlerOptionName, $.extend({validatingTargetName: "itemElement"}, actionConfig));
  14334. return this._itemEventHandlerImpl(initiator, action, actionArgs)
  14335. },
  14336. _itemEventHandlerByHandler: function(initiator, handler, actionArgs, actionConfig) {
  14337. var action = this._createAction(handler, $.extend({validatingTargetName: "itemElement"}, actionConfig));
  14338. return this._itemEventHandlerImpl(initiator, action, actionArgs)
  14339. },
  14340. _itemEventHandlerImpl: function(initiator, action, actionArgs) {
  14341. var $itemElement = this._closestItemElement($(initiator));
  14342. return action($.extend(this._extendActionArgs($itemElement), actionArgs))
  14343. },
  14344. _extendActionArgs: function($itemElement) {
  14345. return {
  14346. itemElement: $itemElement,
  14347. itemIndex: $itemElement.index(this._itemSelector()),
  14348. itemData: this._getItemData($itemElement)
  14349. }
  14350. },
  14351. _closestItemElement: function($element) {
  14352. return $($element).closest(this._itemSelector())
  14353. },
  14354. _getItemData: function(itemElement) {
  14355. return $(itemElement).data(this._itemDataKey())
  14356. },
  14357. getFocusedItemId: function() {
  14358. if (!this._focusedItemId)
  14359. this._focusedItemId = new DevExpress.data.Guid;
  14360. return this._focusedItemId
  14361. },
  14362. itemElements: function() {
  14363. return this._itemElements()
  14364. },
  14365. itemsContainer: function() {
  14366. return this._itemContainer()
  14367. }
  14368. }).include(ui.DataHelperMixin);
  14369. ui.CollectionWidget = CollectionWidget
  14370. })(jQuery, DevExpress);
  14371. /*! Module core, file ui.CollectionWidget.edit.js */
  14372. (function($, DX, undefined) {
  14373. var ui = DX.ui,
  14374. utils = DX.utils;
  14375. var ITEM_DELETING_DATA_KEY = "dxItemDeleting";
  14376. var CollectionWidget = ui.CollectionWidget.inherit({
  14377. _setOptionsByReference: function() {
  14378. this.callBase();
  14379. $.extend(this._optionsByReference, {selectedItem: true})
  14380. },
  14381. _setDeprecatedOptions: function() {
  14382. this.callBase();
  14383. $.extend(this._deprecatedOptions, {itemSelectAction: {
  14384. since: "14.2",
  14385. message: "Use the 'onSelectionChanged' option instead"
  14386. }})
  14387. },
  14388. _setDefaultOptions: function() {
  14389. this.callBase();
  14390. this.option({
  14391. selectionMode: 'none',
  14392. selectionRequired: false,
  14393. selectionByClick: true,
  14394. selectedItems: [],
  14395. selectedIndex: -1,
  14396. selectedItem: null,
  14397. onSelectionChanged: null,
  14398. onItemReordered: null,
  14399. onItemDeleting: null,
  14400. onItemDeleted: null
  14401. })
  14402. },
  14403. _init: function() {
  14404. this.callBase();
  14405. this._initEditStrategy();
  14406. this._selectedItemIndices = []
  14407. },
  14408. _initEditStrategy: function() {
  14409. var strategy = ui.CollectionWidget.PlainEditStrategy;
  14410. this._editStrategy = new strategy(this)
  14411. },
  14412. _render: function() {
  14413. this._syncSelectionOptions();
  14414. this._normalizeSelectedItems();
  14415. this._initSelectedItems();
  14416. this.callBase();
  14417. this._renderSelection(this._selectedItemIndices, [])
  14418. },
  14419. _syncSelectionOptions: function(byOption) {
  14420. byOption = byOption || this._chooseSelectOption();
  14421. var selectedItem,
  14422. selectedItems;
  14423. switch (byOption) {
  14424. case"selectedIndex":
  14425. selectedItem = this._editStrategy.getItemDataByIndex(this.option("selectedIndex"));
  14426. if (utils.isDefined(selectedItem)) {
  14427. this._setOptionSilent("selectedItems", [selectedItem]);
  14428. this._setOptionSilent("selectedItem", selectedItem)
  14429. }
  14430. else {
  14431. this._setOptionSilent("selectedItems", []);
  14432. this._setOptionSilent("selectedItem", null)
  14433. }
  14434. break;
  14435. case"selectedItems":
  14436. selectedItems = this.option("selectedItems") || [];
  14437. this._setOptionSilent("selectedItem", selectedItems[0]);
  14438. this._setOptionSilent("selectedIndex", this._editStrategy.getIndexByItemData(selectedItems[0]));
  14439. break;
  14440. case"selectedItem":
  14441. selectedItem = this.option("selectedItem");
  14442. if (utils.isDefined(selectedItem)) {
  14443. this._setOptionSilent("selectedItems", [selectedItem]);
  14444. this._setOptionSilent("selectedIndex", this._editStrategy.getIndexByItemData(selectedItem))
  14445. }
  14446. else {
  14447. this._setOptionSilent("selectedItems", []);
  14448. this._setOptionSilent("selectedIndex", -1)
  14449. }
  14450. break
  14451. }
  14452. },
  14453. _chooseSelectOption: function() {
  14454. var optionName = "selectedIndex";
  14455. if (this.option("selectedItems").length)
  14456. optionName = "selectedItems";
  14457. else if (utils.isDefined(this.option("selectedItem")))
  14458. optionName = "selectedItem";
  14459. return optionName
  14460. },
  14461. _normalizeSelectedItems: function() {
  14462. if (this.option("selectionMode") === "none") {
  14463. this._setOptionSilent("selectedItems", []);
  14464. this._syncSelectionOptions("selectedItems")
  14465. }
  14466. else if (this.option("selectionMode") === "single") {
  14467. var newSelection = this._editStrategy.selectedItemIndices(this.option("selectedItems"));
  14468. if (newSelection.length > 1 || !newSelection.length && this.option("selectionRequired") && this.option("items") && this.option("items").length) {
  14469. var normalizedSelection = [newSelection[0] || this._selectedItemIndices[0] || 0];
  14470. this._setOptionSilent("selectedItems", this._editStrategy.fetchSelectedItems(normalizedSelection));
  14471. this._syncSelectionOptions("selectedItems")
  14472. }
  14473. }
  14474. },
  14475. _initSelectedItems: function() {
  14476. this._selectedItemIndices = this._editStrategy.selectedItemIndices(this.option("selectedItems"))
  14477. },
  14478. _renderSelection: $.noop,
  14479. _itemClickHandler: function(e) {
  14480. this._createAction($.proxy(function(e) {
  14481. this._itemSelectHandler(e.jQueryEvent)
  14482. }, this), {validatingTargetName: "itemElement"})({
  14483. itemElement: $(e.currentTarget),
  14484. jQueryEvent: e
  14485. });
  14486. this.callBase.apply(this, arguments)
  14487. },
  14488. _itemSelectHandler: function(e) {
  14489. if (!this.option("selectionByClick"))
  14490. return;
  14491. var $itemElement = e.currentTarget;
  14492. if (this.isItemSelected($itemElement))
  14493. this.unselectItem(e.currentTarget);
  14494. else
  14495. this.selectItem(e.currentTarget)
  14496. },
  14497. _selectedItemElement: function(index) {
  14498. return this._itemElements().eq(index)
  14499. },
  14500. _postprocessRenderItem: function(args) {
  14501. var $itemElement = $(args.itemElement);
  14502. if (this._isItemSelected(this._editStrategy.getNormalizedIndex($itemElement))) {
  14503. $itemElement.addClass(this._selectedItemClass());
  14504. this._setAriaSelected($itemElement, "true")
  14505. }
  14506. else
  14507. this._setAriaSelected($itemElement, "false")
  14508. },
  14509. _updateSelectedItems: function() {
  14510. var oldSelection = this._selectedItemIndices.slice(),
  14511. newSelection = this._editStrategy.selectedItemIndices(),
  14512. addedSelection = utils.removeDublicates(newSelection, oldSelection),
  14513. removedSelection = utils.removeDublicates(oldSelection, newSelection);
  14514. $.each(removedSelection, $.proxy(function(_, normalizedIndex) {
  14515. this._removeSelection(normalizedIndex)
  14516. }, this));
  14517. $.each(addedSelection, $.proxy(function(_, normalizedIndex) {
  14518. this._addSelection(normalizedIndex)
  14519. }, this));
  14520. if (removedSelection.length || addedSelection.length) {
  14521. var selectionChangePromise = this._selectionChangePromise;
  14522. this._updateSelection(addedSelection, removedSelection);
  14523. $.when(selectionChangePromise).done($.proxy(function() {
  14524. this._fireSelectItemEvent(addedSelection, removedSelection);
  14525. this._fireSelectionChangeEvent(addedSelection, removedSelection)
  14526. }, this))
  14527. }
  14528. },
  14529. _fireSelectionChangeEvent: function(addedSelection, removedSelection) {
  14530. this._createActionByOption("onSelectionChanged", {excludeValidators: ["disabled", "readOnly"]})({
  14531. addedItems: this._editStrategy.fetchSelectedItems(addedSelection),
  14532. removedItems: this._editStrategy.fetchSelectedItems(removedSelection)
  14533. })
  14534. },
  14535. _fireSelectItemEvent: function(addedSelection, removedSelection) {
  14536. if (this.NAME === "dxList" && this.option("selectionMode") !== "single")
  14537. return;
  14538. this._itemEventHandler(this._selectedItemElement(addedSelection[0]), "itemSelectAction", {
  14539. selectedIndex: addedSelection[0],
  14540. previousIndex: removedSelection[0]
  14541. }, {excludeValidators: ["disabled", "readOnly"]})
  14542. },
  14543. _updateSelection: function() {
  14544. this._renderSelection.apply(this, arguments)
  14545. },
  14546. _setAriaSelected: function($target, value) {
  14547. this.setAria("selected", value, $target)
  14548. },
  14549. _removeSelection: function(normalizedIndex) {
  14550. var $itemElement = this._editStrategy.getItemElement(normalizedIndex),
  14551. itemSelectionIndex = $.inArray(normalizedIndex, this._selectedItemIndices);
  14552. if (itemSelectionIndex > -1) {
  14553. $itemElement.removeClass(this._selectedItemClass());
  14554. this._setAriaSelected($itemElement, "false");
  14555. this._selectedItemIndices.splice(itemSelectionIndex, 1);
  14556. $itemElement.triggerHandler("stateChanged");
  14557. if (this.NAME === "dxList")
  14558. this._itemEventHandler($itemElement, "itemUnselectAction", {}, {excludeValidators: ["disabled", "readOnly"]})
  14559. }
  14560. },
  14561. _addSelection: function(normalizedIndex) {
  14562. var $itemElement = this._editStrategy.getItemElement(normalizedIndex);
  14563. if (normalizedIndex > -1 && !this._isItemSelected(normalizedIndex)) {
  14564. $itemElement.addClass(this._selectedItemClass());
  14565. this._setAriaSelected($itemElement, "true");
  14566. this._selectedItemIndices.push(normalizedIndex);
  14567. $itemElement.triggerHandler("stateChanged");
  14568. if (this.NAME === "dxList")
  14569. this._itemEventHandler($itemElement, "itemSelectAction", {}, {excludeValidators: ["disabled", "readOnly"]})
  14570. }
  14571. },
  14572. _isItemSelected: function(index) {
  14573. return $.inArray(index, this._selectedItemIndices) > -1
  14574. },
  14575. _optionChanged: function(args) {
  14576. if (this._cancelOptionChange)
  14577. return;
  14578. switch (args.name) {
  14579. case"items":
  14580. if (args.previousValue && args.previousValue.length > 0)
  14581. this._clearSelectedItems();
  14582. this.callBase(args);
  14583. break;
  14584. case"selectionMode":
  14585. this._invalidate();
  14586. break;
  14587. case"selectedIndex":
  14588. case"selectedItem":
  14589. case"selectedItems":
  14590. this._syncSelectionOptions(args.name);
  14591. this._normalizeSelectedItems();
  14592. this._updateSelectedItems();
  14593. break;
  14594. case"selectionRequired":
  14595. this._normalizeSelectedItems();
  14596. this._updateSelectedItems();
  14597. break;
  14598. case"selectionByClick":
  14599. case"onSelectionChanged":
  14600. case"onItemDeleting":
  14601. case"onItemDeleted":
  14602. case"onItemReordered":
  14603. case"itemSelectAction":
  14604. case"itemUnselectAction":
  14605. break;
  14606. default:
  14607. this.callBase(args)
  14608. }
  14609. },
  14610. _clearSelectedItems: function() {
  14611. this._selectedItemIndices = [];
  14612. this.option("selectedItems", [])
  14613. },
  14614. _setOptionSilent: function(name, value) {
  14615. this._cancelOptionChange = true;
  14616. this.option(name, value);
  14617. this._cancelOptionChange = false
  14618. },
  14619. _waitDeletingPrepare: function($itemElement) {
  14620. if ($itemElement.data(ITEM_DELETING_DATA_KEY))
  14621. return $.Deferred().resolve().promise();
  14622. $itemElement.data(ITEM_DELETING_DATA_KEY, true);
  14623. var deferred = $.Deferred(),
  14624. deletePromise = this._itemEventHandler($itemElement, "onItemDeleting", {}, {excludeValidators: ["disabled", "readOnly"]});
  14625. $.when(deletePromise).always($.proxy(function(value) {
  14626. var deletePromiseExists = !deletePromise,
  14627. deletePromiseResolved = !deletePromiseExists && deletePromise.state() === "resolved",
  14628. argumentsSpecified = !!arguments.length,
  14629. shouldDelete = deletePromiseExists || deletePromiseResolved && !argumentsSpecified || deletePromiseResolved && value;
  14630. $itemElement.data(ITEM_DELETING_DATA_KEY, false);
  14631. shouldDelete ? deferred.resolve() : deferred.reject()
  14632. }, this));
  14633. return deferred.promise()
  14634. },
  14635. _deleteItemFromDS: function($item) {
  14636. if (!this._dataSource)
  14637. return $.Deferred().resolve().promise();
  14638. var deferred = $.Deferred(),
  14639. disabledState = this.option("disabled"),
  14640. dataStore = this._dataSource.store();
  14641. this.option("disabled", true);
  14642. if (!dataStore.remove)
  14643. throw DX.Error("E1011");
  14644. dataStore.remove(dataStore.keyOf(this._getItemData($item))).done(function(key) {
  14645. if (key !== undefined)
  14646. deferred.resolve();
  14647. else
  14648. deferred.reject()
  14649. }).fail(function() {
  14650. deferred.reject()
  14651. });
  14652. deferred.always($.proxy(function() {
  14653. this.option("disabled", disabledState)
  14654. }, this));
  14655. return deferred
  14656. },
  14657. _tryRefreshLastPage: function() {
  14658. var deferred = $.Deferred();
  14659. if (this._isLastPage() || this.option("grouped"))
  14660. deferred.resolve();
  14661. else
  14662. this._refreshLastPage().done(function() {
  14663. deferred.resolve()
  14664. });
  14665. return deferred.promise()
  14666. },
  14667. _refreshLastPage: function() {
  14668. this._expectLastItemLoading();
  14669. return this._dataSource.load()
  14670. },
  14671. _updateSelectionAfterDelete: function(fromIndex) {
  14672. var itemIndex = $.inArray(fromIndex, this._selectedItemIndices);
  14673. if (itemIndex > -1)
  14674. this._selectedItemIndices.splice(itemIndex, 1);
  14675. this._editStrategy.updateSelectionAfterDelete(fromIndex);
  14676. this.option("selectedItems", this._editStrategy.fetchSelectedItems())
  14677. },
  14678. _simulateOptionChange: function(optionName) {
  14679. var optionValue = this.option(optionName);
  14680. if (optionValue instanceof DX.data.DataSource)
  14681. return;
  14682. this.fireEvent("optionChanged", [{
  14683. name: optionName,
  14684. fullName: optionName,
  14685. value: optionValue
  14686. }])
  14687. },
  14688. isItemSelected: function(itemElement) {
  14689. return this._isItemSelected(this._editStrategy.getNormalizedIndex(itemElement))
  14690. },
  14691. selectItem: function(itemElement) {
  14692. var itemIndex = this._editStrategy.getNormalizedIndex(itemElement);
  14693. if (itemIndex === -1)
  14694. return;
  14695. var itemSelectionIndex = $.inArray(itemIndex, this._selectedItemIndices);
  14696. if (itemSelectionIndex !== -1)
  14697. return;
  14698. if (this.option("selectionMode") === "single")
  14699. this.option("selectedItems", this._editStrategy.fetchSelectedItems([itemIndex]));
  14700. else {
  14701. var newSelectedIndices = this._selectedItemIndices.slice();
  14702. newSelectedIndices.push(itemIndex);
  14703. this.option("selectedItems", this._editStrategy.fetchSelectedItems(newSelectedIndices))
  14704. }
  14705. },
  14706. unselectItem: function(itemElement) {
  14707. var itemIndex = this._editStrategy.getNormalizedIndex(itemElement);
  14708. if (itemIndex === -1)
  14709. return;
  14710. var itemSelectionIndex = $.inArray(itemIndex, this._selectedItemIndices);
  14711. if (itemSelectionIndex === -1)
  14712. return;
  14713. var newSelectedIndices = this._selectedItemIndices.slice();
  14714. newSelectedIndices.splice(itemSelectionIndex, 1);
  14715. if (this.option("selectionRequired") && newSelectedIndices.length === 0)
  14716. return;
  14717. this.option("selectedItems", this._editStrategy.fetchSelectedItems(newSelectedIndices))
  14718. },
  14719. deleteItem: function(itemElement) {
  14720. var that = this,
  14721. deferred = $.Deferred(),
  14722. $item = this._editStrategy.getItemElement(itemElement),
  14723. index = this._editStrategy.getNormalizedIndex(itemElement),
  14724. changingOption = this._dataSource ? "dataSource" : "items",
  14725. itemResponseWaitClass = this._itemResponseWaitClass();
  14726. if (index > -1)
  14727. this._waitDeletingPrepare($item).done(function() {
  14728. $item.addClass(itemResponseWaitClass);
  14729. that._deleteItemFromDS($item).done(function() {
  14730. that._editStrategy.deleteItemAtIndex(index);
  14731. that._simulateOptionChange(changingOption);
  14732. that._updateSelectionAfterDelete(index);
  14733. that._itemEventHandler($item, "onItemDeleted", {}, {
  14734. beforeExecute: function() {
  14735. $item.detach()
  14736. },
  14737. excludeValidators: ["disabled", "readOnly"]
  14738. });
  14739. that._renderEmptyMessage();
  14740. that._tryRefreshLastPage().done(function() {
  14741. deferred.resolveWith(that)
  14742. })
  14743. }).fail(function() {
  14744. $item.removeClass(itemResponseWaitClass);
  14745. deferred.rejectWith(that)
  14746. })
  14747. }).fail(function() {
  14748. deferred.rejectWith(that)
  14749. });
  14750. else
  14751. deferred.rejectWith(that);
  14752. return deferred.promise()
  14753. },
  14754. reorderItem: function(itemElement, toItemElement) {
  14755. var deferred = $.Deferred(),
  14756. that = this,
  14757. strategy = this._editStrategy,
  14758. $movingItem = strategy.getItemElement(itemElement),
  14759. $destinationItem = strategy.getItemElement(toItemElement),
  14760. movingIndex = strategy.getNormalizedIndex(itemElement),
  14761. destinationIndex = strategy.getNormalizedIndex(toItemElement),
  14762. changingOption;
  14763. var canMoveItems = movingIndex > -1 && destinationIndex > -1 && movingIndex !== destinationIndex;
  14764. if (canMoveItems)
  14765. if (this._dataSource) {
  14766. changingOption = "dataSource";
  14767. deferred.resolveWith(this)
  14768. }
  14769. else {
  14770. changingOption = "items";
  14771. deferred.resolveWith(this)
  14772. }
  14773. else
  14774. deferred.rejectWith(this);
  14775. return deferred.promise().done(function() {
  14776. $destinationItem[strategy.itemPlacementFunc(movingIndex, destinationIndex)]($movingItem);
  14777. var newSelectedItems = strategy.getSelectedItemsAfterReorderItem(movingIndex, destinationIndex);
  14778. strategy.moveItemAtIndexToIndex(movingIndex, destinationIndex);
  14779. that._selectedItemIndices = strategy.selectedItemIndices(newSelectedItems);
  14780. that.option("selectedItems", strategy.fetchSelectedItems());
  14781. that._simulateOptionChange(changingOption);
  14782. that._itemEventHandler($movingItem, "onItemReordered", {
  14783. fromIndex: strategy.getIndex(movingIndex),
  14784. toIndex: strategy.getIndex(destinationIndex)
  14785. }, {excludeValidators: ["disabled", "readOnly"]})
  14786. })
  14787. }
  14788. });
  14789. ui.CollectionWidget = CollectionWidget
  14790. })(jQuery, DevExpress);
  14791. /*! Module core, file ui.collectionWidget.edit.strategy.js */
  14792. (function($, DX, undefined) {
  14793. var ui = DX.ui;
  14794. ui.CollectionWidget.EditStrategy = DX.Class.inherit({
  14795. ctor: function(collectionWidget) {
  14796. this._collectionWidget = collectionWidget
  14797. },
  14798. getIndexByItemData: DX.abstract,
  14799. getItemDataByIndex: DX.abstract,
  14800. getNormalizedIndex: function(value) {
  14801. if (this._isNormalisedItemIndex(value))
  14802. return value;
  14803. if (this._isItemIndex(value))
  14804. return this._normalizeItemIndex(value);
  14805. return this._getNormalizedItemIndex(value)
  14806. },
  14807. getIndex: function(value) {
  14808. if (this._isNormalisedItemIndex(value))
  14809. return this._denormalizeItemIndex(value);
  14810. if (this._isItemIndex(value))
  14811. return value;
  14812. return this._denormalizeItemIndex(this._getNormalizedItemIndex(value))
  14813. },
  14814. getItemElement: function(value) {
  14815. if (this._isNormalisedItemIndex(value))
  14816. return this._getItemByNormalizedIndex(value);
  14817. if (this._isItemIndex(value))
  14818. return this._getItemByNormalizedIndex(this._normalizeItemIndex(value));
  14819. return $(value)
  14820. },
  14821. deleteItemAtIndex: DX.abstract,
  14822. updateSelectionAfterDelete: DX.abstract,
  14823. fetchSelectedItems: DX.abstract,
  14824. selectedItemIndices: DX.abstract,
  14825. itemPlacementFunc: function(movingIndex, destinationIndex) {
  14826. return this._itemsFromSameParent(movingIndex, destinationIndex) && movingIndex < destinationIndex ? "after" : "before"
  14827. },
  14828. moveItemAtIndexToIndex: DX.abstract,
  14829. getSelectedItemsAfterReorderItem: function() {
  14830. return this._collectionWidget.option("selectedItems")
  14831. },
  14832. _isNormalisedItemIndex: function(index) {
  14833. return $.isNumeric(index)
  14834. },
  14835. _isItemIndex: DX.abstract,
  14836. _getNormalizedItemIndex: DX.abstract,
  14837. _normalizeItemIndex: DX.abstract,
  14838. _denormalizeItemIndex: DX.abstract,
  14839. _getItemByNormalizedIndex: DX.abstract,
  14840. _itemsFromSameParent: DX.abstract
  14841. })
  14842. })(jQuery, DevExpress);
  14843. /*! Module core, file ui.collectionWidget.edit.strategy.plain.js */
  14844. (function($, DX, undefined) {
  14845. var ui = DX.ui;
  14846. ui.CollectionWidget.PlainEditStrategy = ui.CollectionWidget.EditStrategy.inherit({
  14847. _getPlainItems: function() {
  14848. return this._collectionWidget.option("items") || []
  14849. },
  14850. getIndexByItemData: function(itemData) {
  14851. return $.inArray(itemData, this._getPlainItems())
  14852. },
  14853. getItemDataByIndex: function(index) {
  14854. return this._getPlainItems()[index]
  14855. },
  14856. deleteItemAtIndex: function(index) {
  14857. this._getPlainItems().splice(index, 1)
  14858. },
  14859. updateSelectionAfterDelete: function(fromIndex) {
  14860. var selectedItemIndices = this._collectionWidget._selectedItemIndices;
  14861. $.each(selectedItemIndices, function(i, index) {
  14862. if (index > fromIndex)
  14863. selectedItemIndices[i] -= 1
  14864. })
  14865. },
  14866. fetchSelectedItems: function(indices) {
  14867. indices = indices || this._collectionWidget._selectedItemIndices;
  14868. var items = this._getPlainItems(),
  14869. selectedItems = [];
  14870. $.each(indices, function(_, index) {
  14871. selectedItems.push(items[index])
  14872. });
  14873. return selectedItems
  14874. },
  14875. selectedItemIndices: function() {
  14876. var selectedIndices = [],
  14877. items = this._getPlainItems(),
  14878. selected = this._collectionWidget.option("selectedItems");
  14879. $.each(selected, function(_, selectedItem) {
  14880. var index = $.inArray(selectedItem, items);
  14881. if (index !== -1)
  14882. selectedIndices.push(index);
  14883. else
  14884. DX.log("W1002", selectedItem)
  14885. });
  14886. return selectedIndices
  14887. },
  14888. moveItemAtIndexToIndex: function(movingIndex, destinationIndex) {
  14889. var items = this._getPlainItems(),
  14890. movedItemData = items[movingIndex];
  14891. items.splice(movingIndex, 1);
  14892. items.splice(destinationIndex, 0, movedItemData)
  14893. },
  14894. _isItemIndex: function(index) {
  14895. return $.isNumeric(index)
  14896. },
  14897. _getNormalizedItemIndex: function(itemElement) {
  14898. return this._collectionWidget._itemElements().index(itemElement)
  14899. },
  14900. _normalizeItemIndex: function(index) {
  14901. return index
  14902. },
  14903. _denormalizeItemIndex: function(index) {
  14904. return index
  14905. },
  14906. _getItemByNormalizedIndex: function(index) {
  14907. return this._collectionWidget._itemElements().eq(index)
  14908. },
  14909. _itemsFromSameParent: function() {
  14910. return true
  14911. }
  14912. })
  14913. })(jQuery, DevExpress);
  14914. /*! Module core, file ui.tooltip.js */
  14915. (function($, DX, undefined) {
  14916. var $tooltip = null;
  14917. var createTooltip = function(options) {
  14918. options = $.extend({position: "top"}, options);
  14919. var content = options.content;
  14920. delete options.content;
  14921. return $("<div />").html(content).appendTo(DX.viewPort()).dxTooltip(options)
  14922. };
  14923. var removeTooltip = function() {
  14924. if (!$tooltip)
  14925. return;
  14926. $tooltip.remove();
  14927. $tooltip = null
  14928. };
  14929. var tooltip = {
  14930. show: function(options) {
  14931. removeTooltip();
  14932. $tooltip = createTooltip(options);
  14933. return $tooltip.dxTooltip("show")
  14934. },
  14935. hide: function() {
  14936. if (!$tooltip)
  14937. return $.when();
  14938. return $tooltip.dxTooltip("hide").done(removeTooltip).promise()
  14939. }
  14940. };
  14941. DX.ui.tooltip = tooltip
  14942. })(jQuery, DevExpress)
  14943. }
  14944. if (!DevExpress.MOD_WIDGETS_BASE) {
  14945. if (!window.DevExpress)
  14946. throw Error('Required module is not referenced: core');
  14947. /*! Module widgets-base, file ui.errors.js */
  14948. (function($, DX) {
  14949. $.extend(DX.ERROR_MESSAGES, {
  14950. E1001: "Module '{0}'. Controller '{1}' is already registered",
  14951. E1002: "Module '{0}'. Controller '{1}' must be inheritor of DevExpress.ui.dxDataGrid.Controller",
  14952. E1003: "Module '{0}'. View '{1}' is already registered",
  14953. E1004: "Module '{0}'. View '{1}' must be inheritor of DevExpress.ui.dxDataGrid.View",
  14954. E1005: "Public method '{0}' is already registered",
  14955. E1006: "Public method '{0}.{1}' is not exists",
  14956. E1007: "State storing can not be provided due to the restrictions of your browser",
  14957. E1010: "A template should contain dxTextBox widget",
  14958. E1011: "You have to implement 'remove' method in dataStore used by dxList to be able to delete items",
  14959. E1012: "Editing type '{0}' with name '{1}' not supported",
  14960. E1016: "Unexpected type of data source is provided for a lookup column",
  14961. E1018: "The 'collapseAll' method cannot be called when using a remote data source",
  14962. E1019: "Search mode '{0}' is unavailable",
  14963. E1020: "Type can not be changed after initialization",
  14964. E1021: "{0} '{1}' you are trying to remove does not exist",
  14965. E1022: "Markers option should be an array",
  14966. E1023: "Routes option should be an array",
  14967. E1024: "Google provider cannot be used in WinJS application",
  14968. E1025: "This layout is too complex to render",
  14969. E1026: "The 'custom' value is set to a summary item's summaryType option, but a function for calculating the custom summary is not assigned to the grid's calculateCustomSummary option",
  14970. E1030: "Unknown dxScrollView refresh strategy: '{0}'",
  14971. E1031: "Unknown subscription is detected in the dxScheduler widget: '{0}'",
  14972. E1032: "Unknown start date is detected in an appointment of the dxScheduler widget: '{0}'",
  14973. E1033: "Unknown step is specified for the scheduler's navigator: '{0}'",
  14974. E1034: "The current browser does not implement an API required for saving files",
  14975. W1001: "Key option can not be modified after initialization",
  14976. W1002: "Item '{0}' you are trying to select does not exist",
  14977. W1003: "Group with key '{0}' in which you are trying to select items does not exist",
  14978. W1004: "Item '{0}' you are trying to select in group '{1}' does not exist",
  14979. W1005: "Due to column data types being unspecified, data has been loaded twice in order to apply initial filter settings. To resolve this issue, specify data types for all grid columns."
  14980. })
  14981. })(jQuery, DevExpress);
  14982. /*! Module widgets-base, file ui.scrollable.js */
  14983. (function($, DX, undefined) {
  14984. var ui = DX.ui,
  14985. events = ui.events;
  14986. var SCROLLABLE = "dxScrollable",
  14987. SCROLLABLE_STRATEGY = "dxScrollableStrategy",
  14988. SCROLLABLE_CLASS = "dx-scrollable",
  14989. SCROLLABLE_DISABLED_CLASS = "dx-scrollable-disabled",
  14990. SCROLLABLE_CONTAINER_CLASS = "dx-scrollable-container",
  14991. SCROLLABLE_CONTENT_CLASS = "dx-scrollable-content",
  14992. VERTICAL = "vertical",
  14993. HORIZONTAL = "horizontal",
  14994. BOTH = "both";
  14995. var deviceDependentOptions = function() {
  14996. return [{
  14997. device: function(device) {
  14998. return !DX.support.nativeScrolling
  14999. },
  15000. options: {useNative: false}
  15001. }, {
  15002. device: function(device) {
  15003. return !DX.support.nativeScrolling && !DX.devices.isSimulator() && DX.devices.real().platform === "generic" && device.platform === "generic"
  15004. },
  15005. options: {
  15006. bounceEnabled: false,
  15007. scrollByThumb: true,
  15008. scrollByContent: DX.support.touch,
  15009. showScrollbar: "onHover"
  15010. }
  15011. }]
  15012. };
  15013. DX.registerComponent(SCROLLABLE, ui, DX.DOMComponent.inherit({
  15014. _setDeprecatedOptions: function() {
  15015. this.callBase();
  15016. $.extend(this._deprecatedOptions, {
  15017. updateAction: {
  15018. since: "14.2",
  15019. alias: "onUpdated"
  15020. },
  15021. scrollAction: {
  15022. since: "14.2",
  15023. alias: "onScroll"
  15024. },
  15025. startAction: {
  15026. since: "14.2",
  15027. alias: "onStart"
  15028. },
  15029. stopAction: {
  15030. since: "14.2",
  15031. alias: "onStop"
  15032. },
  15033. endAction: {
  15034. since: "14.2",
  15035. alias: "onEnd"
  15036. }
  15037. })
  15038. },
  15039. _setDefaultOptions: function() {
  15040. this.callBase();
  15041. this.option({
  15042. disabled: false,
  15043. onScroll: null,
  15044. direction: VERTICAL,
  15045. showScrollbar: "onScroll",
  15046. useNative: true,
  15047. bounceEnabled: true,
  15048. scrollByContent: true,
  15049. scrollByThumb: false,
  15050. onUpdated: null,
  15051. onStart: null,
  15052. onEnd: null,
  15053. onBounce: null,
  15054. onStop: null,
  15055. useSimulatedScrollbar: false,
  15056. useKeyboard: true,
  15057. inertiaEnabled: true,
  15058. pushBackValue: 0
  15059. })
  15060. },
  15061. _defaultOptionsRules: function() {
  15062. return this.callBase().concat(deviceDependentOptions(), [{
  15063. device: function(device) {
  15064. return DX.support.nativeScrolling && DX.devices.real().platform === "android"
  15065. },
  15066. options: {useSimulatedScrollbar: true}
  15067. }, {
  15068. device: function(device) {
  15069. return DX.devices.real().platform === "ios"
  15070. },
  15071. options: {pushBackValue: 1}
  15072. }])
  15073. },
  15074. _initOptions: function(options) {
  15075. this.callBase(options);
  15076. if (!("useSimulatedScrollbar" in options))
  15077. this._setUseSimulatedScrollbar()
  15078. },
  15079. _setUseSimulatedScrollbar: function() {
  15080. if (!this._initialOptions.useSimulatedScrollbar)
  15081. this.option("useSimulatedScrollbar", !this.option("useNative"))
  15082. },
  15083. _init: function() {
  15084. this.callBase();
  15085. this._initMarkup();
  15086. this._attachNativeScrollbarsCustomizationCss();
  15087. this._locked = false
  15088. },
  15089. _visibilityChanged: function(visible) {
  15090. if (this.element().is(":hidden"))
  15091. return;
  15092. if (visible) {
  15093. this.update();
  15094. this._toggleRTLDirection(this.option("rtlEnabled"));
  15095. this._savedScrollOffset && this.scrollTo(this._savedScrollOffset)
  15096. }
  15097. else
  15098. this._savedScrollOffset = this.scrollOffset()
  15099. },
  15100. _initMarkup: function() {
  15101. var $element = this.element().addClass(SCROLLABLE_CLASS),
  15102. $container = this._$container = $("<div>").addClass(SCROLLABLE_CONTAINER_CLASS),
  15103. $content = this._$content = $("<div>").addClass(SCROLLABLE_CONTENT_CLASS);
  15104. $content.append($element.contents()).appendTo($container);
  15105. $container.appendTo($element)
  15106. },
  15107. _dimensionChanged: function() {
  15108. this.update()
  15109. },
  15110. _attachNativeScrollbarsCustomizationCss: function() {
  15111. if (!(navigator.platform.indexOf('Mac') > -1 && DevExpress.browser['webkit']))
  15112. this.element().addClass("dx-scrollable-customizable-scrollbars")
  15113. },
  15114. _render: function() {
  15115. this._renderPushBackOffset();
  15116. this._renderDirection();
  15117. this._renderStrategy();
  15118. this._attachEventHandlers();
  15119. this._renderDisabledState();
  15120. this._createActions();
  15121. this.update();
  15122. this.callBase()
  15123. },
  15124. _renderPushBackOffset: function() {
  15125. var pushBackValue = this.option("pushBackValue");
  15126. this._$content.css({
  15127. paddingTop: pushBackValue,
  15128. paddingBottom: pushBackValue
  15129. })
  15130. },
  15131. _toggleRTLDirection: function(rtl) {
  15132. this.callBase(rtl);
  15133. if (rtl && this.option("direction") !== VERTICAL)
  15134. this.scrollTo({left: this.scrollWidth() - this.clientWidth()})
  15135. },
  15136. _attachEventHandlers: function() {
  15137. var strategy = this._strategy;
  15138. var initEventData = {
  15139. getDirection: $.proxy(strategy.getDirection, strategy),
  15140. validate: $.proxy(this._validate, this),
  15141. isNative: this.option("useNative")
  15142. };
  15143. this._$container.off("." + SCROLLABLE).on(events.addNamespace("scroll", SCROLLABLE), $.proxy(strategy.handleScroll, strategy)).on(events.addNamespace("dxscrollinit", SCROLLABLE), initEventData, $.proxy(this._initHandler, this)).on(events.addNamespace("dxscrollstart", SCROLLABLE), $.proxy(strategy.handleStart, strategy)).on(events.addNamespace("dxscroll", SCROLLABLE), $.proxy(strategy.handleMove, strategy)).on(events.addNamespace("dxscrollend", SCROLLABLE), $.proxy(strategy.handleEnd, strategy)).on(events.addNamespace("dxscrollcancel", SCROLLABLE), $.proxy(strategy.handleCancel, strategy)).on(events.addNamespace("dxscrollstop", SCROLLABLE), $.proxy(strategy.handleStop, strategy))
  15144. },
  15145. _validate: function(e) {
  15146. if (this._isLocked())
  15147. return false;
  15148. this.update();
  15149. return this._strategy.validate(e)
  15150. },
  15151. _initHandler: function() {
  15152. var strategy = this._strategy;
  15153. strategy.handleInit.apply(strategy, arguments)
  15154. },
  15155. _renderDisabledState: function() {
  15156. this.element().toggleClass(SCROLLABLE_DISABLED_CLASS, this.option("disabled"));
  15157. if (this.option("disabled"))
  15158. this._lock();
  15159. else
  15160. this._unlock()
  15161. },
  15162. _renderDirection: function() {
  15163. this.element().removeClass("dx-scrollable-" + HORIZONTAL).removeClass("dx-scrollable-" + VERTICAL).removeClass("dx-scrollable-" + BOTH).addClass("dx-scrollable-" + this.option("direction"))
  15164. },
  15165. _renderStrategy: function() {
  15166. this._createStrategy();
  15167. this._strategy.render();
  15168. this.element().data(SCROLLABLE_STRATEGY, this._strategy)
  15169. },
  15170. _createStrategy: function() {
  15171. this._strategy = this.option("useNative") ? new ui.dxScrollable.NativeStrategy(this) : new ui.dxScrollable.SimulatedStrategy(this)
  15172. },
  15173. _createActions: function() {
  15174. this._strategy.createActions()
  15175. },
  15176. _clean: function() {
  15177. this._strategy.dispose()
  15178. },
  15179. _optionChanged: function(args) {
  15180. switch (args.name) {
  15181. case"onStart":
  15182. case"onEnd":
  15183. case"onStop":
  15184. case"onUpdated":
  15185. case"onScroll":
  15186. case"onBounce":
  15187. this._createActions();
  15188. break;
  15189. case"direction":
  15190. this._resetInactiveDirection();
  15191. this._invalidate();
  15192. break;
  15193. case"useNative":
  15194. this._setUseSimulatedScrollbar();
  15195. this._invalidate();
  15196. break;
  15197. case"inertiaEnabled":
  15198. case"bounceEnabled":
  15199. case"scrollByContent":
  15200. case"scrollByThumb":
  15201. case"bounceEnabled":
  15202. case"useKeyboard":
  15203. case"showScrollbar":
  15204. case"useSimulatedScrollbar":
  15205. case"pushBackValue":
  15206. this._invalidate();
  15207. break;
  15208. case"disabled":
  15209. this._renderDisabledState();
  15210. break;
  15211. default:
  15212. this.callBase(args)
  15213. }
  15214. },
  15215. _resetInactiveDirection: function() {
  15216. var inactiveProp = this._getInactiveProp();
  15217. if (!inactiveProp)
  15218. return;
  15219. var scrollOffset = this.scrollOffset();
  15220. scrollOffset[inactiveProp] = 0;
  15221. this.scrollTo(scrollOffset)
  15222. },
  15223. _getInactiveProp: function() {
  15224. var direction = this.option("direction");
  15225. if (direction === VERTICAL)
  15226. return "left";
  15227. if (direction === HORIZONTAL)
  15228. return "top"
  15229. },
  15230. _location: function() {
  15231. return this._strategy.location()
  15232. },
  15233. _normalizeLocation: function(location) {
  15234. var direction = this.option("direction");
  15235. return {
  15236. left: $.isPlainObject(location) ? -(location.left || location.x || 0) : direction !== VERTICAL ? -location : 0,
  15237. top: $.isPlainObject(location) ? -(location.top || location.y || 0) : direction !== HORIZONTAL ? -location : 0
  15238. }
  15239. },
  15240. _isLocked: function() {
  15241. return this._locked
  15242. },
  15243. _lock: function() {
  15244. this._locked = true
  15245. },
  15246. _unlock: function() {
  15247. this._locked = false
  15248. },
  15249. _isDirection: function(direction) {
  15250. var current = this.option("direction");
  15251. if (direction === VERTICAL)
  15252. return current !== HORIZONTAL;
  15253. if (direction === HORIZONTAL)
  15254. return current !== VERTICAL;
  15255. return current === direction
  15256. },
  15257. _updateAllowedDirection: function() {
  15258. var allowedDirections = this._strategy._allowedDirections();
  15259. if (this._isDirection(BOTH) && allowedDirections.vertical && allowedDirections.horizontal)
  15260. this._allowedDirectionValue = BOTH;
  15261. else if (this._isDirection(HORIZONTAL) && allowedDirections.horizontal)
  15262. this._allowedDirectionValue = HORIZONTAL;
  15263. else if (this._isDirection(VERTICAL) && allowedDirections.vertical)
  15264. this._allowedDirectionValue = VERTICAL;
  15265. else
  15266. this._allowedDirectionValue = null
  15267. },
  15268. _allowedDirection: function() {
  15269. return this._allowedDirectionValue
  15270. },
  15271. content: function() {
  15272. return this._$content
  15273. },
  15274. scrollOffset: function() {
  15275. var location = this._location();
  15276. return {
  15277. top: -location.top,
  15278. left: -location.left
  15279. }
  15280. },
  15281. scrollTop: function() {
  15282. return this.scrollOffset().top
  15283. },
  15284. scrollLeft: function() {
  15285. return this.scrollOffset().left
  15286. },
  15287. clientHeight: function() {
  15288. return this._$container.height()
  15289. },
  15290. scrollHeight: function() {
  15291. return this.content().height()
  15292. },
  15293. clientWidth: function() {
  15294. return this._$container.width()
  15295. },
  15296. scrollWidth: function() {
  15297. return this.content().width()
  15298. },
  15299. update: function() {
  15300. this._strategy.update();
  15301. this._updateAllowedDirection();
  15302. return $.when().promise()
  15303. },
  15304. scrollBy: function(distance) {
  15305. distance = this._normalizeLocation(distance);
  15306. if (!distance.top && !distance.left)
  15307. return;
  15308. this._strategy.scrollBy(distance)
  15309. },
  15310. scrollTo: function(targetLocation) {
  15311. targetLocation = this._normalizeLocation(targetLocation);
  15312. var location = this._location();
  15313. this.scrollBy({
  15314. left: location.left - targetLocation.left,
  15315. top: location.top - targetLocation.top
  15316. })
  15317. },
  15318. scrollToElement: function(element, offset) {
  15319. offset = offset || {};
  15320. var $element = $(element);
  15321. var elementInsideContent = this.content().find(element).length;
  15322. var elementIsInsideContent = $element.parents("." + SCROLLABLE_CLASS).length - $element.parents("." + SCROLLABLE_CONTENT_CLASS).length === 0;
  15323. if (!elementInsideContent || !elementIsInsideContent)
  15324. return;
  15325. var scrollPosition = {
  15326. top: 0,
  15327. left: 0
  15328. };
  15329. var direction = this.option("direction");
  15330. if (direction !== VERTICAL)
  15331. scrollPosition.left = this._scrollToElementPosition($element, HORIZONTAL, offset);
  15332. if (direction !== HORIZONTAL)
  15333. scrollPosition.top = this._scrollToElementPosition($element, VERTICAL, offset);
  15334. this.scrollTo(scrollPosition)
  15335. },
  15336. _scrollToElementPosition: function($element, direction, offset) {
  15337. var isVertical = direction === VERTICAL;
  15338. var startOffset = (isVertical ? offset.top : offset.left) || 0;
  15339. var endOffset = (isVertical ? offset.bottom : offset.right) || 0;
  15340. var pushBackOffset = isVertical ? this.option("pushBackValue") : 0;
  15341. var elementPositionRelativeToContent = this._elementPositionRelativeToContent($element, isVertical ? 'top' : 'left');
  15342. var elementPosition = elementPositionRelativeToContent - pushBackOffset;
  15343. var elementSize = $element[isVertical ? 'outerHeight' : 'outerWidth']();
  15344. var elementBottom = elementPositionRelativeToContent + elementSize;
  15345. var scrollLocation = (isVertical ? this.scrollTop() : this.scrollLeft()) - startOffset;
  15346. var clientSize = (isVertical ? this.clientHeight() : this.clientWidth()) - startOffset - endOffset;
  15347. var scrollBottom = scrollLocation + clientSize;
  15348. var isEntirelyVisible = scrollLocation <= elementPosition && scrollBottom >= elementBottom;
  15349. var isEntirelyWithOversizeVisible = scrollLocation >= elementPosition && scrollBottom <= elementBottom;
  15350. var isAlreadyVisible = isEntirelyVisible || isEntirelyWithOversizeVisible;
  15351. var isElementAboveScrollLocation = scrollLocation > elementPosition;
  15352. return isAlreadyVisible ? scrollLocation : elementPosition - (isElementAboveScrollLocation ? 0 : clientSize - elementSize)
  15353. },
  15354. _elementPositionRelativeToContent: function($element, prop) {
  15355. var result = 0;
  15356. while (this._hasScrollContent($element)) {
  15357. result += $element.position()[prop];
  15358. $element = $element.offsetParent()
  15359. }
  15360. return result
  15361. },
  15362. _hasScrollContent: function($element) {
  15363. var $content = this.content();
  15364. return $element.closest($content).length && !$element.is($content)
  15365. }
  15366. }));
  15367. ui.dxScrollable.deviceDependentOptions = deviceDependentOptions
  15368. })(jQuery, DevExpress);
  15369. /*! Module widgets-base, file ui.scrollbar.js */
  15370. (function($, DX, undefined) {
  15371. var ui = DX.ui,
  15372. events = ui.events;
  15373. var SCROLLBAR = "dxScrollbar",
  15374. SCROLLABLE_SCROLLBAR_CLASS = "dx-scrollable-scrollbar",
  15375. SCROLLABLE_SCROLLBAR_ACTIVE_CLASS = SCROLLABLE_SCROLLBAR_CLASS + "-active",
  15376. SCROLLABLE_SCROLL_CLASS = "dx-scrollable-scroll",
  15377. SCROLLABLE_SCROLL_CONTENT_CLASS = "dx-scrollable-scroll-content",
  15378. HOVER_ENABLED_STATE = "dx-scrollbar-hoverable",
  15379. HORIZONTAL = "horizontal",
  15380. THUMB_MIN_SIZE = 15;
  15381. var SCROLLBAR_VISIBLE = {
  15382. onScroll: "onScroll",
  15383. onHover: "onHover",
  15384. always: "always",
  15385. never: "never"
  15386. };
  15387. DX.registerComponent(SCROLLBAR, ui.dxScrollable, ui.Widget.inherit({
  15388. _setDefaultOptions: function() {
  15389. this.callBase();
  15390. this.option({
  15391. direction: null,
  15392. visible: false,
  15393. activeStateEnabled: false,
  15394. visibilityMode: SCROLLBAR_VISIBLE.onScroll,
  15395. containerSize: 0,
  15396. contentSize: 0,
  15397. expandable: true
  15398. })
  15399. },
  15400. _init: function() {
  15401. this.callBase();
  15402. this._isHovered = false
  15403. },
  15404. _render: function() {
  15405. this._renderThumb();
  15406. this.callBase();
  15407. this._renderDirection();
  15408. this._update();
  15409. this._attachPointerDownHandler();
  15410. this.option("hoverStateEnabled", this._isHoverMode());
  15411. this.element().toggleClass(HOVER_ENABLED_STATE, this.option("hoverStateEnabled"))
  15412. },
  15413. _renderThumb: function() {
  15414. this._$thumb = $("<div>").addClass(SCROLLABLE_SCROLL_CLASS);
  15415. $("<div>").addClass(SCROLLABLE_SCROLL_CONTENT_CLASS).appendTo(this._$thumb);
  15416. this.element().addClass(SCROLLABLE_SCROLLBAR_CLASS).append(this._$thumb)
  15417. },
  15418. isThumb: function($element) {
  15419. return !!this.element().find($element).length
  15420. },
  15421. _isHoverMode: function() {
  15422. return this.option("visibilityMode") === SCROLLBAR_VISIBLE.onHover && this.option("expandable")
  15423. },
  15424. _renderDirection: function() {
  15425. var direction = this.option("direction");
  15426. this.element().addClass("dx-scrollbar-" + direction);
  15427. this._dimension = direction === HORIZONTAL ? "width" : "height";
  15428. this._prop = direction === HORIZONTAL ? "left" : "top"
  15429. },
  15430. _attachPointerDownHandler: function() {
  15431. this._$thumb.on(events.addNamespace("dxpointerdown", SCROLLBAR), $.proxy(this.feedbackOn, this))
  15432. },
  15433. feedbackOn: function() {
  15434. this.element().addClass(SCROLLABLE_SCROLLBAR_ACTIVE_CLASS);
  15435. activeScrollbar = this
  15436. },
  15437. feedbackOff: function() {
  15438. this.element().removeClass(SCROLLABLE_SCROLLBAR_ACTIVE_CLASS);
  15439. activeScrollbar = null
  15440. },
  15441. cursorEnter: function() {
  15442. this._isHovered = true;
  15443. this.option("visible", true)
  15444. },
  15445. cursorLeave: function() {
  15446. this._isHovered = false;
  15447. this.option("visible", false)
  15448. },
  15449. _renderDimensions: function() {
  15450. this._$thumb.outerHeight(this.option("height"));
  15451. this._$thumb.outerWidth(this.option("width"))
  15452. },
  15453. _toggleVisibility: function(visible) {
  15454. if (this.option("visibilityMode") === SCROLLBAR_VISIBLE.onScroll)
  15455. this._$thumb.css("opacity");
  15456. visible = this._adjustVisibility(visible);
  15457. this.option().visible = visible;
  15458. this._$thumb.toggleClass("dx-state-invisible", !visible)
  15459. },
  15460. _adjustVisibility: function(visible) {
  15461. if (this.containerToContentRatio() && !this._needScrollbar())
  15462. return false;
  15463. switch (this.option("visibilityMode")) {
  15464. case SCROLLBAR_VISIBLE.onScroll:
  15465. break;
  15466. case SCROLLBAR_VISIBLE.onHover:
  15467. visible = visible || !!this._isHovered;
  15468. break;
  15469. case SCROLLBAR_VISIBLE.never:
  15470. visible = false;
  15471. break;
  15472. case SCROLLBAR_VISIBLE.always:
  15473. visible = true;
  15474. break
  15475. }
  15476. return visible
  15477. },
  15478. moveTo: function(location) {
  15479. if (this._isHidden())
  15480. return;
  15481. if ($.isPlainObject(location))
  15482. location = location[this._prop] || 0;
  15483. var scrollBarLocation = {};
  15484. scrollBarLocation[this._prop] = this._calculateScrollBarPosition(location);
  15485. DX.translator.move(this._$thumb, scrollBarLocation)
  15486. },
  15487. _calculateScrollBarPosition: function(location) {
  15488. return -location * this._thumbRatio
  15489. },
  15490. _update: function() {
  15491. var containerSize = this.option("containerSize"),
  15492. contentSize = this.option("contentSize");
  15493. this._containerToContentRatio = containerSize / contentSize;
  15494. var thumbSize = Math.round(Math.max(Math.round(containerSize * this._containerToContentRatio), THUMB_MIN_SIZE));
  15495. this._thumbRatio = (containerSize - thumbSize) / (contentSize - containerSize);
  15496. this.option(this._dimension, thumbSize);
  15497. this.element().toggle(this._needScrollbar())
  15498. },
  15499. _isHidden: function() {
  15500. return this.option("visibilityMode") === SCROLLBAR_VISIBLE.never
  15501. },
  15502. _needScrollbar: function() {
  15503. return !this._isHidden() && this._containerToContentRatio < 1
  15504. },
  15505. containerToContentRatio: function() {
  15506. return this._containerToContentRatio
  15507. },
  15508. _normalizeSize: function(size) {
  15509. return $.isPlainObject(size) ? size[this._dimension] || 0 : size
  15510. },
  15511. _clean: function() {
  15512. this.callBase();
  15513. if (this === activeScrollbar)
  15514. activeScrollbar = null;
  15515. this._$thumb.off("." + SCROLLBAR)
  15516. },
  15517. _optionChanged: function(args) {
  15518. if (this._isHidden())
  15519. return;
  15520. switch (args.name) {
  15521. case"containerSize":
  15522. case"contentSize":
  15523. this.option()[args.name] = this._normalizeSize(args.value);
  15524. this._update();
  15525. break;
  15526. case"visibilityMode":
  15527. case"direction":
  15528. this._invalidate();
  15529. break;
  15530. default:
  15531. this.callBase.apply(this, arguments)
  15532. }
  15533. },
  15534. update: function() {
  15535. this._adjustVisibility() && this.option("visible", true)
  15536. }
  15537. }));
  15538. var activeScrollbar = null;
  15539. $(document).on(events.addNamespace("dxpointerup", SCROLLBAR), function() {
  15540. if (activeScrollbar)
  15541. activeScrollbar.feedbackOff()
  15542. })
  15543. })(jQuery, DevExpress);
  15544. /*! Module widgets-base, file ui.scrollable.native.js */
  15545. (function($, DX, undefined) {
  15546. var ui = DX.ui,
  15547. devices = DX.devices;
  15548. var SCROLLABLE_NATIVE = "dxNativeScrollable",
  15549. SCROLLABLE_NATIVE_CLASS = "dx-scrollable-native",
  15550. SCROLLABLE_SCROLLBAR_SIMULATED = "dx-scrollable-scrollbar-simulated",
  15551. SCROLLABLE_SCROLLBARS_HIDDEN = "dx-scrollable-scrollbars-hidden",
  15552. VERTICAL = "vertical",
  15553. HORIZONTAL = "horizontal",
  15554. HIDE_SCROLLBAR_TIMOUT = 500;
  15555. ui.dxScrollable.NativeStrategy = DX.Class.inherit({
  15556. ctor: function(scrollable) {
  15557. this._init(scrollable)
  15558. },
  15559. _init: function(scrollable) {
  15560. this._component = scrollable;
  15561. this._$element = scrollable.element();
  15562. this._$container = scrollable._$container;
  15563. this._$content = scrollable._$content;
  15564. this._direction = scrollable.option("direction");
  15565. this._useSimulatedScrollbar = scrollable.option("useSimulatedScrollbar");
  15566. this._showScrollbar = scrollable.option("showScrollbar");
  15567. this.option = $.proxy(scrollable.option, scrollable);
  15568. this._createActionByOption = $.proxy(scrollable._createActionByOption, scrollable);
  15569. this._isLocked = $.proxy(scrollable._isLocked, scrollable);
  15570. this._isDirection = $.proxy(scrollable._isDirection, scrollable);
  15571. this._allowedDirection = $.proxy(scrollable._allowedDirection, scrollable)
  15572. },
  15573. render: function() {
  15574. var device = devices.real(),
  15575. deviceType = device.platform;
  15576. this._$element.addClass(SCROLLABLE_NATIVE_CLASS).addClass(SCROLLABLE_NATIVE_CLASS + "-" + deviceType).toggleClass(SCROLLABLE_SCROLLBARS_HIDDEN, !this._showScrollbar);
  15577. if (this._showScrollbar && this._useSimulatedScrollbar)
  15578. this._renderScrollbars()
  15579. },
  15580. _renderScrollbars: function() {
  15581. this._scrollbars = {};
  15582. this._hideScrollbarTimeout = 0;
  15583. this._$element.addClass(SCROLLABLE_SCROLLBAR_SIMULATED);
  15584. this._renderScrollbar(VERTICAL);
  15585. this._renderScrollbar(HORIZONTAL)
  15586. },
  15587. _renderScrollbar: function(direction) {
  15588. if (!this._isDirection(direction))
  15589. return;
  15590. var $scrollbar = $("<div>").dxScrollbar({
  15591. direction: direction,
  15592. expandable: this._component.option("scrollByThumb")
  15593. }).appendTo(this._$element);
  15594. this._scrollbars[direction] = $scrollbar.dxScrollbar("instance")
  15595. },
  15596. handleInit: $.noop,
  15597. handleStart: $.noop,
  15598. handleMove: function(e) {
  15599. if (this._isLocked()) {
  15600. e.cancel = true;
  15601. return
  15602. }
  15603. if (this._allowedDirection())
  15604. e.originalEvent.isScrollingEvent = true
  15605. },
  15606. handleEnd: $.noop,
  15607. handleStop: $.noop,
  15608. _eachScrollbar: function(callback) {
  15609. callback = $.proxy(callback, this);
  15610. $.each(this._scrollbars || {}, function(direction, scrollbar) {
  15611. callback(scrollbar, direction)
  15612. })
  15613. },
  15614. createActions: function() {
  15615. this._scrollAction = this._createActionByOption("onScroll");
  15616. this._updateAction = this._createActionByOption("onUpdated")
  15617. },
  15618. _createActionArgs: function() {
  15619. var location = this.location();
  15620. return {
  15621. jQueryEvent: this._eventForUserAction,
  15622. scrollOffset: {
  15623. top: -location.top,
  15624. left: -location.left
  15625. },
  15626. reachedLeft: this._isDirection(HORIZONTAL) ? location.left >= 0 : undefined,
  15627. reachedRight: this._isDirection(HORIZONTAL) ? location.left <= this._containerSize.width - this._componentContentSize.width : undefined,
  15628. reachedTop: this._isDirection(VERTICAL) ? location.top >= 0 : undefined,
  15629. reachedBottom: this._isDirection(VERTICAL) ? location.top <= this._containerSize.height - this._componentContentSize.height : undefined
  15630. }
  15631. },
  15632. handleScroll: function(e) {
  15633. if (!this._isScrollLocationChanged()) {
  15634. e.stopImmediatePropagation();
  15635. return
  15636. }
  15637. this._eventForUserAction = e;
  15638. this._moveScrollbars();
  15639. this._scrollAction(this._createActionArgs());
  15640. this._lastLocation = this.location();
  15641. this._pushBackFromBoundary()
  15642. },
  15643. _pushBackFromBoundary: function() {
  15644. var pushBackValue = this.option("pushBackValue");
  15645. if (!pushBackValue)
  15646. return;
  15647. var scrollOffset = this._containerSize.height - this._contentSize.height,
  15648. scrollTopPos = this._$container.scrollTop(),
  15649. scrollBottomPos = scrollOffset + scrollTopPos - pushBackValue * 2;
  15650. if (!scrollTopPos)
  15651. this._$container.scrollTop(pushBackValue);
  15652. else if (!scrollBottomPos)
  15653. this._$container.scrollTop(pushBackValue - scrollOffset)
  15654. },
  15655. _isScrollLocationChanged: function() {
  15656. var currentLocation = this.location(),
  15657. lastLocation = this._lastLocation || {},
  15658. isTopChanged = lastLocation.top !== currentLocation.top,
  15659. isLeftChanged = lastLocation.left !== currentLocation.left;
  15660. return isTopChanged || isLeftChanged
  15661. },
  15662. _moveScrollbars: function() {
  15663. this._eachScrollbar(function(scrollbar) {
  15664. scrollbar.moveTo(this.location());
  15665. scrollbar.option("visible", true)
  15666. });
  15667. this._hideScrollbars()
  15668. },
  15669. _hideScrollbars: function() {
  15670. clearTimeout(this._hideScrollbarTimeout);
  15671. this._hideScrollbarTimeout = setTimeout($.proxy(function() {
  15672. this._eachScrollbar(function(scrollbar) {
  15673. scrollbar.option("visible", false)
  15674. })
  15675. }, this), HIDE_SCROLLBAR_TIMOUT)
  15676. },
  15677. location: function() {
  15678. return {
  15679. left: -this._$container.scrollLeft(),
  15680. top: this.option("pushBackValue") - this._$container.scrollTop()
  15681. }
  15682. },
  15683. disabledChanged: $.noop,
  15684. update: function() {
  15685. this._update();
  15686. this._updateAction(this._createActionArgs())
  15687. },
  15688. _update: function() {
  15689. this._updateDimensions();
  15690. this._updateScrollbars()
  15691. },
  15692. _updateDimensions: function() {
  15693. this._containerSize = {
  15694. height: this._$container.height(),
  15695. width: this._$container.width()
  15696. };
  15697. this._componentContentSize = {
  15698. height: this._component.content().height(),
  15699. width: this._component.content().width()
  15700. };
  15701. this._contentSize = {
  15702. height: this._$content.height(),
  15703. width: this._$content.width()
  15704. };
  15705. this._pushBackFromBoundary()
  15706. },
  15707. _updateScrollbars: function() {
  15708. this._eachScrollbar(function(scrollbar, direction) {
  15709. var dimension = direction === VERTICAL ? "height" : "width";
  15710. scrollbar.option({
  15711. containerSize: this._containerSize[dimension],
  15712. contentSize: this._componentContentSize[dimension]
  15713. });
  15714. scrollbar.update()
  15715. })
  15716. },
  15717. _allowedDirections: function() {
  15718. return {
  15719. vertical: this._isDirection(VERTICAL) && this._contentSize.height > this._containerSize.height,
  15720. horizontal: this._isDirection(HORIZONTAL) && this._contentSize.width > this._containerSize.width
  15721. }
  15722. },
  15723. dispose: function() {
  15724. this._$element.removeClass(function(index, className) {
  15725. var scrollableNativeRegexp = new RegExp(SCROLLABLE_NATIVE_CLASS + "\\S*", "g");
  15726. if (scrollableNativeRegexp.test(className))
  15727. return className.match(scrollableNativeRegexp).join(" ")
  15728. });
  15729. this._$element.off("." + SCROLLABLE_NATIVE);
  15730. this._$container.off("." + SCROLLABLE_NATIVE);
  15731. this._removeScrollbars();
  15732. clearTimeout(this._gestureEndTimer);
  15733. clearTimeout(this._hideScrollbarTimeout)
  15734. },
  15735. _removeScrollbars: function() {
  15736. this._eachScrollbar(function(scrollbar) {
  15737. scrollbar.element().remove()
  15738. })
  15739. },
  15740. scrollBy: function(distance) {
  15741. var location = this.location();
  15742. this._$container.scrollTop(-location.top - distance.top + this.option("pushBackValue"));
  15743. this._$container.scrollLeft(-location.left - distance.left)
  15744. },
  15745. validate: function() {
  15746. return !this.option("disabled") && this._allowedDirection()
  15747. },
  15748. getDirection: function() {
  15749. return this._allowedDirection()
  15750. }
  15751. })
  15752. })(jQuery, DevExpress);
  15753. /*! Module widgets-base, file ui.scrollable.simulated.js */
  15754. (function($, DX, undefined) {
  15755. var ui = DX.ui,
  15756. events = ui.events,
  15757. math = Math,
  15758. translator = DX.translator;
  15759. var realDevice = DX.devices.real;
  15760. var isSluggishPlatform = realDevice.platform === "win8" || realDevice.platform === "android";
  15761. var SCROLLABLE_SIMULATED = "dxSimulatedScrollable",
  15762. SCROLLABLE_STRATEGY = "dxScrollableStrategy",
  15763. SCROLLABLE_SIMULATED_CURSOR = SCROLLABLE_SIMULATED + "Cursor",
  15764. SCROLLABLE_SIMULATED_KEYBOARD = SCROLLABLE_SIMULATED + "Keyboard",
  15765. SCROLLABLE_SIMULATED_CLASS = "dx-scrollable-simulated",
  15766. SCROLLABLE_SCROLLBARS_HIDDEN = "dx-scrollable-scrollbars-hidden",
  15767. SCROLLABLE_SCROLLBAR_CLASS = "dx-scrollable-scrollbar",
  15768. VERTICAL = "vertical",
  15769. HORIZONTAL = "horizontal",
  15770. ACCELERATION = isSluggishPlatform ? 0.95 : 0.92,
  15771. OUT_BOUNDS_ACCELERATION = 0.5,
  15772. MIN_VELOCITY_LIMIT = 1,
  15773. FRAME_DURATION = math.round(1000 / 60),
  15774. SCROLL_LINE_HEIGHT = 20,
  15775. BOUNCE_MIN_VELOCITY_LIMIT = MIN_VELOCITY_LIMIT / 5,
  15776. BOUNCE_DURATION = isSluggishPlatform ? 300 : 400,
  15777. BOUNCE_FRAMES = BOUNCE_DURATION / FRAME_DURATION,
  15778. BOUNCE_ACCELERATION_SUM = (1 - math.pow(ACCELERATION, BOUNCE_FRAMES)) / (1 - ACCELERATION);
  15779. var KEY_CODES = {
  15780. PAGE_UP: 33,
  15781. PAGE_DOWN: 34,
  15782. END: 35,
  15783. HOME: 36,
  15784. LEFT: 37,
  15785. UP: 38,
  15786. RIGHT: 39,
  15787. DOWN: 40
  15788. };
  15789. var scrollIntoViewIfNeededCallbacks = function() {
  15790. var callbacks = $.Callbacks();
  15791. var FOCUS_TIMEOUT = 50,
  15792. cancelChangeTimestamp = null;
  15793. $(window).on(events.addNamespace("focus", SCROLLABLE_STRATEGY), function() {
  15794. cancelChangeTimestamp = $.now()
  15795. });
  15796. $(document).on(events.addNamespace("dxpointerdown", SCROLLABLE_STRATEGY), function() {
  15797. cancelChangeTimestamp = $.now()
  15798. });
  15799. var focusChange = function(e) {
  15800. var keyboardElementChange = $.now() - cancelChangeTimestamp > FOCUS_TIMEOUT,
  15801. focusedCorrectElement = e.target === document.activeElement;
  15802. if (keyboardElementChange && focusedCorrectElement)
  15803. callbacks.fire(e.target)
  15804. };
  15805. if (window.addEventListener)
  15806. window.addEventListener("focus", focusChange, true);
  15807. else
  15808. window.attachEvent("onfocusin", focusChange);
  15809. return callbacks
  15810. }();
  15811. var InertiaAnimator = DX.Animator.inherit({
  15812. ctor: function(scroller) {
  15813. this.callBase();
  15814. this.scroller = scroller
  15815. },
  15816. VELOCITY_LIMIT: MIN_VELOCITY_LIMIT,
  15817. _isFinished: function() {
  15818. return math.abs(this.scroller._velocity) <= this.VELOCITY_LIMIT
  15819. },
  15820. _step: function() {
  15821. this.scroller._scrollStep(this.scroller._velocity);
  15822. this.scroller._velocity *= this._acceleration()
  15823. },
  15824. _acceleration: function() {
  15825. return this.scroller._inBounds() ? ACCELERATION : OUT_BOUNDS_ACCELERATION
  15826. },
  15827. _complete: function() {
  15828. this.scroller._scrollComplete()
  15829. },
  15830. _stop: function() {
  15831. this.scroller._stopComplete()
  15832. }
  15833. });
  15834. var BounceAnimator = InertiaAnimator.inherit({
  15835. VELOCITY_LIMIT: BOUNCE_MIN_VELOCITY_LIMIT,
  15836. _isFinished: function() {
  15837. return this.scroller._crossBoundOnNextStep() || this.callBase()
  15838. },
  15839. _acceleration: function() {
  15840. return ACCELERATION
  15841. },
  15842. _complete: function() {
  15843. this.scroller._move(this.scroller._bounceLocation);
  15844. this.callBase()
  15845. }
  15846. });
  15847. var isWheelEvent = function(e) {
  15848. return e.type === "dxmousewheel"
  15849. };
  15850. var Scroller = ui.dxScrollable.Scroller = DX.Class.inherit({
  15851. ctor: function(options) {
  15852. this._initOptions(options);
  15853. this._initAnimators();
  15854. this._initScrollbar()
  15855. },
  15856. _initOptions: function(options) {
  15857. this._location = 0;
  15858. this._topReached = false;
  15859. this._bottomReached = false;
  15860. this._axis = options.direction === HORIZONTAL ? "x" : "y";
  15861. this._prop = options.direction === HORIZONTAL ? "left" : "top";
  15862. this._dimension = options.direction === HORIZONTAL ? "width" : "height";
  15863. this._scrollProp = options.direction === HORIZONTAL ? "scrollLeft" : "scrollTop";
  15864. $.each(options, $.proxy(function(optionName, optionValue) {
  15865. this["_" + optionName] = optionValue
  15866. }, this))
  15867. },
  15868. _initAnimators: function() {
  15869. this._inertiaAnimator = new InertiaAnimator(this);
  15870. this._bounceAnimator = new BounceAnimator(this)
  15871. },
  15872. _initScrollbar: function() {
  15873. this._$scrollbar = $("<div>").dxScrollbar({
  15874. direction: this._direction,
  15875. visible: this._scrollByThumb,
  15876. visibilityMode: this._visibilityModeNormalize(this._scrollbarVisible),
  15877. containerSize: this._containerSize(),
  15878. contentSize: this._contentSize(),
  15879. expandable: this._scrollByThumb
  15880. }).appendTo(this._$container);
  15881. this._scrollbar = this._$scrollbar.dxScrollbar("instance")
  15882. },
  15883. _visibilityModeNormalize: function(mode) {
  15884. return mode === true ? "onScroll" : mode === false ? "never" : mode
  15885. },
  15886. _scrollStep: function(delta) {
  15887. var prevLocation = this._location;
  15888. this._location += delta;
  15889. this._suppressBounce();
  15890. this._move();
  15891. if (prevLocation !== this._location) {
  15892. this._scrollAction();
  15893. $.data(this._$container.get(0), "scroll")()
  15894. }
  15895. },
  15896. _suppressBounce: function() {
  15897. if (this._bounceEnabled || this._inBounds(this._location))
  15898. return;
  15899. this._velocity = 0;
  15900. this._location = this._boundLocation()
  15901. },
  15902. _boundLocation: function() {
  15903. var location = math.min(this._location, this._maxOffset);
  15904. return math.max(location, this._minOffset)
  15905. },
  15906. _move: function(location) {
  15907. this._location = location !== undefined ? location : this._location;
  15908. this._moveContent();
  15909. this._moveScrollbar()
  15910. },
  15911. _moveContent: function() {
  15912. var targetLocation = {};
  15913. targetLocation[this._prop] = this._location;
  15914. translator.move(this._$content, targetLocation)
  15915. },
  15916. _moveScrollbar: function() {
  15917. this._scrollbar.moveTo(this._location)
  15918. },
  15919. _scrollComplete: function() {
  15920. if (this._inBounds()) {
  15921. this._hideScrollbar();
  15922. this._correctLocation();
  15923. if (this._completeDeferred)
  15924. this._completeDeferred.resolve()
  15925. }
  15926. this._scrollToBounds()
  15927. },
  15928. _correctLocation: function() {
  15929. this._location = math.round(this._location);
  15930. this._move()
  15931. },
  15932. _scrollToBounds: function() {
  15933. if (this._inBounds())
  15934. return;
  15935. this._bounceAction();
  15936. this._setupBounce();
  15937. this._bounceAnimator.start()
  15938. },
  15939. _setupBounce: function() {
  15940. var boundLocation = this._bounceLocation = this._boundLocation(),
  15941. bounceDistance = boundLocation - this._location;
  15942. this._velocity = bounceDistance / BOUNCE_ACCELERATION_SUM
  15943. },
  15944. _inBounds: function(location) {
  15945. location = location !== undefined ? location : this._location;
  15946. return location >= this._minOffset && location <= this._maxOffset
  15947. },
  15948. _crossBoundOnNextStep: function() {
  15949. var location = this._location,
  15950. nextLocation = location + this._velocity;
  15951. return location < this._minOffset && nextLocation >= this._minOffset || location > this._maxOffset && nextLocation <= this._maxOffset
  15952. },
  15953. _initHandler: function(e) {
  15954. this._stopDeferred = $.Deferred();
  15955. this._stopScrolling();
  15956. this._prepareThumbScrolling(e);
  15957. return this._stopDeferred.promise()
  15958. },
  15959. _stopScrolling: function() {
  15960. this._hideScrollbar();
  15961. this._inertiaAnimator.stop();
  15962. this._bounceAnimator.stop()
  15963. },
  15964. _prepareThumbScrolling: function(e) {
  15965. if (isWheelEvent(e.originalEvent))
  15966. return;
  15967. var $target = $(e.originalEvent.target);
  15968. var scrollbarClicked = this._isScrollbar($target);
  15969. if (scrollbarClicked)
  15970. this._moveToMouseLocation(e);
  15971. this._thumbScrolling = scrollbarClicked || this._isThumb($target);
  15972. if (this._thumbScrolling)
  15973. this._scrollbar.feedbackOn()
  15974. },
  15975. _moveToMouseLocation: function(e) {
  15976. var mouseLocation = e["page" + this._axis.toUpperCase()] - this._$element.offset()[this._prop];
  15977. var location = this._location + mouseLocation / this._containerToContentRatio() - this._$container.height() / 2;
  15978. this._scrollStep(-location)
  15979. },
  15980. _stopComplete: function() {
  15981. if (this._stopDeferred)
  15982. this._stopDeferred.resolve()
  15983. },
  15984. _startHandler: function() {
  15985. this._showScrollbar()
  15986. },
  15987. _moveHandler: function(delta) {
  15988. delta = delta[this._axis];
  15989. if (this._thumbScrolling)
  15990. delta = -delta / this._containerToContentRatio();
  15991. if (!this._inBounds())
  15992. delta *= OUT_BOUNDS_ACCELERATION;
  15993. this._scrollStep(delta)
  15994. },
  15995. _containerToContentRatio: function() {
  15996. return this._scrollbar.containerToContentRatio()
  15997. },
  15998. _endHandler: function(velocity) {
  15999. this._completeDeferred = $.Deferred();
  16000. this._velocity = velocity[this._axis];
  16001. this._inertiaHandler();
  16002. this._resetThumbScrolling();
  16003. return this._completeDeferred.promise()
  16004. },
  16005. _inertiaHandler: function() {
  16006. this._suppressIntertia();
  16007. this._inertiaAnimator.start()
  16008. },
  16009. _suppressIntertia: function() {
  16010. if (!this._inertiaEnabled || this._thumbScrolling)
  16011. this._velocity = 0
  16012. },
  16013. _resetThumbScrolling: function() {
  16014. this._thumbScrolling = false
  16015. },
  16016. _stopHandler: function() {
  16017. this._resetThumbScrolling();
  16018. this._scrollToBounds()
  16019. },
  16020. _disposeHandler: function() {
  16021. this._stopScrolling();
  16022. this._$scrollbar.remove()
  16023. },
  16024. _updateHandler: function() {
  16025. this._update();
  16026. this._moveToBounds()
  16027. },
  16028. _update: function() {
  16029. this._stopScrolling();
  16030. this._updateLocation();
  16031. this._updateBounds();
  16032. this._updateScrollbar();
  16033. this._moveScrollbar();
  16034. this._scrollbar.update()
  16035. },
  16036. _updateLocation: function() {
  16037. this._location = translator.locate(this._$content)[this._prop]
  16038. },
  16039. _updateBounds: function() {
  16040. this._maxOffset = this._getMaxOffset();
  16041. this._minOffset = this._getMinOffset()
  16042. },
  16043. _getMaxOffset: function() {
  16044. return 0
  16045. },
  16046. _getMinOffset: function() {
  16047. return math.min(this._containerSize() - this._contentSize(), 0)
  16048. },
  16049. _updateScrollbar: function() {
  16050. this._scrollbar.option({
  16051. containerSize: this._containerSize(),
  16052. contentSize: this._contentSize()
  16053. })
  16054. },
  16055. _moveToBounds: function() {
  16056. this._location = this._boundLocation();
  16057. this._move()
  16058. },
  16059. _createActionsHandler: function(actions) {
  16060. this._scrollAction = actions.scroll;
  16061. this._bounceAction = actions.bounce
  16062. },
  16063. _showScrollbar: function() {
  16064. this._scrollbar.option("visible", true)
  16065. },
  16066. _hideScrollbar: function() {
  16067. this._scrollbar.option("visible", false)
  16068. },
  16069. _containerSize: function() {
  16070. return this._$container[this._dimension]()
  16071. },
  16072. _contentSize: function() {
  16073. return this._$content[this._dimension]()
  16074. },
  16075. _validateEvent: function(e) {
  16076. var $target = $(e.originalEvent.target);
  16077. if (this._isThumb($target) || this._isScrollbar($target)) {
  16078. e.preventDefault();
  16079. return true
  16080. }
  16081. return this._isContent($target)
  16082. },
  16083. _isThumb: function($element) {
  16084. return this._scrollByThumb && this._scrollbar.isThumb($element)
  16085. },
  16086. _isScrollbar: function($element) {
  16087. return this._scrollByThumb && $element && $element.is(this._$scrollbar)
  16088. },
  16089. _isContent: function($element) {
  16090. return this._scrollByContent && !!$element.closest(this._$element).length
  16091. },
  16092. _reachedMin: function() {
  16093. return this._location <= this._minOffset
  16094. },
  16095. _reachedMax: function() {
  16096. return this._location >= this._maxOffset
  16097. },
  16098. _cursorEnterHandler: function() {
  16099. this._scrollbar.cursorEnter()
  16100. },
  16101. _cursorLeaveHandler: function() {
  16102. this._scrollbar.cursorLeave()
  16103. },
  16104. dispose: $.noop
  16105. });
  16106. var hoveredScrollable,
  16107. activeScrollable;
  16108. ui.dxScrollable.SimulatedStrategy = DX.Class.inherit({
  16109. ctor: function(scrollable) {
  16110. this._init(scrollable)
  16111. },
  16112. _init: function(scrollable) {
  16113. this._component = scrollable;
  16114. this._$element = scrollable.element();
  16115. this._$container = scrollable._$container;
  16116. this._$content = scrollable._$content;
  16117. this.option = $.proxy(scrollable.option, scrollable);
  16118. this._createActionByOption = $.proxy(scrollable._createActionByOption, scrollable);
  16119. this._isLocked = $.proxy(scrollable._isLocked, scrollable);
  16120. this._isDirection = $.proxy(scrollable._isDirection, scrollable);
  16121. this._allowedDirection = $.proxy(scrollable._allowedDirection, scrollable);
  16122. this._proxiedActiveElementChangeHandler = $.proxy(this._activeElementChangeHandler, this);
  16123. scrollIntoViewIfNeededCallbacks.add(this._proxiedActiveElementChangeHandler)
  16124. },
  16125. _activeElementChangeHandler: function(activeElement) {
  16126. this._component.scrollToElement(activeElement)
  16127. },
  16128. render: function() {
  16129. this._$element.addClass(SCROLLABLE_SIMULATED_CLASS);
  16130. this._createScrollers();
  16131. if (this.option("useKeyboard"))
  16132. this._$container.prop("tabindex", 0);
  16133. this._attachKeyboardHandler();
  16134. this._attachCursorHandlers()
  16135. },
  16136. _createScrollers: function() {
  16137. this._scrollers = {};
  16138. if (this._isDirection(HORIZONTAL))
  16139. this._createScroller(HORIZONTAL);
  16140. if (this._isDirection(VERTICAL))
  16141. this._createScroller(VERTICAL);
  16142. this._$element.toggleClass(SCROLLABLE_SCROLLBARS_HIDDEN, !this.option("showScrollbar"))
  16143. },
  16144. _createScroller: function(direction) {
  16145. this._scrollers[direction] = new Scroller(this._scrollerOptions(direction))
  16146. },
  16147. _scrollerOptions: function(direction) {
  16148. return {
  16149. direction: direction,
  16150. $content: this._$content,
  16151. $container: this._$container,
  16152. $element: this._$element,
  16153. scrollByContent: this.option("scrollByContent"),
  16154. scrollByThumb: this.option("scrollByThumb"),
  16155. scrollbarVisible: this.option("showScrollbar"),
  16156. bounceEnabled: this.option("bounceEnabled"),
  16157. inertiaEnabled: this.option("inertiaEnabled")
  16158. }
  16159. },
  16160. handleInit: function(e) {
  16161. this._supressDirections(e);
  16162. this._eventForUserAction = e;
  16163. this._eventHandler("init", e).done(this._stopAction)
  16164. },
  16165. _supressDirections: function(e) {
  16166. if (isWheelEvent(e.originalEvent)) {
  16167. this._prepareDirections(true);
  16168. return
  16169. }
  16170. this._prepareDirections();
  16171. this._eachScroller(function(scroller, direction) {
  16172. var isValid = scroller._validateEvent(e);
  16173. this._validDirections[direction] = isValid
  16174. })
  16175. },
  16176. _prepareDirections: function(value) {
  16177. value = value || false;
  16178. this._validDirections = {};
  16179. this._validDirections[HORIZONTAL] = value;
  16180. this._validDirections[VERTICAL] = value
  16181. },
  16182. _eachScroller: function(callback) {
  16183. callback = $.proxy(callback, this);
  16184. $.each(this._scrollers, function(direction, scroller) {
  16185. callback(scroller, direction)
  16186. })
  16187. },
  16188. handleStart: function(e) {
  16189. this._saveActive();
  16190. this._eventHandler("start").done(this._startAction)
  16191. },
  16192. _saveActive: function() {
  16193. activeScrollable = this
  16194. },
  16195. _resetActive: function() {
  16196. activeScrollable = null
  16197. },
  16198. _validateDirection: function(delta) {
  16199. var result = false;
  16200. this._eachScroller(function(scroller) {
  16201. result = result || scroller._validateDirection(delta)
  16202. });
  16203. return result
  16204. },
  16205. handleMove: function(e) {
  16206. if (this._isLocked()) {
  16207. e.cancel = true;
  16208. this._resetActive();
  16209. return
  16210. }
  16211. e.preventDefault && e.preventDefault();
  16212. this._adjustDistance(e.delta);
  16213. this._eventForUserAction = e;
  16214. this._eventHandler("move", e.delta)
  16215. },
  16216. _adjustDistance: function(distance) {
  16217. distance.x *= this._validDirections[HORIZONTAL];
  16218. distance.y *= this._validDirections[VERTICAL]
  16219. },
  16220. handleEnd: function(e) {
  16221. this._resetActive();
  16222. this._refreshCursorState(e.originalEvent && e.originalEvent.target);
  16223. this._adjustDistance(e.velocity);
  16224. this._eventForUserAction = e;
  16225. return this._eventHandler("end", e.velocity).done(this._endAction)
  16226. },
  16227. handleCancel: function(e) {
  16228. this._resetActive();
  16229. this._eventForUserAction = e;
  16230. return this._eventHandler("end", {
  16231. x: 0,
  16232. y: 0
  16233. })
  16234. },
  16235. handleStop: function() {
  16236. this._resetActive();
  16237. this._eventHandler("stop")
  16238. },
  16239. handleScroll: function() {
  16240. var distance = {
  16241. left: this.option("direction") !== VERTICAL ? -this._$container.scrollLeft() : 0,
  16242. top: this.option("direction") !== HORIZONTAL ? -this._$container.scrollTop() : 0
  16243. };
  16244. if (!distance.left && !distance.top)
  16245. return;
  16246. this._$container.scrollLeft(0);
  16247. this._$container.scrollTop(0);
  16248. this.scrollBy(distance)
  16249. },
  16250. _attachKeyboardHandler: function() {
  16251. this._$element.off("." + SCROLLABLE_SIMULATED_KEYBOARD);
  16252. if (!this.option("disabled") && this.option("useKeyboard"))
  16253. this._$element.on(events.addNamespace("keydown", SCROLLABLE_SIMULATED_KEYBOARD), $.proxy(this._keyDownHandler, this))
  16254. },
  16255. _keyDownHandler: function(e) {
  16256. if (!this._$container.is(document.activeElement))
  16257. return;
  16258. var handled = true;
  16259. switch (e.keyCode) {
  16260. case KEY_CODES.DOWN:
  16261. this._scrollByLine({y: 1});
  16262. break;
  16263. case KEY_CODES.UP:
  16264. this._scrollByLine({y: -1});
  16265. break;
  16266. case KEY_CODES.RIGHT:
  16267. this._scrollByLine({x: 1});
  16268. break;
  16269. case KEY_CODES.LEFT:
  16270. this._scrollByLine({x: -1});
  16271. break;
  16272. case KEY_CODES.PAGE_DOWN:
  16273. this._scrollByPage(1);
  16274. break;
  16275. case KEY_CODES.PAGE_UP:
  16276. this._scrollByPage(-1);
  16277. break;
  16278. case KEY_CODES.HOME:
  16279. this._scrollToHome();
  16280. break;
  16281. case KEY_CODES.END:
  16282. this._scrollToEnd();
  16283. break;
  16284. default:
  16285. handled = false;
  16286. break
  16287. }
  16288. if (handled) {
  16289. e.stopPropagation();
  16290. e.preventDefault()
  16291. }
  16292. },
  16293. _scrollByLine: function(lines) {
  16294. this.scrollBy({
  16295. top: (lines.y || 0) * -SCROLL_LINE_HEIGHT,
  16296. left: (lines.x || 0) * -SCROLL_LINE_HEIGHT
  16297. })
  16298. },
  16299. _scrollByPage: function(page) {
  16300. var prop = this._wheelProp(),
  16301. dimension = this._dimensionByProp(prop);
  16302. var distance = {};
  16303. distance[prop] = page * -this._$container[dimension]();
  16304. this.scrollBy(distance)
  16305. },
  16306. _dimensionByProp: function(prop) {
  16307. return prop === "left" ? "width" : "height"
  16308. },
  16309. _scrollToHome: function() {
  16310. var prop = this._wheelProp();
  16311. var distance = {};
  16312. distance[prop] = 0;
  16313. this._component.scrollTo(distance)
  16314. },
  16315. _scrollToEnd: function() {
  16316. var prop = this._wheelProp(),
  16317. dimension = this._dimensionByProp(prop);
  16318. var distance = {};
  16319. distance[prop] = this._$content[dimension]() - this._$container[dimension]();
  16320. this._component.scrollTo(distance)
  16321. },
  16322. createActions: function() {
  16323. this._startAction = this._createActionHandler("onStart");
  16324. this._stopAction = this._createActionHandler("onStop");
  16325. this._endAction = this._createActionHandler("onEnd");
  16326. this._updateAction = this._createActionHandler("onUpdated");
  16327. this._createScrollerActions()
  16328. },
  16329. _createScrollerActions: function() {
  16330. this._eventHandler("createActions", {
  16331. scroll: this._createActionHandler("onScroll"),
  16332. bounce: this._createActionHandler("onBounce")
  16333. })
  16334. },
  16335. _createActionHandler: function(optionName) {
  16336. var that = this,
  16337. actionHandler = that._createActionByOption(optionName);
  16338. return function() {
  16339. actionHandler($.extend(that._createActionArgs(), arguments))
  16340. }
  16341. },
  16342. _createActionArgs: function() {
  16343. var scrollerX = this._scrollers[HORIZONTAL],
  16344. scrollerY = this._scrollers[VERTICAL];
  16345. return {
  16346. jQueryEvent: this._eventForUserAction,
  16347. scrollOffset: {
  16348. top: scrollerY && -scrollerY._location,
  16349. left: scrollerX && -scrollerX._location
  16350. },
  16351. reachedLeft: scrollerX && scrollerX._reachedMax(),
  16352. reachedRight: scrollerX && scrollerX._reachedMin(),
  16353. reachedTop: scrollerY && scrollerY._reachedMax(),
  16354. reachedBottom: scrollerY && scrollerY._reachedMin()
  16355. }
  16356. },
  16357. _eventHandler: function(eventName) {
  16358. var args = $.makeArray(arguments).slice(1),
  16359. deferreds = $.map(this._scrollers, function(scroller) {
  16360. return scroller["_" + eventName + "Handler"].apply(scroller, args)
  16361. });
  16362. return $.when.apply($, deferreds).promise()
  16363. },
  16364. location: function() {
  16365. return translator.locate(this._$content)
  16366. },
  16367. disabledChanged: function() {
  16368. this._attachCursorHandlers()
  16369. },
  16370. _attachCursorHandlers: function() {
  16371. this._$element.off("." + SCROLLABLE_SIMULATED_CURSOR);
  16372. if (!this.option("disabled") && this._isHoverMode())
  16373. this._$element.on(events.addNamespace("mouseenter", SCROLLABLE_SIMULATED_CURSOR), $.proxy(this._cursorEnterHandler, this)).on(events.addNamespace("mouseleave", SCROLLABLE_SIMULATED_CURSOR), $.proxy(this._cursorLeaveHandler, this))
  16374. },
  16375. _isHoverMode: function() {
  16376. return this.option("showScrollbar") === "onHover"
  16377. },
  16378. _cursorEnterHandler: function(e) {
  16379. e = e || {};
  16380. e.originalEvent = e.originalEvent || {};
  16381. if (activeScrollable || e.originalEvent._hoverHandled)
  16382. return;
  16383. if (hoveredScrollable)
  16384. hoveredScrollable._cursorLeaveHandler();
  16385. hoveredScrollable = this;
  16386. this._eventHandler("cursorEnter");
  16387. e.originalEvent._hoverHandled = true
  16388. },
  16389. _cursorLeaveHandler: function(e) {
  16390. if (hoveredScrollable !== this || activeScrollable === hoveredScrollable)
  16391. return;
  16392. this._eventHandler("cursorLeave");
  16393. hoveredScrollable = null;
  16394. this._refreshCursorState(e && e.relatedTarget)
  16395. },
  16396. _refreshCursorState: function(target) {
  16397. if (!this._isHoverMode() && (!target || activeScrollable))
  16398. return;
  16399. var $target = $(target);
  16400. var $scrollable = $target.closest("." + SCROLLABLE_SIMULATED_CLASS + ":not(.dx-state-disabled)");
  16401. var targetScrollable = $scrollable.length && $scrollable.data(SCROLLABLE_STRATEGY);
  16402. if (hoveredScrollable && hoveredScrollable !== targetScrollable)
  16403. hoveredScrollable._cursorLeaveHandler();
  16404. if (targetScrollable)
  16405. targetScrollable._cursorEnterHandler()
  16406. },
  16407. update: function() {
  16408. return this._eventHandler("update").done(this._updateAction)
  16409. },
  16410. _allowedDirections: function() {
  16411. var bounceEnabled = this.option("bounceEnabled");
  16412. return {
  16413. vertical: this._isDirection(VERTICAL) && (this._scrollers[VERTICAL]._minOffset < 0 || bounceEnabled),
  16414. horizontal: this._isDirection(HORIZONTAL) && (this._scrollers[HORIZONTAL]._minOffset < 0 || bounceEnabled)
  16415. }
  16416. },
  16417. scrollBy: function(distance) {
  16418. this._prepareDirections(true);
  16419. this._eventHandler("start").done(this._startAction);
  16420. this._eventHandler("move", {
  16421. x: distance.left,
  16422. y: distance.top
  16423. });
  16424. this._eventHandler("end", {
  16425. x: 0,
  16426. y: 0
  16427. }).done(this._endAction)
  16428. },
  16429. validate: function(e) {
  16430. if (this.option("disabled"))
  16431. return false;
  16432. if (this.option("bounceEnabled"))
  16433. return true;
  16434. return isWheelEvent(e) ? this._validateWheel(e) : this._validateMove(e)
  16435. },
  16436. _validateWheel: function(e) {
  16437. var scroller = this._scrollers[this._wheelDirection()];
  16438. var reachedMin = scroller._reachedMin();
  16439. var reachedMax = scroller._reachedMax();
  16440. var contentGreaterThanContainer = !reachedMin || !reachedMax;
  16441. var locatedNotAtBound = !reachedMin && !reachedMax;
  16442. var scrollFromMin = reachedMin && e.delta > 0;
  16443. var scrollFromMax = reachedMax && e.delta < 0;
  16444. return contentGreaterThanContainer && (locatedNotAtBound || scrollFromMin || scrollFromMax)
  16445. },
  16446. _validateMove: function(e) {
  16447. if (!this.option("scrollByContent") && !$(e.target).closest("." + SCROLLABLE_SCROLLBAR_CLASS).length)
  16448. return false;
  16449. return this._allowedDirection()
  16450. },
  16451. getDirection: function(e) {
  16452. return isWheelEvent(e) ? this._wheelDirection() : this._allowedDirection()
  16453. },
  16454. _wheelProp: function() {
  16455. return this._wheelDirection() === HORIZONTAL ? "left" : "top"
  16456. },
  16457. _wheelDirection: function() {
  16458. switch (this.option("direction")) {
  16459. case HORIZONTAL:
  16460. return HORIZONTAL;
  16461. case VERTICAL:
  16462. return VERTICAL;
  16463. default:
  16464. return this._scrollers[VERTICAL]._containerToContentRatio() >= 1 ? HORIZONTAL : VERTICAL
  16465. }
  16466. },
  16467. dispose: function() {
  16468. scrollIntoViewIfNeededCallbacks.remove(this._proxiedActiveElementChangeHandler);
  16469. if (activeScrollable === this)
  16470. activeScrollable = null;
  16471. if (hoveredScrollable === this)
  16472. hoveredScrollable = null;
  16473. this._eventHandler("dispose");
  16474. this._detachEventHandlers();
  16475. this._$element.removeClass(SCROLLABLE_SIMULATED_CLASS);
  16476. this._eventForUserAction = null;
  16477. clearTimeout(this._gestureEndTimer)
  16478. },
  16479. _detachEventHandlers: function() {
  16480. this._$element.off("." + SCROLLABLE_SIMULATED_CURSOR);
  16481. this._$container.off("." + SCROLLABLE_SIMULATED_KEYBOARD)
  16482. }
  16483. });
  16484. ui.dxScrollable.__internals = $.extend(ui.dxScrollable.__internals || {}, {
  16485. ACCELERATION: ACCELERATION,
  16486. MIN_VELOCITY_LIMIT: MIN_VELOCITY_LIMIT,
  16487. FRAME_DURATION: FRAME_DURATION,
  16488. SCROLL_LINE_HEIGHT: SCROLL_LINE_HEIGHT,
  16489. scrollIntoViewIfNeededCallbacks: scrollIntoViewIfNeededCallbacks
  16490. })
  16491. })(jQuery, DevExpress);
  16492. /*! Module widgets-base, file ui.scrollView.js */
  16493. (function($, DX, undefined) {
  16494. var ui = DX.ui;
  16495. var SCROLLVIEW_CLASS = "dx-scrollview",
  16496. SCROLLVIEW_CONTENT_CLASS = SCROLLVIEW_CLASS + "-content",
  16497. SCROLLVIEW_TOP_POCKET_CLASS = SCROLLVIEW_CLASS + "-top-pocket",
  16498. SCROLLVIEW_BOTTOM_POCKET_CLASS = SCROLLVIEW_CLASS + "-bottom-pocket",
  16499. SCROLLVIEW_PULLDOWN_CLASS = SCROLLVIEW_CLASS + "-pull-down",
  16500. SCROLLVIEW_REACHBOTTOM_CLASS = SCROLLVIEW_CLASS + "-scrollbottom",
  16501. SCROLLVIEW_REACHBOTTOM_INDICATOR_CLASS = SCROLLVIEW_REACHBOTTOM_CLASS + "-indicator",
  16502. SCROLLVIEW_REACHBOTTOM_TEXT_CLASS = SCROLLVIEW_REACHBOTTOM_CLASS + "-text",
  16503. SCROLLVIEW_LOADPANEL = SCROLLVIEW_CLASS + "-loadpanel";
  16504. DX.registerComponent("dxScrollView", ui, ui.dxScrollable.inherit({
  16505. _setDeprecatedOptions: function() {
  16506. this.callBase();
  16507. $.extend(this._deprecatedOptions, {
  16508. pullDownAction: {
  16509. since: "14.2",
  16510. alias: "onPullDown"
  16511. },
  16512. reachBottomAction: {
  16513. since: "14.2",
  16514. alias: "onReachBottom"
  16515. }
  16516. })
  16517. },
  16518. _setDefaultOptions: function() {
  16519. this.callBase();
  16520. this.option({
  16521. pullingDownText: Globalize.localize("dxScrollView-pullingDownText"),
  16522. pulledDownText: Globalize.localize("dxScrollView-pulledDownText"),
  16523. refreshingText: Globalize.localize("dxScrollView-refreshingText"),
  16524. reachBottomText: Globalize.localize("dxScrollView-reachBottomText"),
  16525. onPullDown: null,
  16526. onReachBottom: null,
  16527. refreshStrategy: "pullDown"
  16528. })
  16529. },
  16530. _defaultOptionsRules: function() {
  16531. return this.callBase().concat([{
  16532. device: function(device) {
  16533. var realDevice = DevExpress.devices.real();
  16534. return realDevice.platform === "android"
  16535. },
  16536. options: {refreshStrategy: "swipeDown"}
  16537. }, {
  16538. device: function(device) {
  16539. return DevExpress.devices.real().platform === "win8"
  16540. },
  16541. options: {refreshStrategy: "slideDown"}
  16542. }])
  16543. },
  16544. _init: function() {
  16545. this.callBase();
  16546. this._loadingIndicatorEnabled = true
  16547. },
  16548. _initMarkup: function() {
  16549. this.callBase();
  16550. this.element().addClass(SCROLLVIEW_CLASS);
  16551. this._initContent();
  16552. this._initTopPocket();
  16553. this._initBottomPocket();
  16554. this._initLoadPanel()
  16555. },
  16556. _initContent: function() {
  16557. var $content = $("<div>").addClass(SCROLLVIEW_CONTENT_CLASS);
  16558. this._$content.wrapInner($content)
  16559. },
  16560. _initTopPocket: function() {
  16561. var $topPocket = this._$topPocket = $("<div>").addClass(SCROLLVIEW_TOP_POCKET_CLASS),
  16562. $pullDown = this._$pullDown = $("<div>").addClass(SCROLLVIEW_PULLDOWN_CLASS);
  16563. $topPocket.append($pullDown);
  16564. this._$content.prepend($topPocket)
  16565. },
  16566. _initBottomPocket: function() {
  16567. var $bottomPocket = this._$bottomPocket = $("<div>").addClass(SCROLLVIEW_BOTTOM_POCKET_CLASS),
  16568. $reachBottom = this._$reachBottom = $("<div>").addClass(SCROLLVIEW_REACHBOTTOM_CLASS),
  16569. $loadContainer = $("<div>").addClass(SCROLLVIEW_REACHBOTTOM_INDICATOR_CLASS),
  16570. $loadIndicator = $("<div>").dxLoadIndicator(),
  16571. $text = this._$reachBottomText = $("<div>").addClass(SCROLLVIEW_REACHBOTTOM_TEXT_CLASS);
  16572. this._updateReachBottomText();
  16573. $reachBottom.append($loadContainer.append($loadIndicator)).append($text);
  16574. $bottomPocket.append($reachBottom);
  16575. this._$content.append($bottomPocket)
  16576. },
  16577. _initLoadPanel: function() {
  16578. this._loadPanel = this._createComponent($("<div>").addClass(SCROLLVIEW_LOADPANEL).appendTo(this.element()), "dxLoadPanel", {
  16579. shading: false,
  16580. delay: 400,
  16581. message: this.option("refreshingText"),
  16582. position: {of: this.element()}
  16583. })
  16584. },
  16585. _updateReachBottomText: function() {
  16586. this._$reachBottomText.text(this.option("reachBottomText"))
  16587. },
  16588. _createStrategy: function() {
  16589. var strategyName = this.option("useNative") ? this.option("refreshStrategy") : "simulated";
  16590. var strategyClass = ui.dxScrollView.refreshStrategies[strategyName];
  16591. if (!strategyClass)
  16592. throw Error("E1030", this.option("refreshStrategy"));
  16593. this._strategy = new strategyClass(this);
  16594. this._strategy.pullDownCallbacks.add($.proxy(this._pullDownHandler, this));
  16595. this._strategy.releaseCallbacks.add($.proxy(this._releaseHandler, this));
  16596. this._strategy.reachBottomCallbacks.add($.proxy(this._reachBottomHandler, this))
  16597. },
  16598. _createActions: function() {
  16599. this.callBase();
  16600. this._pullDownAction = this._createActionByOption("onPullDown");
  16601. this._reachBottomAction = this._createActionByOption("onReachBottom");
  16602. this._pullDownEnable(!!this.option("onPullDown") && !DX.designMode);
  16603. this._reachBottomEnable(!!this.option("onReachBottom") && !DX.designMode)
  16604. },
  16605. _pullDownEnable: function(enabled) {
  16606. if (arguments.length === 0)
  16607. return this._pullDownEnabled;
  16608. this._$pullDown.toggle(enabled);
  16609. this._strategy.pullDownEnable(enabled);
  16610. this._pullDownEnabled = enabled
  16611. },
  16612. _reachBottomEnable: function(enabled) {
  16613. if (arguments.length === 0)
  16614. return this._reachBottomEnabled;
  16615. this._$reachBottom.toggle(enabled);
  16616. this._strategy.reachBottomEnable(enabled);
  16617. this._reachBottomEnabled = enabled
  16618. },
  16619. _pullDownHandler: function() {
  16620. this._loadingIndicator(false);
  16621. this._pullDownLoading()
  16622. },
  16623. _loadingIndicator: function(value) {
  16624. if (arguments.length < 1)
  16625. return this._loadingIndicatorEnabled;
  16626. this._loadingIndicatorEnabled = value
  16627. },
  16628. _pullDownLoading: function() {
  16629. this.startLoading();
  16630. this._pullDownAction()
  16631. },
  16632. _reachBottomHandler: function() {
  16633. this._loadingIndicator(false);
  16634. this._reachBottomLoading()
  16635. },
  16636. _reachBottomLoading: function() {
  16637. this.startLoading();
  16638. this._reachBottomAction()
  16639. },
  16640. _releaseHandler: function() {
  16641. this.finishLoading();
  16642. this._loadingIndicator(true)
  16643. },
  16644. _optionChanged: function(args) {
  16645. switch (args.name) {
  16646. case"onPullDown":
  16647. case"onReachBottom":
  16648. this._createActions();
  16649. break;
  16650. case"pullingDownText":
  16651. case"pulledDownText":
  16652. case"refreshingText":
  16653. case"refreshStrategy":
  16654. this._invalidate();
  16655. break;
  16656. case"reachBottomText":
  16657. this._updateReachBottomText();
  16658. break;
  16659. default:
  16660. this.callBase(args)
  16661. }
  16662. },
  16663. isEmpty: function() {
  16664. return !this.content().children().length
  16665. },
  16666. content: function() {
  16667. return this._$content.children().eq(1)
  16668. },
  16669. release: function(preventReachBottom) {
  16670. if (preventReachBottom !== undefined)
  16671. this.toggleLoading(!preventReachBottom);
  16672. return this._strategy.release()
  16673. },
  16674. toggleLoading: function(showOrHide) {
  16675. this._reachBottomEnable(showOrHide)
  16676. },
  16677. isFull: function() {
  16678. return this.content().height() >= this._$container.height()
  16679. },
  16680. refresh: function() {
  16681. if (!this.option("onPullDown"))
  16682. return;
  16683. this._strategy.pendingRelease();
  16684. this._pullDownLoading()
  16685. },
  16686. startLoading: function() {
  16687. if (this._loadingIndicator() && this.element().is(":visible"))
  16688. this._loadPanel.show();
  16689. this._lock()
  16690. },
  16691. finishLoading: function() {
  16692. this._loadPanel.hide();
  16693. this._unlock()
  16694. },
  16695. _dispose: function() {
  16696. this._strategy.dispose();
  16697. this.callBase();
  16698. if (this._loadPanel)
  16699. this._loadPanel.element().remove()
  16700. }
  16701. }));
  16702. ui.dxScrollView.refreshStrategies = {}
  16703. })(jQuery, DevExpress);
  16704. /*! Module widgets-base, file ui.scrollView.native.pullDown.js */
  16705. (function($, DX, undefined) {
  16706. var ui = DX.ui;
  16707. var SCROLLVIEW_PULLDOWN_REFRESHING_CLASS = "dx-scrollview-pull-down-loading",
  16708. SCROLLVIEW_PULLDOWN_READY_CLASS = "dx-scrollview-pull-down-ready",
  16709. SCROLLVIEW_PULLDOWN_IMAGE_CLASS = "dx-scrollview-pull-down-image",
  16710. SCROLLVIEW_PULLDOWN_INDICATOR_CLASS = "dx-scrollview-pull-down-indicator",
  16711. SCROLLVIEW_PULLDOWN_TEXT_CLASS = "dx-scrollview-pull-down-text",
  16712. STATE_RELEASED = 0,
  16713. STATE_READY = 1,
  16714. STATE_REFRESHING = 2,
  16715. STATE_LOADING = 3;
  16716. var PullDownNativeScrollViewStrategy = ui.dxScrollable.NativeStrategy.inherit({
  16717. _init: function(scrollView) {
  16718. this.callBase(scrollView);
  16719. this._$topPocket = scrollView._$topPocket;
  16720. this._$pullDown = scrollView._$pullDown;
  16721. this._$bottomPocket = scrollView._$bottomPocket;
  16722. this._$refreshingText = scrollView._$refreshingText;
  16723. this._$scrollViewContent = scrollView.content();
  16724. this._initCallbacks()
  16725. },
  16726. _initCallbacks: function() {
  16727. this.pullDownCallbacks = $.Callbacks();
  16728. this.releaseCallbacks = $.Callbacks();
  16729. this.reachBottomCallbacks = $.Callbacks()
  16730. },
  16731. render: function() {
  16732. this.callBase();
  16733. this._renderPullDown();
  16734. this._releaseState()
  16735. },
  16736. _renderPullDown: function() {
  16737. var $image = $("<div>").addClass(SCROLLVIEW_PULLDOWN_IMAGE_CLASS),
  16738. $loadContainer = $("<div>").addClass(SCROLLVIEW_PULLDOWN_INDICATOR_CLASS),
  16739. $loadIndicator = $("<div>").dxLoadIndicator(),
  16740. $text = this._$pullDownText = $("<div>").addClass(SCROLLVIEW_PULLDOWN_TEXT_CLASS);
  16741. this._$pullingDownText = $("<div>").text(this.option("pullingDownText")).appendTo($text);
  16742. this._$pulledDownText = $("<div>").text(this.option("pulledDownText")).appendTo($text);
  16743. this._$refreshingText = $("<div>").text(this.option("refreshingText")).appendTo($text);
  16744. this._$pullDown.empty().append($image).append($loadContainer.append($loadIndicator)).append($text)
  16745. },
  16746. _releaseState: function() {
  16747. this._state = STATE_RELEASED;
  16748. this._refreshPullDownText()
  16749. },
  16750. _pushBackFromBoundary: function() {
  16751. if (!this._isLocked() && !this._component.isEmpty())
  16752. this.callBase()
  16753. },
  16754. _refreshPullDownText: function() {
  16755. this._$pullingDownText.css("opacity", this._state === STATE_RELEASED ? 1 : 0);
  16756. this._$pulledDownText.css("opacity", this._state === STATE_READY ? 1 : 0);
  16757. this._$refreshingText.css("opacity", this._state === STATE_REFRESHING ? 1 : 0)
  16758. },
  16759. update: function() {
  16760. this.callBase();
  16761. this._setTopPocketOffset()
  16762. },
  16763. _updateDimensions: function() {
  16764. this.callBase();
  16765. this._topPocketSize = this._$topPocket.height();
  16766. this._bottomPocketSize = this._$bottomPocket.height();
  16767. this._scrollOffset = this._$container.height() - this._$content.height()
  16768. },
  16769. _allowedDirections: function() {
  16770. var allowedDirections = this.callBase();
  16771. allowedDirections.vertical = allowedDirections.vertical || this._pullDownEnabled;
  16772. return allowedDirections
  16773. },
  16774. _setTopPocketOffset: function() {
  16775. this._$topPocket.css({top: -this._topPocketSize})
  16776. },
  16777. handleEnd: function() {
  16778. this._complete()
  16779. },
  16780. handleStop: function() {
  16781. this._complete()
  16782. },
  16783. _complete: function() {
  16784. if (this._state === STATE_READY) {
  16785. this._setPullDownOffset(this._topPocketSize);
  16786. clearTimeout(this._pullDownRefreshTimeout);
  16787. this._pullDownRefreshTimeout = setTimeout($.proxy(function() {
  16788. this._pullDownRefreshing()
  16789. }, this), 400)
  16790. }
  16791. },
  16792. _setPullDownOffset: function(offset) {
  16793. DX.translator.move(this._$topPocket, {top: offset});
  16794. DX.translator.move(this._$scrollViewContent, {top: offset})
  16795. },
  16796. handleScroll: function(e) {
  16797. this.callBase(e);
  16798. if (this._state === STATE_REFRESHING)
  16799. return;
  16800. this._location = this.location().top;
  16801. if (this._isPullDown())
  16802. this._pullDownReady();
  16803. else if (this._isReachBottom())
  16804. this._reachBottom();
  16805. else
  16806. this._stateReleased()
  16807. },
  16808. _isPullDown: function() {
  16809. return this._pullDownEnabled && this._location >= this._topPocketSize
  16810. },
  16811. _isReachBottom: function() {
  16812. return this._reachBottomEnabled && this._location <= this._scrollOffset + this._bottomPocketSize
  16813. },
  16814. _reachBottom: function() {
  16815. if (this._state === STATE_LOADING)
  16816. return;
  16817. this._state = STATE_LOADING;
  16818. this.reachBottomCallbacks.fire()
  16819. },
  16820. _pullDownReady: function() {
  16821. if (this._state === STATE_READY)
  16822. return;
  16823. this._state = STATE_READY;
  16824. this._$pullDown.addClass(SCROLLVIEW_PULLDOWN_READY_CLASS);
  16825. this._refreshPullDownText()
  16826. },
  16827. _stateReleased: function() {
  16828. if (this._state === STATE_RELEASED)
  16829. return;
  16830. this._$pullDown.removeClass(SCROLLVIEW_PULLDOWN_REFRESHING_CLASS).removeClass(SCROLLVIEW_PULLDOWN_READY_CLASS);
  16831. this._releaseState()
  16832. },
  16833. _pullDownRefreshing: function() {
  16834. if (this._state === STATE_REFRESHING)
  16835. return;
  16836. this._state = STATE_REFRESHING;
  16837. this._$pullDown.addClass(SCROLLVIEW_PULLDOWN_REFRESHING_CLASS).removeClass(SCROLLVIEW_PULLDOWN_READY_CLASS);
  16838. this._refreshPullDownText();
  16839. this.pullDownCallbacks.fire()
  16840. },
  16841. pullDownEnable: function(enabled) {
  16842. this._pullDownEnabled = enabled
  16843. },
  16844. reachBottomEnable: function(enabled) {
  16845. this._reachBottomEnabled = enabled
  16846. },
  16847. pendingRelease: function() {
  16848. this._state = STATE_READY
  16849. },
  16850. release: function() {
  16851. var deferred = $.Deferred();
  16852. this._updateDimensions();
  16853. clearTimeout(this._releaseTimeout);
  16854. this._releaseTimeout = setTimeout($.proxy(function() {
  16855. this._setPullDownOffset(0);
  16856. this._stateReleased();
  16857. this.releaseCallbacks.fire();
  16858. this._updateAction();
  16859. deferred.resolve()
  16860. }, this), 400);
  16861. return deferred.promise()
  16862. },
  16863. dispose: function() {
  16864. clearTimeout(this._pullDownRefreshTimeout);
  16865. clearTimeout(this._releaseTimeout);
  16866. this.callBase()
  16867. }
  16868. });
  16869. ui.dxScrollView.refreshStrategies.pullDown = PullDownNativeScrollViewStrategy
  16870. })(jQuery, DevExpress);
  16871. /*! Module widgets-base, file ui.scrollView.native.swipeDown.js */
  16872. (function($, DX, undefined) {
  16873. var ui = DX.ui,
  16874. events = ui.events;
  16875. var SCROLLVIEW_PULLDOWN_DOWN_LOADING_CLASS = "dx-scrollview-pull-down-loading",
  16876. SCROLLVIEW_PULLDOWN_INDICATOR_CLASS = "dx-scrollview-pull-down-indicator",
  16877. SCROLLVIEW_PULLDOWN_REFRESHING_CLASS = "dx-scrollview-pull-down-refreshing",
  16878. PULLDOWN_ICON_CLASS = "dx-icon-pulldown",
  16879. STATE_RELEASED = 0,
  16880. STATE_READY = 1,
  16881. STATE_REFRESHING = 2,
  16882. STATE_TOUCHED = 4,
  16883. STATE_PULLED = 5;
  16884. var SwipeDownNativeScrollViewStrategy = ui.dxScrollable.NativeStrategy.inherit({
  16885. _init: function(scrollView) {
  16886. this.callBase(scrollView);
  16887. this._$topPocket = scrollView._$topPocket;
  16888. this._$bottomPocket = scrollView._$bottomPocket;
  16889. this._$pullDown = scrollView._$pullDown;
  16890. this._$scrollViewContent = scrollView.content();
  16891. this._initCallbacks();
  16892. this._location = 0
  16893. },
  16894. _initCallbacks: function() {
  16895. this.pullDownCallbacks = $.Callbacks();
  16896. this.releaseCallbacks = $.Callbacks();
  16897. this.reachBottomCallbacks = $.Callbacks()
  16898. },
  16899. render: function() {
  16900. this.callBase();
  16901. this._renderPullDown();
  16902. this._releaseState()
  16903. },
  16904. _renderPullDown: function() {
  16905. var $loadContainer = $("<div>").addClass(SCROLLVIEW_PULLDOWN_INDICATOR_CLASS),
  16906. $loadIndicator = $("<div>").dxLoadIndicator({});
  16907. this._$icon = $("<div>").addClass(PULLDOWN_ICON_CLASS);
  16908. this._$pullDown.empty().append(this._$icon).append($loadContainer.append($loadIndicator))
  16909. },
  16910. _releaseState: function() {
  16911. this._state = STATE_RELEASED;
  16912. this._releasePullDown();
  16913. this._updateDimensions()
  16914. },
  16915. _releasePullDown: function() {
  16916. this._$pullDown.css({opacity: 0})
  16917. },
  16918. _updateDimensions: function() {
  16919. this.callBase();
  16920. this._topPocketSize = this._$topPocket.height();
  16921. this._bottomPocketSize = this._$bottomPocket.height();
  16922. this._scrollOffset = this._$container.height() - this._$content.height()
  16923. },
  16924. _allowedDirections: function() {
  16925. var allowedDirections = this.callBase();
  16926. allowedDirections.vertical = allowedDirections.vertical || this._pullDownEnabled;
  16927. return allowedDirections
  16928. },
  16929. handleInit: function(e) {
  16930. this.callBase(e);
  16931. if (this._state === STATE_RELEASED && this._location === 0) {
  16932. this._startClientY = events.eventData(e.originalEvent).y;
  16933. this._state = STATE_TOUCHED
  16934. }
  16935. },
  16936. handleMove: function(e) {
  16937. this.callBase(e);
  16938. this._deltaY = events.eventData(e.originalEvent).y - this._startClientY;
  16939. if (this._state === STATE_TOUCHED)
  16940. if (this._pullDownEnabled && this._deltaY > 0)
  16941. this._state = STATE_PULLED;
  16942. else
  16943. this._complete();
  16944. if (this._state === STATE_PULLED) {
  16945. e.preventDefault();
  16946. this._movePullDown()
  16947. }
  16948. },
  16949. _movePullDown: function() {
  16950. var pullDownHeight = this._getPullDownHeight(),
  16951. top = Math.min(pullDownHeight * 3, this._deltaY + this._getPullDownStartPosition()),
  16952. angle = 180 * top / pullDownHeight / 3;
  16953. this._$pullDown.css({opacity: 1}).toggleClass(SCROLLVIEW_PULLDOWN_REFRESHING_CLASS, top < pullDownHeight);
  16954. DX.translator.move(this._$pullDown, {top: top});
  16955. this._$icon.css({transform: "rotate(" + angle + "deg)"})
  16956. },
  16957. _isPullDown: function() {
  16958. return this._pullDownEnabled && this._deltaY >= this._getPullDownHeight() - this._getPullDownStartPosition()
  16959. },
  16960. _getPullDownHeight: function() {
  16961. return Math.round(this._$element.outerHeight() * 0.05)
  16962. },
  16963. _getPullDownStartPosition: function() {
  16964. return -Math.round(this._$pullDown.outerHeight() * 1.5)
  16965. },
  16966. handleEnd: function() {
  16967. if (this._isPullDown())
  16968. this._pullDownRefreshing();
  16969. this._complete()
  16970. },
  16971. handleStop: function() {
  16972. this._complete()
  16973. },
  16974. _complete: function() {
  16975. if (this._state === STATE_TOUCHED || this._state === STATE_PULLED)
  16976. this._releaseState()
  16977. },
  16978. handleScroll: function(e) {
  16979. this.callBase(e);
  16980. if (this._state === STATE_REFRESHING)
  16981. return;
  16982. var currentLocation = this.location().top,
  16983. scrollDelta = this._location - currentLocation;
  16984. this._location = currentLocation;
  16985. if (scrollDelta > 0 && this._isReachBottom())
  16986. this._reachBottom();
  16987. else
  16988. this._stateReleased()
  16989. },
  16990. _isReachBottom: function() {
  16991. return this._reachBottomEnabled && this._location <= this._scrollOffset + this._bottomPocketSize
  16992. },
  16993. _reachBottom: function() {
  16994. this.reachBottomCallbacks.fire()
  16995. },
  16996. _stateReleased: function() {
  16997. if (this._state === STATE_RELEASED)
  16998. return;
  16999. this._$pullDown.removeClass(SCROLLVIEW_PULLDOWN_DOWN_LOADING_CLASS);
  17000. this._releaseState()
  17001. },
  17002. _pullDownRefreshing: function() {
  17003. this._state = STATE_REFRESHING;
  17004. this._pullDownRefreshHandler()
  17005. },
  17006. _pullDownRefreshHandler: function() {
  17007. this._refreshPullDown();
  17008. this.pullDownCallbacks.fire()
  17009. },
  17010. _refreshPullDown: function() {
  17011. this._$pullDown.addClass(SCROLLVIEW_PULLDOWN_DOWN_LOADING_CLASS);
  17012. DX.translator.move(this._$pullDown, {top: this._getPullDownHeight()})
  17013. },
  17014. pullDownEnable: function(enabled) {
  17015. this._$topPocket.toggle(enabled);
  17016. this._pullDownEnabled = enabled
  17017. },
  17018. reachBottomEnable: function(enabled) {
  17019. this._reachBottomEnabled = enabled
  17020. },
  17021. pendingRelease: function() {
  17022. this._state = STATE_READY
  17023. },
  17024. release: function() {
  17025. var deferred = $.Deferred();
  17026. this._updateDimensions();
  17027. clearTimeout(this._releaseTimeout);
  17028. this._releaseTimeout = setTimeout($.proxy(function() {
  17029. this._stateReleased();
  17030. this.releaseCallbacks.fire();
  17031. this._updateAction();
  17032. deferred.resolve()
  17033. }, this), 800);
  17034. return deferred.promise()
  17035. },
  17036. dispose: function() {
  17037. clearTimeout(this._pullDownRefreshTimeout);
  17038. clearTimeout(this._releaseTimeout);
  17039. this.callBase()
  17040. }
  17041. });
  17042. ui.dxScrollView.refreshStrategies.swipeDown = SwipeDownNativeScrollViewStrategy
  17043. })(jQuery, DevExpress);
  17044. /*! Module widgets-base, file ui.scrollView.native.slideDown.js */
  17045. (function($, DX, undefined) {
  17046. var ui = DX.ui;
  17047. var STATE_RELEASED = 0,
  17048. STATE_READY = 1,
  17049. STATE_LOADING = 2,
  17050. LOADING_HEIGHT = 80;
  17051. var SlideDownNativeScrollViewStrategy = ui.dxScrollable.NativeStrategy.inherit({
  17052. _init: function(scrollView) {
  17053. this.callBase(scrollView);
  17054. this._$topPocket = scrollView._$topPocket;
  17055. this._$bottomPocket = scrollView._$bottomPocket;
  17056. this._initCallbacks()
  17057. },
  17058. _initCallbacks: function() {
  17059. this.pullDownCallbacks = $.Callbacks();
  17060. this.releaseCallbacks = $.Callbacks();
  17061. this.reachBottomCallbacks = $.Callbacks()
  17062. },
  17063. render: function() {
  17064. this.callBase();
  17065. this._renderPullDown();
  17066. this._renderBottom();
  17067. this._releaseState();
  17068. this._updateDimensions()
  17069. },
  17070. _renderPullDown: function() {
  17071. this._$topPocket.empty()
  17072. },
  17073. _renderBottom: function() {
  17074. this._$bottomPocket.empty().append("<progress>")
  17075. },
  17076. _releaseState: function() {
  17077. if (this._state === STATE_RELEASED)
  17078. return;
  17079. this._state = STATE_RELEASED
  17080. },
  17081. _updateDimensions: function() {
  17082. this._scrollOffset = this._$container.prop("scrollHeight") - this._$container.prop("clientHeight");
  17083. this._containerSize = {
  17084. height: this._$container.prop("clientHeight"),
  17085. width: this._$container.prop("clientWidth")
  17086. };
  17087. this._contentSize = this._componentContentSize = {
  17088. height: this._$container.prop("scrollHeight"),
  17089. width: this._$container.prop("scrollWidth")
  17090. }
  17091. },
  17092. handleScroll: function(e) {
  17093. this.callBase(e);
  17094. if (this._isReachBottom(this._lastLocation.top))
  17095. this._reachBottom()
  17096. },
  17097. _isReachBottom: function(location) {
  17098. this._scrollContent = this._$container.prop("scrollHeight") - this._$container.prop("clientHeight");
  17099. return this._reachBottomEnabled && location < -this._scrollContent + LOADING_HEIGHT
  17100. },
  17101. _reachBottom: function() {
  17102. if (this._state === STATE_LOADING)
  17103. return;
  17104. this._state = STATE_LOADING;
  17105. this.reachBottomCallbacks.fire()
  17106. },
  17107. pullDownEnable: function(enabled) {
  17108. this._pullDownEnabled = enabled
  17109. },
  17110. reachBottomEnable: function(enabled) {
  17111. this._reachBottomEnabled = enabled;
  17112. this._$bottomPocket.toggle(enabled)
  17113. },
  17114. pendingRelease: function() {
  17115. this._state = STATE_READY
  17116. },
  17117. release: function() {
  17118. var deferred = $.Deferred();
  17119. this._state = STATE_RELEASED;
  17120. this.releaseCallbacks.fire();
  17121. this.update();
  17122. return deferred.resolve().promise()
  17123. }
  17124. });
  17125. ui.dxScrollView.refreshStrategies.slideDown = SlideDownNativeScrollViewStrategy
  17126. })(jQuery, DevExpress);
  17127. /*! Module widgets-base, file ui.scrollView.simulated.js */
  17128. (function($, DX, undefined) {
  17129. var ui = DX.ui,
  17130. math = Math;
  17131. var SCROLLVIEW_PULLDOWN_REFRESHING_CLASS = "dx-scrollview-pull-down-loading",
  17132. SCROLLVIEW_PULLDOWN_READY_CLASS = "dx-scrollview-pull-down-ready",
  17133. SCROLLVIEW_PULLDOWN_IMAGE_CLASS = "dx-scrollview-pull-down-image",
  17134. SCROLLVIEW_PULLDOWN_INDICATOR_CLASS = "dx-scrollview-pull-down-indicator",
  17135. SCROLLVIEW_PULLDOWN_TEXT_CLASS = "dx-scrollview-pull-down-text",
  17136. STATE_RELEASED = 0,
  17137. STATE_READY = 1,
  17138. STATE_REFRESHING = 2,
  17139. STATE_LOADING = 3;
  17140. var ScrollViewScroller = ui.dxScrollView.Scroller = ui.dxScrollable.Scroller.inherit({
  17141. ctor: function() {
  17142. this.callBase.apply(this, arguments);
  17143. this._initCallbacks();
  17144. this._releaseState()
  17145. },
  17146. _releaseState: function() {
  17147. this._state = STATE_RELEASED;
  17148. this._refreshPullDownText()
  17149. },
  17150. _refreshPullDownText: function() {
  17151. this._$pullingDownText.css("opacity", this._state === STATE_RELEASED ? 1 : 0);
  17152. this._$pulledDownText.css("opacity", this._state === STATE_READY ? 1 : 0);
  17153. this._$refreshingText.css("opacity", this._state === STATE_REFRESHING ? 1 : 0)
  17154. },
  17155. _initCallbacks: function() {
  17156. this.pullDownCallbacks = $.Callbacks();
  17157. this.releaseCallbacks = $.Callbacks();
  17158. this.reachBottomCallbacks = $.Callbacks()
  17159. },
  17160. _updateBounds: function() {
  17161. var considerPockets = this._direction !== "horizontal";
  17162. this._topPocketSize = considerPockets ? this._$topPocket[this._dimension]() : 0;
  17163. this._bottomPocketSize = considerPockets ? this._$bottomPocket[this._dimension]() : 0;
  17164. this.callBase();
  17165. this._bottomBound = this._minOffset
  17166. },
  17167. _updateScrollbar: function() {
  17168. this._scrollbar.option({
  17169. containerSize: this._containerSize(),
  17170. contentSize: this._contentSize() - this._topPocketSize - this._bottomPocketSize
  17171. })
  17172. },
  17173. _moveContent: function() {
  17174. this.callBase();
  17175. if (this._isPullDown())
  17176. this._pullDownReady();
  17177. else if (this._isReachBottom())
  17178. this._reachBottomReady();
  17179. else if (this._state !== STATE_RELEASED)
  17180. this._stateReleased()
  17181. },
  17182. _moveScrollbar: function() {
  17183. this._scrollbar.moveTo(this._topPocketSize + this._location)
  17184. },
  17185. _isPullDown: function() {
  17186. return this._pullDownEnabled && this._location >= 0
  17187. },
  17188. _isReachBottom: function() {
  17189. return this._reachBottomEnabled && this._location <= this._bottomBound
  17190. },
  17191. _scrollComplete: function() {
  17192. if (this._inBounds() && this._state === STATE_READY)
  17193. this._pullDownRefreshing();
  17194. else if (this._inBounds() && this._state === STATE_LOADING)
  17195. this._reachBottomLoading();
  17196. else
  17197. this.callBase()
  17198. },
  17199. _reachBottomReady: function() {
  17200. if (this._state === STATE_LOADING)
  17201. return;
  17202. this._state = STATE_LOADING;
  17203. this._minOffset = this._getMinOffset()
  17204. },
  17205. _getMaxOffset: function() {
  17206. return -this._topPocketSize
  17207. },
  17208. _getMinOffset: function() {
  17209. return math.min(this.callBase(), -this._topPocketSize)
  17210. },
  17211. _reachBottomLoading: function() {
  17212. this.reachBottomCallbacks.fire()
  17213. },
  17214. _pullDownReady: function() {
  17215. if (this._state === STATE_READY)
  17216. return;
  17217. this._state = STATE_READY;
  17218. this._maxOffset = 0;
  17219. this._$pullDown.addClass(SCROLLVIEW_PULLDOWN_READY_CLASS);
  17220. this._refreshPullDownText()
  17221. },
  17222. _stateReleased: function() {
  17223. if (this._state === STATE_RELEASED)
  17224. return;
  17225. this._releaseState();
  17226. this._updateBounds();
  17227. this._$pullDown.removeClass(SCROLLVIEW_PULLDOWN_REFRESHING_CLASS).removeClass(SCROLLVIEW_PULLDOWN_READY_CLASS);
  17228. this.releaseCallbacks.fire()
  17229. },
  17230. _pullDownRefreshing: function() {
  17231. if (this._state === STATE_REFRESHING)
  17232. return;
  17233. this._state = STATE_REFRESHING;
  17234. this._$pullDown.addClass(SCROLLVIEW_PULLDOWN_REFRESHING_CLASS).removeClass(SCROLLVIEW_PULLDOWN_READY_CLASS);
  17235. this._refreshPullDownText();
  17236. this.pullDownCallbacks.fire()
  17237. },
  17238. _releaseHandler: function() {
  17239. if (this._state === STATE_RELEASED)
  17240. this._moveToBounds();
  17241. this._update();
  17242. if (this._releaseTask)
  17243. this._releaseTask.abort();
  17244. this._releaseTask = DX.utils.executeAsync($.proxy(this._release, this));
  17245. return this._releaseTask.promise
  17246. },
  17247. _release: function() {
  17248. this._stateReleased();
  17249. this._scrollComplete()
  17250. },
  17251. _reachBottomEnablingHandler: function(enabled) {
  17252. if (this._reachBottomEnabled === enabled)
  17253. return;
  17254. this._reachBottomEnabled = enabled;
  17255. this._updateBounds()
  17256. },
  17257. _pullDownEnablingHandler: function(enabled) {
  17258. if (this._pullDownEnabled === enabled)
  17259. return;
  17260. this._pullDownEnabled = enabled;
  17261. this._considerTopPocketChange();
  17262. this._updateHandler()
  17263. },
  17264. _considerTopPocketChange: function() {
  17265. this._location -= this._$topPocket.height() || -this._topPocketSize;
  17266. this._move()
  17267. },
  17268. _pendingReleaseHandler: function() {
  17269. this._state = STATE_READY
  17270. },
  17271. dispose: function() {
  17272. if (this._releaseTask)
  17273. this._releaseTask.abort();
  17274. this.callBase()
  17275. }
  17276. });
  17277. var SimulatedScrollViewStrategy = ui.dxScrollable.SimulatedStrategy.inherit({
  17278. _init: function(scrollView) {
  17279. this.callBase(scrollView);
  17280. this._$pullDown = scrollView._$pullDown;
  17281. this._$topPocket = scrollView._$topPocket;
  17282. this._$bottomPocket = scrollView._$bottomPocket;
  17283. this._initCallbacks()
  17284. },
  17285. _initCallbacks: function() {
  17286. this.pullDownCallbacks = $.Callbacks();
  17287. this.releaseCallbacks = $.Callbacks();
  17288. this.reachBottomCallbacks = $.Callbacks()
  17289. },
  17290. render: function() {
  17291. this._renderPullDown();
  17292. this.callBase()
  17293. },
  17294. _renderPullDown: function() {
  17295. var $image = $("<div>").addClass(SCROLLVIEW_PULLDOWN_IMAGE_CLASS),
  17296. $loadContainer = $("<div>").addClass(SCROLLVIEW_PULLDOWN_INDICATOR_CLASS),
  17297. $loadIndicator = $("<div>").dxLoadIndicator(),
  17298. $text = this._$pullDownText = $("<div>").addClass(SCROLLVIEW_PULLDOWN_TEXT_CLASS);
  17299. this._$pullingDownText = $("<div>").text(this.option("pullingDownText")).appendTo($text);
  17300. this._$pulledDownText = $("<div>").text(this.option("pulledDownText")).appendTo($text);
  17301. this._$refreshingText = $("<div>").text(this.option("refreshingText")).appendTo($text);
  17302. this._$pullDown.empty().append($image).append($loadContainer.append($loadIndicator)).append($text)
  17303. },
  17304. pullDownEnable: function(enabled) {
  17305. this._eventHandler("pullDownEnabling", enabled)
  17306. },
  17307. reachBottomEnable: function(enabled) {
  17308. this._eventHandler("reachBottomEnabling", enabled)
  17309. },
  17310. _createScroller: function(direction) {
  17311. var that = this;
  17312. var scroller = that._scrollers[direction] = new ScrollViewScroller(that._scrollerOptions(direction));
  17313. scroller.pullDownCallbacks.add(function() {
  17314. that.pullDownCallbacks.fire()
  17315. });
  17316. scroller.releaseCallbacks.add(function() {
  17317. that.releaseCallbacks.fire()
  17318. });
  17319. scroller.reachBottomCallbacks.add(function() {
  17320. that.reachBottomCallbacks.fire()
  17321. })
  17322. },
  17323. _scrollerOptions: function(direction) {
  17324. return $.extend(this.callBase(direction), {
  17325. $topPocket: this._$topPocket,
  17326. $bottomPocket: this._$bottomPocket,
  17327. $pullDown: this._$pullDown,
  17328. $pullDownText: this._$pullDownText,
  17329. $pullingDownText: this._$pullingDownText,
  17330. $pulledDownText: this._$pulledDownText,
  17331. $refreshingText: this._$refreshingText
  17332. })
  17333. },
  17334. pendingRelease: function() {
  17335. this._eventHandler("pendingRelease")
  17336. },
  17337. release: function() {
  17338. return this._eventHandler("release").done(this._updateAction)
  17339. },
  17340. location: function() {
  17341. var location = this.callBase();
  17342. location.top += this._$topPocket.height();
  17343. return location
  17344. },
  17345. dispose: function() {
  17346. $.each(this._scrollers, function() {
  17347. this.dispose()
  17348. });
  17349. this.callBase()
  17350. }
  17351. });
  17352. ui.dxScrollView.refreshStrategies.simulated = SimulatedScrollViewStrategy
  17353. })(jQuery, DevExpress);
  17354. /*! Module widgets-base, file ui.map.js */
  17355. (function($, DX, undefined) {
  17356. var ui = DX.ui,
  17357. events = ui.events,
  17358. utils = DX.utils,
  17359. winJS = DX.support.winJS,
  17360. wrapToArray = utils.wrapToArray,
  17361. removeDublicates = utils.removeDublicates,
  17362. titleize = DX.inflector.titleize;
  17363. var MAP_CLASS = "dx-map",
  17364. MAP_CONTAINER_CLASS = "dx-map-container",
  17365. MAP_SHIELD_CLASS = "dx-map-shield";
  17366. DX.registerComponent("dxMap", ui, ui.Widget.inherit({
  17367. ctor: function() {
  17368. this.callBase.apply(this, arguments);
  17369. this.addMarker = $.proxy(this._addFunction, this, "markers");
  17370. this.removeMarker = $.proxy(this._removeFunction, this, "markers");
  17371. this.addRoute = $.proxy(this._addFunction, this, "routes");
  17372. this.removeRoute = $.proxy(this._removeFunction, this, "routes")
  17373. },
  17374. _addFunction: function(optionName, addingValue) {
  17375. var deferred = $.Deferred(),
  17376. that = this,
  17377. providerDeffered = $.Deferred(),
  17378. optionValue = this.option(optionName),
  17379. addingValues = wrapToArray(addingValue);
  17380. optionValue.push.apply(optionValue, addingValues);
  17381. this._notificationDeffered = providerDeffered;
  17382. this.option(optionName, optionValue);
  17383. providerDeffered.done(function(instance) {
  17384. deferred.resolveWith(that, instance && instance.length > 1 ? [instance] : instance)
  17385. });
  17386. return deferred.promise()
  17387. },
  17388. _removeFunction: function(optionName, removingValue) {
  17389. var deferred = $.Deferred(),
  17390. that = this,
  17391. providerDeffered = $.Deferred(),
  17392. optionValue = this.option(optionName),
  17393. removingValues = wrapToArray(removingValue);
  17394. $.each(removingValues, function(_, removingValue) {
  17395. var index = $.isNumeric(removingValue) ? removingValue : $.inArray(removingValue, optionValue);
  17396. if (index !== -1)
  17397. optionValue.splice(index, 1);
  17398. else
  17399. throw DX.log("E1021", titleize(optionName.substring(0, optionName.length - 1)), removingValue);
  17400. });
  17401. this._notificationDeffered = providerDeffered;
  17402. this.option(optionName, optionValue);
  17403. providerDeffered.done(function() {
  17404. deferred.resolveWith(that)
  17405. });
  17406. return deferred.promise()
  17407. },
  17408. _setDeprecatedOptions: function() {
  17409. this.callBase();
  17410. $.extend(this._deprecatedOptions, {
  17411. markerAddedAction: {
  17412. since: "14.2",
  17413. alias: "onMarkerAdded"
  17414. },
  17415. markerRemovedAction: {
  17416. since: "14.2",
  17417. alias: "onMarkerRemoved"
  17418. },
  17419. readyAction: {
  17420. since: "14.2",
  17421. alias: "onReady"
  17422. },
  17423. routeAddedAction: {
  17424. since: "14.2",
  17425. alias: "onRouteAdded"
  17426. },
  17427. routeRemovedAction: {
  17428. since: "14.2",
  17429. alias: "onRouteRemoved"
  17430. },
  17431. clickAction: {
  17432. since: "14.2",
  17433. alias: "onClick"
  17434. }
  17435. })
  17436. },
  17437. _setDefaultOptions: function() {
  17438. this.callBase();
  17439. this.option({
  17440. bounds: {
  17441. northEast: null,
  17442. southWest: null
  17443. },
  17444. center: {
  17445. lat: 0,
  17446. lng: 0
  17447. },
  17448. zoom: 1,
  17449. width: 300,
  17450. height: 300,
  17451. type: "roadmap",
  17452. provider: "google",
  17453. autoAdjust: true,
  17454. markers: [],
  17455. markerIconSrc: null,
  17456. onMarkerAdded: null,
  17457. onMarkerRemoved: null,
  17458. routes: [],
  17459. onRouteAdded: null,
  17460. onRouteRemoved: null,
  17461. key: {
  17462. bing: "",
  17463. google: "",
  17464. googleStatic: ""
  17465. },
  17466. controls: false,
  17467. onReady: null,
  17468. onUpdated: null,
  17469. onClick: null
  17470. })
  17471. },
  17472. _defaultOptionsRules: function() {
  17473. return this.callBase().concat([{
  17474. device: function(device) {
  17475. return DX.devices.real().generic && !DX.devices.isSimulator()
  17476. },
  17477. options: {focusStateEnabled: true}
  17478. }])
  17479. },
  17480. _init: function() {
  17481. this.callBase();
  17482. this._asyncQueue = [];
  17483. this._checkProvider();
  17484. this._checkMarkersOption(this.option("markers"));
  17485. this._checkRoutesOption(this.option("routes"));
  17486. this._initContainer();
  17487. this._grabEvents();
  17488. this._cleanRenderedMarkers();
  17489. this._cleanRenderedRoutes()
  17490. },
  17491. _checkProvider: function() {
  17492. if (winJS && this.option("provider") === "google")
  17493. throw DX.Error("E1024");
  17494. },
  17495. _checkMarkersOption: function(markers) {
  17496. if (!$.isArray(markers))
  17497. throw DX.Error("E1022");
  17498. },
  17499. _checkRoutesOption: function(routes) {
  17500. if (!$.isArray(routes))
  17501. throw DX.Error("E1023");
  17502. },
  17503. _initContainer: function() {
  17504. this._$container = $("<div />").addClass(MAP_CONTAINER_CLASS);
  17505. this.element().append(this._$container)
  17506. },
  17507. _grabEvents: function() {
  17508. var eventName = events.addNamespace("dxpointerdown", this.NAME);
  17509. this.element().on(eventName, $.proxy(this._cancelEvent, this))
  17510. },
  17511. _cancelEvent: function(e) {
  17512. var cancelByProvider = this._provider.cancelEvents && !this.option("disabled");
  17513. if (!DX.designMode && cancelByProvider)
  17514. e.stopPropagation()
  17515. },
  17516. _cleanRenderedMarkers: function() {
  17517. this._renderedMarkers = []
  17518. },
  17519. _cleanRenderedRoutes: function(routes) {
  17520. this._renderedRoutes = []
  17521. },
  17522. _render: function() {
  17523. this.callBase();
  17524. this.element().addClass(MAP_CLASS);
  17525. this._renderShield();
  17526. this._queueAsyncAction("render", this.option("markers"), this.option("routes"));
  17527. this._saveRenderedMarkers();
  17528. this._saveRenderedRoutes()
  17529. },
  17530. _saveRenderedMarkers: function(markers) {
  17531. markers = markers || this.option("markers");
  17532. this._renderedMarkers = markers.slice()
  17533. },
  17534. _saveRenderedRoutes: function(routes) {
  17535. routes = routes || this.option("routes");
  17536. this._renderedRoutes = routes.slice()
  17537. },
  17538. _renderShield: function() {
  17539. var $shield;
  17540. if (DX.designMode || this.option("disabled")) {
  17541. $shield = $("<div/>").addClass(MAP_SHIELD_CLASS);
  17542. this.element().append($shield)
  17543. }
  17544. else {
  17545. $shield = this.element().find("." + MAP_SHIELD_CLASS);
  17546. $shield.remove()
  17547. }
  17548. },
  17549. _clean: function() {
  17550. this._cleanFocusState();
  17551. if (!this._provider)
  17552. return;
  17553. this._queueAsyncAction("clean");
  17554. this._cleanRenderedMarkers();
  17555. this._cleanRenderedRoutes()
  17556. },
  17557. _optionChanged: function(args) {
  17558. var value = args.value;
  17559. if (this._cancelOptionChange)
  17560. return;
  17561. var notificationDeffered = this._notificationDeffered;
  17562. delete this._notificationDeffered;
  17563. switch (args.name) {
  17564. case"disabled":
  17565. this._renderShield();
  17566. this.callBase(args);
  17567. break;
  17568. case"width":
  17569. case"height":
  17570. this.callBase(args);
  17571. this._dimensionChanged();
  17572. break;
  17573. case"provider":
  17574. this._invalidate();
  17575. break;
  17576. case"key":
  17577. DX.log("W1001");
  17578. break;
  17579. case"bounds":
  17580. this._queueAsyncAction("updateBounds");
  17581. break;
  17582. case"center":
  17583. this._queueAsyncAction("updateCenter");
  17584. break;
  17585. case"zoom":
  17586. this._queueAsyncAction("updateZoom");
  17587. break;
  17588. case"type":
  17589. this._queueAsyncAction("updateMapType");
  17590. break;
  17591. case"controls":
  17592. this._queueAsyncAction("updateControls", this.option("markers"), this.option("routes"));
  17593. break;
  17594. case"autoAdjust":
  17595. this._queueAsyncAction("adjustViewport");
  17596. break;
  17597. case"markers":
  17598. this._checkMarkersOption(value);
  17599. this._queueAsyncAction("updateMarkers", notificationDeffered ? removeDublicates(this._renderedMarkers, value) : this._renderedMarkers, notificationDeffered ? removeDublicates(value, this._renderedMarkers) : value).done($.proxy(function() {
  17600. if (notificationDeffered)
  17601. notificationDeffered.resolve.apply(notificationDeffered, arguments)
  17602. }, this));
  17603. this._saveRenderedMarkers(value);
  17604. break;
  17605. case"markerIconSrc":
  17606. this._queueAsyncAction("updateMarkers", this._renderedMarkers, this._renderedMarkers);
  17607. break;
  17608. case"routes":
  17609. this._checkRoutesOption(value);
  17610. this._queueAsyncAction("updateRoutes", notificationDeffered ? removeDublicates(this._renderedRoutes, value) : this._renderedRoutes, notificationDeffered ? removeDublicates(value, this._renderedRoutes) : value).done($.proxy(function() {
  17611. if (notificationDeffered)
  17612. notificationDeffered.resolve.apply(notificationDeffered, arguments)
  17613. }, this));
  17614. this._saveRenderedRoutes(value);
  17615. break;
  17616. case"onReady":
  17617. case"onUpdated":
  17618. case"onMarkerAdded":
  17619. case"onMarkerRemoved":
  17620. case"onRouteAdded":
  17621. case"onRouteRemoved":
  17622. case"onClick":
  17623. break;
  17624. default:
  17625. this.callBase.apply(this, arguments)
  17626. }
  17627. },
  17628. _visibilityChanged: function(visible) {
  17629. if (visible)
  17630. this._dimensionChanged()
  17631. },
  17632. _dimensionChanged: function() {
  17633. this._queueAsyncAction("updateDimensions")
  17634. },
  17635. _queueAsyncAction: function(name) {
  17636. var deferred = $.Deferred(),
  17637. emptyQueue = !this._asyncQueue.length;
  17638. this._asyncQueue.push({
  17639. name: name,
  17640. options: $.makeArray(arguments).slice(1),
  17641. deferred: deferred
  17642. });
  17643. if (emptyQueue)
  17644. this._enqueueAsyncAction();
  17645. return deferred.promise()
  17646. },
  17647. _enqueueAsyncAction: function() {
  17648. var emptyQueue = !this._asyncQueue.length;
  17649. if (emptyQueue)
  17650. return;
  17651. this._execAsyncAction(this._asyncQueue[0]).done($.proxy(function() {
  17652. this._asyncQueue.shift();
  17653. this._enqueueAsyncAction()
  17654. }, this))
  17655. },
  17656. _execAsyncAction: function(action) {
  17657. var deferred = $.Deferred(),
  17658. actionName = action.name,
  17659. actionOptions = action.options,
  17660. actionDeferred = action.deferred,
  17661. provider = this._getProvider(actionName);
  17662. provider[actionName].apply(provider, actionOptions).done($.proxy(function(mapRefreshed) {
  17663. actionDeferred.resolve.apply(actionDeferred, $.makeArray(arguments).slice(1));
  17664. if (mapRefreshed)
  17665. this._triggerReadyAction();
  17666. else if (actionName !== "clean")
  17667. this._triggerUpdateAction();
  17668. deferred.resolve()
  17669. }, this));
  17670. return deferred.promise()
  17671. },
  17672. _getProvider: function(actionName) {
  17673. var currentProvider = this.option("provider");
  17674. if (actionName !== "clean" && this._usedProvider !== currentProvider) {
  17675. this._provider = new providers[currentProvider](this, this._$container);
  17676. this._usedProvider = currentProvider
  17677. }
  17678. return this._provider
  17679. },
  17680. _triggerReadyAction: function() {
  17681. this._createActionByOption("onReady")({originalMap: this._provider.map()})
  17682. },
  17683. _triggerUpdateAction: function() {
  17684. this._createActionByOption("onUpdated")()
  17685. },
  17686. setOptionSilent: function(name, value) {
  17687. this._cancelOptionChange = true;
  17688. this.option(name, value);
  17689. this._cancelOptionChange = false
  17690. }
  17691. }));
  17692. var providers = {};
  17693. ui.dxMap.registerProvider = function(name, provider) {
  17694. providers[name] = provider
  17695. }
  17696. })(jQuery, DevExpress);
  17697. /*! Module widgets-base, file ui.map.provider.js */
  17698. (function($, DX, undefined) {
  17699. var ui = DX.ui,
  17700. events = ui.events;
  17701. ui.dxMap.Provider = DX.Class.inherit({
  17702. _defaultRouteWeight: function() {
  17703. return 5
  17704. },
  17705. _defaultRouteOpacity: function() {
  17706. return 0.5
  17707. },
  17708. _defaultRouteColor: function() {
  17709. return "#0000FF"
  17710. },
  17711. cancelEvents: false,
  17712. ctor: function(map, $container) {
  17713. this._mapWidget = map;
  17714. this._$container = $container
  17715. },
  17716. render: function(markerOptions, routeOptions) {
  17717. var deferred = $.Deferred();
  17718. this._renderImpl().done($.proxy(function() {
  17719. var markersPromise = this.addMarkers(markerOptions);
  17720. var routesPromise = this.addRoutes(routeOptions);
  17721. $.when(markersPromise, routesPromise).done(function() {
  17722. deferred.resolve(true)
  17723. })
  17724. }, this));
  17725. return deferred.promise()
  17726. },
  17727. _renderImpl: DX.abstract,
  17728. updateDimensions: DX.abstract,
  17729. updateMapType: DX.abstract,
  17730. updateBounds: DX.abstract,
  17731. updateCenter: DX.abstract,
  17732. updateZoom: DX.abstract,
  17733. updateControls: DX.abstract,
  17734. updateMarkers: function(markerOptionsToRemove, markerOptionsToAdd) {
  17735. var deferred = $.Deferred(),
  17736. that = this;
  17737. this.removeMarkers(markerOptionsToRemove).done(function() {
  17738. that.addMarkers(markerOptionsToAdd).done(function() {
  17739. deferred.resolve.apply(deferred, arguments)
  17740. })
  17741. });
  17742. return deferred.promise()
  17743. },
  17744. addMarkers: DX.abstract,
  17745. removeMarkers: DX.abstract,
  17746. adjustViewport: DX.abstract,
  17747. updateRoutes: function(routeOptionsToRemove, routeOptionsToAdd) {
  17748. var deferred = $.Deferred(),
  17749. that = this;
  17750. this.removeRoutes(routeOptionsToRemove).done(function() {
  17751. that.addRoutes(routeOptionsToAdd).done(function() {
  17752. deferred.resolve.apply(deferred, arguments)
  17753. })
  17754. });
  17755. return deferred.promise()
  17756. },
  17757. addRoutes: DX.abstract,
  17758. removeRoutes: DX.abstract,
  17759. clean: DX.abstract,
  17760. map: function() {
  17761. return this._map
  17762. },
  17763. _option: function(name, value) {
  17764. if (value === undefined)
  17765. return this._mapWidget.option(name);
  17766. this._mapWidget.setOptionSilent(name, value)
  17767. },
  17768. _keyOption: function(providerName) {
  17769. var key = this._option("key");
  17770. return key[providerName] === undefined ? key : key[providerName]
  17771. },
  17772. _parseTooltipOptions: function(option) {
  17773. return {
  17774. text: option.text || option,
  17775. visible: option.isShown || false
  17776. }
  17777. },
  17778. _getLatLng: function(location) {
  17779. if (typeof location === "string") {
  17780. var coords = $.map(location.split(","), $.trim),
  17781. numericRegex = /[-+]?[0-9]*\.?[0-9]*/;
  17782. if (coords.length === 2 && coords[0].match(numericRegex) && coords[1].match(numericRegex))
  17783. return {
  17784. lat: parseFloat(coords[0]),
  17785. lng: parseFloat(coords[1])
  17786. }
  17787. }
  17788. else if ($.isArray(location) && location.length === 2)
  17789. return {
  17790. lat: location[0],
  17791. lng: location[1]
  17792. };
  17793. else if ($.isPlainObject(location) && $.isNumeric(location.lat) && $.isNumeric(location.lng))
  17794. return location;
  17795. return null
  17796. },
  17797. _isBoundsSetted: function() {
  17798. return this._option("bounds.northEast") && this._option("bounds.southWest")
  17799. },
  17800. _addEventNamespace: function(name) {
  17801. return events.addNamespace(name, this._mapWidget.NAME)
  17802. },
  17803. _createAction: function() {
  17804. var mapWidget = this._mapWidget;
  17805. return mapWidget._createAction.apply(mapWidget, arguments)
  17806. },
  17807. _fireAction: function(name, actionArguments) {
  17808. var option = this._option(name);
  17809. if (option)
  17810. this._createAction(option)(actionArguments)
  17811. },
  17812. _fireClickAction: function(actionArguments) {
  17813. this._fireAction("onClick", actionArguments)
  17814. },
  17815. _fireMarkerAddedAction: function(actionArguments) {
  17816. this._fireAction("onMarkerAdded", actionArguments)
  17817. },
  17818. _fireMarkerRemovedAction: function(actionArguments) {
  17819. this._fireAction("onMarkerRemoved", actionArguments)
  17820. },
  17821. _fireRouteAddedAction: function(actionArguments) {
  17822. this._fireAction("onRouteAdded", actionArguments)
  17823. },
  17824. _fireRouteRemovedAction: function(actionArguments) {
  17825. this._fireAction("onRouteRemoved", actionArguments)
  17826. }
  17827. })
  17828. })(jQuery, DevExpress);
  17829. /*! Module widgets-base, file ui.map.provider.googleStatic.js */
  17830. (function($, DX, undefined) {
  17831. var ui = DX.ui;
  17832. var GOOGLE_STATIC_URL = "https://maps.google.com/maps/api/staticmap?";
  17833. ui.dxMap.registerProvider("googleStatic", ui.dxMap.Provider.inherit({
  17834. _locationToString: function(location) {
  17835. var latlng = this._getLatLng(location);
  17836. return latlng ? latlng.lat + "," + latlng.lng : location.toString().replace(/ /g, "+")
  17837. },
  17838. _renderImpl: function() {
  17839. return this._updateMap()
  17840. },
  17841. updateDimensions: function() {
  17842. return this._updateMap()
  17843. },
  17844. updateMapType: function() {
  17845. return this._updateMap()
  17846. },
  17847. updateBounds: function() {
  17848. return $.Deferred().resolve().promise()
  17849. },
  17850. updateCenter: function() {
  17851. return this._updateMap()
  17852. },
  17853. updateZoom: function() {
  17854. return this._updateMap()
  17855. },
  17856. updateControls: function() {
  17857. return $.Deferred().resolve().promise()
  17858. },
  17859. addMarkers: function(options) {
  17860. var that = this;
  17861. return this._updateMap().done(function() {
  17862. $.each(options, function(_, options) {
  17863. that._fireMarkerAddedAction({options: options})
  17864. })
  17865. })
  17866. },
  17867. removeMarkers: function(options) {
  17868. var that = this;
  17869. return this._updateMap().done(function() {
  17870. $.each(options, function(_, options) {
  17871. that._fireMarkerRemovedAction({options: options})
  17872. })
  17873. })
  17874. },
  17875. adjustViewport: function() {
  17876. return $.Deferred().resolve().promise()
  17877. },
  17878. addRoutes: function(options) {
  17879. var that = this;
  17880. return this._updateMap().done(function() {
  17881. $.each(options, function(_, options) {
  17882. that._fireRouteAddedAction({options: options})
  17883. })
  17884. })
  17885. },
  17886. removeRoutes: function(options) {
  17887. var that = this;
  17888. return this._updateMap().done(function() {
  17889. $.each(options, function(_, options) {
  17890. that._fireRouteRemovedAction({options: options})
  17891. })
  17892. })
  17893. },
  17894. clean: function() {
  17895. this._$container.css("background-image", "none");
  17896. this._$container.off(this._addEventNamespace("dxclick"));
  17897. return $.Deferred().resolve().promise()
  17898. },
  17899. mapRendered: function() {
  17900. return true
  17901. },
  17902. _updateMap: function() {
  17903. var key = this._keyOption("googleStatic"),
  17904. $container = this._$container;
  17905. var requestOptions = ["sensor=false", "size=" + $container.width() + "x" + $container.height(), "maptype=" + this._option("type"), "center=" + this._locationToString(this._option("center")), "zoom=" + this._option("zoom"), this._markersSubstring()];
  17906. requestOptions.push.apply(requestOptions, this._routeSubstrings());
  17907. if (key)
  17908. requestOptions.push("key=" + key);
  17909. var request = GOOGLE_STATIC_URL + requestOptions.join("&");
  17910. this._$container.css("background", "url(\"" + request + "\") no-repeat 0 0");
  17911. this._attachClickEvent();
  17912. return $.Deferred().resolve(true).promise()
  17913. },
  17914. _markersSubstring: function() {
  17915. var that = this,
  17916. markers = [],
  17917. markerIcon = this._option("markerIconSrc");
  17918. if (markerIcon)
  17919. markers.push("icon:" + markerIcon);
  17920. $.each(this._option("markers"), function(_, marker) {
  17921. markers.push(that._locationToString(marker.location))
  17922. });
  17923. return "markers=" + markers.join("|")
  17924. },
  17925. _routeSubstrings: function() {
  17926. var that = this,
  17927. routes = [];
  17928. $.each(this._option("routes"), function(_, route) {
  17929. var color = new DX.Color(route.color || that._defaultRouteColor()).toHex().replace('#', '0x'),
  17930. opacity = Math.round((route.opacity || that._defaultRouteOpacity()) * 255).toString(16),
  17931. width = route.weight || that._defaultRouteWeight(),
  17932. locations = [];
  17933. $.each(route.locations, function(_, routePoint) {
  17934. locations.push(that._locationToString(routePoint))
  17935. });
  17936. routes.push("path=color:" + color + opacity + "|weight:" + width + "|" + locations.join("|"))
  17937. });
  17938. return routes
  17939. },
  17940. _attachClickEvent: function() {
  17941. var that = this,
  17942. eventName = this._addEventNamespace("dxclick");
  17943. this._$container.off(eventName).on(eventName, function(e) {
  17944. that._fireClickAction({jQueryEvent: e})
  17945. })
  17946. }
  17947. }));
  17948. ui.dxMap.__internals = $.extend(ui.dxMap.__internals, {remapGoogleStaticConstant: function(newValue) {
  17949. GOOGLE_STATIC_URL = newValue
  17950. }})
  17951. })(jQuery, DevExpress);
  17952. /*! Module widgets-base, file ui.map.provider.dynamic.js */
  17953. (function($, DX, undefined) {
  17954. var ui = DX.ui;
  17955. ui.dxMap.DynamicProvider = ui.dxMap.Provider.inherit({
  17956. cancelEvents: true,
  17957. _renderImpl: function(markerOptions, routeOptions) {
  17958. var deferred = $.Deferred();
  17959. this._load().done($.proxy(function() {
  17960. this._init().done($.proxy(function() {
  17961. var mapTypePromise = this.updateMapType(),
  17962. boundsPromise = this._isBoundsSetted() ? this.updateBounds() : this.updateCenter();
  17963. $.when(mapTypePromise, boundsPromise).done($.proxy(function() {
  17964. this._attachHandlers();
  17965. setTimeout(function() {
  17966. deferred.resolve()
  17967. })
  17968. }, this))
  17969. }, this))
  17970. }, this));
  17971. return deferred.promise()
  17972. },
  17973. _load: function() {
  17974. if (!this._mapsLoader) {
  17975. this._mapsLoader = $.Deferred();
  17976. this._loadImpl().done($.proxy(function() {
  17977. this._mapsLoader.resolve()
  17978. }, this))
  17979. }
  17980. this._markers = [];
  17981. this._routes = [];
  17982. return this._mapsLoader.promise()
  17983. },
  17984. _loadImpl: DX.abstract,
  17985. _init: DX.abstract,
  17986. _attachHandlers: DX.abstract,
  17987. addMarkers: function(options) {
  17988. var deferred = $.Deferred(),
  17989. that = this;
  17990. var markerPromises = $.map(options, function(options) {
  17991. return that._addMarker(options)
  17992. });
  17993. $.when.apply($, markerPromises).done(function() {
  17994. var instances = $.map($.makeArray(arguments), function(markerObject) {
  17995. return markerObject.marker
  17996. });
  17997. deferred.resolve(false, instances)
  17998. });
  17999. return deferred.promise()
  18000. },
  18001. _addMarker: function(options) {
  18002. var that = this;
  18003. return this._renderMarker(options).done(function(markerObject) {
  18004. that._markers.push($.extend({options: options}, markerObject));
  18005. that._fitBounds();
  18006. that._fireMarkerAddedAction({
  18007. options: options,
  18008. originalMarker: markerObject.marker
  18009. })
  18010. })
  18011. },
  18012. _renderMarker: DX.abstract,
  18013. removeMarkers: function(markersOptionsToRemove) {
  18014. var that = this;
  18015. $.each(markersOptionsToRemove, function(_, markerOptionToRemove) {
  18016. that._removeMarker(markerOptionToRemove)
  18017. });
  18018. return $.Deferred().resolve().promise()
  18019. },
  18020. _removeMarker: function(markersOptionToRemove) {
  18021. var that = this;
  18022. $.each(this._markers, function(markerIndex, markerObject) {
  18023. if (markerObject.options !== markersOptionToRemove)
  18024. return true;
  18025. that._destroyMarker(markerObject);
  18026. that._markers.splice(markerIndex, 1);
  18027. that._fireMarkerRemovedAction({options: markerObject.options});
  18028. return false
  18029. })
  18030. },
  18031. _destroyMarker: DX.abstract,
  18032. _clearMarkers: function() {
  18033. while (this._markers.length > 0)
  18034. this._removeMarker(this._markers[0].options)
  18035. },
  18036. addRoutes: function(options) {
  18037. var deferred = $.Deferred(),
  18038. that = this;
  18039. var routePromises = $.map(options, function(options) {
  18040. return that._addRoute(options)
  18041. });
  18042. $.when.apply($, routePromises).done(function() {
  18043. var instances = $.map($.makeArray(arguments), function(routeObject) {
  18044. return routeObject.instance
  18045. });
  18046. deferred.resolve(false, instances)
  18047. });
  18048. return deferred.promise()
  18049. },
  18050. _addRoute: function(options) {
  18051. var that = this;
  18052. return this._renderRoute(options).done(function(routeObject) {
  18053. that._routes.push($.extend({options: options}, routeObject));
  18054. that._fitBounds();
  18055. that._fireRouteAddedAction({
  18056. options: options,
  18057. originalRoute: routeObject.instance
  18058. })
  18059. })
  18060. },
  18061. _renderRoute: DX.abstract,
  18062. removeRoutes: function(options) {
  18063. var that = this;
  18064. $.each(options, function(routeIndex, options) {
  18065. that._removeRoute(options)
  18066. });
  18067. return $.Deferred().resolve().promise()
  18068. },
  18069. _removeRoute: function(options) {
  18070. var that = this;
  18071. $.each(this._routes, function(routeIndex, routeObject) {
  18072. if (routeObject.options !== options)
  18073. return true;
  18074. that._destroyRoute(routeObject);
  18075. that._routes.splice(routeIndex, 1);
  18076. that._fireRouteRemovedAction({options: options});
  18077. return false
  18078. })
  18079. },
  18080. _destroyRoute: DX.abstract,
  18081. _clearRoutes: function() {
  18082. while (this._routes.length > 0)
  18083. this._removeRoute(this._routes[0].options)
  18084. },
  18085. adjustViewport: function() {
  18086. return this._fitBounds()
  18087. },
  18088. _fitBounds: DX.abstract,
  18089. _updateBounds: function() {
  18090. var that = this;
  18091. this._clearBounds();
  18092. $.each(this._markers, function(_, markerObject) {
  18093. that._extendBounds(markerObject.location)
  18094. });
  18095. $.each(this._routes, function(_, routeObject) {
  18096. that._extendBounds(routeObject.northEast);
  18097. that._extendBounds(routeObject.southWest)
  18098. })
  18099. },
  18100. _clearBounds: function() {
  18101. this._bounds = null
  18102. },
  18103. _extendBounds: DX.abstract
  18104. })
  18105. })(jQuery, DevExpress);
  18106. /*! Module widgets-base, file ui.map.provider.dynamic.bing.js */
  18107. (function($, DX, undefined) {
  18108. var ui = DX.ui,
  18109. winJS = DX.support.winJS;
  18110. var BING_MAP_READY = "_bingScriptReady",
  18111. BING_URL = "https://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&s=1&onScriptLoad=" + BING_MAP_READY,
  18112. BING_LOCAL_FILES1 = "ms-appx:///Bing.Maps.JavaScript/js/veapicore.js",
  18113. BING_LOCAL_FILES2 = "ms-appx:///Bing.Maps.JavaScript/js/veapiModules.js",
  18114. BING_CREDENTIALS = "AhuxC0dQ1DBTNo8L-H9ToVMQStmizZzBJdraTSgCzDSWPsA1Qd8uIvFSflzxdaLH",
  18115. MIN_LOCATION_RECT_LENGTH = 0.0000000000000001;
  18116. var msMapsLoaded = function() {
  18117. return window.Microsoft && window.Microsoft.Maps
  18118. };
  18119. var msMapsLoader;
  18120. ui.dxMap.registerProvider("bing", ui.dxMap.DynamicProvider.inherit({
  18121. _mapType: function(type) {
  18122. var mapTypes = {
  18123. roadmap: Microsoft.Maps.MapTypeId.road,
  18124. hybrid: Microsoft.Maps.MapTypeId.aerial,
  18125. satellite: Microsoft.Maps.MapTypeId.aerial
  18126. };
  18127. return mapTypes[type] || mapTypes.road
  18128. },
  18129. _movementMode: function(type) {
  18130. var movementTypes = {
  18131. driving: Microsoft.Maps.Directions.RouteMode.driving,
  18132. walking: Microsoft.Maps.Directions.RouteMode.walking
  18133. };
  18134. return movementTypes[type] || movementTypes.driving
  18135. },
  18136. _resolveLocation: function(location) {
  18137. var d = $.Deferred();
  18138. var latLng = this._getLatLng(location);
  18139. if (latLng)
  18140. d.resolve(new Microsoft.Maps.Location(latLng.lat, latLng.lng));
  18141. else {
  18142. var searchManager = new Microsoft.Maps.Search.SearchManager(this._map);
  18143. var searchRequest = {
  18144. where: location,
  18145. count: 1,
  18146. callback: function(searchResponse) {
  18147. var boundsBox = searchResponse.results[0].location;
  18148. d.resolve(new Microsoft.Maps.Location(boundsBox.latitude, boundsBox.longitude))
  18149. }
  18150. };
  18151. searchManager.geocode(searchRequest)
  18152. }
  18153. return d.promise()
  18154. },
  18155. _normalizeLocation: function(location) {
  18156. return {
  18157. lat: location.latitude,
  18158. lng: location.longitude
  18159. }
  18160. },
  18161. _normalizeLocationRect: function(locationRect) {
  18162. var northWest = this._normalizeLocation(locationRect.getNorthwest()),
  18163. southEast = this._normalizeLocation(locationRect.getSoutheast());
  18164. return {
  18165. northEast: {
  18166. lat: northWest.lat,
  18167. lng: southEast.lng
  18168. },
  18169. southWest: {
  18170. lat: southEast.lat,
  18171. lng: northWest.lng
  18172. }
  18173. }
  18174. },
  18175. _loadImpl: function() {
  18176. this._msMapsLoader = $.Deferred();
  18177. if (msMapsLoaded())
  18178. this._mapReady();
  18179. else {
  18180. if (!msMapsLoader || msMapsLoader.state() === "resolved" && !msMapsLoaded()) {
  18181. msMapsLoader = $.Deferred();
  18182. window[BING_MAP_READY] = $.proxy(msMapsLoader.resolve, msMapsLoader);
  18183. if (winJS)
  18184. $.when($.getScript(BING_LOCAL_FILES1), $.getScript(BING_LOCAL_FILES2)).done(function() {
  18185. Microsoft.Maps.loadModule("Microsoft.Maps.Map", {callback: window[BING_MAP_READY]})
  18186. });
  18187. else
  18188. $.getScript(BING_URL)
  18189. }
  18190. msMapsLoader.done($.proxy(this._mapReady, this))
  18191. }
  18192. return this._msMapsLoader.promise()
  18193. },
  18194. _mapReady: function() {
  18195. try {
  18196. delete window[BING_MAP_READY]
  18197. }
  18198. catch(e) {
  18199. window[BING_MAP_READY] = undefined
  18200. }
  18201. var searchModulePromise = $.Deferred();
  18202. var directionsModulePromise = $.Deferred();
  18203. Microsoft.Maps.loadModule('Microsoft.Maps.Search', {callback: $.proxy(searchModulePromise.resolve, searchModulePromise)});
  18204. Microsoft.Maps.loadModule('Microsoft.Maps.Directions', {callback: $.proxy(directionsModulePromise.resolve, directionsModulePromise)});
  18205. $.when(searchModulePromise, directionsModulePromise).done($.proxy(function() {
  18206. this._msMapsLoader.resolve()
  18207. }, this))
  18208. },
  18209. _init: function() {
  18210. var deferred = $.Deferred(),
  18211. initPromise = $.Deferred(),
  18212. controls = this._option("controls");
  18213. this._map = new Microsoft.Maps.Map(this._$container[0], {
  18214. credentials: this._keyOption("bing") || BING_CREDENTIALS,
  18215. zoom: this._option("zoom"),
  18216. showDashboard: controls,
  18217. showMapTypeSelector: controls,
  18218. showScalebar: controls
  18219. });
  18220. var handler = Microsoft.Maps.Events.addHandler(this._map, 'tiledownloadcomplete', $.proxy(initPromise.resolve, initPromise));
  18221. $.when(initPromise).done($.proxy(function() {
  18222. Microsoft.Maps.Events.removeHandler(handler);
  18223. deferred.resolve()
  18224. }, this));
  18225. return deferred.promise()
  18226. },
  18227. _attachHandlers: function() {
  18228. this._providerViewChangeHandler = Microsoft.Maps.Events.addHandler(this._map, 'viewchange', $.proxy(this._viewChangeHandler, this));
  18229. this._providerClickHandler = Microsoft.Maps.Events.addHandler(this._map, 'click', $.proxy(this._clickActionHandler, this))
  18230. },
  18231. _viewChangeHandler: function() {
  18232. var bounds = this._map.getBounds();
  18233. this._option("bounds", this._normalizeLocationRect(bounds));
  18234. var center = this._map.getCenter();
  18235. this._option("center", this._normalizeLocation(center));
  18236. if (!this._preventZoomChangeEvent)
  18237. this._option("zoom", this._map.getZoom())
  18238. },
  18239. _clickActionHandler: function(e) {
  18240. if (e.targetType === "map") {
  18241. var point = new Microsoft.Maps.Point(e.getX(), e.getY()),
  18242. location = e.target.tryPixelToLocation(point);
  18243. this._fireClickAction({location: this._normalizeLocation(location)})
  18244. }
  18245. },
  18246. updateDimensions: function() {
  18247. var $container = this._$container;
  18248. this._map.setOptions({
  18249. width: $container.width(),
  18250. height: $container.height()
  18251. });
  18252. return $.Deferred().resolve().promise()
  18253. },
  18254. updateMapType: function() {
  18255. var type = this._option("type"),
  18256. labelOverlay = Microsoft.Maps.LabelOverlay;
  18257. this._map.setView({
  18258. animate: false,
  18259. mapTypeId: this._mapType(type),
  18260. labelOverlay: type === "satellite" ? labelOverlay.hidden : labelOverlay.visible
  18261. });
  18262. return $.Deferred().resolve().promise()
  18263. },
  18264. updateBounds: function() {
  18265. var deferred = $.Deferred(),
  18266. that = this;
  18267. var northEastPromise = this._resolveLocation(this._option("bounds.northEast")),
  18268. southWestPromise = this._resolveLocation(this._option("bounds.southWest"));
  18269. $.when(northEastPromise, southWestPromise).done(function(northEast, southWest) {
  18270. var bounds = new Microsoft.Maps.LocationRect.fromLocations(northEast, southWest);
  18271. that._map.setView({
  18272. animate: false,
  18273. bounds: bounds
  18274. });
  18275. deferred.resolve()
  18276. });
  18277. return deferred.promise()
  18278. },
  18279. updateCenter: function() {
  18280. var deferred = $.Deferred(),
  18281. that = this;
  18282. this._resolveLocation(this._option("center")).done(function(location) {
  18283. that._map.setView({
  18284. animate: false,
  18285. center: location
  18286. });
  18287. deferred.resolve()
  18288. });
  18289. return deferred.promise()
  18290. },
  18291. updateZoom: function() {
  18292. this._map.setView({
  18293. animate: false,
  18294. zoom: this._option("zoom")
  18295. });
  18296. return $.Deferred().resolve().promise()
  18297. },
  18298. updateControls: function() {
  18299. this.clean();
  18300. return this.render.apply(this, arguments)
  18301. },
  18302. _renderMarker: function(options) {
  18303. var d = $.Deferred(),
  18304. that = this;
  18305. this._resolveLocation(options.location).done(function(location) {
  18306. var pushpinOptions = {icon: options.iconSrc || that._option("markerIconSrc")};
  18307. if (options.html) {
  18308. $.extend(pushpinOptions, {
  18309. htmlContent: options.html,
  18310. width: null,
  18311. height: null
  18312. });
  18313. var htmlOffset = options.htmlOffset;
  18314. if (htmlOffset)
  18315. pushpinOptions.anchor = new Microsoft.Maps.Point(-htmlOffset.left, -htmlOffset.top)
  18316. }
  18317. var pushpin = new Microsoft.Maps.Pushpin(location, pushpinOptions);
  18318. that._map.entities.push(pushpin);
  18319. var infobox = that._renderTooltip(location, options.tooltip);
  18320. if (options.clickAction) {
  18321. DX.log("W0001", "dxMap", "marker.clickAction", "14.2", "Use 'onClick' option instead");
  18322. options.onClick = options.clickAction
  18323. }
  18324. var handler;
  18325. if (options.onClick || options.tooltip) {
  18326. var markerClickAction = that._createAction(options.onClick || $.noop),
  18327. markerNormalizedLocation = that._normalizeLocation(location);
  18328. handler = Microsoft.Maps.Events.addHandler(pushpin, "click", function() {
  18329. markerClickAction({location: markerNormalizedLocation});
  18330. if (infobox)
  18331. infobox.setOptions({visible: true})
  18332. })
  18333. }
  18334. d.resolve({
  18335. location: location,
  18336. marker: pushpin,
  18337. infobox: infobox,
  18338. handler: handler
  18339. })
  18340. });
  18341. return d.promise()
  18342. },
  18343. _renderTooltip: function(location, options) {
  18344. if (!options)
  18345. return;
  18346. options = this._parseTooltipOptions(options);
  18347. var infobox = new Microsoft.Maps.Infobox(location, {
  18348. description: options.text,
  18349. offset: new Microsoft.Maps.Point(0, 33),
  18350. visible: options.visible
  18351. });
  18352. this._map.entities.push(infobox, null);
  18353. return infobox
  18354. },
  18355. _destroyMarker: function(marker) {
  18356. this._map.entities.remove(marker.marker);
  18357. if (marker.infobox)
  18358. this._map.entities.remove(marker.infobox);
  18359. if (marker.handler)
  18360. Microsoft.Maps.Events.removeHandler(marker.handler)
  18361. },
  18362. _renderRoute: function(options) {
  18363. var d = $.Deferred(),
  18364. that = this;
  18365. var points = $.map(options.locations, function(point) {
  18366. return that._resolveLocation(point)
  18367. });
  18368. $.when.apply($, points).done(function() {
  18369. var locations = $.makeArray(arguments),
  18370. direction = new Microsoft.Maps.Directions.DirectionsManager(that._map),
  18371. color = new DX.Color(options.color || that._defaultRouteColor()).toHex(),
  18372. routeColor = new Microsoft.Maps.Color.fromHex(color);
  18373. routeColor.a = (options.opacity || that._defaultRouteOpacity()) * 255;
  18374. direction.setRenderOptions({
  18375. autoUpdateMapView: false,
  18376. displayRouteSelector: false,
  18377. waypointPushpinOptions: {visible: false},
  18378. drivingPolylineOptions: {
  18379. strokeColor: routeColor,
  18380. strokeThickness: options.weight || that._defaultRouteWeight()
  18381. },
  18382. walkingPolylineOptions: {
  18383. strokeColor: routeColor,
  18384. strokeThickness: options.weight || that._defaultRouteWeight()
  18385. }
  18386. });
  18387. direction.setRequestOptions({
  18388. routeMode: that._movementMode(options.mode),
  18389. routeDraggable: false
  18390. });
  18391. $.each(locations, function(_, location) {
  18392. var waypoint = new Microsoft.Maps.Directions.Waypoint({location: location});
  18393. direction.addWaypoint(waypoint)
  18394. });
  18395. var handler = Microsoft.Maps.Events.addHandler(direction, 'directionsUpdated', function(args) {
  18396. Microsoft.Maps.Events.removeHandler(handler);
  18397. var routeSummary = args.routeSummary[0];
  18398. d.resolve({
  18399. instance: direction,
  18400. northEast: routeSummary.northEast,
  18401. southWest: routeSummary.southWest
  18402. })
  18403. });
  18404. direction.calculateDirections()
  18405. });
  18406. return d.promise()
  18407. },
  18408. _destroyRoute: function(routeObject) {
  18409. routeObject.instance.dispose()
  18410. },
  18411. _fitBounds: function() {
  18412. this._updateBounds();
  18413. if (this._bounds && this._option("autoAdjust")) {
  18414. var zoomBeforeFitting = this._map.getZoom();
  18415. this._preventZoomChangeEvent = true;
  18416. var bounds = this._bounds.clone();
  18417. bounds.height = bounds.height * 1.1;
  18418. bounds.width = bounds.width * 1.1;
  18419. this._map.setView({
  18420. animate: false,
  18421. bounds: bounds,
  18422. zoom: zoomBeforeFitting
  18423. });
  18424. var zoomAfterFitting = this._map.getZoom();
  18425. if (zoomBeforeFitting < zoomAfterFitting)
  18426. this._map.setView({
  18427. animate: false,
  18428. zoom: zoomBeforeFitting
  18429. });
  18430. else
  18431. this._option("zoom", zoomAfterFitting);
  18432. delete this._preventZoomChangeEvent
  18433. }
  18434. return $.Deferred().resolve().promise()
  18435. },
  18436. _extendBounds: function(location) {
  18437. if (this._bounds)
  18438. this._bounds = new Microsoft.Maps.LocationRect.fromLocations(this._bounds.getNorthwest(), this._bounds.getSoutheast(), location);
  18439. else
  18440. this._bounds = new Microsoft.Maps.LocationRect(location, MIN_LOCATION_RECT_LENGTH, MIN_LOCATION_RECT_LENGTH)
  18441. },
  18442. clean: function() {
  18443. if (this._map) {
  18444. Microsoft.Maps.Events.removeHandler(this._providerViewChangeHandler);
  18445. Microsoft.Maps.Events.removeHandler(this._providerClickHandler);
  18446. this._clearMarkers();
  18447. this._clearRoutes();
  18448. this._map.dispose()
  18449. }
  18450. return $.Deferred().resolve().promise()
  18451. }
  18452. }));
  18453. ui.dxMap.__internals = $.extend(ui.dxMap.__internals, {remapBingConstant: function(newValue) {
  18454. BING_URL = newValue
  18455. }})
  18456. })(jQuery, DevExpress);
  18457. /*! Module widgets-base, file ui.map.provider.dynamic.google.js */
  18458. (function($, DX, undefined) {
  18459. var ui = DX.ui;
  18460. var GOOGLE_MAP_READY = "_googleScriptReady",
  18461. GOOGLE_URL = "https://maps.google.com/maps/api/js?v=3.18&sensor=false&callback=" + GOOGLE_MAP_READY;
  18462. var CustomMarker;
  18463. var initCustomMarkerClass = function() {
  18464. CustomMarker = function(options) {
  18465. this._position = options.position;
  18466. this._offset = options.offset;
  18467. this._$overlayContainer = $("<div>").css({
  18468. position: "absolute",
  18469. display: "none",
  18470. cursor: "pointer"
  18471. }).append(options.html);
  18472. this.setMap(options.map)
  18473. };
  18474. CustomMarker.prototype = new google.maps.OverlayView;
  18475. CustomMarker.prototype.onAdd = function() {
  18476. var $pane = $(this.getPanes().overlayMouseTarget);
  18477. $pane.append(this._$overlayContainer);
  18478. this._clickListner = google.maps.event.addDomListener(this._$overlayContainer.get(0), 'click', $.proxy(function(e) {
  18479. google.maps.event.trigger(this, 'click');
  18480. e.preventDefault()
  18481. }, this));
  18482. this.draw()
  18483. };
  18484. CustomMarker.prototype.onRemove = function() {
  18485. google.maps.event.removeListener(this._clickListner);
  18486. this._$overlayContainer.remove()
  18487. };
  18488. CustomMarker.prototype.draw = function() {
  18489. var position = this.getProjection().fromLatLngToDivPixel(this._position);
  18490. this._$overlayContainer.css({
  18491. left: position.x + this._offset.left,
  18492. top: position.y + this._offset.top,
  18493. display: 'block'
  18494. })
  18495. }
  18496. };
  18497. var googleMapsLoaded = function() {
  18498. return window.google && window.google.maps
  18499. };
  18500. var googleMapsLoader;
  18501. ui.dxMap.registerProvider("google", ui.dxMap.DynamicProvider.inherit({
  18502. _mapType: function(type) {
  18503. var mapTypes = {
  18504. hybrid: google.maps.MapTypeId.HYBRID,
  18505. roadmap: google.maps.MapTypeId.ROADMAP,
  18506. satellite: google.maps.MapTypeId.SATELLITE
  18507. };
  18508. return mapTypes[type] || mapTypes.hybrid
  18509. },
  18510. _movementMode: function(type) {
  18511. var movementTypes = {
  18512. driving: google.maps.TravelMode.DRIVING,
  18513. walking: google.maps.TravelMode.WALKING
  18514. };
  18515. return movementTypes[type] || movementTypes.driving
  18516. },
  18517. _resolveLocation: function(location) {
  18518. var d = $.Deferred();
  18519. var latLng = this._getLatLng(location);
  18520. if (latLng)
  18521. d.resolve(new google.maps.LatLng(latLng.lat, latLng.lng));
  18522. else {
  18523. var geocoder = new google.maps.Geocoder;
  18524. geocoder.geocode({address: location}, function(results, status) {
  18525. if (status === google.maps.GeocoderStatus.OK)
  18526. d.resolve(results[0].geometry.location)
  18527. })
  18528. }
  18529. return d.promise()
  18530. },
  18531. _normalizeLocation: function(location) {
  18532. return {
  18533. lat: location.lat(),
  18534. lng: location.lng()
  18535. }
  18536. },
  18537. _normalizeLocationRect: function(locationRect) {
  18538. return {
  18539. northEast: this._normalizeLocation(locationRect.getNorthEast()),
  18540. southWest: this._normalizeLocation(locationRect.getSouthWest())
  18541. }
  18542. },
  18543. _loadImpl: function() {
  18544. this._googleMapsLoader = $.Deferred();
  18545. if (googleMapsLoaded())
  18546. this._mapReady();
  18547. else {
  18548. if (!googleMapsLoader || googleMapsLoader.state() === "resolved" && !googleMapsLoaded()) {
  18549. googleMapsLoader = $.Deferred();
  18550. var key = this._keyOption("google");
  18551. window[GOOGLE_MAP_READY] = $.proxy(googleMapsLoader.resolve, googleMapsLoader);
  18552. $.getScript(GOOGLE_URL + (key ? "&key=" + key : ""))
  18553. }
  18554. googleMapsLoader.done($.proxy(this._mapReady, this))
  18555. }
  18556. return this._googleMapsLoader.promise()
  18557. },
  18558. _mapReady: function() {
  18559. try {
  18560. delete window[GOOGLE_MAP_READY]
  18561. }
  18562. catch(e) {
  18563. window[GOOGLE_MAP_READY] = undefined
  18564. }
  18565. initCustomMarkerClass();
  18566. this._googleMapsLoader.resolve()
  18567. },
  18568. _init: function() {
  18569. var deferred = $.Deferred(),
  18570. initPromise = $.Deferred(),
  18571. controls = this._option("controls");
  18572. this._map = new google.maps.Map(this._$container[0], {
  18573. zoom: this._option("zoom"),
  18574. panControl: controls,
  18575. zoomControl: controls,
  18576. mapTypeControl: controls,
  18577. streetViewControl: controls
  18578. });
  18579. var listner = google.maps.event.addListener(this._map, 'idle', $.proxy(initPromise.resolve, initPromise));
  18580. $.when(initPromise).done($.proxy(function() {
  18581. google.maps.event.removeListener(listner);
  18582. deferred.resolve()
  18583. }, this));
  18584. return deferred.promise()
  18585. },
  18586. _attachHandlers: function() {
  18587. this._boundsChangeListener = google.maps.event.addListener(this._map, 'bounds_changed', $.proxy(this._boundsChangeHandler, this));
  18588. this._clickListener = google.maps.event.addListener(this._map, 'click', $.proxy(this._clickActionHandler, this))
  18589. },
  18590. _boundsChangeHandler: function() {
  18591. var bounds = this._map.getBounds();
  18592. this._option("bounds", this._normalizeLocationRect(bounds));
  18593. var center = this._map.getCenter();
  18594. this._option("center", this._normalizeLocation(center));
  18595. if (!this._preventZoomChangeEvent)
  18596. this._option("zoom", this._map.getZoom())
  18597. },
  18598. _clickActionHandler: function(e) {
  18599. this._fireClickAction({location: this._normalizeLocation(e.latLng)})
  18600. },
  18601. updateDimensions: function() {
  18602. var center = this._option("center");
  18603. google.maps.event.trigger(this._map, 'resize');
  18604. this._option("center", center);
  18605. return this.updateCenter()
  18606. },
  18607. updateMapType: function() {
  18608. this._map.setMapTypeId(this._mapType(this._option("type")));
  18609. return $.Deferred().resolve().promise()
  18610. },
  18611. updateBounds: function() {
  18612. var deferred = $.Deferred(),
  18613. that = this;
  18614. var northEastPromise = this._resolveLocation(this._option("bounds.northEast")),
  18615. southWestPromise = this._resolveLocation(this._option("bounds.southWest"));
  18616. $.when(northEastPromise, southWestPromise).done(function(northEast, southWest) {
  18617. var bounds = new google.maps.LatLngBounds;
  18618. bounds.extend(northEast);
  18619. bounds.extend(southWest);
  18620. that._map.fitBounds(bounds);
  18621. deferred.resolve()
  18622. });
  18623. return deferred.promise()
  18624. },
  18625. updateCenter: function() {
  18626. var deferred = $.Deferred(),
  18627. that = this;
  18628. this._resolveLocation(this._option("center")).done(function(center) {
  18629. that._map.setCenter(center);
  18630. that._option("center", that._normalizeLocation(center));
  18631. deferred.resolve()
  18632. });
  18633. return deferred.promise()
  18634. },
  18635. updateZoom: function() {
  18636. this._map.setZoom(this._option("zoom"));
  18637. return $.Deferred().resolve().promise()
  18638. },
  18639. updateControls: function() {
  18640. var controls = this._option("controls");
  18641. this._map.setOptions({
  18642. panControl: controls,
  18643. zoomControl: controls,
  18644. mapTypeControl: controls,
  18645. streetViewControl: controls
  18646. });
  18647. return $.Deferred().resolve().promise()
  18648. },
  18649. _renderMarker: function(options) {
  18650. var d = $.Deferred(),
  18651. that = this;
  18652. this._resolveLocation(options.location).done(function(location) {
  18653. var marker;
  18654. if (options.html)
  18655. marker = new CustomMarker({
  18656. map: that._map,
  18657. position: location,
  18658. html: options.html,
  18659. offset: $.extend({
  18660. top: 0,
  18661. left: 0
  18662. }, options.htmlOffset)
  18663. });
  18664. else
  18665. marker = new google.maps.Marker({
  18666. position: location,
  18667. map: that._map,
  18668. icon: options.iconSrc || that._option("markerIconSrc")
  18669. });
  18670. var infoWindow = that._renderTooltip(marker, options.tooltip);
  18671. if (options.clickAction) {
  18672. DX.log("W0001", "dxMap", "marker.clickAction", "14.2", "Use 'onClick' option instead");
  18673. options.onClick = options.clickAction
  18674. }
  18675. var listner;
  18676. if (options.onClick || options.tooltip) {
  18677. var markerClickAction = that._createAction(options.onClick || $.noop),
  18678. markerNormalizedLocation = that._normalizeLocation(location);
  18679. listner = google.maps.event.addListener(marker, "click", function() {
  18680. markerClickAction({location: markerNormalizedLocation});
  18681. if (infoWindow)
  18682. infoWindow.open(that._map, marker)
  18683. })
  18684. }
  18685. d.resolve({
  18686. location: location,
  18687. marker: marker,
  18688. listner: listner
  18689. })
  18690. });
  18691. return d.promise()
  18692. },
  18693. _renderTooltip: function(marker, options) {
  18694. if (!options)
  18695. return;
  18696. options = this._parseTooltipOptions(options);
  18697. var infoWindow = new google.maps.InfoWindow({content: options.text});
  18698. if (options.visible)
  18699. infoWindow.open(this._map, marker);
  18700. return infoWindow
  18701. },
  18702. _destroyMarker: function(marker) {
  18703. marker.marker.setMap(null);
  18704. if (marker.listner)
  18705. google.maps.event.removeListener(marker.listner)
  18706. },
  18707. _renderRoute: function(options) {
  18708. var d = $.Deferred(),
  18709. that = this,
  18710. directionsService = new google.maps.DirectionsService;
  18711. var points = $.map(options.locations, function(point) {
  18712. return that._resolveLocation(point)
  18713. });
  18714. $.when.apply($, points).done(function() {
  18715. var locations = $.makeArray(arguments),
  18716. origin = locations.shift(),
  18717. destination = locations.pop(),
  18718. waypoints = $.map(locations, function(location) {
  18719. return {
  18720. location: location,
  18721. stopover: true
  18722. }
  18723. });
  18724. var request = {
  18725. origin: origin,
  18726. destination: destination,
  18727. waypoints: waypoints,
  18728. optimizeWaypoints: true,
  18729. travelMode: that._movementMode(options.mode)
  18730. };
  18731. directionsService.route(request, function(response, status) {
  18732. if (status === google.maps.DirectionsStatus.OK) {
  18733. var color = new DX.Color(options.color || that._defaultRouteColor()).toHex(),
  18734. directionOptions = {
  18735. directions: response,
  18736. map: that._map,
  18737. suppressMarkers: true,
  18738. preserveViewport: true,
  18739. polylineOptions: {
  18740. strokeWeight: options.weight || that._defaultRouteWeight(),
  18741. strokeOpacity: options.opacity || that._defaultRouteOpacity(),
  18742. strokeColor: color
  18743. }
  18744. };
  18745. var route = new google.maps.DirectionsRenderer(directionOptions),
  18746. bounds = response.routes[0].bounds;
  18747. d.resolve({
  18748. instance: route,
  18749. northEast: bounds.getNorthEast(),
  18750. southWest: bounds.getSouthWest()
  18751. })
  18752. }
  18753. })
  18754. });
  18755. return d.promise()
  18756. },
  18757. _destroyRoute: function(routeObject) {
  18758. routeObject.instance.setMap(null)
  18759. },
  18760. _fitBounds: function() {
  18761. this._updateBounds();
  18762. if (this._bounds && this._option("autoAdjust")) {
  18763. var zoomBeforeFitting = this._map.getZoom();
  18764. this._preventZoomChangeEvent = true;
  18765. this._map.fitBounds(this._bounds);
  18766. var zoomAfterFitting = this._map.getZoom();
  18767. if (zoomBeforeFitting < zoomAfterFitting)
  18768. this._map.setZoom(zoomBeforeFitting);
  18769. else
  18770. this._option("zoom", zoomAfterFitting);
  18771. delete this._preventZoomChangeEvent
  18772. }
  18773. return $.Deferred().resolve().promise()
  18774. },
  18775. _extendBounds: function(location) {
  18776. if (this._bounds)
  18777. this._bounds.extend(location);
  18778. else {
  18779. this._bounds = new google.maps.LatLngBounds;
  18780. this._bounds.extend(location)
  18781. }
  18782. },
  18783. clean: function() {
  18784. if (this._map) {
  18785. google.maps.event.removeListener(this._boundsChangeListener);
  18786. google.maps.event.removeListener(this._clickListener);
  18787. this._clearMarkers();
  18788. this._clearRoutes();
  18789. delete this._map;
  18790. this._$container.empty()
  18791. }
  18792. return $.Deferred().resolve().promise()
  18793. }
  18794. }));
  18795. ui.dxMap.__internals = $.extend(ui.dxMap.__internals, {remapGoogleConstant: function(newValue) {
  18796. GOOGLE_URL = newValue
  18797. }})
  18798. })(jQuery, DevExpress);
  18799. /*! Module widgets-base, file ui.swipeable.js */
  18800. (function($, DX, undefined) {
  18801. var ui = DX.ui,
  18802. events = ui.events,
  18803. DX_SWIPEABLE = "dxSwipeable",
  18804. SWIPEABLE_CLASS = "dx-swipeable",
  18805. ACTION_TO_EVENT_MAP = {
  18806. onStart: "dxswipestart",
  18807. onUpdated: "dxswipe",
  18808. onEnd: "dxswipeend",
  18809. onCancel: "dxswipecancel"
  18810. };
  18811. DX.registerComponent(DX_SWIPEABLE, ui, DX.DOMComponent.inherit({
  18812. _setDefaultOptions: function() {
  18813. this.callBase();
  18814. this.option({
  18815. elastic: true,
  18816. immediate: false,
  18817. direction: "horizontal",
  18818. itemSizeFunc: null,
  18819. onStart: null,
  18820. onUpdated: null,
  18821. onEnd: null,
  18822. onCancel: null
  18823. })
  18824. },
  18825. _render: function() {
  18826. this.callBase();
  18827. this.element().addClass(SWIPEABLE_CLASS);
  18828. this._attachEventHandlers()
  18829. },
  18830. _attachEventHandlers: function() {
  18831. this._detachEventHanlers();
  18832. if (this.option("disabled"))
  18833. return;
  18834. var NAME = this.NAME;
  18835. this._createEventData();
  18836. $.each(ACTION_TO_EVENT_MAP, $.proxy(function(actionName, eventName) {
  18837. var action = this._createActionByOption(actionName, {context: this});
  18838. eventName = events.addNamespace(eventName, NAME);
  18839. this.element().on(eventName, this._eventData, function(e) {
  18840. return action({jQueryEvent: e})
  18841. })
  18842. }, this))
  18843. },
  18844. _createEventData: function() {
  18845. this._eventData = {
  18846. elastic: this.option("elastic"),
  18847. itemSizeFunc: this.option("itemSizeFunc"),
  18848. direction: this.option("direction"),
  18849. immediate: this.option("immediate")
  18850. }
  18851. },
  18852. _detachEventHanlers: function() {
  18853. this.element().off("." + DX_SWIPEABLE)
  18854. },
  18855. _optionChanged: function(args) {
  18856. switch (args.name) {
  18857. case"disabled":
  18858. case"onStart":
  18859. case"onUpdated":
  18860. case"onEnd":
  18861. case"onCancel":
  18862. case"elastic":
  18863. case"immediate":
  18864. case"itemSizeFunc":
  18865. case"direction":
  18866. this._detachEventHanlers();
  18867. this._attachEventHandlers();
  18868. break;
  18869. case"rtlEnabled":
  18870. break;
  18871. default:
  18872. this.callBase(args)
  18873. }
  18874. }
  18875. }))
  18876. })(jQuery, DevExpress);
  18877. /*! Module widgets-base, file ui.draggable.js */
  18878. (function($, DX, undefined) {
  18879. var ui = DX.ui,
  18880. translator = DX.translator,
  18881. inflector = DX.inflector,
  18882. events = ui.events,
  18883. DRAGGABLE = "dxDraggable",
  18884. DRAGSTART_EVENT_NAME = events.addNamespace("dxdragstart", DRAGGABLE),
  18885. DRAG_EVENT_NAME = events.addNamespace("dxdrag", DRAGGABLE),
  18886. DRAGEND_EVENT_NAME = events.addNamespace("dxdragend", DRAGGABLE),
  18887. POINTERDOWN_EVENT_NAME = events.addNamespace("dxpointerdown", DRAGGABLE),
  18888. DRAGGABLE_CLASS = inflector.dasherize(DRAGGABLE),
  18889. DRAGGABLE_DRAGGING_CLASS = DRAGGABLE_CLASS + "-dragging";
  18890. DX.registerComponent(DRAGGABLE, ui, DX.DOMComponent.inherit({
  18891. _setDefaultOptions: function() {
  18892. this.callBase();
  18893. this.option({
  18894. onDragStart: $.noop,
  18895. onDrag: $.noop,
  18896. onDragEnd: $.noop,
  18897. direction: "both",
  18898. area: window,
  18899. boundOffset: 0,
  18900. allowMoveByClick: false
  18901. })
  18902. },
  18903. _init: function() {
  18904. this.callBase();
  18905. this._attachEventHandlers()
  18906. },
  18907. _attachEventHandlers: function() {
  18908. var $element = this.element().css("position", "absolute"),
  18909. eventHandlers = {},
  18910. allowMoveByClick = this.option("allowMoveByClick");
  18911. eventHandlers[DRAGSTART_EVENT_NAME] = $.proxy(this._dragStartHandler, this);
  18912. eventHandlers[DRAG_EVENT_NAME] = $.proxy(this._dragHandler, this);
  18913. eventHandlers[DRAGEND_EVENT_NAME] = $.proxy(this._dragEndHandler, this);
  18914. if (allowMoveByClick) {
  18915. eventHandlers[POINTERDOWN_EVENT_NAME] = $.proxy(this._pointerDownHandler, this);
  18916. $element = this._getArea()
  18917. }
  18918. $element.on(eventHandlers, {
  18919. direction: this.option("direction"),
  18920. immediate: true
  18921. })
  18922. },
  18923. _detachEventHandlers: function() {
  18924. this.element().off("." + DRAGGABLE);
  18925. this._getArea().off("." + DRAGGABLE)
  18926. },
  18927. _move: function(position) {
  18928. translator.move(this.element(), position)
  18929. },
  18930. _pointerDownHandler: function(e) {
  18931. var $area = $(e.currentTarget),
  18932. areaOffset = $.isWindow($area.get(0)) ? {
  18933. left: 0,
  18934. top: 0
  18935. } : $area.offset(),
  18936. direction = this.option("direction"),
  18937. position = {};
  18938. if (direction === "horizontal" || direction === "both")
  18939. position.left = e.pageX - this.element().width() / 2 - areaOffset.left;
  18940. if (direction === "vertical" || direction === "both")
  18941. position.top = e.pageY - this.element().height() / 2 - areaOffset.top;
  18942. this._move(position);
  18943. this._getAction("onDrag")({jQueryEvent: e})
  18944. },
  18945. _dragStartHandler: function(e) {
  18946. var $element = this.element(),
  18947. $area = this._getArea(),
  18948. boundOffset = this._getBoundOffset(),
  18949. areaWidth = $area.outerWidth(),
  18950. areaHeight = $area.outerHeight(),
  18951. elementWidth = $element.width(),
  18952. elementHeight = $element.height();
  18953. this._toggleDraggingClass(true);
  18954. this._startPosition = translator.locate($element);
  18955. e.maxLeftOffset = this._startPosition.left - boundOffset.h;
  18956. e.maxRightOffset = areaWidth - this._startPosition.left - elementWidth - boundOffset.h;
  18957. e.maxTopOffset = this._startPosition.top - boundOffset.v;
  18958. e.maxBottomOffset = areaHeight - this._startPosition.top - elementHeight - boundOffset.v;
  18959. this._getAction("onDragStart")({jQueryEvent: e})
  18960. },
  18961. _toggleDraggingClass: function(value) {
  18962. this.element().toggleClass(DRAGGABLE_DRAGGING_CLASS, value)
  18963. },
  18964. _getBoundOffset: function() {
  18965. var boundOffset = this.option("boundOffset");
  18966. if ($.isFunction(boundOffset))
  18967. boundOffset = boundOffset.call(this);
  18968. return DX.utils.stringPairToObject(boundOffset)
  18969. },
  18970. _getArea: function() {
  18971. var area = this.option("area");
  18972. if ($.isFunction(area))
  18973. area = area.call(this);
  18974. return $(area)
  18975. },
  18976. _dragHandler: function(e) {
  18977. var offset = e.offset,
  18978. startPosition = this._startPosition;
  18979. this._move({
  18980. left: startPosition.left + offset.x,
  18981. top: startPosition.top + offset.y
  18982. });
  18983. this._getAction("onDrag")({jQueryEvent: e})
  18984. },
  18985. _dragEndHandler: function(e) {
  18986. this._toggleDraggingClass(false);
  18987. this._getAction("onDragEnd")({jQueryEvent: e})
  18988. },
  18989. _getAction: function(name) {
  18990. return this["_" + name + "Action"] || this._createActionByOption(name)
  18991. },
  18992. _render: function() {
  18993. this.callBase();
  18994. this.element().addClass(DRAGGABLE_CLASS)
  18995. },
  18996. _optionChanged: function(args) {
  18997. var name = args.name;
  18998. switch (name) {
  18999. case"onDragStart":
  19000. case"onDrag":
  19001. case"onDragEnd":
  19002. this["_" + name + "Action"] = this._createActionByOption(name);
  19003. break;
  19004. case"allowMoveByClick":
  19005. case"direction":
  19006. this._detachEventHandlers();
  19007. this._attachEventHandlers();
  19008. break;
  19009. case"boundOffset":
  19010. case"area":
  19011. break;
  19012. default:
  19013. this.callBase(args)
  19014. }
  19015. },
  19016. _dispose: function() {
  19017. this.callBase();
  19018. this._detachEventHandlers()
  19019. }
  19020. }));
  19021. ui.dxDraggable.__internals = {DRAGGABLE_CLASS: DRAGGABLE_CLASS}
  19022. })(jQuery, DevExpress);
  19023. /*! Module widgets-base, file ui.resizable.js */
  19024. (function($, DX, undefined) {
  19025. var ui = DX.ui,
  19026. utils = DX.utils,
  19027. events = ui.events,
  19028. RESIZABLE = "dxResizable",
  19029. RESIZABLE_CLASS = "dx-resizable",
  19030. RESIZABLE_RESIZING_CLASS = "dx-resizable-resizing",
  19031. RESIZABLE_HANDLE_CLASS = "dx-resizable-handle",
  19032. RESIZABLE_HANDLE_TOP_CLASS = "dx-resizable-handle-top",
  19033. RESIZABLE_HANDLE_BOTTOM_CLASS = "dx-resizable-handle-bottom",
  19034. RESIZABLE_HANDLE_LEFT_CLASS = "dx-resizable-handle-left",
  19035. RESIZABLE_HANDLE_RIGHT_CLASS = "dx-resizable-handle-right",
  19036. RESIZABLE_HANDLE_CORNER_CLASS = "dx-resizable-handle-corner",
  19037. DRAGSTART_START_EVENT_NAME = events.addNamespace("dxdragstart", RESIZABLE),
  19038. DRAGSTART_EVENT_NAME = events.addNamespace("dxdrag", RESIZABLE),
  19039. DRAGSTART_END_EVENT_NAME = events.addNamespace("dxdragend", RESIZABLE);
  19040. DX.registerComponent(RESIZABLE, ui, DX.DOMComponent.inherit({
  19041. _setDefaultOptions: function() {
  19042. this.callBase();
  19043. this.option({
  19044. handles: "all",
  19045. step: "1",
  19046. area: undefined,
  19047. minWidth: 30,
  19048. maxWidth: Infinity,
  19049. minHeight: 30,
  19050. maxHeight: Infinity,
  19051. onResizeStart: null,
  19052. onResize: null,
  19053. onResizeEnd: null
  19054. })
  19055. },
  19056. _init: function() {
  19057. this.callBase();
  19058. this.element().addClass(RESIZABLE_CLASS)
  19059. },
  19060. _render: function() {
  19061. this.callBase();
  19062. this._renderActions();
  19063. this._renderHandles()
  19064. },
  19065. _renderActions: function() {
  19066. this._resizeStartAction = this._createActionByOption("onResizeStart");
  19067. this._resizeEndAction = this._createActionByOption("onResizeEnd");
  19068. this._resizeAction = this._createActionByOption("onResize")
  19069. },
  19070. _renderHandles: function() {
  19071. var handles = this.option("handles");
  19072. if (handles === "none")
  19073. return;
  19074. var directions = handles === "all" ? ['top', 'bottom', 'left', 'right'] : handles.split(" ");
  19075. $.each(directions, $.proxy(function(index, handleName) {
  19076. this._renderHandle(handleName)
  19077. }, this));
  19078. $.inArray('bottom', directions) + 1 && $.inArray('right', directions) + 1 && this._renderHandle("corner-bottom-right");
  19079. $.inArray('bottom', directions) + 1 && $.inArray('left', directions) + 1 && this._renderHandle("corner-bottom-left");
  19080. $.inArray('top', directions) + 1 && $.inArray('right', directions) + 1 && this._renderHandle("corner-top-right");
  19081. $.inArray('top', directions) + 1 && $.inArray('left', directions) + 1 && this._renderHandle("corner-top-left")
  19082. },
  19083. _renderHandle: function(handleName) {
  19084. var $element = this.element(),
  19085. $handle = $("<div>");
  19086. $handle.addClass(RESIZABLE_HANDLE_CLASS).addClass(RESIZABLE_HANDLE_CLASS + "-" + handleName).appendTo($element);
  19087. var handlers = {};
  19088. handlers[DRAGSTART_START_EVENT_NAME] = $.proxy(this._dragStartHandler, this);
  19089. handlers[DRAGSTART_EVENT_NAME] = $.proxy(this._dragHandler, this);
  19090. handlers[DRAGSTART_END_EVENT_NAME] = $.proxy(this._dragEndHandler, this);
  19091. $handle.on(handlers, {
  19092. direction: this._dragEventDirection(handleName),
  19093. immediate: true
  19094. })
  19095. },
  19096. _dragEventDirection: function(handleName) {
  19097. switch (handleName) {
  19098. case"right":
  19099. case"left":
  19100. return "horizontal";
  19101. case"top":
  19102. case"bottom":
  19103. return "vertical";
  19104. default:
  19105. return "both"
  19106. }
  19107. },
  19108. _dragStartHandler: function(e) {
  19109. this._toggleResizingClass(true);
  19110. this._movingSides = this._getMovingSides(e);
  19111. var $element = this.element();
  19112. this._elementLocation = DX.translator.locate($element);
  19113. this._elementSize = {
  19114. width: $element.outerWidth(),
  19115. height: $element.outerHeight()
  19116. };
  19117. this._renderDragOffsets(e);
  19118. this._resizeStartAction({
  19119. jQueryEvent: e,
  19120. width: this._elementSize.width,
  19121. height: this._elementSize.height,
  19122. handles: this._movingSides
  19123. });
  19124. e.targetElements = null
  19125. },
  19126. _toggleResizingClass: function(value) {
  19127. this.element().toggleClass(RESIZABLE_RESIZING_CLASS, value)
  19128. },
  19129. _renderDragOffsets: function(e) {
  19130. var $area = this._getArea(),
  19131. $handle = $(e.target).closest("." + RESIZABLE_HANDLE_CLASS);
  19132. if (!$area.length)
  19133. return;
  19134. var areaWidth = $area.innerWidth(),
  19135. areaHeight = $area.innerHeight(),
  19136. handleWidth = $handle.outerWidth(),
  19137. handleHeight = $handle.outerHeight();
  19138. var handleOffset = $handle.offset(),
  19139. areaOffset = $area.offset() || {
  19140. top: 0,
  19141. left: 0
  19142. };
  19143. areaOffset.left += this._getBorderWidth($area, "left") + this._getBorderWidth(this.element(), "left");
  19144. areaOffset.top += this._getBorderWidth($area, "top") + this._getBorderWidth(this.element(), "top");
  19145. areaWidth -= this.element().outerWidth() - this.element().innerWidth();
  19146. areaHeight -= this.element().outerHeight() - this.element().innerHeight();
  19147. e.maxLeftOffset = handleOffset.left - areaOffset.left;
  19148. e.maxRightOffset = areaOffset.left + areaWidth - handleOffset.left - handleWidth;
  19149. e.maxTopOffset = handleOffset.top - areaOffset.top;
  19150. e.maxBottomOffset = areaOffset.top + areaHeight - handleOffset.top - handleHeight
  19151. },
  19152. _getBorderWidth: function($element, direction) {
  19153. var borderWidth = $element.css("border-" + direction + "-width");
  19154. return parseInt(borderWidth) || 0
  19155. },
  19156. _dragHandler: function(e) {
  19157. var $element = this.element(),
  19158. offset = this._getOffset(e),
  19159. sides = this._movingSides;
  19160. var location = this._elementLocation,
  19161. size = this._elementSize;
  19162. var width = size.width + offset.x * (sides.left ? -1 : 1),
  19163. height = size.height + offset.y * (sides.top ? -1 : 1);
  19164. this._renderSize(width, height);
  19165. var offsetTop = offset.y - (this.option("height") - height),
  19166. offsetLeft = offset.x - (this.option("width") - width);
  19167. DX.translator.move($element, {
  19168. top: location.top + (sides.top ? offsetTop : 0),
  19169. left: location.left + (sides.left ? offsetLeft : 0)
  19170. });
  19171. this._resizeAction({
  19172. jQueryEvent: e,
  19173. width: width,
  19174. height: height,
  19175. handles: this._movingSides
  19176. })
  19177. },
  19178. _getOffset: function(e) {
  19179. var offset = e.offset,
  19180. steps = DX.utils.stringPairToObject(this.option("step"));
  19181. return {
  19182. x: offset.x - offset.x % steps.h,
  19183. y: offset.y - offset.y % steps.v
  19184. }
  19185. },
  19186. _getMovingSides: function(e) {
  19187. var $target = $(e.target);
  19188. return {
  19189. top: $target.hasClass(RESIZABLE_HANDLE_TOP_CLASS) || $target.hasClass(RESIZABLE_HANDLE_CORNER_CLASS + "-top-left") || $target.hasClass(RESIZABLE_HANDLE_CORNER_CLASS + "-top-right"),
  19190. left: $target.hasClass(RESIZABLE_HANDLE_LEFT_CLASS) || $target.hasClass(RESIZABLE_HANDLE_CORNER_CLASS + "-top-left") || $target.hasClass(RESIZABLE_HANDLE_CORNER_CLASS + "-bottom-left"),
  19191. bottom: $target.hasClass(RESIZABLE_HANDLE_BOTTOM_CLASS) || $target.hasClass(RESIZABLE_HANDLE_CORNER_CLASS + "-bottom-left") || $target.hasClass(RESIZABLE_HANDLE_CORNER_CLASS + "-bottom-right"),
  19192. right: $target.hasClass(RESIZABLE_HANDLE_RIGHT_CLASS) || $target.hasClass(RESIZABLE_HANDLE_CORNER_CLASS + "-top-right") || $target.hasClass(RESIZABLE_HANDLE_CORNER_CLASS + "-bottom-right")
  19193. }
  19194. },
  19195. _getArea: function() {
  19196. var area = this.option("area");
  19197. if ($.isFunction(area))
  19198. area = area.call(this);
  19199. return $(area)
  19200. },
  19201. _dragEndHandler: function(e) {
  19202. var $element = this.element();
  19203. this._resizeEndAction({
  19204. jQueryEvent: e,
  19205. width: $element.outerWidth(),
  19206. height: $element.outerHeight(),
  19207. handles: this._movingSides
  19208. });
  19209. this._toggleResizingClass(false)
  19210. },
  19211. _renderSize: function(width, height) {
  19212. this.option("width", utils.fitIntoRange(width, this.option("minWidth"), this.option("maxWidth")));
  19213. this.option("height", utils.fitIntoRange(height, this.option("minHeight"), this.option("maxHeight")))
  19214. },
  19215. _optionChanged: function(args) {
  19216. switch (args.name) {
  19217. case"handles":
  19218. this._invalidate();
  19219. break;
  19220. case"minWidth":
  19221. case"maxWidth":
  19222. case"minHeight":
  19223. case"maxHeight":
  19224. this._renderSize(this.element().outerWidth(), this.element().outerHeight());
  19225. break;
  19226. case"onResize":
  19227. case"onResizeStart":
  19228. case"onResizeEnd":
  19229. this._renderActions();
  19230. break;
  19231. case"gridStepHorizontal":
  19232. case"gridStepVertical":
  19233. case"area":
  19234. case"step":
  19235. break;
  19236. default:
  19237. this.callBase(args);
  19238. break
  19239. }
  19240. },
  19241. _clean: function() {
  19242. this.element().find("." + RESIZABLE_HANDLE_CLASS).remove()
  19243. }
  19244. }))
  19245. })(jQuery, DevExpress);
  19246. /*! Module widgets-base, file ui.box.js */
  19247. (function($, DX, undefined) {
  19248. var ui = DevExpress.ui,
  19249. utils = DX.utils;
  19250. var BOX_CLASS = "dx-box",
  19251. BOX_SELECTOR = ".dx-box",
  19252. BOX_ITEM_CLASS = "dx-box-item",
  19253. BOX_ITEM_DATA_KEY = "dxBoxItemData";
  19254. var flexGrowProp = DX.support.styleProp("flexGrow");
  19255. var flexShrinkProp = DX.support.styleProp("flexShrink");
  19256. var flexPropPrefix = DX.support.stylePropPrefix("flexDirection");
  19257. var MINSIZE_MAP = {
  19258. row: "minWidth",
  19259. col: "minHeight"
  19260. };
  19261. var MAXSIZE_MAP = {
  19262. row: "maxWidth",
  19263. col: "maxHeight"
  19264. };
  19265. var SHRINK = 1;
  19266. var FLEX_JUSTIFY_CONTENT_MAP = {
  19267. start: "flex-start",
  19268. end: "flex-end",
  19269. center: "center",
  19270. "space-between": "space-between",
  19271. "space-around": "space-around"
  19272. };
  19273. var FLEX_ALIGN_ITEMS_MAP = {
  19274. start: "flex-start",
  19275. end: "flex-end",
  19276. center: "center",
  19277. stretch: "stretch"
  19278. };
  19279. var FLEX_DIRECTION_MAP = {
  19280. row: "row",
  19281. col: "column"
  19282. };
  19283. var FlexLayoutStrategy = DX.Class.inherit({
  19284. ctor: function($element, option) {
  19285. this._$element = $element;
  19286. this._option = option
  19287. },
  19288. renderBox: function() {
  19289. this._$element.css({
  19290. display: DX.support.stylePropPrefix("flexDirection") + "flex",
  19291. flexDirection: FLEX_DIRECTION_MAP[this._option("direction")]
  19292. })
  19293. },
  19294. renderAlign: function() {
  19295. this._$element.css({justifyContent: this._normalizedAlign()})
  19296. },
  19297. _normalizedAlign: function() {
  19298. var align = this._option("align");
  19299. return align in FLEX_JUSTIFY_CONTENT_MAP ? FLEX_JUSTIFY_CONTENT_MAP[align] : align
  19300. },
  19301. renderCrossAlign: function() {
  19302. this._$element.css({alignItems: this._normalizedCrossAlign()})
  19303. },
  19304. _normalizedCrossAlign: function() {
  19305. var crossAlign = this._option("crossAlign");
  19306. return crossAlign in FLEX_ALIGN_ITEMS_MAP ? FLEX_ALIGN_ITEMS_MAP[crossAlign] : crossAlign
  19307. },
  19308. renderItems: function($items) {
  19309. var direction = this._option("direction");
  19310. $.each($items, function() {
  19311. var $item = $(this);
  19312. var item = $item.data(BOX_ITEM_DATA_KEY);
  19313. $item.css({
  19314. display: flexPropPrefix + "flex",
  19315. flexBasis: item.baseSize || 0
  19316. }).css(MAXSIZE_MAP[direction], item.maxSize || "none").css(MINSIZE_MAP[direction], item.minSize || "0");
  19317. var itemStyle = $item.get(0).style;
  19318. itemStyle[flexGrowProp] = item.ratio;
  19319. itemStyle[flexShrinkProp] = utils.isDefined(item.shrink) ? item.shrink : SHRINK;
  19320. $item.children().each(function(_, itemContent) {
  19321. $(itemContent).css({
  19322. width: "auto",
  19323. height: "auto",
  19324. display: DX.support.stylePropPrefix("flexDirection") + "flex",
  19325. flexDirection: $item.children().css("flexDirection") || "column"
  19326. });
  19327. itemContent.style[flexGrowProp] = 1
  19328. })
  19329. })
  19330. },
  19331. update: $.noop
  19332. });
  19333. var BOX_EVENTNAMESPACE = "dxBox",
  19334. UPDATE_EVENT = "dxupdate." + BOX_EVENTNAMESPACE,
  19335. FALLBACK_BOX_ITEM = "dx-box-fallback-item";
  19336. var FALLBACK_WRAP_MAP = {
  19337. row: "nowrap",
  19338. col: "normal"
  19339. };
  19340. var FALLBACK_MAIN_SIZE_MAP = {
  19341. row: "width",
  19342. col: "height"
  19343. };
  19344. var FALLBACK_CROSS_SIZE_MAP = {
  19345. row: "height",
  19346. col: "width"
  19347. };
  19348. var FALLBACK_PRE_MARGIN_MAP = {
  19349. row: "marginLeft",
  19350. col: "marginTop"
  19351. };
  19352. var FALLBACK_POST_MARGIN_MAP = {
  19353. row: "marginRight",
  19354. col: "marginBottom"
  19355. };
  19356. var FALLBACK_CROSS_PRE_MARGIN_MAP = {
  19357. row: "marginTop",
  19358. col: "marginLeft"
  19359. };
  19360. var FALLBACK_CROSS_POST_MARGIN_MAP = {
  19361. row: "marginBottom",
  19362. col: "marginRight"
  19363. };
  19364. var MARGINS_RTL_FLIP_MAP = {
  19365. marginLeft: "marginRight",
  19366. marginRight: "marginLeft"
  19367. };
  19368. var FallbackLayoutStrategy = DX.Class.inherit({
  19369. ctor: function($element, option) {
  19370. this._$element = $element;
  19371. this._option = option
  19372. },
  19373. renderBox: function() {
  19374. this._$element.css({
  19375. fontSize: 0,
  19376. whiteSpace: FALLBACK_WRAP_MAP[this._option("direction")],
  19377. verticalAlign: "top"
  19378. });
  19379. this._$element.off(UPDATE_EVENT).on(UPDATE_EVENT, $.proxy(this.update, this))
  19380. },
  19381. renderAlign: function() {
  19382. var $items = this._$items;
  19383. if (!$items)
  19384. return;
  19385. var align = this._option("align"),
  19386. shift = 0,
  19387. totalItemSize = this.totalItemSize,
  19388. direction = this._option("direction"),
  19389. boxSize = this._$element[FALLBACK_MAIN_SIZE_MAP[direction]](),
  19390. freeSpace = boxSize - totalItemSize;
  19391. this._setItemsMargins($items, direction, 0);
  19392. switch (align) {
  19393. case"start":
  19394. break;
  19395. case"end":
  19396. shift = freeSpace;
  19397. $items.first().css(this._chooseMarginSide(FALLBACK_PRE_MARGIN_MAP[direction]), shift);
  19398. break;
  19399. case"center":
  19400. shift = 0.5 * freeSpace;
  19401. $items.first().css(this._chooseMarginSide(FALLBACK_PRE_MARGIN_MAP[direction]), shift);
  19402. $items.last().css(this._chooseMarginSide(FALLBACK_POST_MARGIN_MAP[direction]), shift);
  19403. break;
  19404. case"space-between":
  19405. shift = 0.5 * freeSpace / ($items.length - 1);
  19406. this._setItemsMargins($items, direction, shift);
  19407. $items.first().css(this._chooseMarginSide(FALLBACK_PRE_MARGIN_MAP[direction]), 0);
  19408. $items.last().css(this._chooseMarginSide(FALLBACK_POST_MARGIN_MAP[direction]), 0);
  19409. break;
  19410. case"space-around":
  19411. shift = 0.5 * freeSpace / $items.length;
  19412. this._setItemsMargins($items, direction, shift);
  19413. break
  19414. }
  19415. },
  19416. _setItemsMargins: function($items, direction, shift) {
  19417. $items.css(this._chooseMarginSide(FALLBACK_PRE_MARGIN_MAP[direction]), shift).css(this._chooseMarginSide(FALLBACK_POST_MARGIN_MAP[direction]), shift)
  19418. },
  19419. renderCrossAlign: function() {
  19420. var $items = this._$items;
  19421. if (!$items)
  19422. return;
  19423. var crossAlign = this._option("crossAlign"),
  19424. direction = this._option("direction"),
  19425. size = this._$element[FALLBACK_CROSS_SIZE_MAP[direction]]();
  19426. var that = this;
  19427. switch (crossAlign) {
  19428. case"start":
  19429. break;
  19430. case"end":
  19431. $.each($items, function() {
  19432. var $item = $(this),
  19433. itemSize = $item[FALLBACK_CROSS_SIZE_MAP[direction]](),
  19434. shift = size - itemSize;
  19435. $item.css(that._chooseMarginSide(FALLBACK_CROSS_PRE_MARGIN_MAP[direction]), shift)
  19436. });
  19437. break;
  19438. case"center":
  19439. $.each($items, function() {
  19440. var $item = $(this),
  19441. itemSize = $item[FALLBACK_CROSS_SIZE_MAP[direction]](),
  19442. shift = 0.5 * (size - itemSize);
  19443. $item.css(that._chooseMarginSide(FALLBACK_CROSS_PRE_MARGIN_MAP[direction]), shift).css(that._chooseMarginSide(FALLBACK_CROSS_POST_MARGIN_MAP[direction]), shift)
  19444. });
  19445. break;
  19446. case"stretch":
  19447. $items.css(that._chooseMarginSide(FALLBACK_CROSS_PRE_MARGIN_MAP[direction]), 0).css(that._chooseMarginSide(FALLBACK_CROSS_POST_MARGIN_MAP[direction]), 0).css(FALLBACK_CROSS_SIZE_MAP[direction], "100%");
  19448. break
  19449. }
  19450. },
  19451. _chooseMarginSide: function(value) {
  19452. if (!this._option("rtlEnabled"))
  19453. return value;
  19454. return MARGINS_RTL_FLIP_MAP[value] || value
  19455. },
  19456. renderItems: function($items) {
  19457. this._$items = $items;
  19458. var direction = this._option("direction"),
  19459. totalRatio = 0,
  19460. totalWeightedShrink = 0,
  19461. totalBaseSize = 0;
  19462. $.each($items, $.proxy(function(_, item) {
  19463. var $item = $(item);
  19464. $item.css({
  19465. display: "inline-block",
  19466. verticalAlign: "top"
  19467. });
  19468. $item[FALLBACK_MAIN_SIZE_MAP[direction]]("auto");
  19469. $item.removeClass(FALLBACK_BOX_ITEM);
  19470. var itemData = $item.data(BOX_ITEM_DATA_KEY),
  19471. ratio = itemData.ratio || 0,
  19472. size = this._baseSize($item),
  19473. shrink = utils.isDefined(itemData.shrink) ? itemData.shrink : SHRINK;
  19474. totalRatio += ratio;
  19475. totalWeightedShrink += shrink * size;
  19476. totalBaseSize += size
  19477. }, this));
  19478. var freeSpaceSize = this._boxSize() - totalBaseSize;
  19479. var itemSize = $.proxy(function($item) {
  19480. var itemData = $item.data(BOX_ITEM_DATA_KEY),
  19481. size = this._baseSize($item),
  19482. factor = freeSpaceSize >= 0 ? itemData.ratio || 0 : (utils.isDefined(itemData.shrink) ? itemData.shrink : SHRINK) * size,
  19483. totalFactor = freeSpaceSize >= 0 ? totalRatio : totalWeightedShrink,
  19484. shift = totalFactor ? Math.round(freeSpaceSize * factor / totalFactor) : 0;
  19485. return size + shift
  19486. }, this);
  19487. var totalItemSize = 0;
  19488. $.each($items, function(_, item) {
  19489. var $item = $(item),
  19490. itemData = $(item).data(BOX_ITEM_DATA_KEY),
  19491. size = itemSize($item);
  19492. totalItemSize += size;
  19493. $item.css(MAXSIZE_MAP[direction], itemData.maxSize || "none").css(MINSIZE_MAP[direction], itemData.minSize || "0").css(FALLBACK_MAIN_SIZE_MAP[direction], size);
  19494. $item.addClass(FALLBACK_BOX_ITEM)
  19495. });
  19496. this.totalItemSize = totalItemSize
  19497. },
  19498. _baseSize: function(item) {
  19499. var itemData = $(item).data(BOX_ITEM_DATA_KEY);
  19500. return itemData.baseSize == null ? 0 : itemData.baseSize === "auto" ? this._contentSize(item) : this._parseSize(itemData.baseSize)
  19501. },
  19502. _contentSize: function(item) {
  19503. return $(item)[FALLBACK_MAIN_SIZE_MAP[this._option("direction")]]()
  19504. },
  19505. _parseSize: function(size) {
  19506. return String(size).match(/.+%$/) ? 0.01 * parseFloat(size) * this._boxSize() : size
  19507. },
  19508. _boxSize: function() {
  19509. return this._$element[FALLBACK_MAIN_SIZE_MAP[this._option("direction")]]()
  19510. },
  19511. _totalBaseSize: function() {
  19512. var result = 0;
  19513. $.each(this._$items, $.proxy(function(_, item) {
  19514. result += this._baseSize(item)
  19515. }, this));
  19516. return result
  19517. },
  19518. update: function() {
  19519. if (!this._$items || this._$element.is(":hidden"))
  19520. return;
  19521. this.renderItems(this._$items);
  19522. this.renderAlign();
  19523. this.renderCrossAlign();
  19524. var element = this._$element.get(0);
  19525. this._$items.find(BOX_SELECTOR).each(function() {
  19526. if (element === $(this).parent().closest(BOX_SELECTOR).get(0))
  19527. $(this).triggerHandler(UPDATE_EVENT)
  19528. })
  19529. }
  19530. });
  19531. DX.registerComponent("dxBox", ui, ui.CollectionWidget.inherit({
  19532. _setDefaultOptions: function() {
  19533. this.callBase();
  19534. this.option({
  19535. direction: "row",
  19536. align: "start",
  19537. crossAlign: "stretch",
  19538. activeStateEnabled: false,
  19539. focusStateEnabled: false,
  19540. _layoutStrategy: "flex"
  19541. })
  19542. },
  19543. _defaultOptionsRules: function() {
  19544. return this.callBase().concat([{
  19545. device: function() {
  19546. var device = DX.devices.real();
  19547. var isOldAndroid = device.platform === "android" && (device.version[0] < 4 || device.version[0] === 4 && device.version[1] < 4),
  19548. isOldIos = device.platform === "ios" && device.version[0] < 7;
  19549. return device.platform === "win8" || DX.browser["msie"] || isOldAndroid || isOldIos
  19550. },
  19551. options: {_layoutStrategy: "fallback"}
  19552. }])
  19553. },
  19554. _itemClass: function() {
  19555. return BOX_ITEM_CLASS
  19556. },
  19557. _itemDataKey: function() {
  19558. return BOX_ITEM_DATA_KEY
  19559. },
  19560. _itemElements: function() {
  19561. return this._itemContainer().children(this._itemSelector())
  19562. },
  19563. _init: function() {
  19564. this.callBase();
  19565. this.element().addClass(BOX_CLASS + "-" + this.option("_layoutStrategy"));
  19566. this._initLayout()
  19567. },
  19568. _initLayout: function() {
  19569. this._layout = this.option("_layoutStrategy") === "fallback" ? new FallbackLayoutStrategy(this.element(), $.proxy(this.option, this)) : new FlexLayoutStrategy(this.element(), $.proxy(this.option, this))
  19570. },
  19571. _render: function() {
  19572. this.callBase();
  19573. this.element().addClass(BOX_CLASS);
  19574. this._renderBox()
  19575. },
  19576. _renderBox: function() {
  19577. this._layout.renderBox();
  19578. this._layout.renderAlign();
  19579. this._layout.renderCrossAlign()
  19580. },
  19581. _renderItems: function(items) {
  19582. this.callBase(items);
  19583. this._layout.renderItems(this._itemElements());
  19584. clearTimeout(this._updateTimer);
  19585. this._updateTimer = setTimeout($.proxy(function() {
  19586. if (!this._isUpdated)
  19587. this._layout.update();
  19588. this._isUpdated = false
  19589. }, this))
  19590. },
  19591. _postprocessRenderItem: function(args) {
  19592. var boxConfig = args.itemData.box;
  19593. if (!boxConfig)
  19594. return;
  19595. this._createComponent(args.itemContent, "dxBox", $.extend({
  19596. itemTemplate: this.option("itemTemplate"),
  19597. itemHoldTimeout: this.option("itemHoldTimeout"),
  19598. onItemHold: this.option("onItemHold"),
  19599. onItemClick: this.option("onItemClick"),
  19600. onItemContextMenu: this.option("onItemContextMenu"),
  19601. onItemRendered: this.option("onItemRendered")
  19602. }, boxConfig))
  19603. },
  19604. _createItemByTemplate: function(itemTemplate, args) {
  19605. return args.item.box ? itemTemplate.source() : this.callBase(itemTemplate, args)
  19606. },
  19607. _visibilityChanged: function(visible) {
  19608. if (visible)
  19609. this._dimensionChanged()
  19610. },
  19611. _dimensionChanged: function() {
  19612. this._isUpdated = true;
  19613. this._layout.update()
  19614. },
  19615. _dispose: function() {
  19616. clearTimeout(this._updateTimer);
  19617. this.callBase.apply(this, arguments)
  19618. },
  19619. _optionChanged: function(args) {
  19620. switch (args.name) {
  19621. case"_layoutStrategy":
  19622. case"direction":
  19623. this._invalidate();
  19624. break;
  19625. case"align":
  19626. this._layout.renderAlign();
  19627. break;
  19628. case"crossAlign":
  19629. this._layout.renderCrossAlign();
  19630. break;
  19631. default:
  19632. this.callBase(args)
  19633. }
  19634. },
  19635. repaint: function() {
  19636. this._dimensionChanged()
  19637. }
  19638. }))
  19639. })(jQuery, DevExpress);
  19640. /*! Module widgets-base, file ui.responsiveBox.js */
  19641. (function($, DX, undefined) {
  19642. var ui = DX.ui;
  19643. var RESPONSIVE_BOX_CLASS = "dx-responsivebox",
  19644. BOX_ITEM_CLASS = "dx-box-item",
  19645. BOX_ITEM_DATA_KEY = "dxBoxItemData";
  19646. var DEFAULT_SCREEN_FACTOR_FUNC = function(width) {
  19647. if (width < 768)
  19648. return "xs";
  19649. else if (width < 992)
  19650. return "sm";
  19651. else if (width < 1200)
  19652. return "md";
  19653. else
  19654. return "lg"
  19655. };
  19656. DX.registerComponent("dxResponsiveBox", ui, ui.CollectionWidget.inherit({
  19657. _setDefaultOptions: function() {
  19658. this.callBase();
  19659. this.option({
  19660. rows: [],
  19661. cols: [],
  19662. screenByWidth: DEFAULT_SCREEN_FACTOR_FUNC,
  19663. singleColumnScreen: "xs",
  19664. activeStateEnabled: false,
  19665. focusStateEnabled: false
  19666. })
  19667. },
  19668. _initOptions: function(options) {
  19669. if (options.screenByWidth)
  19670. this.option("singleColumnScreen", options.screenByWidth(0));
  19671. this.callBase(options)
  19672. },
  19673. _itemClass: function() {
  19674. return BOX_ITEM_CLASS
  19675. },
  19676. _itemDataKey: function() {
  19677. return BOX_ITEM_DATA_KEY
  19678. },
  19679. _render: function() {
  19680. this.callBase();
  19681. this.element().addClass(RESPONSIVE_BOX_CLASS);
  19682. this._updateRootBox()
  19683. },
  19684. _updateRootBox: function() {
  19685. clearTimeout(this._updateTimer);
  19686. this._updateTimer = setTimeout($.proxy(function() {
  19687. if (this._$root)
  19688. this._$root.trigger("dxupdate")
  19689. }, this))
  19690. },
  19691. _renderItems: function() {
  19692. this._screenItems = this._itemsByScreen();
  19693. this._prepareGrid();
  19694. this._spreadItems();
  19695. this._layoutItems();
  19696. this._linkNodeToItem()
  19697. },
  19698. _prepareGrid: function() {
  19699. var grid = this._grid = [];
  19700. this._prepareRowsAndCols();
  19701. $.each(this._rows, $.proxy(function() {
  19702. var row = [];
  19703. grid.push(row);
  19704. $.each(this._cols, $.proxy(function() {
  19705. row.push(this._createEmptyCell())
  19706. }, this))
  19707. }, this))
  19708. },
  19709. _prepareRowsAndCols: function() {
  19710. if (this._isSingleColumnScreen()) {
  19711. this._prepareSingleColumnScreenItems();
  19712. this._rows = this._defaultSizeConfig(this._screenItems.length);
  19713. this._cols = this._defaultSizeConfig(1)
  19714. }
  19715. else {
  19716. this._rows = this._sizesByScreen(this.option("rows"));
  19717. this._cols = this._sizesByScreen(this.option("cols"))
  19718. }
  19719. },
  19720. _isSingleColumnScreen: function() {
  19721. return this._screenRegExp().test(this.option("singleColumnScreen")) || !this.option("rows").length || !this.option("cols").length
  19722. },
  19723. _prepareSingleColumnScreenItems: function() {
  19724. this._screenItems.sort(function(item1, item2) {
  19725. return item1.location.row - item2.location.row || item1.location.col - item2.location.col
  19726. });
  19727. $.each(this._screenItems, function(index, item) {
  19728. $.extend(item.location, {
  19729. row: index,
  19730. col: 0,
  19731. rowspan: 1,
  19732. colspan: 1
  19733. })
  19734. })
  19735. },
  19736. _sizesByScreen: function(sizeConfigs) {
  19737. return $.map(this._filterByScreen(sizeConfigs), $.proxy(function(sizeConfig) {
  19738. return $.extend(this._defaultSizeConfig(), sizeConfig)
  19739. }, this))
  19740. },
  19741. _defaultSizeConfig: function(size) {
  19742. var defaultSizeConfig = {
  19743. ratio: 1,
  19744. baseSize: 0,
  19745. minSize: 0,
  19746. maxSize: 0
  19747. };
  19748. if (!arguments.length)
  19749. return defaultSizeConfig;
  19750. var result = [];
  19751. for (var i = 0; i < size; i++)
  19752. result.push(defaultSizeConfig);
  19753. return result
  19754. },
  19755. _filterByScreen: function(items) {
  19756. var screenRegExp = this._screenRegExp();
  19757. return $.grep(items, function(item) {
  19758. return !item.screen || screenRegExp.test(item.screen)
  19759. })
  19760. },
  19761. _screenRegExp: function() {
  19762. var width = this._screenWidth();
  19763. var screen = this.option("screenByWidth")(width);
  19764. return new RegExp("(^|\\s)" + screen + "($|\\s)", "i")
  19765. },
  19766. _screenWidth: function() {
  19767. return $(window).width()
  19768. },
  19769. _createEmptyCell: function() {
  19770. return {
  19771. item: {},
  19772. location: {
  19773. colspan: 1,
  19774. rowspan: 1
  19775. }
  19776. }
  19777. },
  19778. _spreadItems: function() {
  19779. $.each(this._screenItems, $.proxy(function(_, itemInfo) {
  19780. var location = itemInfo.location || {};
  19781. var itemCol = location.col;
  19782. var itemRow = location.row;
  19783. var row = this._grid[itemRow];
  19784. var itemCell = row && row[itemCol];
  19785. this._occupyCells(itemCell, itemInfo)
  19786. }, this))
  19787. },
  19788. _itemsByScreen: function() {
  19789. return $.map(this.option("items"), $.proxy(function(item) {
  19790. var locations = item.location || {};
  19791. locations = $.isPlainObject(locations) ? [locations] : locations;
  19792. return $.map(this._filterByScreen(locations), function(location) {
  19793. return {
  19794. item: item,
  19795. location: $.extend({
  19796. rowspan: 1,
  19797. colspan: 1
  19798. }, location)
  19799. }
  19800. })
  19801. }, this))
  19802. },
  19803. _occupyCells: function(itemCell, itemInfo) {
  19804. if (!itemCell || this._isItemCellOccupied(itemCell, itemInfo))
  19805. return;
  19806. $.extend(itemCell, itemInfo);
  19807. this._markSpanningCell(itemCell)
  19808. },
  19809. _isItemCellOccupied: function(itemCell, itemInfo) {
  19810. if (!$.isEmptyObject(itemCell.item))
  19811. return true;
  19812. var result = false;
  19813. this._loopOverSpanning(itemInfo.location, function(cell) {
  19814. result = result || !$.isEmptyObject(cell.item)
  19815. });
  19816. return result
  19817. },
  19818. _loopOverSpanning: function(location, callback) {
  19819. var rowEnd = location.row + location.rowspan - 1;
  19820. var colEnd = location.col + location.colspan - 1;
  19821. var boundRowEnd = Math.min(rowEnd, this._rows.length - 1);
  19822. var boundColEnd = Math.min(colEnd, this._cols.length - 1);
  19823. location.rowspan -= rowEnd - boundRowEnd;
  19824. location.colspan -= colEnd - boundColEnd;
  19825. for (var rowIndex = location.row; rowIndex <= boundRowEnd; rowIndex++)
  19826. for (var colIndex = location.col; colIndex <= boundColEnd; colIndex++)
  19827. if (rowIndex !== location.row || colIndex !== location.col)
  19828. callback(this._grid[rowIndex][colIndex])
  19829. },
  19830. _markSpanningCell: function(itemCell) {
  19831. this._loopOverSpanning(itemCell.location, function(cell) {
  19832. $.extend(cell, {
  19833. item: itemCell.item,
  19834. spanningCell: itemCell
  19835. })
  19836. })
  19837. },
  19838. _linkNodeToItem: function() {
  19839. $.each(this._itemElements(), function(_, itemNode) {
  19840. var $item = $(itemNode),
  19841. item = $item.data(BOX_ITEM_DATA_KEY);
  19842. if (!item.box)
  19843. item.node = $item.children()
  19844. })
  19845. },
  19846. _layoutItems: function() {
  19847. var rowsCount = this._grid.length;
  19848. var colsCount = rowsCount && this._grid[0].length;
  19849. if (!rowsCount && !colsCount)
  19850. return;
  19851. var result = this._layoutBlock({
  19852. direction: "col",
  19853. row: {
  19854. start: 0,
  19855. end: rowsCount - 1
  19856. },
  19857. col: {
  19858. start: 0,
  19859. end: colsCount - 1
  19860. }
  19861. });
  19862. var rootBox = this._prepareBoxConfig(result.box || {
  19863. direction: "col",
  19864. items: [result]
  19865. });
  19866. $.extend(rootBox, this._rootBoxConfig());
  19867. this._$root = $("<div>").appendTo(this._itemContainer());
  19868. this._createComponent(this._$root, "dxBox", rootBox)
  19869. },
  19870. _rootBoxConfig: function(config) {
  19871. return {
  19872. width: "100%",
  19873. height: "100%",
  19874. itemTemplate: this.option("itemTemplate"),
  19875. itemHoldTimeout: this.option("itemHoldTimeout"),
  19876. onItemHold: this.option("onItemHold"),
  19877. onItemClick: this.option("onItemClick"),
  19878. onItemContextMenu: this.option("onItemContextMenu"),
  19879. onItemRendered: this.option("onItemRendered")
  19880. }
  19881. },
  19882. _prepareBoxConfig: function(config) {
  19883. return $.extend(config || {}, {crossAlign: "stretch"})
  19884. },
  19885. _layoutBlock: function(options) {
  19886. if (this._isSingleItem(options))
  19887. return this._itemByCell(options.row.start, options.col.start);
  19888. return this._layoutDirection(options)
  19889. },
  19890. _isSingleItem: function(options) {
  19891. var firstCellLocation = this._grid[options.row.start][options.col.start].location;
  19892. var isItemRowSpanned = options.row.end - options.row.start === firstCellLocation.rowspan - 1;
  19893. var isItemColSpanned = options.col.end - options.col.start === firstCellLocation.colspan - 1;
  19894. return isItemRowSpanned && isItemColSpanned
  19895. },
  19896. _itemByCell: function(rowIndex, colIndex) {
  19897. var itemCell = this._grid[rowIndex][colIndex];
  19898. return itemCell.spanningCell ? null : itemCell.item
  19899. },
  19900. _layoutDirection: function(options) {
  19901. var items = [];
  19902. var direction = options.direction;
  19903. var crossDirection = this._crossDirection(direction);
  19904. var block;
  19905. while (block = this._nextBlock(options)) {
  19906. if (this._isBlockIndivisible(options.prevBlockOptions, block))
  19907. throw DX.Error("E1025");
  19908. var item = this._layoutBlock({
  19909. direction: crossDirection,
  19910. row: block.row,
  19911. col: block.col,
  19912. prevBlockOptions: options
  19913. });
  19914. if (item) {
  19915. $.extend(item, this._blockSize(block, crossDirection));
  19916. items.push(item)
  19917. }
  19918. options[crossDirection].start = block[crossDirection].end + 1
  19919. }
  19920. return {box: this._prepareBoxConfig({
  19921. direction: direction,
  19922. items: items
  19923. })}
  19924. },
  19925. _isBlockIndivisible: function(options, block) {
  19926. return options && options.col.start === block.col.start && options.col.end === block.col.end && options.row.start === block.row.start && options.row.end === block.row.end
  19927. },
  19928. _crossDirection: function(direction) {
  19929. return direction === "col" ? "row" : "col"
  19930. },
  19931. _nextBlock: function(options) {
  19932. var direction = options.direction;
  19933. var crossDirection = this._crossDirection(direction);
  19934. var startIndex = options[direction].start;
  19935. var endIndex = options[direction].end;
  19936. var crossStartIndex = options[crossDirection].start;
  19937. if (crossStartIndex > options[crossDirection].end)
  19938. return null;
  19939. var crossSpan = 1;
  19940. for (var crossIndex = crossStartIndex; crossIndex < crossStartIndex + crossSpan; crossIndex++) {
  19941. var lineCrossSpan = 1;
  19942. for (var index = startIndex; index <= endIndex; index++) {
  19943. var cell = this._cellByDirection(direction, index, crossIndex);
  19944. lineCrossSpan = Math.max(lineCrossSpan, cell.location[crossDirection + "span"])
  19945. }
  19946. var lineCrossEndIndex = crossIndex + lineCrossSpan;
  19947. var crossEndIndex = crossStartIndex + crossSpan;
  19948. if (lineCrossEndIndex > crossEndIndex)
  19949. crossSpan += lineCrossEndIndex - crossEndIndex
  19950. }
  19951. var result = {};
  19952. result[direction] = {
  19953. start: startIndex,
  19954. end: endIndex
  19955. };
  19956. result[crossDirection] = {
  19957. start: crossStartIndex,
  19958. end: crossStartIndex + crossSpan - 1
  19959. };
  19960. return result
  19961. },
  19962. _cellByDirection: function(direction, index, crossIndex) {
  19963. return direction === "col" ? this._grid[crossIndex][index] : this._grid[index][crossIndex]
  19964. },
  19965. _blockSize: function(block, direction) {
  19966. var sizeConfigs = direction === "row" ? this._rows : this._cols;
  19967. var result = {
  19968. ratio: 0,
  19969. baseSize: 0,
  19970. minSize: 0,
  19971. maxSize: 0
  19972. };
  19973. for (var index = block[direction].start; index <= block[direction].end; index++) {
  19974. var sizeConfig = sizeConfigs[index];
  19975. result.ratio += sizeConfig.ratio;
  19976. result.baseSize += sizeConfig.baseSize;
  19977. result.minSize += sizeConfig.minSize;
  19978. result.maxSize += sizeConfig.maxSize
  19979. }
  19980. result.minSize = result.minSize ? result.minSize : "auto";
  19981. result.maxSize = result.maxSize ? result.maxSize : "auto";
  19982. this._isSingleColumnScreen() && (result.baseSize = 'auto');
  19983. return result
  19984. },
  19985. _update: function() {
  19986. var $existingRoot = this._$root;
  19987. this._renderItems();
  19988. $existingRoot.remove()
  19989. },
  19990. _dispose: function() {
  19991. clearTimeout(this._updateTimer);
  19992. this.callBase.apply(this, arguments)
  19993. },
  19994. _optionChanged: function(args) {
  19995. switch (args.name) {
  19996. case"rows":
  19997. case"cols":
  19998. case"screenByWidth":
  19999. case"singleColumnScreen":
  20000. this._invalidate();
  20001. break;
  20002. case"width":
  20003. case"height":
  20004. this.callBase(args);
  20005. this._update();
  20006. break;
  20007. default:
  20008. this.callBase(args)
  20009. }
  20010. },
  20011. _dimensionChanged: function() {
  20012. this._update()
  20013. },
  20014. repaint: function() {
  20015. this._update()
  20016. }
  20017. }))
  20018. })(jQuery, DevExpress);
  20019. /*! Module widgets-base, file ui.button.js */
  20020. (function($, DX, undefined) {
  20021. var ui = DX.ui,
  20022. events = ui.events,
  20023. utils = DX.utils;
  20024. var BUTTON_CLASS = "dx-button",
  20025. BUTTON_CONTENT_CLASS = "dx-button-content",
  20026. BUTTON_HAS_TEXT_CLASS = "dx-button-has-text",
  20027. BUTTON_HAS_ICON_CLASS = "dx-button-has-icon",
  20028. TEMPLATE_WRAPPER_CLASS = "dx-template-wrapper",
  20029. BUTTON_FEEDBACK_HIDE_TIMEOUT = 100;
  20030. DX.registerComponent("dxButton", ui, ui.Widget.inherit({
  20031. _supportedKeys: function() {
  20032. var that = this,
  20033. click = function(e) {
  20034. e.preventDefault();
  20035. that._executeClickAction(e)
  20036. };
  20037. return $.extend(this.callBase(), {
  20038. space: click,
  20039. enter: click
  20040. })
  20041. },
  20042. _setDeprecatedOptions: function() {
  20043. this.callBase();
  20044. $.extend(this._deprecatedOptions, {
  20045. clickAction: {
  20046. since: "14.2",
  20047. alias: "onClick"
  20048. },
  20049. iconSrc: {
  20050. since: "15.1",
  20051. alias: "icon"
  20052. }
  20053. })
  20054. },
  20055. _setDefaultOptions: function() {
  20056. this.callBase();
  20057. this.option({
  20058. onClick: null,
  20059. type: "normal",
  20060. text: "",
  20061. icon: "",
  20062. validationGroup: undefined,
  20063. activeStateEnabled: true,
  20064. template: "content"
  20065. })
  20066. },
  20067. _defaultOptionsRules: function() {
  20068. return this.callBase().concat([{
  20069. device: function(device) {
  20070. return DX.devices.real().generic && !DX.devices.isSimulator()
  20071. },
  20072. options: {
  20073. hoverStateEnabled: true,
  20074. focusStateEnabled: true
  20075. }
  20076. }])
  20077. },
  20078. _init: function() {
  20079. this.callBase();
  20080. this._feedbackHideTimeout = BUTTON_FEEDBACK_HIDE_TIMEOUT
  20081. },
  20082. _render: function() {
  20083. this.callBase();
  20084. this.element().addClass(BUTTON_CLASS);
  20085. this._renderType();
  20086. this._renderClick();
  20087. this.setAria("role", "button");
  20088. this._updateAriaLabel()
  20089. },
  20090. _renderContentImpl: function() {
  20091. var $content = $("<div>").addClass(BUTTON_CONTENT_CLASS),
  20092. data = this._getContentData();
  20093. this.element().empty();
  20094. this.element().append($content);
  20095. this.element().toggleClass(BUTTON_HAS_ICON_CLASS, !!data.icon);
  20096. this.element().toggleClass(BUTTON_HAS_TEXT_CLASS, !!data.text);
  20097. var template = this._getTemplateByOption("template");
  20098. var $result = template.render(data, $content);
  20099. if ($result.hasClass(TEMPLATE_WRAPPER_CLASS)) {
  20100. $content.replaceWith($result);
  20101. $content = $result;
  20102. $content.addClass(BUTTON_CONTENT_CLASS)
  20103. }
  20104. },
  20105. _getContentData: function() {
  20106. var icon = this.option("icon"),
  20107. text = this.option("text"),
  20108. back = this.option("type") === "back";
  20109. if (back && !icon)
  20110. icon = "back";
  20111. if (back && !text)
  20112. text = DX.localization.localizeString("@Back");
  20113. return {
  20114. icon: icon,
  20115. text: text
  20116. }
  20117. },
  20118. _renderClick: function() {
  20119. var that = this,
  20120. eventName = events.addNamespace("dxclick", this.NAME);
  20121. this._clickAction = this._createActionByOption("onClick");
  20122. this.element().off(eventName).on(eventName, function(e) {
  20123. that._executeClickAction(e)
  20124. })
  20125. },
  20126. _executeClickAction: function(e) {
  20127. this._clickAction({
  20128. jQueryEvent: e,
  20129. validationGroup: DX.validationEngine.getGroupConfig(this._findGroup())
  20130. })
  20131. },
  20132. _updateAriaLabel: function() {
  20133. var icon = this.option("icon"),
  20134. text = this.option("text");
  20135. icon = utils.getImageSourceType(icon) === "image" ? icon.replace(/.+\/([^\.]+)\..+$/, "$1") : icon;
  20136. var ariaLabel = text || icon;
  20137. this.setAria("label", $.trim(ariaLabel))
  20138. },
  20139. _renderType: function() {
  20140. var type = this.option("type");
  20141. if (type)
  20142. this.element().addClass("dx-button-" + type)
  20143. },
  20144. _refreshType: function(prevType) {
  20145. var type = this.option("type");
  20146. prevType && this.element().removeClass("dx-button-" + prevType).addClass("dx-button-" + type);
  20147. if (!this.element().hasClass("dx-button-has-icon") && type === "back")
  20148. this._renderContentImpl()
  20149. },
  20150. _optionChanged: function(args) {
  20151. switch (args.name) {
  20152. case"onClick":
  20153. this._renderClick();
  20154. break;
  20155. case"icon":
  20156. case"text":
  20157. this._renderContentImpl();
  20158. this._updateAriaLabel();
  20159. break;
  20160. case"type":
  20161. this._refreshType(args.previousValue);
  20162. this._updateAriaLabel();
  20163. break;
  20164. case"template":
  20165. this._renderContentImpl();
  20166. break;
  20167. default:
  20168. this.callBase(args)
  20169. }
  20170. },
  20171. _findGroup: DX.ui.validation.findGroup
  20172. }))
  20173. })(jQuery, DevExpress);
  20174. /*! Module widgets-base, file ui.checkBox.js */
  20175. (function($, DX, undefined) {
  20176. var ui = DX.ui,
  20177. events = ui.events;
  20178. var CHECKBOX_CLASS = "dx-checkbox",
  20179. CHECKBOX_ICON_CLASS = "dx-checkbox-icon",
  20180. CHECKBOX_CHECKED_CLASS = "dx-checkbox-checked",
  20181. CHECKBOX_CONTAINER_CLASS = "dx-checkbox-container",
  20182. CHECKBOX_CONTAINER_SELECTOR = ".dx-checkbox-container",
  20183. CHECKBOX_TEXT_CLASS = "dx-checkbox-text",
  20184. CHECKBOX_TEXT_SELECTOR = ".dx-checkbox-text",
  20185. CHECKBOX_HAS_TEXT_CLASS = "dx-checkbox-has-text",
  20186. CHECKBOX_INDETERMINATE_CLASS = "dx-checkbox-indeterminate",
  20187. CHECKBOX_FEEDBACK_HIDE_TIMEOUT = 100,
  20188. CHECKBOX_DXCLICK_EVENT_NAME = events.addNamespace("dxclick", "dxCheckBox");
  20189. DX.registerComponent("dxCheckBox", ui, ui.Editor.inherit({
  20190. _supportedKeys: function() {
  20191. var click = function(e) {
  20192. e.preventDefault();
  20193. this._clickAction({jQueryEvent: e})
  20194. };
  20195. return $.extend(this.callBase(), {space: click})
  20196. },
  20197. _setDefaultOptions: function() {
  20198. this.callBase();
  20199. this.option({
  20200. value: false,
  20201. text: ""
  20202. })
  20203. },
  20204. _defaultOptionsRules: function() {
  20205. return this.callBase().concat([{
  20206. device: function(device) {
  20207. return DX.devices.real().generic && !DX.devices.isSimulator()
  20208. },
  20209. options: {
  20210. hoverStateEnabled: true,
  20211. focusStateEnabled: true
  20212. }
  20213. }])
  20214. },
  20215. _init: function() {
  20216. this.callBase();
  20217. this._feedbackHideTimeout = CHECKBOX_FEEDBACK_HIDE_TIMEOUT
  20218. },
  20219. _render: function() {
  20220. this.callBase();
  20221. this.element().addClass(CHECKBOX_CLASS).append($("<div>").addClass(CHECKBOX_CONTAINER_CLASS));
  20222. this.setAria("role", "checkbox");
  20223. this._$container = this.element().find(CHECKBOX_CONTAINER_SELECTOR);
  20224. this._renderClick();
  20225. this._renderValue();
  20226. this._renderIcon();
  20227. this._renderText()
  20228. },
  20229. _renderDimensions: function() {
  20230. this.callBase()
  20231. },
  20232. _renderIcon: function() {
  20233. this._$icon = $("<span>").addClass(CHECKBOX_ICON_CLASS).prependTo(this._$container)
  20234. },
  20235. _renderText: function() {
  20236. this._$text = this._$container.find(CHECKBOX_TEXT_SELECTOR);
  20237. if (!this.option("text")) {
  20238. if (this._$text) {
  20239. this._$text.remove();
  20240. this.element().removeClass(CHECKBOX_HAS_TEXT_CLASS)
  20241. }
  20242. return
  20243. }
  20244. if (!this._$text.length)
  20245. this._$text = $("<span>").addClass(CHECKBOX_TEXT_CLASS);
  20246. this._$text.text(this.option("text"));
  20247. this._$container.append(this._$text);
  20248. this.element().addClass(CHECKBOX_HAS_TEXT_CLASS)
  20249. },
  20250. _renderClick: function() {
  20251. this._clickAction = this._createAction(this._clickHandler);
  20252. this.element().off(CHECKBOX_DXCLICK_EVENT_NAME).on(CHECKBOX_DXCLICK_EVENT_NAME, $.proxy(function(e) {
  20253. this._clickAction({jQueryEvent: e})
  20254. }, this))
  20255. },
  20256. _clickHandler: function(args) {
  20257. var that = args.component;
  20258. that._saveValueChangeEvent(args.jQueryEvent);
  20259. that.option("value", !that.option("value"))
  20260. },
  20261. _renderValue: function() {
  20262. var $element = this.element(),
  20263. checked = this.option("value"),
  20264. indeterminate = checked === undefined;
  20265. $element.toggleClass(CHECKBOX_CHECKED_CLASS, Boolean(checked));
  20266. $element.toggleClass(CHECKBOX_INDETERMINATE_CLASS, indeterminate);
  20267. this.setAria("checked", indeterminate ? "mixed" : checked || "false")
  20268. },
  20269. _optionChanged: function(args) {
  20270. switch (args.name) {
  20271. case"value":
  20272. this._renderValue();
  20273. this.callBase(args);
  20274. break;
  20275. case"text":
  20276. this._renderText();
  20277. this._renderDimensions();
  20278. break;
  20279. default:
  20280. this.callBase(args)
  20281. }
  20282. }
  20283. }))
  20284. })(jQuery, DevExpress);
  20285. /*! Module widgets-base, file ui.switch.js */
  20286. (function($, DX, undefined) {
  20287. var ui = DX.ui,
  20288. events = ui.events,
  20289. fx = DX.fx;
  20290. var SWITCH_CLASS = "dx-switch",
  20291. SWITCH_WRAPPER_CLASS = SWITCH_CLASS + "-wrapper",
  20292. SWITCH_CONTAINER_CLASS = SWITCH_CLASS + "-container",
  20293. SWITCH_INNER_CLASS = SWITCH_CLASS + "-inner",
  20294. SWITCH_HANDLE_CLASS = SWITCH_CLASS + "-handle",
  20295. SWITCH_ON_VALUE_CLASS = SWITCH_CLASS + "-on-value",
  20296. SWITCH_ON_CLASS = SWITCH_CLASS + "-on",
  20297. SWITCH_OFF_CLASS = SWITCH_CLASS + "-off",
  20298. SWITCH_ANIMATION_DURATION = 100;
  20299. DX.registerComponent("dxSwitch", ui, ui.Editor.inherit({
  20300. _supportedKeys: function() {
  20301. var isRTL = this.option("rtlEnabled");
  20302. var click = function(e) {
  20303. e.preventDefault();
  20304. this._clickAction({jQueryEvent: e})
  20305. },
  20306. move = function(value, e) {
  20307. e.preventDefault();
  20308. e.stopPropagation();
  20309. this._animateValue(value)
  20310. };
  20311. return $.extend(this.callBase(), {
  20312. space: click,
  20313. enter: click,
  20314. leftArrow: $.proxy(move, this, isRTL ? true : false),
  20315. rightArrow: $.proxy(move, this, isRTL ? false : true)
  20316. })
  20317. },
  20318. _setDefaultOptions: function() {
  20319. this.callBase();
  20320. this.option({
  20321. onText: Globalize.localize("dxSwitch-onText"),
  20322. offText: Globalize.localize("dxSwitch-offText"),
  20323. value: false
  20324. })
  20325. },
  20326. _defaultOptionsRules: function() {
  20327. return this.callBase().concat([{
  20328. device: function(device) {
  20329. return DX.devices.real().generic && !DX.devices.isSimulator()
  20330. },
  20331. options: {
  20332. hoverStateEnabled: true,
  20333. focusStateEnabled: true
  20334. }
  20335. }])
  20336. },
  20337. _init: function() {
  20338. this.callBase();
  20339. this._animating = false;
  20340. this._animationDuration = SWITCH_ANIMATION_DURATION
  20341. },
  20342. _render: function() {
  20343. var element = this.element();
  20344. this._$switchInner = $("<div>").addClass(SWITCH_INNER_CLASS);
  20345. this._$handle = $("<div>").addClass(SWITCH_HANDLE_CLASS).appendTo(this._$switchInner);
  20346. this._$labelOn = $("<div>").addClass(SWITCH_ON_CLASS).prependTo(this._$switchInner);
  20347. this._$labelOff = $("<div>").addClass(SWITCH_OFF_CLASS).appendTo(this._$switchInner);
  20348. this._$switchContainer = $("<div>").addClass(SWITCH_CONTAINER_CLASS).append(this._$switchInner);
  20349. this._$switchWrapper = $("<div>").addClass(SWITCH_WRAPPER_CLASS).append(this._$switchContainer);
  20350. element.addClass(SWITCH_CLASS).append(this._$switchWrapper);
  20351. this.setAria("role", "button");
  20352. this._createComponent(element, "dxSwipeable", {
  20353. elastic: false,
  20354. immediate: true,
  20355. onStart: $.proxy(this._swipeStartHandler, this),
  20356. onUpdated: $.proxy(this._swipeUpdateHandler, this),
  20357. onEnd: $.proxy(this._swipeEndHandler, this)
  20358. });
  20359. this._renderLabels();
  20360. this.callBase();
  20361. this._updateMarginBound();
  20362. this._renderValue();
  20363. this._renderClick()
  20364. },
  20365. _updateMarginBound: function() {
  20366. this._marginBound = this._$switchContainer.outerWidth(true) - this._$handle.outerWidth()
  20367. },
  20368. _marginDirection: function() {
  20369. return this.option("rtlEnabled") ? "Right" : "Left"
  20370. },
  20371. _offsetDirection: function() {
  20372. return this.option("rtlEnabled") ? -1 : 1
  20373. },
  20374. _renderPosition: function(state, swipeOffset) {
  20375. var stateInt = state ? 1 : 0,
  20376. marginDirection = this._marginDirection(),
  20377. resetMarginDirection = marginDirection === "Left" ? "Right" : "Left";
  20378. this._$switchInner.css("margin" + marginDirection, this._marginBound * (stateInt + swipeOffset - 1));
  20379. this._$switchInner.css("margin" + resetMarginDirection, 0)
  20380. },
  20381. _validateValue: function() {
  20382. var check = this.option("value");
  20383. if (typeof check !== "boolean")
  20384. this._options["value"] = !!check
  20385. },
  20386. _renderClick: function() {
  20387. var eventName = events.addNamespace("dxclick", this.NAME);
  20388. this._clickAction = this._createAction($.proxy(this._clickHandler, this));
  20389. this.element().off(eventName).on(eventName, $.proxy(function(e) {
  20390. this._clickAction({jQueryEvent: e})
  20391. }, this))
  20392. },
  20393. _clickHandler: function(args) {
  20394. var e = args.jQueryEvent;
  20395. this._saveValueChangeEvent(e);
  20396. if (this._animating || this._swiping)
  20397. return;
  20398. this._animateValue(!this.option("value"))
  20399. },
  20400. _animateValue: function(value) {
  20401. var startValue = this.option("value"),
  20402. endValue = value;
  20403. if (startValue === endValue)
  20404. return;
  20405. this._animating = true;
  20406. var that = this,
  20407. marginDirection = this._marginDirection(),
  20408. resetMarginDirection = marginDirection === "Left" ? "Right" : "Left",
  20409. fromConfig = {},
  20410. toConfig = {};
  20411. this._$switchInner.css("margin" + resetMarginDirection, 0);
  20412. fromConfig["margin" + marginDirection] = (Number(startValue) - 1) * this._marginBound;
  20413. toConfig["margin" + marginDirection] = (Number(endValue) - 1) * this._marginBound;
  20414. fx.animate(this._$switchInner, {
  20415. from: fromConfig,
  20416. to: toConfig,
  20417. duration: this._animationDuration,
  20418. complete: function() {
  20419. that._animating = false;
  20420. that.option("value", endValue)
  20421. }
  20422. })
  20423. },
  20424. _swipeStartHandler: function(e) {
  20425. var state = this.option("value"),
  20426. rtlEnabled = this.option("rtlEnabled"),
  20427. maxOffOffset = rtlEnabled ? 0 : 1,
  20428. maxOnOffset = rtlEnabled ? 1 : 0;
  20429. e.jQueryEvent.maxLeftOffset = state ? maxOffOffset : maxOnOffset;
  20430. e.jQueryEvent.maxRightOffset = state ? maxOnOffset : maxOffOffset;
  20431. this._swiping = true;
  20432. this._toggleActiveState(this.element(), true)
  20433. },
  20434. _swipeUpdateHandler: function(e) {
  20435. this._renderPosition(this.option("value"), this._offsetDirection() * e.jQueryEvent.offset)
  20436. },
  20437. _swipeEndHandler: function(e) {
  20438. var that = this,
  20439. offsetDirection = this._offsetDirection(),
  20440. toConfig = {};
  20441. toConfig["margin" + this._marginDirection()] = this._marginBound * (that.option("value") + offsetDirection * e.jQueryEvent.targetOffset - 1);
  20442. fx.animate(this._$switchInner, {
  20443. to: toConfig,
  20444. duration: that._animationDuration,
  20445. complete: function() {
  20446. that._swiping = false;
  20447. var pos = that.option("value") + offsetDirection * e.jQueryEvent.targetOffset;
  20448. that.option("value", Boolean(pos));
  20449. that._toggleActiveState(that.element(), false)
  20450. }
  20451. })
  20452. },
  20453. _renderValue: function() {
  20454. this._validateValue();
  20455. var val = this.option("value");
  20456. this._renderPosition(val, 0);
  20457. this.element().toggleClass(SWITCH_ON_VALUE_CLASS, val);
  20458. this.setAria({
  20459. pressed: val,
  20460. label: val ? this.option("onText") : this.option("offText")
  20461. })
  20462. },
  20463. _renderLabels: function() {
  20464. this._$labelOn.text(this.option("onText"));
  20465. this._$labelOff.text(this.option("offText"))
  20466. },
  20467. _visibilityChanged: function(visible) {
  20468. if (visible)
  20469. this.repaint()
  20470. },
  20471. _optionChanged: function(args) {
  20472. switch (args.name) {
  20473. case"visible":
  20474. case"width":
  20475. this._refresh();
  20476. break;
  20477. case"onText":
  20478. case"offText":
  20479. this._renderLabels();
  20480. break;
  20481. case"value":
  20482. this._renderValue();
  20483. this.callBase(args);
  20484. break;
  20485. default:
  20486. this.callBase(args)
  20487. }
  20488. }
  20489. }))
  20490. })(jQuery, DevExpress);
  20491. /*! Module widgets-base, file ui.textEditor.js */
  20492. (function($, DX, undefined) {
  20493. var ui = DX.ui,
  20494. events = ui.events,
  20495. inflector = DX.inflector;
  20496. var TEXTEDITOR_CLASS = "dx-texteditor",
  20497. TEXTEDITOR_INPUT_CLASS = "dx-texteditor-input",
  20498. TEXTEDITOR_INPUT_SELECTOR = "." + TEXTEDITOR_INPUT_CLASS,
  20499. TEXTEDITOR_CONTAINER_CLASS = "dx-texteditor-container",
  20500. TEXTEDITOR_BUTTONS_CONTAINER_CLASS = "dx-texteditor-buttons-container",
  20501. TEXTEDITOR_PLACEHOLDER_CLASS = "dx-placeholder",
  20502. TEXTEDITOR_SHOW_CLEAR_BUTTON_CLASS = "dx-show-clear-button",
  20503. TEXTEDITOR_ICON_CLASS = "dx-icon",
  20504. TEXTEDITOR_CLEAR_ICON_CLASS = "dx-icon-clear",
  20505. TEXTEDITOR_CLEAR_BUTTON_CLASS = "dx-clear-button-area",
  20506. TEXTEDITOR_EMPTY_INPUT_CLASS = "dx-texteditor-empty",
  20507. TEXTEDITOR_STATE_FOCUSED_CLASS = "dx-state-focused",
  20508. EVENTS_LIST = ["keyDown", "keyPress", "keyUp", "change", "cut", "copy", "paste", "input"];
  20509. DX.registerComponent("dxTextEditor", ui, ui.Editor.inherit({
  20510. _supportedKeys: function() {
  20511. var stop = function(e) {
  20512. e.stopPropagation()
  20513. };
  20514. return {
  20515. space: stop,
  20516. enter: stop,
  20517. leftArrow: stop,
  20518. rightArrow: stop
  20519. }
  20520. },
  20521. _setDeprecatedOptions: function() {
  20522. this.callBase();
  20523. $.extend(this._deprecatedOptions, {
  20524. keyDownAction: {
  20525. since: "14.2",
  20526. alias: "onKeyDown"
  20527. },
  20528. keyPressAction: {
  20529. since: "14.2",
  20530. alias: "onKeyPress"
  20531. },
  20532. keyUpAction: {
  20533. since: "14.2",
  20534. alias: "onKeyUp"
  20535. },
  20536. cutAction: {
  20537. since: "14.2",
  20538. alias: "onCut"
  20539. },
  20540. copyAction: {
  20541. since: "14.2",
  20542. alias: "onCopy"
  20543. },
  20544. pasteAction: {
  20545. since: "14.2",
  20546. alias: "onPaste"
  20547. },
  20548. changeAction: {
  20549. since: "14.2",
  20550. alias: "onChange"
  20551. },
  20552. inputAction: {
  20553. since: "14.2",
  20554. alias: "onInput"
  20555. },
  20556. focusInAction: {
  20557. since: "14.2",
  20558. alias: "onFocusIn"
  20559. },
  20560. focusOutAction: {
  20561. since: "14.2",
  20562. alias: "onFocusOut"
  20563. },
  20564. enterKeyAction: {
  20565. since: "14.2",
  20566. alias: "onEnterKey"
  20567. }
  20568. })
  20569. },
  20570. _setDefaultOptions: function() {
  20571. this.callBase();
  20572. this.option({
  20573. value: "",
  20574. spellcheck: false,
  20575. showClearButton: false,
  20576. valueChangeEvent: "change",
  20577. placeholder: "",
  20578. attr: {},
  20579. onFocusIn: null,
  20580. onFocusOut: null,
  20581. onKeyDown: null,
  20582. onKeyPress: null,
  20583. onKeyUp: null,
  20584. onChange: null,
  20585. onInput: null,
  20586. onCut: null,
  20587. onCopy: null,
  20588. onPaste: null,
  20589. onEnterKey: null,
  20590. mode: "text",
  20591. hoverStateEnabled: true,
  20592. focusStateEnabled: true,
  20593. text: undefined,
  20594. valueFormat: function(value) {
  20595. return value
  20596. }
  20597. })
  20598. },
  20599. _input: function() {
  20600. return this.element().find(TEXTEDITOR_INPUT_SELECTOR).first()
  20601. },
  20602. _inputWrapper: function() {
  20603. return this.element()
  20604. },
  20605. _buttonsContainer: function() {
  20606. return this._inputWrapper().find("." + TEXTEDITOR_BUTTONS_CONTAINER_CLASS)
  20607. },
  20608. _render: function() {
  20609. this.element().addClass(TEXTEDITOR_CLASS);
  20610. this._renderInput();
  20611. this._renderInputType();
  20612. this._renderValue();
  20613. this._renderProps();
  20614. this._renderPlaceholder();
  20615. this._renderEvents();
  20616. this._renderEnterKeyAction();
  20617. this._renderEmptinessEvent();
  20618. this.callBase()
  20619. },
  20620. _renderInput: function() {
  20621. $("<div>").addClass(TEXTEDITOR_CONTAINER_CLASS).append(this._createInput()).append($("<div>").addClass(TEXTEDITOR_BUTTONS_CONTAINER_CLASS)).appendTo(this.element())
  20622. },
  20623. _createInput: function() {
  20624. return $("<input>").addClass(TEXTEDITOR_INPUT_CLASS).attr("autocomplete", "off").attr(this.option("attr"))
  20625. },
  20626. _renderValue: function() {
  20627. this._renderInputValue();
  20628. this._renderInputAddons()
  20629. },
  20630. _renderInputValue: function() {
  20631. var text = this.option("text"),
  20632. value = this.option("value"),
  20633. displayValue = this.option("displayValue"),
  20634. valueFormat = this.option("valueFormat");
  20635. if (displayValue !== undefined)
  20636. text = valueFormat(displayValue);
  20637. else if (!DX.utils.isDefined(text))
  20638. text = valueFormat(value);
  20639. if (this._input().val() !== (DX.utils.isDefined(text) ? text : ""))
  20640. this._renderDisplayText(text)
  20641. },
  20642. _renderDisplayText: function(text) {
  20643. this._input().val(text);
  20644. this._toggleEmptinessEventHandler()
  20645. },
  20646. _isValueValid: function() {
  20647. var validity = this._input().get(0).validity;
  20648. if (validity)
  20649. return validity.valid;
  20650. return true
  20651. },
  20652. _toggleEmptiness: function(isEmpty) {
  20653. this.element().toggleClass(TEXTEDITOR_EMPTY_INPUT_CLASS, isEmpty);
  20654. this._togglePlaceholder(isEmpty)
  20655. },
  20656. _togglePlaceholder: function(isEmpty) {
  20657. if (!this._$placeholder)
  20658. return;
  20659. if (DX.browser["msie"])
  20660. this._$placeholder.toggle(!this._input().is(":focus") && isEmpty);
  20661. else
  20662. this._$placeholder.toggle(isEmpty)
  20663. },
  20664. _renderProps: function() {
  20665. this._toggleDisabledState(this.option("disabled"));
  20666. this._toggleReadOnlyState(this._readOnlyPropValue());
  20667. this._toggleSpellcheckState()
  20668. },
  20669. _toggleDisabledState: function() {
  20670. this.callBase.apply(this, arguments);
  20671. var $input = this._input();
  20672. if (this.option("disabled"))
  20673. $input.attr("disabled", true).attr("tabindex", -1);
  20674. else
  20675. $input.removeAttr("disabled").removeAttr("tabindex")
  20676. },
  20677. _toggleReadOnlyState: function(value) {
  20678. this._input().prop("readOnly", value);
  20679. this.callBase()
  20680. },
  20681. _readOnlyPropValue: function() {
  20682. return this.option("readOnly")
  20683. },
  20684. _toggleSpellcheckState: function() {
  20685. this._input().prop("spellcheck", this.option("spellcheck"))
  20686. },
  20687. _renderPlaceholder: function() {
  20688. if (this._$placeholder) {
  20689. this._$placeholder.remove();
  20690. this._$placeholder = null
  20691. }
  20692. var that = this,
  20693. $input = that._input(),
  20694. placeholderText = that.option("placeholder"),
  20695. $placeholder = this._$placeholder = $('<div>').attr("data-dx_placeholder", placeholderText),
  20696. startEvent = events.addNamespace("dxpointerup", this.NAME);
  20697. $placeholder.on(startEvent, function() {
  20698. $input.focus()
  20699. });
  20700. $placeholder.insertAfter($input);
  20701. $placeholder.addClass(TEXTEDITOR_PLACEHOLDER_CLASS)
  20702. },
  20703. _placeholder: function() {
  20704. return this._$placeholder || $()
  20705. },
  20706. _renderInputAddons: function() {
  20707. this._renderClearButton()
  20708. },
  20709. _checkIfClearButtonShouldBeRendered: function() {
  20710. return this.option("showClearButton") && !this.option("readOnly")
  20711. },
  20712. _renderClearButton: function() {
  20713. var shouldClearButtonBeRendered = this._checkIfClearButtonShouldBeRendered();
  20714. this.element().toggleClass(TEXTEDITOR_SHOW_CLEAR_BUTTON_CLASS, shouldClearButtonBeRendered);
  20715. if (!shouldClearButtonBeRendered) {
  20716. this._$clearButton && this._$clearButton.remove();
  20717. this._$clearButton = null;
  20718. return
  20719. }
  20720. if (this._$clearButton)
  20721. return;
  20722. this._$clearButton = this._createClearButton()
  20723. },
  20724. _createClearButton: function() {
  20725. return $("<span>").addClass(TEXTEDITOR_CLEAR_BUTTON_CLASS).append($("<span>").addClass(TEXTEDITOR_ICON_CLASS).addClass(TEXTEDITOR_CLEAR_ICON_CLASS)).prependTo(this._buttonsContainer()).on(events.addNamespace("dxpointerdown", this.NAME), function(e) {
  20726. e.preventDefault();
  20727. e.dxPreventBlur = true
  20728. }).on(events.addNamespace("dxclick", this.NAME), $.proxy(this._clearValueHandler, this))
  20729. },
  20730. _clearValueHandler: function(e) {
  20731. var $input = this._input();
  20732. e.stopPropagation();
  20733. this.reset();
  20734. if ($input.is(":focus")) {
  20735. $input.val("");
  20736. this._toggleEmptinessEventHandler()
  20737. }
  20738. else
  20739. $input.focus()
  20740. },
  20741. _renderEvents: function() {
  20742. var that = this,
  20743. $input = that._input();
  20744. that._renderValueChangeEvent();
  20745. that._attachFocusEvents();
  20746. $.each(EVENTS_LIST, function(_, event) {
  20747. var eventName = events.addNamespace(event.toLowerCase(), that.NAME),
  20748. action = that._createActionByOption("on" + inflector.camelize(event, true), {excludeValidators: ["readOnly"]});
  20749. $input.off(eventName).on(eventName, function(e) {
  20750. action({jQueryEvent: e})
  20751. })
  20752. })
  20753. },
  20754. _keyUpHandler: function(e) {
  20755. this.option("text", this._input().val())
  20756. },
  20757. _renderValueChangeEvent: function() {
  20758. var eventNamespace = this.NAME + "ValueChange";
  20759. var keyUpNamespace = events.addNamespace(this._renderValueEventName(), this.NAME + "TextChange");
  20760. this._input().off(keyUpNamespace).on(keyUpNamespace, $.proxy(this._keyUpHandler, this));
  20761. var valueChangeEventNamespace = events.addNamespace(this.option("valueChangeEvent"), eventNamespace);
  20762. this._input().off("." + eventNamespace).on(valueChangeEventNamespace, $.proxy(this._valueChangeEventHandler, this)).on("paste", $.proxy(this._pasteHandler, this))
  20763. },
  20764. _renderValueEventName: function() {
  20765. return "input change keyup"
  20766. },
  20767. _focusTarget: function() {
  20768. return this._input()
  20769. },
  20770. _pasteHandler: function(e) {
  20771. clearTimeout(this._pasteTimer);
  20772. this._pasteTimer = setTimeout($.proxy(this._valueChangeEventHandler, this, e))
  20773. },
  20774. _focusInHandler: function(e) {
  20775. e.stopPropagation();
  20776. this.element().addClass(TEXTEDITOR_STATE_FOCUSED_CLASS)
  20777. },
  20778. _focusOutHandler: function(e) {
  20779. e.stopPropagation();
  20780. this.element().removeClass(TEXTEDITOR_STATE_FOCUSED_CLASS)
  20781. },
  20782. _renderEmptinessEvent: function() {
  20783. var $input = this._input();
  20784. $input.on("input blur", $.proxy(this._toggleEmptinessEventHandler, this));
  20785. this._toggleEmptinessEventHandler()
  20786. },
  20787. _toggleEmptinessEventHandler: function(value) {
  20788. var text = this._input().val(),
  20789. isEmpty = (text === "" || text === null) && this._isValueValid();
  20790. this._toggleEmptiness(isEmpty)
  20791. },
  20792. _valueChangeEventHandler: function(e, formattedValue) {
  20793. this._saveValueChangeEvent(e);
  20794. this.option("value", arguments.length > 1 ? formattedValue : this._input().val())
  20795. },
  20796. _renderEnterKeyAction: function() {
  20797. if (this.option("onEnterKey")) {
  20798. this._enterKeyAction = this._createActionByOption("onEnterKey", {excludeValidators: ["readOnly"]});
  20799. this._input().on("keyup.onEnterKey.dxTextEditor", $.proxy(this._enterKeyHandlerUp, this))
  20800. }
  20801. else {
  20802. this._input().off("keyup.onEnterKey.dxTextEditor");
  20803. this._enterKeyAction = undefined
  20804. }
  20805. },
  20806. _enterKeyHandlerUp: function(e) {
  20807. if (e.which === 13)
  20808. this._enterKeyAction({jQueryEvent: e})
  20809. },
  20810. _updateValue: function() {
  20811. this.option("text", undefined);
  20812. this._renderValue()
  20813. },
  20814. _clean: function() {
  20815. if (this._$placeholder) {
  20816. this._$placeholder.remove();
  20817. delete this._$placeholder
  20818. }
  20819. delete this._$clearButton;
  20820. this.callBase()
  20821. },
  20822. _dispose: function() {
  20823. clearTimeout(this._pasteTimer);
  20824. this.callBase()
  20825. },
  20826. _optionChanged: function(args) {
  20827. var name = args.name;
  20828. if ($.inArray(inflector.camelize(name.replace("on", "")), EVENTS_LIST) > -1) {
  20829. this._renderEvents();
  20830. return
  20831. }
  20832. switch (name) {
  20833. case"valueChangeEvent":
  20834. this._renderValueChangeEvent();
  20835. break;
  20836. case"onValueChanged":
  20837. this._createValueChangeAction();
  20838. break;
  20839. case"readOnly":
  20840. this._toggleReadOnlyState(args.value);
  20841. this.callBase(args);
  20842. this._renderInputAddons();
  20843. break;
  20844. case"spellcheck":
  20845. this._toggleSpellcheckState();
  20846. break;
  20847. case"mode":
  20848. this._renderInputType();
  20849. break;
  20850. case"onEnterKey":
  20851. this._renderEnterKeyAction();
  20852. break;
  20853. case"placeholder":
  20854. this._invalidate();
  20855. break;
  20856. case"showClearButton":
  20857. this._renderInputAddons();
  20858. break;
  20859. case"text":
  20860. break;
  20861. case"value":
  20862. this._updateValue();
  20863. this.callBase(args);
  20864. break;
  20865. case"attr":
  20866. this._input().attr(args.value);
  20867. break;
  20868. case"valueFormat":
  20869. this._invalidate();
  20870. break;
  20871. default:
  20872. this.callBase(args)
  20873. }
  20874. },
  20875. _renderInputType: function() {
  20876. this._setInputType(this.option("mode"))
  20877. },
  20878. _setInputType: function(type) {
  20879. var input = this._input();
  20880. if (type === "search")
  20881. type = "text";
  20882. try {
  20883. input.prop("type", type)
  20884. }
  20885. catch(e) {
  20886. input.prop("type", "text")
  20887. }
  20888. },
  20889. focus: function() {
  20890. this._input().focus()
  20891. },
  20892. blur: function() {
  20893. if (this._input().is(document.activeElement))
  20894. DX.utils.resetActiveElement()
  20895. },
  20896. reset: function() {
  20897. this.option("value", "")
  20898. }
  20899. }))
  20900. })(jQuery, DevExpress);
  20901. /*! Module widgets-base, file ui.textEditor.mask.js */
  20902. (function($, DX, undefined) {
  20903. var ui = DX.ui,
  20904. events = ui.events,
  20905. utils = DX.utils;
  20906. var EMPTY_CHAR = " ";
  20907. var EMPTY_CHAR_CODE = 32;
  20908. var TEXTEDITOR_MASKED_CLASS = "dx-texteditor-masked";
  20909. var MASK_EVENT_NAMESPACE = "dxMask";
  20910. var FORWARD_DIRECTION = "forward";
  20911. var BACKWARD_DIRECTION = "backward";
  20912. var buildInMaskRules = {
  20913. "0": /[0-9]/,
  20914. "9": /[0-9\s]/,
  20915. "#": /[-+0-9\s]/,
  20916. L: /[a-zA-Z]/,
  20917. l: /[a-zA-Z\s]/,
  20918. C: /\S/,
  20919. c: /./,
  20920. A: /[0-9a-zA-Z]/,
  20921. a: /[0-9a-zA-Z\s]/
  20922. };
  20923. var CONTROL_KEYS = {
  20924. 35: "end",
  20925. 36: "home",
  20926. 37: "leftArrow",
  20927. 38: "upArrow",
  20928. 39: "rightArrow",
  20929. 40: "downArrow"
  20930. };
  20931. DX.registerComponent("dxTextEditor", ui, ui.dxTextEditor.inherit({
  20932. _setDefaultOptions: function() {
  20933. this.callBase();
  20934. this.option({
  20935. mask: "",
  20936. maskChar: "_",
  20937. maskRules: {},
  20938. maskInvalidMessage: Globalize.localize("validation-mask")
  20939. })
  20940. },
  20941. _supportedKeys: function() {
  20942. var that = this;
  20943. var keyHandlerMap = {
  20944. backspace: that._maskBackspaceHandler,
  20945. del: that._maskDelHandler,
  20946. enter: that._changeHandler
  20947. };
  20948. var result = that.callBase();
  20949. $.each(keyHandlerMap, function(key, callback) {
  20950. var parentHandler = result[key];
  20951. result[key] = function(e) {
  20952. that.option("mask") && callback.call(that, e);
  20953. parentHandler && parentHandler(e)
  20954. }
  20955. });
  20956. return result
  20957. },
  20958. _render: function() {
  20959. this.callBase();
  20960. this._renderMask()
  20961. },
  20962. _renderMask: function() {
  20963. this.element().removeClass(TEXTEDITOR_MASKED_CLASS);
  20964. this._maskRulesChain = null;
  20965. if (!this.option("mask"))
  20966. return;
  20967. this.element().addClass(TEXTEDITOR_MASKED_CLASS);
  20968. this._attachMaskEventHandlers();
  20969. this._parseMask();
  20970. this._renderMaskedValue()
  20971. },
  20972. _attachMaskEventHandlers: function() {
  20973. this._input().off("." + MASK_EVENT_NAMESPACE).on(events.addNamespace("focus", MASK_EVENT_NAMESPACE), $.proxy(this._maskFocusHandler, this)).on(events.addNamespace("keypress", MASK_EVENT_NAMESPACE), $.proxy(this._maskKeyPressHandler, this)).on(events.addNamespace("paste", MASK_EVENT_NAMESPACE), $.proxy(this._maskPasteHandler, this)).on(events.addNamespace("cut", MASK_EVENT_NAMESPACE), $.proxy(this._maskCutHandler, this)).on(events.addNamespace("drop", MASK_EVENT_NAMESPACE), $.proxy(this._maskDragHandler, this));
  20974. this._attachChangeEventHandlers()
  20975. },
  20976. _attachChangeEventHandlers: function() {
  20977. if ($.inArray("change", this.option("valueChangeEvent").split(" ")) === -1)
  20978. return;
  20979. this._input().on(events.addNamespace("blur", MASK_EVENT_NAMESPACE), $.proxy(this._changeHandler, this))
  20980. },
  20981. _changeHandler: function(e) {
  20982. this._valueChangeEventHandler(events.createEvent(e, {type: "change"}))
  20983. },
  20984. _parseMask: function() {
  20985. this._maskRules = $.extend({}, buildInMaskRules, this.option("maskRules"));
  20986. this._maskRulesChain = this._parseMaskRule(0)
  20987. },
  20988. _parseMaskRule: function(index) {
  20989. var mask = this.option("mask");
  20990. if (index >= mask.length)
  20991. return new ui.dxTextEditor.EmptyMaskRule;
  20992. var result = this._getMaskRule(mask[index]);
  20993. result.next(this._parseMaskRule(index + 1));
  20994. return result
  20995. },
  20996. _getMaskRule: function(pattern) {
  20997. var ruleConfig;
  20998. $.each(this._maskRules, function(rulePattern, allowedChars) {
  20999. if (rulePattern === pattern) {
  21000. ruleConfig = {
  21001. pattern: rulePattern,
  21002. allowedChars: allowedChars
  21003. };
  21004. return false
  21005. }
  21006. });
  21007. return utils.isDefined(ruleConfig) ? new ui.dxTextEditor.MaskRule($.extend({maskChar: this.option("maskChar")}, ruleConfig)) : new ui.dxTextEditor.StubMaskRule({maskChar: pattern})
  21008. },
  21009. _renderMaskedValue: function() {
  21010. if (!this._maskRulesChain)
  21011. return;
  21012. var value = this.option("value");
  21013. this._maskRulesChain.clear();
  21014. this._handleChain({
  21015. value: value,
  21016. length: value.length
  21017. });
  21018. this._displayMask()
  21019. },
  21020. _displayMask: function() {
  21021. var caret = this._caret();
  21022. this._renderValue();
  21023. this._caret(caret)
  21024. },
  21025. _renderValue: function() {
  21026. if (this._maskRulesChain)
  21027. this.option("text", this._maskRulesChain.text());
  21028. this.callBase()
  21029. },
  21030. _valueChangeEventHandler: function(e) {
  21031. if (this._maskRulesChain) {
  21032. this._saveValueChangeEvent(e);
  21033. this.option("value", (this._value || "").replace(/\s+$/, ""));
  21034. return
  21035. }
  21036. this.callBase.apply(this, arguments)
  21037. },
  21038. _maskFocusHandler: function() {
  21039. this._direction(FORWARD_DIRECTION);
  21040. this._adjustCaret()
  21041. },
  21042. _maskKeyPressHandler: function(e) {
  21043. if (this._isControlKeyFired(e))
  21044. return;
  21045. this._maskKeyHandler(e, function() {
  21046. this._handleKey(e.which);
  21047. return true
  21048. })
  21049. },
  21050. _isControlKeyFired: function(e) {
  21051. return CONTROL_KEYS[e.keyCode] && !e.which || e.metaKey
  21052. },
  21053. _maskBackspaceHandler: function(e) {
  21054. this._maskKeyHandler(e, function() {
  21055. if (this._hasSelection())
  21056. return true;
  21057. if (this._tryMoveCaretBackward())
  21058. return false;
  21059. this._handleKey(EMPTY_CHAR_CODE, BACKWARD_DIRECTION);
  21060. return true
  21061. })
  21062. },
  21063. _maskDelHandler: function(e) {
  21064. this._maskKeyHandler(e, function() {
  21065. !this._hasSelection() && this._handleKey(EMPTY_CHAR_CODE);
  21066. return true
  21067. })
  21068. },
  21069. _maskPasteHandler: function(e) {
  21070. var caret = this._caret();
  21071. this._maskKeyHandler(e, function() {
  21072. var pastingText = utils.clipboardText(e);
  21073. var restText = this._maskRulesChain.text().substring(caret.end);
  21074. var accepted = this._handleChain({
  21075. text: pastingText,
  21076. start: caret.start,
  21077. length: pastingText.length
  21078. });
  21079. var newCaret = caret.start + accepted;
  21080. this._handleChain({
  21081. text: restText,
  21082. start: newCaret,
  21083. length: restText.length
  21084. });
  21085. this._caret({
  21086. start: newCaret,
  21087. end: newCaret
  21088. });
  21089. return true
  21090. })
  21091. },
  21092. _handleChain: function(args) {
  21093. var handledCount = this._maskRulesChain.handle(args);
  21094. this._value = this._maskRulesChain.value();
  21095. return handledCount
  21096. },
  21097. _maskCutHandler: function(e) {
  21098. var caret = this._caret();
  21099. var selectedText = this._input().val().substring(caret.start, caret.end);
  21100. this._maskKeyHandler(e, function() {
  21101. utils.clipboardText(e, selectedText);
  21102. return true
  21103. })
  21104. },
  21105. _maskDragHandler: function() {
  21106. this._clearDragTimer();
  21107. this._dragTimer = setTimeout($.proxy(function() {
  21108. this.option("value", this._convertToValue(this._input().val()))
  21109. }, this))
  21110. },
  21111. _convertToValue: function(text) {
  21112. return text.replace(new RegExp(this.option("maskChar"), "g"), EMPTY_CHAR)
  21113. },
  21114. _maskKeyHandler: function(e, tryHandleKeyCallback) {
  21115. this._direction(FORWARD_DIRECTION);
  21116. e.preventDefault();
  21117. this._handleSelection();
  21118. if (!tryHandleKeyCallback.call(this))
  21119. return;
  21120. this._direction(FORWARD_DIRECTION);
  21121. this._adjustCaret();
  21122. this._displayMask();
  21123. this._maskRulesChain.reset()
  21124. },
  21125. _handleKey: function(keyCode, direction) {
  21126. var char = String.fromCharCode(keyCode);
  21127. this._direction(direction || FORWARD_DIRECTION);
  21128. this._adjustCaret(char);
  21129. this._handleKeyChain(char);
  21130. this._moveCaret()
  21131. },
  21132. _handleSelection: function() {
  21133. if (!this._hasSelection())
  21134. return;
  21135. var caret = this._caret();
  21136. var emptyChars = new Array(caret.end - caret.start + 1).join(EMPTY_CHAR);
  21137. this._handleKeyChain(emptyChars)
  21138. },
  21139. _handleKeyChain: function(chars) {
  21140. var caret = this._caret();
  21141. var start = this._isForwardDirection() ? caret.start : caret.start - 1;
  21142. var end = this._isForwardDirection() ? caret.end : caret.end - 1;
  21143. var length = start === end ? 1 : end - start;
  21144. this._handleChain({
  21145. text: chars,
  21146. start: start,
  21147. length: length
  21148. })
  21149. },
  21150. _tryMoveCaretBackward: function() {
  21151. this._direction(BACKWARD_DIRECTION);
  21152. var currentCaret = this._caret().start;
  21153. this._adjustCaret();
  21154. return !currentCaret || currentCaret !== this._caret().start
  21155. },
  21156. _adjustCaret: function(char) {
  21157. var caret = this._maskRulesChain.adjustedCaret(this._caret().start, this._isForwardDirection(), char);
  21158. this._caret({
  21159. start: caret,
  21160. end: caret
  21161. })
  21162. },
  21163. _moveCaret: function() {
  21164. var currentCaret = this._caret().start;
  21165. var maskRuleIndex = currentCaret + (this._isForwardDirection() ? 0 : -1);
  21166. var caret = this._maskRulesChain.isAccepted(maskRuleIndex) ? currentCaret + (this._isForwardDirection() ? 1 : -1) : currentCaret;
  21167. this._caret({
  21168. start: caret,
  21169. end: caret
  21170. })
  21171. },
  21172. _caret: function(position) {
  21173. if (!arguments.length)
  21174. return utils.caret(this._input());
  21175. utils.caret(this._input(), position)
  21176. },
  21177. _hasSelection: function() {
  21178. var caret = this._caret();
  21179. return caret.start !== caret.end
  21180. },
  21181. _direction: function(direction) {
  21182. if (!arguments.length)
  21183. return this._typingDirection;
  21184. this._typingDirection = direction
  21185. },
  21186. _isForwardDirection: function() {
  21187. return this._direction() === FORWARD_DIRECTION
  21188. },
  21189. _clearDragTimer: function() {
  21190. clearTimeout(this._dragTimer)
  21191. },
  21192. _clean: function() {
  21193. this._clearDragTimer();
  21194. this.callBase()
  21195. },
  21196. _validateMask: function() {
  21197. if (!this._maskRulesChain)
  21198. return;
  21199. var isValid = this._maskRulesChain.isValid();
  21200. this.option({
  21201. isValid: isValid,
  21202. validationError: isValid ? null : {
  21203. editorSpecific: true,
  21204. message: this.option("maskInvalidMessage")
  21205. }
  21206. })
  21207. },
  21208. _optionChanged: function(args) {
  21209. switch (args.name) {
  21210. case"mask":
  21211. case"maskChar":
  21212. case"maskRules":
  21213. this._renderMask();
  21214. this._validateMask();
  21215. break;
  21216. case"value":
  21217. this._renderMaskedValue();
  21218. this._validateMask();
  21219. this.callBase(args);
  21220. break;
  21221. case"maskInvalidMessage":
  21222. break;
  21223. default:
  21224. this.callBase(args)
  21225. }
  21226. }
  21227. }))
  21228. })(jQuery, DevExpress);
  21229. /*! Module widgets-base, file ui.textEditor.mask.rule.js */
  21230. (function($, DX, undefined) {
  21231. var ui = DX.ui;
  21232. var EMPTY_CHAR = " ";
  21233. var BaseMaskRule = DX.Class.inherit({
  21234. ctor: function(config) {
  21235. this._value = EMPTY_CHAR;
  21236. $.extend(this, config)
  21237. },
  21238. next: function(rule) {
  21239. if (!arguments.length)
  21240. return this._next;
  21241. this._next = rule
  21242. },
  21243. text: $.noop,
  21244. value: $.noop,
  21245. rawValue: $.noop,
  21246. handle: $.noop,
  21247. _prepareHandlingArgs: function(args, config) {
  21248. var handlingProperty = args.hasOwnProperty("value") ? "value" : "text";
  21249. args[handlingProperty] = DX.utils.isDefined(config.str) ? config.str : args[handlingProperty];
  21250. args.start = DX.utils.isDefined(config.start) ? config.start : args.start;
  21251. args.length = DX.utils.isDefined(config.length) ? config.length : args.length;
  21252. return args
  21253. },
  21254. reset: $.noop,
  21255. clear: $.noop,
  21256. isAccepted: function() {
  21257. return false
  21258. },
  21259. adjustedCaret: function(caret, isForwardDirection, char) {
  21260. return isForwardDirection ? this._adjustedForward(caret, 0, char) : this._adjustedBackward(caret, 0, char)
  21261. },
  21262. _adjustedForward: $.noop,
  21263. _adjustedBackward: $.noop,
  21264. isValid: $.noop
  21265. });
  21266. var EmptyMaskRule = BaseMaskRule.inherit({
  21267. next: $.noop,
  21268. handle: function() {
  21269. return 0
  21270. },
  21271. text: function() {
  21272. return ""
  21273. },
  21274. value: function() {
  21275. return ""
  21276. },
  21277. rawValue: function() {
  21278. return ""
  21279. },
  21280. adjustedCaret: function() {
  21281. return 0
  21282. },
  21283. isValid: function() {
  21284. return true
  21285. }
  21286. });
  21287. var MaskRule = BaseMaskRule.inherit({
  21288. text: function() {
  21289. return (this._value !== EMPTY_CHAR ? this._value : this.maskChar) + this.next().text()
  21290. },
  21291. value: function() {
  21292. return this._value + this.next().value()
  21293. },
  21294. rawValue: function() {
  21295. return this._value + this.next().rawValue()
  21296. },
  21297. handle: function(args) {
  21298. var str = args.hasOwnProperty("value") ? args.value : args.text;
  21299. if (!str.length || !args.length)
  21300. return 0;
  21301. if (args.start)
  21302. return this.next().handle(this._prepareHandlingArgs(args, {start: args.start - 1}));
  21303. var char = str[0];
  21304. var rest = str.substring(1);
  21305. this._tryAcceptChar(char);
  21306. return this._accepted() ? this.next().handle(this._prepareHandlingArgs(args, {
  21307. str: rest,
  21308. length: args.length - 1
  21309. })) + 1 : this.handle(this._prepareHandlingArgs(args, {
  21310. str: rest,
  21311. length: args.length - 1
  21312. }))
  21313. },
  21314. clear: function() {
  21315. this._tryAcceptChar(EMPTY_CHAR);
  21316. this.next().clear()
  21317. },
  21318. reset: function() {
  21319. this._accepted(false);
  21320. this.next().reset()
  21321. },
  21322. _tryAcceptChar: function(char) {
  21323. this._accepted(false);
  21324. if (!this._isAllowed(char))
  21325. return;
  21326. this._accepted(true);
  21327. this._value = char
  21328. },
  21329. _accepted: function(value) {
  21330. if (!arguments.length)
  21331. return !!this._isAccepted;
  21332. this._isAccepted = !!value
  21333. },
  21334. _isAllowed: function(char) {
  21335. if (char === EMPTY_CHAR)
  21336. return true;
  21337. return this._isValid(char)
  21338. },
  21339. _isValid: function(char) {
  21340. var allowedChars = this.allowedChars;
  21341. if (allowedChars instanceof RegExp)
  21342. return allowedChars.test(char);
  21343. if ($.isFunction(allowedChars))
  21344. return allowedChars(char);
  21345. if ($.isArray(allowedChars))
  21346. return $.inArray(char, allowedChars) > -1;
  21347. return allowedChars === char
  21348. },
  21349. isAccepted: function(caret) {
  21350. return caret === 0 ? this._accepted() : this.next().isAccepted(caret - 1)
  21351. },
  21352. _adjustedForward: function(caret, index, char) {
  21353. if (index >= caret)
  21354. return index;
  21355. return this.next()._adjustedForward(caret, index + 1, char) || index + 1
  21356. },
  21357. _adjustedBackward: function(caret, index) {
  21358. if (index >= caret - 1)
  21359. return caret;
  21360. return this.next()._adjustedBackward(caret, index + 1) || index + 1
  21361. },
  21362. isValid: function() {
  21363. return this._isValid(this._value) && this.next().isValid()
  21364. }
  21365. });
  21366. var StubMaskRule = MaskRule.inherit({
  21367. value: function() {
  21368. return this.next().value()
  21369. },
  21370. handle: function(args) {
  21371. var hasValueProperty = args.hasOwnProperty("value");
  21372. var str = hasValueProperty ? args.value : args.text;
  21373. if (!str.length || !args.length)
  21374. return 0;
  21375. if (args.start || hasValueProperty)
  21376. return this.next().handle(this._prepareHandlingArgs(args, {start: args.start && args.start - 1}));
  21377. var char = str[0];
  21378. var rest = str.substring(1);
  21379. this._tryAcceptChar(char);
  21380. var nextArgs = this._isAllowed(char) ? this._prepareHandlingArgs(args, {
  21381. str: rest,
  21382. length: args.length - 1
  21383. }) : args;
  21384. return this.next().handle(nextArgs) + 1
  21385. },
  21386. clear: function() {
  21387. this._accepted(false);
  21388. this.next().clear()
  21389. },
  21390. _tryAcceptChar: function(char) {
  21391. this._accepted(this._isValid(char))
  21392. },
  21393. _isValid: function(char) {
  21394. return char === this.maskChar
  21395. },
  21396. _adjustedForward: function(caret, index, char) {
  21397. if (index >= caret && char === this.maskChar)
  21398. return index;
  21399. if (caret === index + 1 && this._accepted())
  21400. return caret;
  21401. return this.next()._adjustedForward(caret, index + 1, char)
  21402. },
  21403. _adjustedBackward: function(caret, index) {
  21404. if (index >= caret - 1)
  21405. return 0;
  21406. return this.next()._adjustedBackward(caret, index + 1)
  21407. },
  21408. isValid: function() {
  21409. return this.next().isValid()
  21410. }
  21411. });
  21412. $.extend(ui.dxTextEditor, {
  21413. MaskRule: MaskRule,
  21414. StubMaskRule: StubMaskRule,
  21415. EmptyMaskRule: EmptyMaskRule
  21416. })
  21417. })(jQuery, DevExpress);
  21418. /*! Module widgets-base, file ui.textBox.js */
  21419. (function($, DX, undefined) {
  21420. var ui = DX.ui,
  21421. events = ui.events,
  21422. devices = DX.devices,
  21423. ua = window.navigator.userAgent,
  21424. ignoreCode = [8, 9, 13, 33, 34, 35, 36, 37, 38, 39, 40, 46],
  21425. TEXTBOX_CLASS = "dx-textbox",
  21426. SEARCHBOX_CLASS = "dx-searchbox",
  21427. ICON_CLASS = "dx-icon",
  21428. SEARCH_ICON_CLASS = "dx-icon-search";
  21429. DX.registerComponent("dxTextBox", ui, ui.dxTextEditor.inherit({
  21430. ctor: function(element, options) {
  21431. if (options)
  21432. this._showClearButton = options.showClearButton;
  21433. this.callBase.apply(this, arguments)
  21434. },
  21435. _setDefaultOptions: function() {
  21436. this.callBase();
  21437. this.option({
  21438. mode: "text",
  21439. maxLength: null
  21440. })
  21441. },
  21442. _render: function() {
  21443. this.callBase();
  21444. this.element().addClass(TEXTBOX_CLASS);
  21445. this.setAria("role", "textbox");
  21446. this._renderMaxLengthHandlers()
  21447. },
  21448. _renderInputType: function() {
  21449. this.callBase();
  21450. this._renderSearchMode()
  21451. },
  21452. _renderMaxLengthHandlers: function() {
  21453. if (this._isAndroid())
  21454. this._input().on(events.addNamespace("keydown", this.NAME), $.proxy(this._onKeyDownAndroidHandler, this)).on(events.addNamespace("change", this.NAME), $.proxy(this._onChangeAndroidHandler, this))
  21455. },
  21456. _getAriaTarget: function() {
  21457. return this._input()
  21458. },
  21459. _renderProps: function() {
  21460. this.callBase();
  21461. this._toggleMaxLengthProp()
  21462. },
  21463. _toggleMaxLengthProp: function() {
  21464. if (this._isAndroid())
  21465. return;
  21466. var maxLength = this.option("maxLength");
  21467. if (maxLength > 0)
  21468. this._input().attr("maxLength", maxLength);
  21469. else
  21470. this._input().removeAttr("maxLength")
  21471. },
  21472. _renderSearchMode: function() {
  21473. var $element = this._$element;
  21474. if (this.option("mode") === "search") {
  21475. $element.addClass(SEARCHBOX_CLASS);
  21476. this._renderSearchIcon();
  21477. if (this._showClearButton === undefined) {
  21478. this._showClearButton = this.option("showClearButton");
  21479. this.option("showClearButton", true)
  21480. }
  21481. }
  21482. else {
  21483. $element.removeClass(SEARCHBOX_CLASS);
  21484. this._$searchIcon && this._$searchIcon.remove();
  21485. this.option("showClearButton", this._showClearButton === undefined ? this.option("showClearButton") : this._showClearButton);
  21486. delete this._showClearButton
  21487. }
  21488. },
  21489. _renderSearchIcon: function() {
  21490. var $searchIcon = $("<div>").addClass(ICON_CLASS).addClass(SEARCH_ICON_CLASS);
  21491. $searchIcon.prependTo(this._input().parent());
  21492. this._$searchIcon = $searchIcon
  21493. },
  21494. _optionChanged: function(args) {
  21495. switch (args.name) {
  21496. case"maxLength":
  21497. this._toggleMaxLengthProp();
  21498. this._renderMaxLengthHandlers();
  21499. break;
  21500. default:
  21501. this.callBase(args)
  21502. }
  21503. },
  21504. _onKeyDownAndroidHandler: function(e) {
  21505. var maxLength = this.option("maxLength");
  21506. if (maxLength) {
  21507. var $input = $(e.target),
  21508. code = e.keyCode;
  21509. this._cutOffExtraChar($input);
  21510. return $input.val().length < maxLength || $.inArray(code, ignoreCode) !== -1 || window.getSelection().toString() !== ""
  21511. }
  21512. else
  21513. return true
  21514. },
  21515. _onChangeAndroidHandler: function(e) {
  21516. var $input = $(e.target);
  21517. if (this.option("maxLength"))
  21518. this._cutOffExtraChar($input)
  21519. },
  21520. _cutOffExtraChar: function($input) {
  21521. var maxLength = this.option("maxLength"),
  21522. textInput = $input.val();
  21523. if (textInput.length > maxLength)
  21524. $input.val(textInput.substr(0, maxLength))
  21525. },
  21526. _isAndroid: function() {
  21527. var realDevice = devices.real();
  21528. var version = realDevice.version.join(".");
  21529. return realDevice.platform === "android" && version && /^(2\.|4\.1)/.test(version) && !/chrome/i.test(ua)
  21530. }
  21531. }));
  21532. ui.dxTextBox.__internals = {
  21533. uaAccessor: function(value) {
  21534. if (!arguments.length)
  21535. return ui;
  21536. ua = value
  21537. },
  21538. SEARCHBOX_CLASS: SEARCHBOX_CLASS,
  21539. SEARCH_ICON_CLASS: SEARCH_ICON_CLASS
  21540. }
  21541. })(jQuery, DevExpress);
  21542. /*! Module widgets-base, file ui.dropDownEditor.js */
  21543. (function($, DX, undefined) {
  21544. var ui = DX.ui,
  21545. events = ui.events,
  21546. DROP_DOWN_EDITOR_CLASS = "dx-dropdowneditor",
  21547. DROP_DOWN_EDITOR_READONLY_CLASS = "dx-dropdowneditor-readonly",
  21548. DROP_DOWN_EDITOR_INPUT_WRAPPER_CLASS = "dx-dropdowneditor-input-wrapper",
  21549. DROP_DOWN_EDITOR_BUTTON_CLASS = "dx-dropdowneditor-button",
  21550. DROP_DOWN_EDITOR_BUTTON_ICON = "dx-dropdowneditor-icon",
  21551. DROP_DOWN_EDITOR_OVERLAY = "dx-dropdowneditor-overlay",
  21552. DROP_DOWN_EDITOR_OVERLAY_FLIPPED = "dx-dropdowneditor-overlay-flipped",
  21553. DROP_DOWN_EDITOR_ACTIVE = "dx-dropdowneditor-active",
  21554. DROP_DOWN_EDITOR_BUTTON_VISIBLE = "dx-dropdowneditor-button-visible",
  21555. DROP_DOWN_EDITOR_FIELD_CLICKABLE = "dx-dropdowneditor-field-clickable",
  21556. DROP_DOWN_EDITOR = "dxDropDownEditor",
  21557. CLICK_EVENT_NAME = events.addNamespace("dxclick", DROP_DOWN_EDITOR);
  21558. DX.registerComponent(DROP_DOWN_EDITOR, ui, ui.dxTextBox.inherit({
  21559. _supportedKeys: function() {
  21560. return $.extend(this.callBase(), {
  21561. escape: function(e) {
  21562. if (this.option("opened"))
  21563. e.preventDefault();
  21564. this.close()
  21565. },
  21566. upArrow: function(e) {
  21567. e.preventDefault();
  21568. e.stopPropagation();
  21569. if (e.altKey) {
  21570. this.close();
  21571. return false
  21572. }
  21573. return true
  21574. },
  21575. downArrow: function(e) {
  21576. e.preventDefault();
  21577. e.stopPropagation();
  21578. if (e.altKey) {
  21579. this._validatedOpening();
  21580. return false
  21581. }
  21582. return true
  21583. },
  21584. enter: function(e) {
  21585. if (this.option("opened")) {
  21586. e.preventDefault();
  21587. this._valueChangeEventHandler(e)
  21588. }
  21589. return true
  21590. }
  21591. })
  21592. },
  21593. _setDeprecatedOptions: function() {
  21594. this.callBase();
  21595. $.extend(this._deprecatedOptions, {
  21596. openAction: {
  21597. since: "14.2",
  21598. alias: "onOpened"
  21599. },
  21600. closeAction: {
  21601. since: "14.2",
  21602. alias: "onClosed"
  21603. },
  21604. shownAction: {
  21605. since: "14.2",
  21606. alias: "onOpened"
  21607. },
  21608. hiddenAction: {
  21609. since: "14.2",
  21610. alias: "onClosed"
  21611. },
  21612. editEnabled: {
  21613. since: "14.2",
  21614. alias: "fieldEditEnabled"
  21615. }
  21616. })
  21617. },
  21618. _setDefaultOptions: function() {
  21619. this.callBase();
  21620. this.option({
  21621. value: null,
  21622. onOpened: null,
  21623. onClosed: null,
  21624. opened: false,
  21625. fieldEditEnabled: true,
  21626. applyValueMode: "instantly",
  21627. fieldTemplate: null,
  21628. contentTemplate: null,
  21629. openOnFieldClick: false,
  21630. deferRendering: true,
  21631. showDropButton: true,
  21632. dropPosition: this._getDefaultDropPosition(),
  21633. applyButtonText: Globalize.localize("OK"),
  21634. cancelButtonText: Globalize.localize("Cancel"),
  21635. buttonsLocation: "default",
  21636. showPopupTitle: false
  21637. })
  21638. },
  21639. _getDefaultDropPosition: function() {
  21640. var position = this.option("rtlEnabled") ? "right" : "left";
  21641. return {
  21642. offset: {
  21643. h: 0,
  21644. v: -1
  21645. },
  21646. my: position + " top",
  21647. at: position + " bottom",
  21648. collision: "flip flip"
  21649. }
  21650. },
  21651. _defaultOptionsRules: function() {
  21652. return this.callBase().concat([{
  21653. device: {platform: "generic"},
  21654. options: {dropPosition: {offset: {v: 0}}}
  21655. }])
  21656. },
  21657. _inputWrapper: function() {
  21658. return this.element().find("." + DROP_DOWN_EDITOR_INPUT_WRAPPER_CLASS)
  21659. },
  21660. _init: function() {
  21661. this.callBase();
  21662. this._initVisibilityActions()
  21663. },
  21664. _initVisibilityActions: function() {
  21665. this._openAction = this._createActionByOption("onOpened");
  21666. this._closeAction = this._createActionByOption("onClosed")
  21667. },
  21668. _render: function() {
  21669. this.callBase();
  21670. this._renderOpenHandler();
  21671. this.element().addClass(DROP_DOWN_EDITOR_CLASS);
  21672. this._renderOpenedState();
  21673. this.setAria("role", "combobox")
  21674. },
  21675. _renderContentImpl: function() {
  21676. if (!this.option("deferRendering"))
  21677. this._createPopup()
  21678. },
  21679. _renderInput: function() {
  21680. this.callBase();
  21681. this.element().wrapInner($("<div>").addClass(DROP_DOWN_EDITOR_INPUT_WRAPPER_CLASS));
  21682. this._$container = this.element().children().eq(0);
  21683. this.setAria({
  21684. haspopup: "true",
  21685. autocomplete: "list"
  21686. })
  21687. },
  21688. _readOnlyPropValue: function() {
  21689. return !this.option("fieldEditEnabled") || this.callBase()
  21690. },
  21691. _renderField: function() {
  21692. var fieldTemplate = this._getTemplateByOption("fieldTemplate");
  21693. if (!(fieldTemplate && this.option("fieldTemplate")))
  21694. return;
  21695. var isFocused = this._input().is(":focus");
  21696. isFocused && this._input().focusout();
  21697. this._cleanFocusState();
  21698. var $container = this._$container;
  21699. var data = this._fieldRenderData();
  21700. $container.empty();
  21701. this._$dropButton = null;
  21702. this._$clearButton = null;
  21703. fieldTemplate.render(data, $container);
  21704. if (!this._input().length)
  21705. throw DX.Error("E1010");
  21706. this._renderFocusState();
  21707. isFocused && this._input().focus()
  21708. },
  21709. _fieldRenderData: function() {
  21710. return this.option("value")
  21711. },
  21712. _renderInputAddons: function() {
  21713. this._renderField();
  21714. this.callBase();
  21715. this._renderDropButton()
  21716. },
  21717. _renderDropButton: function(hideButton) {
  21718. var dropButtonVisible = this.option("showDropButton");
  21719. this.element().toggleClass(DROP_DOWN_EDITOR_BUTTON_VISIBLE, dropButtonVisible);
  21720. if (!dropButtonVisible) {
  21721. this._$dropButton && this._$dropButton.remove();
  21722. this._$dropButton = null;
  21723. return
  21724. }
  21725. if (!this._$dropButton)
  21726. this._$dropButton = this._createDropButton().addClass(DROP_DOWN_EDITOR_BUTTON_CLASS);
  21727. this._$dropButton.prependTo(this._buttonsContainer())
  21728. },
  21729. _createDropButton: function() {
  21730. var $button = $("<div>");
  21731. this._createComponent($button, "dxButton", {
  21732. focusStateEnabled: false,
  21733. disabled: this.option("readOnly"),
  21734. _templates: {}
  21735. });
  21736. var $buttonIcon = $("<div>").addClass(DROP_DOWN_EDITOR_BUTTON_ICON);
  21737. $button.append($buttonIcon).removeClass("dx-button").on("mousedown", function(e) {
  21738. e.preventDefault()
  21739. });
  21740. $button.find(".dx-button-content").remove();
  21741. return $button
  21742. },
  21743. _renderOpenHandler: function() {
  21744. var $inputWrapper = this.element().find(".dx-dropdowneditor-input-wrapper");
  21745. $inputWrapper.off(CLICK_EVENT_NAME);
  21746. var openOnFieldClick = this.option("openOnFieldClick");
  21747. this.element().toggleClass(DROP_DOWN_EDITOR_FIELD_CLICKABLE, openOnFieldClick);
  21748. if (openOnFieldClick) {
  21749. $inputWrapper.on(events.addNamespace("mousedown", this.NAME), function(e) {
  21750. DX.devices.real().platform !== "generic" && e.preventDefault()
  21751. });
  21752. $inputWrapper.on(CLICK_EVENT_NAME, $.proxy(this._openHandler, this));
  21753. return
  21754. }
  21755. if (this.option("showDropButton"))
  21756. this._$dropButton.dxButton("option", "onClick", $.proxy(this._openHandler, this))
  21757. },
  21758. _openHandler: function() {
  21759. this._toggleOpenState()
  21760. },
  21761. _keyboardEventBindingTarget: function() {
  21762. return this._input()
  21763. },
  21764. _toggleOpenState: function(isVisible) {
  21765. if (this.option("disabled"))
  21766. return;
  21767. this._input().focus();
  21768. if (!this.option("readOnly")) {
  21769. isVisible = arguments.length ? isVisible : !this.option("opened");
  21770. this.option("opened", isVisible)
  21771. }
  21772. },
  21773. _renderOpenedState: function() {
  21774. var opened = this.option("opened");
  21775. if (opened)
  21776. this._createPopup();
  21777. this.element().toggleClass(DROP_DOWN_EDITOR_ACTIVE, opened);
  21778. this._setPopupOption("visible", opened);
  21779. this.setAria("expanded", opened)
  21780. },
  21781. _createPopup: function() {
  21782. if (this._$popup)
  21783. return;
  21784. this._$popup = $("<div>").addClass(DROP_DOWN_EDITOR_OVERLAY).addClass(this.option("customOverlayCssClass")).appendTo(this.element());
  21785. this._renderPopup();
  21786. this._renderPopupContent()
  21787. },
  21788. _renderPopup: function() {
  21789. this._popup = this._createComponent(this._$popup, "dxPopup", this._popupConfig());
  21790. this._popup.on({
  21791. showing: $.proxy(this._popupShowingHandler, this),
  21792. shown: $.proxy(this._popupShownHandler, this),
  21793. hiding: $.proxy(this._popupHidingHandler, this),
  21794. hidden: $.proxy(this._popupHiddenHandler, this)
  21795. });
  21796. this._popup.option("onContentReady", $.proxy(this._contentReadyHandler, this));
  21797. this._contentReadyHandler()
  21798. },
  21799. _contentReadyHandler: $.noop,
  21800. _popupConfig: function() {
  21801. return {
  21802. position: $.extend(this.option("dropPosition"), {of: this.element()}),
  21803. showTitle: this.option("showPopupTitle"),
  21804. width: "auto",
  21805. height: "auto",
  21806. shading: false,
  21807. closeOnTargetScroll: true,
  21808. closeOnOutsideClick: $.proxy(this._closeOutsideDropDownHandler, this),
  21809. animation: {
  21810. show: {
  21811. type: "fade",
  21812. duration: 0,
  21813. from: 0,
  21814. to: 1
  21815. },
  21816. hide: {
  21817. type: "fade",
  21818. duration: 400,
  21819. from: 1,
  21820. to: 0
  21821. }
  21822. },
  21823. deferRendering: false,
  21824. focusStateEnabled: false,
  21825. showCloseButton: false,
  21826. buttons: this._getPopupButtons(),
  21827. onPositioned: $.proxy(this._popupPositionedHandler, this)
  21828. }
  21829. },
  21830. _popupPositionedHandler: function(e) {
  21831. this._popup.overlayContent().toggleClass(DROP_DOWN_EDITOR_OVERLAY_FLIPPED, e.position.v.flip)
  21832. },
  21833. _popupShowingHandler: $.noop,
  21834. _popupHidingHandler: function() {
  21835. this.option("opened", false)
  21836. },
  21837. _popupShownHandler: function() {
  21838. this._openAction();
  21839. if (this._$validationMessage)
  21840. this._$validationMessage.dxTooltip("option", "position", this._getValidationTooltipPosition())
  21841. },
  21842. _popupHiddenHandler: function() {
  21843. this._closeAction();
  21844. if (this._$validationMessage)
  21845. this._$validationMessage.dxTooltip("option", "position", this._getValidationTooltipPosition())
  21846. },
  21847. _getValidationTooltipPosition: function() {
  21848. var positionRequest = "below";
  21849. if (this._popup && this._popup.option("visible")) {
  21850. var myTop = DX.position(this.element()).top,
  21851. popupTop = DX.position(this._popup.content()).top;
  21852. positionRequest = myTop + this.option("dropPosition").offset.v > popupTop ? "below" : "above"
  21853. }
  21854. return this.callBase(positionRequest)
  21855. },
  21856. _renderPopupContent: function() {
  21857. var contentTemplate = this._getTemplateByOption("contentTemplate");
  21858. if (!(contentTemplate && this.option("contentTemplate")))
  21859. return;
  21860. var $popupContent = this._popup.content();
  21861. $popupContent.empty();
  21862. contentTemplate.render($popupContent)
  21863. },
  21864. _closeOutsideDropDownHandler: function(e) {
  21865. var $target = $(e.target);
  21866. var isInputClicked = !!$target.closest(this.element()).length;
  21867. var isDropButtonClicked = !!$target.closest(this._$dropButton).length;
  21868. var isOutsideClick = !isInputClicked && !isDropButtonClicked;
  21869. return isOutsideClick
  21870. },
  21871. _clean: function() {
  21872. delete this._$dropButton;
  21873. if (this._$popup) {
  21874. this._$popup.remove();
  21875. delete this._$popup;
  21876. delete this._popup
  21877. }
  21878. this.callBase()
  21879. },
  21880. _setPopupOption: function(optionName, value) {
  21881. this._setWidgetOption("_popup", arguments)
  21882. },
  21883. _validatedOpening: function() {
  21884. if (!this.option("readOnly"))
  21885. this._toggleOpenState(true)
  21886. },
  21887. _getAriaTarget: function() {
  21888. return this._input()
  21889. },
  21890. _getPopupButtons: function() {
  21891. return this.option("applyValueMode") === "useButtons" ? this._popupButtonsConfig() : []
  21892. },
  21893. _popupButtonsConfig: function() {
  21894. var buttonsConfig = [{
  21895. shortcut: "done",
  21896. options: {
  21897. onClick: $.proxy(this._applyButtonHandler, this),
  21898. text: this.option("applyButtonText")
  21899. }
  21900. }, {
  21901. shortcut: "cancel",
  21902. options: {
  21903. onClick: $.proxy(this._cancelButtonHandler, this),
  21904. text: this.option("cancelButtonText")
  21905. }
  21906. }];
  21907. return this._applyButtonsLocation(buttonsConfig)
  21908. },
  21909. _applyButtonsLocation: function(buttonsConfig) {
  21910. var buttonsLocation = this.option("buttonsLocation"),
  21911. resultConfig = buttonsConfig;
  21912. if (buttonsLocation !== "default") {
  21913. var position = DX.utils.splitPair(buttonsLocation);
  21914. $.each(resultConfig, function(_, element) {
  21915. $.extend(element, {
  21916. toolbar: position[0],
  21917. location: position[1]
  21918. })
  21919. })
  21920. }
  21921. return resultConfig
  21922. },
  21923. _applyButtonHandler: function() {
  21924. this.close();
  21925. this.option("focusStateEnabled") && this.focus()
  21926. },
  21927. _cancelButtonHandler: function() {
  21928. this.close();
  21929. this.option("focusStateEnabled") && this.focus()
  21930. },
  21931. _optionChanged: function(args) {
  21932. switch (args.name) {
  21933. case"opened":
  21934. this._renderOpenedState();
  21935. break;
  21936. case"onOpened":
  21937. case"onClosed":
  21938. this._initVisibilityActions();
  21939. break;
  21940. case"fieldTemplate":
  21941. case"fieldRender":
  21942. this._renderInputAddons();
  21943. break;
  21944. case"showDropButton":
  21945. case"contentTemplate":
  21946. case"contentRender":
  21947. case"fieldEditEnabled":
  21948. case"openOnFieldClick":
  21949. this._invalidate();
  21950. break;
  21951. case"dropPosition":
  21952. case"deferRendering":
  21953. break;
  21954. case"applyValueMode":
  21955. case"applyButtonText":
  21956. case"cancelButtonText":
  21957. case"buttonsLocation":
  21958. this._setPopupOption("buttons", this._getPopupButtons());
  21959. break;
  21960. case"showPopupTitle":
  21961. this._setPopupOption("showTitle", args.value);
  21962. break;
  21963. default:
  21964. this.callBase(args)
  21965. }
  21966. },
  21967. open: function() {
  21968. this.option("opened", true)
  21969. },
  21970. close: function() {
  21971. this.option("opened", false)
  21972. },
  21973. reset: function() {
  21974. this.option("value", null)
  21975. },
  21976. field: function() {
  21977. return this._input()
  21978. },
  21979. content: function() {
  21980. return this._popup ? this._popup.content() : null
  21981. }
  21982. }));
  21983. ui.dxDropDownEditor.__internals = {
  21984. DROP_DOWN_EDITOR_CLASS: DROP_DOWN_EDITOR_CLASS,
  21985. DROP_DOWN_EDITOR_READONLY_CLASS: DROP_DOWN_EDITOR_READONLY_CLASS,
  21986. DROP_DOWN_EDITOR_BUTTON_ICON: DROP_DOWN_EDITOR_BUTTON_ICON,
  21987. DROP_DOWN_EDITOR_INPUT_WRAPPER_CLASS: DROP_DOWN_EDITOR_INPUT_WRAPPER_CLASS,
  21988. DROP_DOWN_EDITOR_BUTTON_CLASS: DROP_DOWN_EDITOR_BUTTON_CLASS,
  21989. DROP_DOWN_EDITOR_OVERLAY: DROP_DOWN_EDITOR_OVERLAY,
  21990. DROP_DOWN_EDITOR_ACTIVE: DROP_DOWN_EDITOR_ACTIVE,
  21991. DROP_DOWN_EDITOR_BUTTON_VISIBLE: DROP_DOWN_EDITOR_BUTTON_VISIBLE
  21992. }
  21993. })(jQuery, DevExpress);
  21994. /*! Module widgets-base, file ui.dropDownList.js */
  21995. (function($, DX, undefined) {
  21996. var ui = DX.ui,
  21997. utils = DX.utils;
  21998. var LIST_ITEM_SELECTOR = ".dx-list-item",
  21999. LIST_ITEM_DATA_KEY = "dxListItemData",
  22000. DROPDOWNLIST_SELECTED_CLASS = "dx-dropdownlist-selected",
  22001. DROPDOWNLIST_POPUP_WRAPPER_CLASS = "dx-dropdownlist-popup-wrapper",
  22002. SEARCH_MODES = ["startswith", "contains", "endwith", "notcontains"];
  22003. DX.registerComponent("dxDropDownList", ui, ui.dxDropDownEditor.inherit({
  22004. _supportedKeys: function() {
  22005. return $.extend(this.callBase(), {
  22006. tab: function(e) {
  22007. if (this.option("opened") === true) {
  22008. var $focusedItem = this._list.option("focusedElement");
  22009. if ($focusedItem) {
  22010. var $selectedItem = this._listSelectedItemElements();
  22011. this._changeSelectedItem($selectedItem, $focusedItem);
  22012. this.option("value", this._selectedItemValue())
  22013. }
  22014. this.close()
  22015. }
  22016. else
  22017. this._focusTarget().focusout()
  22018. },
  22019. space: $.noop,
  22020. home: $.noop,
  22021. end: $.noop
  22022. })
  22023. },
  22024. _setDeprecatedOptions: function() {
  22025. this.callBase();
  22026. $.extend(this._deprecatedOptions, this._dataExpressionDeprecatedOptions(), {pagingEnabled: {
  22027. since: "15.1",
  22028. message: "Use the 'dataSource.paginate' option instead"
  22029. }})
  22030. },
  22031. _setDefaultOptions: function() {
  22032. this.callBase();
  22033. this.option($.extend(this._dataExpressionDefaultOptions(), {
  22034. displayValue: undefined,
  22035. searchEnabled: false,
  22036. searchMode: "contains",
  22037. searchTimeout: 500,
  22038. minSearchLength: 0,
  22039. searchExpr: null,
  22040. valueChangeEvent: "change keyup",
  22041. selectedItem: null,
  22042. pagingEnabled: undefined,
  22043. noDataText: Globalize.localize("dxCollectionWidget-noDataText"),
  22044. onSelectionChanged: null,
  22045. onItemClick: $.noop,
  22046. dropPosition: {
  22047. my: "left top",
  22048. at: "left bottom",
  22049. offset: {
  22050. h: 0,
  22051. v: 0
  22052. },
  22053. collision: "flip"
  22054. },
  22055. popupWidthExtension: 0
  22056. }))
  22057. },
  22058. _defaultOptionsRules: function() {
  22059. return this.callBase().concat([{
  22060. device: {platform: "win8"},
  22061. options: {dropPosition: {offset: {v: -6}}}
  22062. }, {
  22063. device: function(device) {
  22064. return device.platform === "android"
  22065. },
  22066. options: {popupWidthExtension: 32}
  22067. }])
  22068. },
  22069. _setOptionsByReference: function() {
  22070. this.callBase();
  22071. $.extend(this._optionsByReference, {
  22072. value: true,
  22073. selectedItem: true,
  22074. displayValue: true
  22075. })
  22076. },
  22077. _init: function() {
  22078. this.callBase();
  22079. this._initDataExpressions();
  22080. this._initActions();
  22081. this._setListDataSource();
  22082. this._validateSearchMode();
  22083. this._clearSelectedItem()
  22084. },
  22085. _initActions: function() {
  22086. this._initContentReadyAction();
  22087. this._initSelectionChangedAction();
  22088. this._initItemClickAction()
  22089. },
  22090. _initContentReadyAction: function() {
  22091. this._contentReadyAction = this._createActionByOption("onContentReady")
  22092. },
  22093. _initSelectionChangedAction: function() {
  22094. this._selectionChangedAction = this._createActionByOption("onSelectionChanged", {excludeValidators: ["disabled", "readOnly"]})
  22095. },
  22096. _initItemClickAction: function() {
  22097. this._itemClickAction = this._createActionByOption("onItemClick")
  22098. },
  22099. _renderContentImpl: function() {
  22100. this.callBase();
  22101. if (this.option("deferRendering"))
  22102. this._loadDataSource()
  22103. },
  22104. _renderField: function() {
  22105. this.callBase();
  22106. this._input().on("input", $.proxy(this._setFocusPolicy, this))
  22107. },
  22108. _preventFocusOnPopup: function(e) {
  22109. if (this._list && this._list.initialOption("focusStateEnabled"))
  22110. e.preventDefault()
  22111. },
  22112. _createPopup: function() {
  22113. this.callBase();
  22114. this._popup._wrapper().addClass(this._popupWrapperClass());
  22115. this._popup.content().off("mousedown").on("mousedown", $.proxy(this._preventFocusOnPopup, this))
  22116. },
  22117. _popupWrapperClass: function() {
  22118. return DROPDOWNLIST_POPUP_WRAPPER_CLASS
  22119. },
  22120. _renderInputValue: function() {
  22121. var callBase = $.proxy(this.callBase, this);
  22122. return this._loadItem(this.option("value")).always($.proxy(function(item) {
  22123. this._setSelectedItem(item);
  22124. this._refreshSelected();
  22125. callBase()
  22126. }, this))
  22127. },
  22128. _loadItem: function(value) {
  22129. var selectedItem = $.grep(this.option("items") || [], $.proxy(function(item) {
  22130. return this._isValueEquals(this._valueGetter(item), value)
  22131. }, this))[0];
  22132. return selectedItem !== undefined ? $.Deferred().resolve(selectedItem).promise() : this._loadValue(value)
  22133. },
  22134. _setSelectedItem: function(item) {
  22135. var displayValue = this._displayValue(item);
  22136. this.option("selectedItem", item);
  22137. this.option("displayValue", displayValue)
  22138. },
  22139. _displayValue: function(item) {
  22140. return this._displayGetter(item)
  22141. },
  22142. _refreshSelected: function() {
  22143. this._listItemElements().each($.proxy(function(_, itemElement) {
  22144. var $itemElement = $(itemElement);
  22145. var itemValue = this._valueGetter($itemElement.data(LIST_ITEM_DATA_KEY));
  22146. var isItemSelected = this._isSelectedValue(itemValue);
  22147. $itemElement.toggleClass(this._selectedItemClass(), isItemSelected);
  22148. if (isItemSelected)
  22149. this._list.selectItem($itemElement);
  22150. else
  22151. this._list.unselectItem($itemElement)
  22152. }, this))
  22153. },
  22154. _popupShownHandler: function() {
  22155. this.callBase();
  22156. this._setFocusPolicy()
  22157. },
  22158. _setFocusPolicy: function() {
  22159. if (!this.option("focusStateEnabled") || !this._list)
  22160. return;
  22161. this._list.option("focusedElement", null)
  22162. },
  22163. _isSelectedValue: function(value) {
  22164. return this._isValueEquals(value, this.option("value"))
  22165. },
  22166. _validateSearchMode: function() {
  22167. var searchMode = this.option("searchMode"),
  22168. normalizedSearchMode = searchMode.toLowerCase();
  22169. if ($.inArray(normalizedSearchMode, SEARCH_MODES) < 0)
  22170. throw DX.Error("E1019", searchMode);
  22171. },
  22172. _clearSelectedItem: function() {
  22173. this.option("selectedItem", null)
  22174. },
  22175. _processDataSourceChanging: function() {
  22176. this._setListDataSource();
  22177. this._renderInputValue().fail($.proxy(this.reset, this))
  22178. },
  22179. reset: function() {
  22180. this.option("value", null);
  22181. this._clearSelectedItem()
  22182. },
  22183. _selectedItemClass: function() {
  22184. return DROPDOWNLIST_SELECTED_CLASS
  22185. },
  22186. _listItemElements: function() {
  22187. return this._$list ? this._$list.find(LIST_ITEM_SELECTOR) : $()
  22188. },
  22189. _listSelectedItemElements: function() {
  22190. return this._$list ? this._$list.find("." + this._selectedItemClass()) : $()
  22191. },
  22192. _popupConfig: function() {
  22193. return $.extend(this.callBase(), {width: this.option("width")})
  22194. },
  22195. _renderPopupContent: function() {
  22196. this._renderList()
  22197. },
  22198. _attachChildKeyboardEvents: function() {
  22199. this._childKeyboardProcessor = this._keyboardProcessor.attachChildProcessor();
  22200. this._setListOption("_keyboardProcessor", this._childKeyboardProcessor)
  22201. },
  22202. _fireContentReadyAction: $.noop,
  22203. _renderList: function() {
  22204. var listId = (new DevExpress.data.Guid)._value,
  22205. $list = this._$list = $("<div>", {id: listId}).appendTo(this._popup.content());
  22206. this._list = this._createComponent($list, "dxList", this._listConfig());
  22207. this.setAria({
  22208. activedescendant: this._list.getFocusedItemId(),
  22209. owns: listId
  22210. });
  22211. this._refreshList()
  22212. },
  22213. _refreshList: function() {
  22214. if (this._list && this._shouldRefreshDataSource())
  22215. this._setListDataSource()
  22216. },
  22217. _shouldRefreshDataSource: function() {
  22218. var dataSourceProvided = !!this._list.option("dataSource");
  22219. return dataSourceProvided !== this._isMinFilterLengthExceeded()
  22220. },
  22221. _refreshActiveDescendant: function() {
  22222. this.setAria("activedescendant", "");
  22223. this.setAria("activedescendant", this._list.getFocusedItemId())
  22224. },
  22225. _listConfig: function() {
  22226. return {
  22227. _templates: this.option("_templates"),
  22228. templateProvider: this.option("templateProvider"),
  22229. noDataText: this.option("noDataText"),
  22230. onContentReady: $.proxy(this._listContentReadyHandler, this),
  22231. itemTemplate: this._getTemplateByOption("itemTemplate"),
  22232. indicateLoading: false,
  22233. tabIndex: -1,
  22234. onItemClick: $.proxy(this._listItemClickAction, this),
  22235. dataSource: this._isMinFilterLengthExceeded() ? this._dataSource : null,
  22236. _keyboardProcessor: this._childKeyboardProcessor,
  22237. onOptionChanged: $.proxy(function(args) {
  22238. if (args.name === "focusedElement")
  22239. this._refreshActiveDescendant()
  22240. }, this)
  22241. }
  22242. },
  22243. _dataSourceOptions: function() {
  22244. this._suppressDeprecatedWarnings();
  22245. var pagingEnabled = this.option("pagingEnabled");
  22246. this._resumeDeprecatedWarnings();
  22247. return {paginate: utils.ensureDefined(pagingEnabled, false)}
  22248. },
  22249. _listContentReadyHandler: function() {
  22250. this._list = this._list || this._$list.dxList("instance");
  22251. this.option().items = this._list.option("items");
  22252. this._refreshSelected();
  22253. this._dimensionChanged();
  22254. this._contentReadyAction()
  22255. },
  22256. _setListOption: function(optionName, value) {
  22257. this._setWidgetOption("_list", arguments)
  22258. },
  22259. _listItemClickAction: function(e) {
  22260. this._listItemClickHandler(e);
  22261. this._itemClickAction(e)
  22262. },
  22263. _listItemClickHandler: $.noop,
  22264. _setListDataSource: function() {
  22265. if (!this._list)
  22266. return;
  22267. var isMinFilterLengthExceeded = this._isMinFilterLengthExceeded();
  22268. this._setListOption("dataSource", isMinFilterLengthExceeded ? this._dataSource : null);
  22269. if (!isMinFilterLengthExceeded)
  22270. this._setListOption("items", [])
  22271. },
  22272. _isMinFilterLengthExceeded: function() {
  22273. return this._searchValue().toString().length >= this.option("minSearchLength")
  22274. },
  22275. _searchValue: function() {
  22276. return this._input().val() || ""
  22277. },
  22278. _search: function() {
  22279. if (!this._isMinFilterLengthExceeded()) {
  22280. this._searchCanceled();
  22281. return
  22282. }
  22283. var searchTimeout = this.option("searchTimeout");
  22284. if (searchTimeout) {
  22285. if (!this._searchTimer)
  22286. this._searchTimer = setTimeout($.proxy(this._searchDataSource, this), searchTimeout)
  22287. }
  22288. else
  22289. this._searchDataSource()
  22290. },
  22291. _searchCanceled: function() {
  22292. this._clearSearchTimer();
  22293. this._refreshList()
  22294. },
  22295. _searchDataSource: function() {
  22296. this._filterDataSource(this._searchValue())
  22297. },
  22298. _filterDataSource: function(searchValue) {
  22299. var dataSource = this._dataSource;
  22300. dataSource.searchExpr(this.option("searchExpr") || this._displayGetterExpr());
  22301. dataSource.searchOperation(this.option("searchMode"));
  22302. dataSource.searchValue(searchValue);
  22303. dataSource.pageIndex(0);
  22304. return dataSource.load().done($.proxy(this._dataSourceFiltered, this))
  22305. },
  22306. _clearFilter: function() {
  22307. this._dataSource.searchValue("")
  22308. },
  22309. _dataSourceFiltered: function() {
  22310. this._clearSearchTimer();
  22311. this._refreshList();
  22312. this._refreshPopupVisibility()
  22313. },
  22314. _refreshPopupVisibility: function() {
  22315. this.option("opened", this._hasItemsToShow());
  22316. if (this.option("opened"))
  22317. this._dimensionChanged()
  22318. },
  22319. _hasItemsToShow: function() {
  22320. var resultItems = this._dataSource && this._dataSource.items() || [];
  22321. var resultAmount = resultItems.length;
  22322. var isMinFilterLengthExceeded = this._isMinFilterLengthExceeded();
  22323. return isMinFilterLengthExceeded && resultAmount && this.element().hasClass("dx-state-focused")
  22324. },
  22325. _clearSearchTimer: function() {
  22326. clearTimeout(this._searchTimer);
  22327. delete this._searchTimer
  22328. },
  22329. _popupShowingHandler: function() {
  22330. this._dimensionChanged()
  22331. },
  22332. _dimensionChanged: function() {
  22333. this._popup && this._updatePopupDimensions()
  22334. },
  22335. _updatePopupDimensions: function() {
  22336. this._updatePopupWidth();
  22337. this._updatePopupHeight()
  22338. },
  22339. _updatePopupWidth: function() {
  22340. this._setPopupOption("width", this.element().outerWidth() + this.option("popupWidthExtension"))
  22341. },
  22342. _updatePopupHeight: function() {
  22343. var popupPadding = this._popup.overlayContent().outerHeight() - this._popup.content().height();
  22344. var listMargin = this._list ? this._list.element().outerHeight() - this._list.clientHeight() : 0;
  22345. var listHeight = this._list ? this._list.scrollHeight() + listMargin : 0;
  22346. var popupHeight = Math.min(listHeight + popupPadding, this._getMaxHeight());
  22347. this._setPopupOption("height", popupHeight);
  22348. this._list && this._list.updateDimensions()
  22349. },
  22350. _getMaxHeight: function() {
  22351. var $element = this.element(),
  22352. offset = $element.offset(),
  22353. windowHeight = $(window).height(),
  22354. maxHeight = Math.max(offset.top, windowHeight - offset.top - $element.outerHeight());
  22355. return Math.min(windowHeight * 0.5, maxHeight)
  22356. },
  22357. _changeSelectedItem: function($selectedItem, $newItem) {
  22358. var selectedItemClass = this._selectedItemClass();
  22359. $selectedItem.removeClass(selectedItemClass);
  22360. $newItem.addClass(selectedItemClass)
  22361. },
  22362. _selectedItemValue: function() {
  22363. var $selectedItem = this._listSelectedItemElements();
  22364. return this._valueGetter($selectedItem.data(LIST_ITEM_DATA_KEY))
  22365. },
  22366. _valueChangeArgs: function() {
  22367. return $.extend(this.callBase.apply(this, arguments), {
  22368. selectedItem: this.option("selectedItem"),
  22369. itemData: this.option("selectedItem")
  22370. })
  22371. },
  22372. _clean: function() {
  22373. if (this._list)
  22374. delete this._list;
  22375. this.callBase()
  22376. },
  22377. _dispose: function() {
  22378. this._clearSearchTimer();
  22379. this.callBase()
  22380. },
  22381. _setCollectionWidgetOption: function() {
  22382. this._setListOption.apply(this, arguments)
  22383. },
  22384. _optionChanged: function(args) {
  22385. this._dataExpressionOptionChanged(args);
  22386. switch (args.name) {
  22387. case"items":
  22388. if (!this.option("dataSource"))
  22389. this._processDataSourceChanging();
  22390. break;
  22391. case"dataSource":
  22392. this._processDataSourceChanging();
  22393. break;
  22394. case"valueExpr":
  22395. case"displayExpr":
  22396. this._renderValue();
  22397. break;
  22398. case"searchMode":
  22399. this._validateSearchMode();
  22400. break;
  22401. case"minSearchLength":
  22402. this._refreshList();
  22403. break;
  22404. case"searchEnabled":
  22405. case"searchExpr":
  22406. case"pagingEnabled":
  22407. this._invalidate();
  22408. break;
  22409. case"onContentReady":
  22410. this._initContentReadyAction();
  22411. break;
  22412. case"onSelectionChanged":
  22413. this._initSelectionChangedAction();
  22414. break;
  22415. case"onItemClick":
  22416. this._initItemClickAction();
  22417. break;
  22418. case"noDataText":
  22419. this._setListOption("noDataText");
  22420. break;
  22421. case"displayValue":
  22422. this.option("text", args.value);
  22423. break;
  22424. case"itemTemplate":
  22425. case"searchTimeout":
  22426. case"popupWidthExtension":
  22427. break;
  22428. case"selectedItem":
  22429. this._selectionChangedAction({selectedItem: args.value});
  22430. break;
  22431. default:
  22432. this.callBase(args)
  22433. }
  22434. }
  22435. }).include(ui.DataExpressionMixin))
  22436. })(jQuery, DevExpress);
  22437. /*! Module widgets-base, file ui.textArea.js */
  22438. (function($, DX, undefined) {
  22439. var ui = DX.ui,
  22440. events = ui.events;
  22441. var TEXTAREA_CLASS = "dx-textarea",
  22442. TEXTEDITOR_INPUT_CLASS = "dx-texteditor-input";
  22443. DX.registerComponent("dxTextArea", ui, ui.dxTextBox.inherit({
  22444. _setDefaultOptions: function() {
  22445. this.callBase();
  22446. this.option({spellcheck: true})
  22447. },
  22448. _render: function() {
  22449. this.callBase();
  22450. this.element().addClass(TEXTAREA_CLASS);
  22451. this.setAria("multiline", "true")
  22452. },
  22453. _renderInput: function() {
  22454. this.callBase();
  22455. this._renderScrollHandler()
  22456. },
  22457. _createInput: function() {
  22458. return $("<textarea>").addClass(TEXTEDITOR_INPUT_CLASS)
  22459. },
  22460. _renderScrollHandler: function() {
  22461. var $input = this._input(),
  22462. eventY = 0;
  22463. $input.on(events.addNamespace("dxpointerdown", this.NAME), function(e) {
  22464. eventY = events.eventData(e).y
  22465. });
  22466. $input.on(events.addNamespace("dxpointermove", this.NAME), function(e) {
  22467. var scrollTopPos = $input.scrollTop(),
  22468. scrollBottomPos = $input.prop("scrollHeight") - $input.prop("clientHeight") - scrollTopPos;
  22469. if (scrollTopPos === 0 && scrollBottomPos === 0)
  22470. return;
  22471. var currentEventY = events.eventData(e).y;
  22472. var isScrollFromTop = scrollTopPos === 0 && eventY >= currentEventY,
  22473. isScrollFromBottom = scrollBottomPos === 0 && eventY <= currentEventY,
  22474. isScrollFromMiddle = scrollTopPos > 0 && scrollBottomPos > 0;
  22475. if (isScrollFromTop || isScrollFromBottom || isScrollFromMiddle)
  22476. e.isScrollingEvent = true;
  22477. eventY = currentEventY
  22478. })
  22479. },
  22480. _renderInputType: $.noop
  22481. }))
  22482. })(jQuery, DevExpress);
  22483. /*! Module widgets-base, file ui.numberBox.js */
  22484. (function($, DX, undefined) {
  22485. var ui = DX.ui,
  22486. math = Math,
  22487. events = ui.events,
  22488. WIDGET_CLASS = "dx-numberbox",
  22489. SPIN_CLASS = "dx-numberbox-spin",
  22490. SPIN_CONTAINER_CLASS = "dx-numberbox-spin-container",
  22491. SPIN_UP_CLASS = "dx-numberbox-spin-up",
  22492. SPIN_DOWN_CLASS = "dx-numberbox-spin-down",
  22493. SPIN_BUTTON_CLASS = "dx-numberbox-spin-button",
  22494. SPIN_BUTTON_SELECTOR = ".dx-numberbox-spin-button",
  22495. SPIN_TOUCH_FRIENDLY_CLASS = "dx-numberbox-spin-touch-friendly",
  22496. SPIN_HOLD_DELAY = 100,
  22497. CONTROL_KEYS = ["Tab", "Del", "Delete", "Backspace", "Left", "ArrowLeft", "Right", "ArrowRight", "Home", "End"],
  22498. NUMBER_BOX = 'dxNumberBox',
  22499. MOUSEWHEEL_EVENT_NAME = events.addNamespace("dxmousewheel", NUMBER_BOX),
  22500. POINTERDOWN_EVENT_NAME = events.addNamespace("dxpointerdown", NUMBER_BOX),
  22501. POINTERUP_EVENT_NAME = events.addNamespace("dxpointerup", NUMBER_BOX),
  22502. POINTERCANCEL_EVENT_NAME = events.addNamespace("dxpointercancel", NUMBER_BOX);
  22503. var androidNativeBrowser = DX.devices.real().android && navigator.userAgent.indexOf("Chrome") === -1;
  22504. var dxSpinButton = ui.Widget.inherit({
  22505. _setDefaultOptions: function() {
  22506. this.callBase();
  22507. this.option({
  22508. direction: "up",
  22509. onChange: null,
  22510. activeStateEnabled: true,
  22511. hoverStateEnabled: false
  22512. })
  22513. },
  22514. _render: function() {
  22515. this.callBase();
  22516. var $element = this.element(),
  22517. direction = SPIN_CLASS + "-" + this.option("direction");
  22518. $element.addClass(SPIN_BUTTON_CLASS).addClass(direction).off(POINTERDOWN_EVENT_NAME).on(POINTERDOWN_EVENT_NAME, $.proxy(this._spinDownHandler, this));
  22519. this._spinIcon = $("<div>").addClass(direction + "-icon").appendTo(this.element());
  22520. this._spinChangeHandler = this._createActionByOption("onChange")
  22521. },
  22522. _spinDownHandler: function(e) {
  22523. e.preventDefault();
  22524. this._clearTimer();
  22525. $(document).on("dxhold", $.proxy(function() {
  22526. this._feedBackDeferred = $.Deferred();
  22527. ui.events.lockFeedback(this._feedBackDeferred);
  22528. this._spinChangeHandler({jQueryEvent: e});
  22529. this._holdTimer = setInterval(this._spinChangeHandler, SPIN_HOLD_DELAY, {jQueryEvent: e})
  22530. }, this)).on(POINTERUP_EVENT_NAME, $.proxy(this._clearTimer, this)).on(POINTERCANCEL_EVENT_NAME, $.proxy(this._clearTimer, this));
  22531. this._spinChangeHandler({jQueryEvent: e})
  22532. },
  22533. _dispose: function() {
  22534. this._clearTimer();
  22535. this.callBase()
  22536. },
  22537. _clearTimer: function(e) {
  22538. $(document).off(POINTERUP_EVENT_NAME).off(POINTERCANCEL_EVENT_NAME).off("dxhold");
  22539. if (this._feedBackDeferred)
  22540. this._feedBackDeferred.resolve();
  22541. if (this._holdTimer)
  22542. clearInterval(this._holdTimer)
  22543. },
  22544. _optionChanged: function(args) {
  22545. switch (args.name) {
  22546. case"onChange":
  22547. case"direction":
  22548. this._invalidate();
  22549. break;
  22550. default:
  22551. this.callBase(args)
  22552. }
  22553. }
  22554. });
  22555. DX.registerComponent("dxNumberBox", ui, ui.dxTextEditor.inherit({
  22556. _activeStateUnit: SPIN_BUTTON_SELECTOR,
  22557. _supportedKeys: function() {
  22558. return $.extend(this.callBase(), {
  22559. upArrow: function(e) {
  22560. e.preventDefault();
  22561. e.stopPropagation();
  22562. this._spinUpChangeHandler()
  22563. },
  22564. downArrow: function(e) {
  22565. e.preventDefault();
  22566. e.stopPropagation();
  22567. this._spinDownChangeHandler()
  22568. },
  22569. enter: function(e) {
  22570. this._input().trigger(this.option("valueChangeEvent"))
  22571. }
  22572. })
  22573. },
  22574. _setDefaultOptions: function() {
  22575. this.callBase();
  22576. this.option({
  22577. value: 0,
  22578. min: undefined,
  22579. max: undefined,
  22580. step: 1,
  22581. showSpinButtons: false,
  22582. useTouchSpinButtons: true,
  22583. mode: "number"
  22584. })
  22585. },
  22586. _defaultOptionsRules: function() {
  22587. return this.callBase().concat([{
  22588. device: function(device) {
  22589. return DX.devices.real().generic && !DX.devices.isSimulator()
  22590. },
  22591. options: {useTouchSpinButtons: false}
  22592. }])
  22593. },
  22594. _render: function() {
  22595. this.callBase();
  22596. this.element().addClass(WIDGET_CLASS);
  22597. this.setAria("role", "spinbutton");
  22598. this._keyPressHandlerEvent();
  22599. this._renderMouseWheelHandler()
  22600. },
  22601. _keyPressHandlerEvent: function() {
  22602. var that = this;
  22603. this._input().keypress(function(e) {
  22604. var ch = String.fromCharCode(e.which),
  22605. validCharRegExp = /[\d.,eE\-+]/,
  22606. isInputCharValid = validCharRegExp.test(ch);
  22607. if (!isInputCharValid) {
  22608. if (e.metaKey || e.ctrlKey || e.key && $.inArray(e.key, CONTROL_KEYS) >= 0)
  22609. return;
  22610. e.preventDefault();
  22611. return false
  22612. }
  22613. that._isIncompleteValue = false;
  22614. if (that._isValueIncomplete(that._input().val() + ch))
  22615. that._isIncompleteValue = true
  22616. })
  22617. },
  22618. _isValueIncomplete: function(value) {
  22619. var expRegex = /\d+[eE]$/,
  22620. dotRegex = /^[\.,]$/,
  22621. negRegex = /^-$/;
  22622. return expRegex.test(value) || dotRegex.test(value) || negRegex.test(value)
  22623. },
  22624. _renderMouseWheelHandler: function(e) {
  22625. var mouseWheelAction = this._createAction($.proxy(function(e) {
  22626. this._mouseWheelHandler(e.jQueryEvent)
  22627. }, this));
  22628. this._input().off(MOUSEWHEEL_EVENT_NAME).on(MOUSEWHEEL_EVENT_NAME, function(e) {
  22629. mouseWheelAction({jQueryEvent: e})
  22630. })
  22631. },
  22632. _mouseWheelHandler: function(e) {
  22633. if (!this._input().is(":focus"))
  22634. return;
  22635. e.delta > 0 ? this._spinValueChange(1) : this._spinValueChange(-1);
  22636. e.preventDefault();
  22637. e.stopPropagation()
  22638. },
  22639. _renderValue: function() {
  22640. if (!this._input().val().length || Number(this._input().val()) !== this.option("value")) {
  22641. this._forceValueRender();
  22642. this._toggleEmptinessEventHandler()
  22643. }
  22644. this._renderInputAddons();
  22645. this.setAria("valuenow", this.option("value"))
  22646. },
  22647. _forceValueRender: function() {
  22648. var $input = this._input(),
  22649. value = this.option("value"),
  22650. valueFormat = this.option("valueFormat");
  22651. if (androidNativeBrowser) {
  22652. var inputType = $input.attr("type");
  22653. this._setInputType("text");
  22654. $input.val(valueFormat(value));
  22655. this._setInputType(inputType)
  22656. }
  22657. else
  22658. $input.val(valueFormat(value))
  22659. },
  22660. _getAriaTarget: function() {
  22661. return this._input()
  22662. },
  22663. _renderProps: function() {
  22664. this.callBase();
  22665. this._input().prop({
  22666. min: this.option("min"),
  22667. max: this.option("max"),
  22668. step: this.option("step")
  22669. });
  22670. this.setAria({
  22671. valuemin: this.option("min") || "undefined",
  22672. valuemax: this.option("max") || "undefined"
  22673. })
  22674. },
  22675. _renderInputAddons: function() {
  22676. this.callBase();
  22677. this._renderSpinButtons()
  22678. },
  22679. _renderSpinButtons: function() {
  22680. var spinButtonsVisible = this.option("showSpinButtons");
  22681. this.element().toggleClass(SPIN_CLASS, spinButtonsVisible);
  22682. this._toggleTouchFriendlyClass();
  22683. if (!spinButtonsVisible) {
  22684. this._$spinContainer && this._$spinContainer.remove();
  22685. this._$spinContainer = null;
  22686. return
  22687. }
  22688. if (!this._$spinContainer)
  22689. this._$spinContainer = this._createSpinButtons();
  22690. this._$spinContainer.prependTo(this._buttonsContainer())
  22691. },
  22692. _toggleTouchFriendlyClass: function() {
  22693. this.element().toggleClass(SPIN_TOUCH_FRIENDLY_CLASS, this.option("showSpinButtons") && this.option("useTouchSpinButtons"))
  22694. },
  22695. _createSpinButtons: function() {
  22696. var pointerDownAction = this._createAction($.proxy(this._spinButtonsPointerDownHandler, this));
  22697. var $spinContainer = $("<div>").addClass(SPIN_CONTAINER_CLASS).off(POINTERDOWN_EVENT_NAME).on(POINTERDOWN_EVENT_NAME, function(e) {
  22698. pointerDownAction({jQueryEvent: e})
  22699. });
  22700. this._$spinUp = $("<div>").appendTo($spinContainer);
  22701. this._createComponent(this._$spinUp, "dxSpinButton", {
  22702. direction: "up",
  22703. onChange: $.proxy(this._spinUpChangeHandler, this)
  22704. });
  22705. this._$spinDown = $("<div>").appendTo($spinContainer);
  22706. this._createComponent(this._$spinDown, "dxSpinButton", {
  22707. direction: "down",
  22708. onChange: $.proxy(this._spinDownChangeHandler, this)
  22709. });
  22710. return $spinContainer
  22711. },
  22712. _spinButtonsPointerDownHandler: function(e) {
  22713. e.dxPreventBlur = true;
  22714. var $input = this._input();
  22715. if (!this.option("useTouchSpinButtons") && document.activeElement !== $input[0])
  22716. $input.trigger("focus")
  22717. },
  22718. _spinUpChangeHandler: function() {
  22719. if (!this.option("readOnly"))
  22720. this._spinValueChange(1)
  22721. },
  22722. _spinDownChangeHandler: function() {
  22723. if (!this.option("readOnly"))
  22724. this._spinValueChange(-1)
  22725. },
  22726. _spinValueChange: function(sign) {
  22727. var value = parseFloat(this._validationRequired() ? this._oldValue : this._normalizeInputValue()) || 0,
  22728. step = parseFloat(this.option("step"));
  22729. value = this._correctRounding(value, step * sign);
  22730. this.option("value", value)
  22731. },
  22732. _correctRounding: function(value, step) {
  22733. var regex = /[,|.](.*)/;
  22734. var isFloatValue = regex.test(value),
  22735. isFloatStep = regex.test(step);
  22736. if (isFloatValue || isFloatStep) {
  22737. var valueAccuracy = isFloatValue ? regex.exec(value)[0].length : 0,
  22738. stepAccuracy = isFloatStep ? regex.exec(step)[0].length : 0,
  22739. accuracy = math.max(valueAccuracy, stepAccuracy);
  22740. value = this._round(value + step, accuracy);
  22741. return value
  22742. }
  22743. return value + step
  22744. },
  22745. _round: function(value, precision) {
  22746. precision = precision || 0;
  22747. var multiplier = Math.pow(10, precision);
  22748. value *= multiplier;
  22749. value = Math.round(value) / multiplier;
  22750. return value
  22751. },
  22752. _renderValueChangeEvent: function() {
  22753. this.callBase();
  22754. this._input().focusout($.proxy(this._forceRefreshInputValue, this))
  22755. },
  22756. _forceRefreshInputValue: function() {
  22757. var $input = this._input(),
  22758. valueFormat = this.option("valueFormat");
  22759. $input.val(null);
  22760. $input.val(valueFormat(this.option("value")))
  22761. },
  22762. _valueChangeEventHandler: function(e) {
  22763. if (this._validationRequired()) {
  22764. this._inputInvalidHandler();
  22765. return
  22766. }
  22767. var $input = this._input(),
  22768. value = this._normalizeInputValue(),
  22769. valueFormat = this.option("valueFormat");
  22770. if (this._isIncompleteValue)
  22771. return;
  22772. if (Number($input.val()) !== value)
  22773. $input.val(valueFormat(this.option("value")), valueFormat(value));
  22774. this.callBase(e, value)
  22775. },
  22776. _validationRequired: function() {
  22777. return !this._isIncompleteValue && !this._validateValue(this._normalizeText())
  22778. },
  22779. _validateValue: function(value) {
  22780. var isValueValid = this._isValueValid();
  22781. if (!value && isValueValid) {
  22782. this.option("value", null);
  22783. return true
  22784. }
  22785. var isNumber = /^-?\d*\.?\d*$/.test(value),
  22786. isExponent = /^-?\d+e[-+]?\d+$/.test(value);
  22787. this._oldValue = this.option("value");
  22788. if (!isNumber && !isExponent && !isValueValid)
  22789. return false;
  22790. return true
  22791. },
  22792. _inputInvalidHandler: function() {
  22793. var $input = this._input(),
  22794. isValueDefined = DX.utils.isDefined(this._oldValue);
  22795. this.option("value", isValueDefined ? this._oldValue : null);
  22796. isValueDefined && $input.val(this._oldValue);
  22797. this._oldValue = null
  22798. },
  22799. _normalizeInputValue: function() {
  22800. var value = this._normalizeValue();
  22801. return DX.utils.isDefined(value) ? value : this.option("value")
  22802. },
  22803. _normalizeValue: function(value) {
  22804. return this._parseValue(this._normalizeText(value))
  22805. },
  22806. _normalizeText: function(value) {
  22807. value = $.trim(DX.utils.isDefined(value) ? value : this._input().val());
  22808. return value.replace(",", ".")
  22809. },
  22810. _parseValue: function(value) {
  22811. var number = parseFloat(value);
  22812. if (this.option("min") !== undefined)
  22813. number = math.max(number, this.option("min"));
  22814. if (this.option("max") !== undefined)
  22815. number = math.min(number, this.option("max"));
  22816. return number
  22817. },
  22818. _setValue: function(value, prevValue) {
  22819. if (value == null || value === "") {
  22820. this.option("value", null);
  22821. if (value !== null)
  22822. this._suppressValueChangeAction();
  22823. return
  22824. }
  22825. var newValue = this._normalizeValue(value);
  22826. if (!newValue && newValue !== 0) {
  22827. this.option("value", prevValue);
  22828. this._suppressValueChangeAction();
  22829. return
  22830. }
  22831. if (value !== newValue) {
  22832. this.option("value", newValue);
  22833. this._suppressValueChangeAction()
  22834. }
  22835. },
  22836. _clean: function() {
  22837. delete this._$spinContainer;
  22838. delete this._$spinUp;
  22839. delete this._$spinDown;
  22840. this.callBase()
  22841. },
  22842. _optionChanged: function(args) {
  22843. switch (args.name) {
  22844. case"value":
  22845. this._setValue(args.value, args.previousValue);
  22846. this.callBase(args);
  22847. this._resumeValueChangeAction();
  22848. break;
  22849. case"step":
  22850. case"min":
  22851. case"max":
  22852. this._renderProps();
  22853. break;
  22854. case"showSpinButtons":
  22855. this._renderInputAddons();
  22856. break;
  22857. case"useTouchSpinButtons":
  22858. this._toggleTouchFriendlyClass();
  22859. break;
  22860. default:
  22861. this.callBase(args)
  22862. }
  22863. }
  22864. }));
  22865. DX.registerComponent("dxSpinButton", ui.dxNumberBox, dxSpinButton);
  22866. ui.dxNumberBox.__internals = {
  22867. WIDGET_CLASS: WIDGET_CLASS,
  22868. SPIN_CLASS: SPIN_CLASS,
  22869. SPIN_CONTAINER_CLASS: SPIN_CONTAINER_CLASS,
  22870. SPIN_UP_CLASS: SPIN_UP_CLASS,
  22871. SPIN_DOWN_CLASS: SPIN_DOWN_CLASS
  22872. }
  22873. })(jQuery, DevExpress);
  22874. /*! Module widgets-base, file ui.radioButton.js */
  22875. (function($, DX, undefined) {
  22876. var ui = DX.ui,
  22877. events = ui.events;
  22878. var RADIO_BUTTON = "dxRadioButton",
  22879. RADIO_BUTTON_CLASS = "dx-radiobutton",
  22880. RADIO_BUTTON_ICON_CLASS = "dx-radiobutton-icon",
  22881. RADIO_BUTTON_ICON_DOT_CLASS = "dx-radiobutton-icon-dot",
  22882. RADIO_BUTTON_CHECKED_CLASS = "dx-radiobutton-checked",
  22883. RADIO_BUTTON_DXCLICK_EVENT_NAME = events.addNamespace("dxclick", RADIO_BUTTON);
  22884. DX.registerComponent(RADIO_BUTTON, ui, ui.Editor.inherit({
  22885. _supportedKeys: function() {
  22886. var click = function(e) {
  22887. e.preventDefault();
  22888. this._clickAction({jQueryEvent: e})
  22889. };
  22890. return $.extend(this.callBase(), {space: click})
  22891. },
  22892. _setDefaultOptions: function() {
  22893. this.callBase();
  22894. this.option({value: false})
  22895. },
  22896. _defaultOptionsRules: function() {
  22897. return this.callBase().concat([{
  22898. device: function(device) {
  22899. return DX.devices.real().generic && !DX.devices.isSimulator()
  22900. },
  22901. options: {
  22902. focusStateEnabled: true,
  22903. hoverStateEnabled: true
  22904. }
  22905. }])
  22906. },
  22907. _init: function() {
  22908. this.callBase();
  22909. this.element().addClass(RADIO_BUTTON_CLASS)
  22910. },
  22911. _render: function() {
  22912. this.callBase();
  22913. this._renderIcon();
  22914. this._renderCheckedState(this.option("value"));
  22915. this._renderClick();
  22916. this.setAria("role", "radio")
  22917. },
  22918. _renderIcon: function() {
  22919. var $icon = $("<div>").addClass(RADIO_BUTTON_ICON_CLASS);
  22920. $("<div>").addClass(RADIO_BUTTON_ICON_DOT_CLASS).appendTo($icon);
  22921. this.element().append($icon)
  22922. },
  22923. _renderCheckedState: function(checked) {
  22924. this.element().toggleClass(RADIO_BUTTON_CHECKED_CLASS, checked);
  22925. this.setAria("checked", checked)
  22926. },
  22927. _renderClick: function() {
  22928. this._clickAction = this._createAction($.proxy(function(args) {
  22929. this._clickHandler(args.jQueryEvent)
  22930. }, this));
  22931. this.element().off(RADIO_BUTTON_DXCLICK_EVENT_NAME).on(RADIO_BUTTON_DXCLICK_EVENT_NAME, $.proxy(function(e) {
  22932. this._clickAction({jQueryEvent: e})
  22933. }, this))
  22934. },
  22935. _clickHandler: function(e) {
  22936. this._saveValueChangeEvent(e);
  22937. this.option("value", true)
  22938. },
  22939. _optionChanged: function(args) {
  22940. switch (args.name) {
  22941. case"value":
  22942. this._renderCheckedState(args.value);
  22943. this.callBase(args);
  22944. break;
  22945. default:
  22946. this.callBase(args)
  22947. }
  22948. }
  22949. }))
  22950. })(jQuery, DevExpress);
  22951. /*! Module widgets-base, file ui.radioGroup.js */
  22952. (function($, DX, undefined) {
  22953. var ui = DX.ui;
  22954. var RADIO_GROUP_CLASS = "dx-radiogroup",
  22955. RADIO_GROUP_VERTICAL_CLASS = "dx-radiogroup-vertical",
  22956. RADIO_GROUP_HORIZONTAL_CLASS = "dx-radiogroup-horizontal",
  22957. RADIO_BUTTON_CLASS = "dx-radiobutton",
  22958. RADIO_BUTTON_ICON_CLASS = "dx-radiobutton-icon",
  22959. RADIO_BUTTON_ICON_DOT_CLASS = "dx-radiobutton-icon-dot",
  22960. RADIO_VALUE_CONTAINER_CLASS = "dx-radio-value-container",
  22961. RADIO_BUTTON_CHECKED_CLASS = "dx-radiobutton-checked",
  22962. ITEM_DATA_KEY = "dxItemData",
  22963. RADIO_FEEDBACK_HIDE_TIMEOUT = 100;
  22964. var dxRadioCollection = ui.CollectionWidget.inherit({
  22965. _setDefaultOptions: function() {
  22966. this.callBase();
  22967. this.option($.extend(this._dataExpressionDefaultOptions(), {_itemAttributes: {role: "radio"}}))
  22968. },
  22969. _getAriaTarget: function() {
  22970. return this._focusTarget()
  22971. },
  22972. _focusTarget: function() {
  22973. return this.element().parent()
  22974. },
  22975. _keyboardEventBindingTarget: function() {
  22976. return this._focusTarget()
  22977. }
  22978. });
  22979. DX.registerComponent("dxRadioGroup", ui, ui.Editor.inherit({
  22980. _activeStateUnit: "." + RADIO_BUTTON_CLASS,
  22981. _setDeprecatedOptions: function() {
  22982. this.callBase();
  22983. $.extend(this._deprecatedOptions, this._dataExpressionDeprecatedOptions())
  22984. },
  22985. _setDefaultOptions: function() {
  22986. this.callBase();
  22987. this.option($.extend(this._dataExpressionDefaultOptions(), {layout: "vertical"}))
  22988. },
  22989. _defaultOptionsRules: function() {
  22990. return this.callBase().concat([{
  22991. device: {tablet: true},
  22992. options: {layout: "horizontal"}
  22993. }, {
  22994. device: function(device) {
  22995. return DX.devices.real().generic && !DX.devices.isSimulator()
  22996. },
  22997. options: {
  22998. focusStateEnabled: true,
  22999. hoverStateEnabled: true
  23000. }
  23001. }])
  23002. },
  23003. _setOptionsByReference: function() {
  23004. this.callBase();
  23005. $.extend(this._optionsByReference, {value: true})
  23006. },
  23007. _dataSourceOptions: function() {
  23008. return {paginate: false}
  23009. },
  23010. _init: function() {
  23011. this.callBase();
  23012. this._initDataExpressions();
  23013. this._feedbackHideTimeout = RADIO_FEEDBACK_HIDE_TIMEOUT
  23014. },
  23015. _render: function() {
  23016. this.element().addClass(RADIO_GROUP_CLASS);
  23017. this._renderRadios();
  23018. this.setAria("role", "radiogroup");
  23019. this.callBase();
  23020. this._renderLayout();
  23021. this._updateItemsSize()
  23022. },
  23023. _renderFocusState: $.noop,
  23024. _renderRadios: function() {
  23025. var $radios = $("<div>").appendTo(this.element());
  23026. this._radios = this._createComponent($radios, "dxRadioCollection", {
  23027. dataSource: this._dataSource,
  23028. onItemRendered: $.proxy(this._itemRenderedHandler, this),
  23029. onItemClick: $.proxy(this._itemClickHandler, this),
  23030. itemTemplate: this._getTemplateByOption("itemTemplate"),
  23031. scrollingEnabled: false,
  23032. focusStateEnabled: this.option("focusStateEnabled"),
  23033. accessKey: this.option("accessKey"),
  23034. tabIndex: this.option("tabIndex"),
  23035. noDataText: "",
  23036. disabled: this.option("disabled")
  23037. });
  23038. this._setCollectionWidgetOption("onContentReady", $.proxy(this._contentReadyHandler, this));
  23039. this._contentReadyHandler()
  23040. },
  23041. _contentReadyHandler: function() {
  23042. this.itemElements().addClass(RADIO_BUTTON_CLASS);
  23043. this._refreshSelected()
  23044. },
  23045. _itemRenderedHandler: function(e) {
  23046. if (e.itemData.html)
  23047. return;
  23048. var $radio,
  23049. $radioContainer;
  23050. $radio = $("<div>").addClass(RADIO_BUTTON_ICON_CLASS);
  23051. $("<div>").addClass(RADIO_BUTTON_ICON_DOT_CLASS).appendTo($radio);
  23052. $radioContainer = $("<div>").append($radio).addClass(RADIO_VALUE_CONTAINER_CLASS);
  23053. e.itemElement.prepend($radioContainer)
  23054. },
  23055. _itemClickHandler: function(e) {
  23056. this.option("value", this._getItemValue(e.itemData))
  23057. },
  23058. _getItemValue: function(item) {
  23059. return !!this._valueGetter ? this._valueGetter(item) : item.text
  23060. },
  23061. itemElements: function() {
  23062. return this._radios.itemElements()
  23063. },
  23064. _renderDimensions: function() {
  23065. this.callBase();
  23066. this._updateItemsSize()
  23067. },
  23068. _renderLayout: function() {
  23069. var layout = this.option("layout");
  23070. this.element().toggleClass(RADIO_GROUP_VERTICAL_CLASS, layout === "vertical");
  23071. this.element().toggleClass(RADIO_GROUP_HORIZONTAL_CLASS, layout === "horizontal")
  23072. },
  23073. _refreshSelected: function() {
  23074. var selectedValue = this.option("value");
  23075. this.itemElements().each($.proxy(function(_, item) {
  23076. var $item = $(item);
  23077. var itemValue = this._valueGetter($item.data(ITEM_DATA_KEY));
  23078. $item.toggleClass(RADIO_BUTTON_CHECKED_CLASS, this._isValueEquals(itemValue, selectedValue));
  23079. this.setAria("checked", this._isValueEquals(itemValue, selectedValue), $item)
  23080. }, this))
  23081. },
  23082. _updateItemsSize: function() {
  23083. if (this.option("layout") === "horizontal")
  23084. this.itemElements().css("height", "auto");
  23085. else {
  23086. var itemsCount = this.option("items").length;
  23087. this.itemElements().css("height", 100 / itemsCount + "%")
  23088. }
  23089. },
  23090. _setCollectionWidgetOption: function() {
  23091. this._setWidgetOption("_radios", arguments)
  23092. },
  23093. _optionChanged: function(args) {
  23094. this._dataExpressionOptionChanged(args);
  23095. switch (args.name) {
  23096. case"focusStateEnabled":
  23097. case"accessKey":
  23098. case"tabIndex":
  23099. this._setCollectionWidgetOption(args.name, args.value);
  23100. break;
  23101. case"disabled":
  23102. this.callBase(args);
  23103. this._setCollectionWidgetOption(args.name, args.value);
  23104. break;
  23105. case"dataSource":
  23106. this._setCollectionWidgetOption("dataSource");
  23107. break;
  23108. case"valueExpr":
  23109. this._refreshSelected();
  23110. break;
  23111. case"value":
  23112. this._refreshSelected();
  23113. this.callBase(args);
  23114. break;
  23115. case"items":
  23116. case"itemTemplate":
  23117. case"displayExpr":
  23118. break;
  23119. case"layout":
  23120. this._renderLayout();
  23121. this._updateItemsSize();
  23122. break;
  23123. default:
  23124. this.callBase(args)
  23125. }
  23126. }
  23127. }).include(ui.DataExpressionMixin));
  23128. DX.registerComponent("dxRadioCollection", ui.dxRadioGroup, dxRadioCollection)
  23129. })(jQuery, DevExpress);
  23130. /*! Module widgets-base, file ui.tabs.js */
  23131. (function($, DX, undefined) {
  23132. var ui = DX.ui,
  23133. events = ui.events,
  23134. TABS_CLASS = "dx-tabs",
  23135. TABS_WRAPPER_CLASS = "dx-indent-wrapper",
  23136. TABS_EXPANDED_CLASS = "dx-tabs-expanded",
  23137. TABS_SCROLLABLE_CLASS = "dx-scrollable-wrapper",
  23138. TABS_NAV_BUTTONS_CLASS = "dx-tabs-nav-buttons",
  23139. TABS_ITEM_CLASS = "dx-tab",
  23140. TABS_ITEM_SELECTOR = ".dx-tab",
  23141. TABS_ITEM_SELECTED_CLASS = "dx-tab-selected",
  23142. TABS_NAV_BUTTON_CLASS = "dx-tabs-nav-button",
  23143. TABS_LEFT_NAV_BUTTON_CLASS = "dx-tabs-nav-button-left",
  23144. TABS_RIGHT_NAV_BUTTON_CLASS = "dx-tabs-nav-button-right",
  23145. TABS_ITEM_DATA_KEY = "dxTabData",
  23146. FEEDBACK_HIDE_TIMEOUT = 100,
  23147. FEEDBACK_DURATION_INTERVAL = 5,
  23148. FEEDBACK_SCROLL_TIMEOUT = 300,
  23149. ACTIVE_STATE_CLASS = "dx-state-active",
  23150. TAB_OFFSET = 30;
  23151. DX.registerComponent("dxTabs", ui, ui.CollectionWidget.inherit({
  23152. _activeStateUnit: TABS_ITEM_SELECTOR,
  23153. _setDefaultOptions: function() {
  23154. this.callBase();
  23155. this.option({
  23156. showNavButtons: false,
  23157. scrollByContent: true,
  23158. scrollingEnabled: true,
  23159. wordWrap: false,
  23160. selectionMode: "single",
  23161. activeStateEnabled: true,
  23162. selectionRequired: false,
  23163. selectOnFocus: true,
  23164. loopItemFocus: false
  23165. })
  23166. },
  23167. _defaultOptionsRules: function() {
  23168. return this.callBase().concat([{
  23169. device: {platform: "win8"},
  23170. options: {wordWrap: true}
  23171. }, {
  23172. device: {platform: "generic"},
  23173. options: {
  23174. showNavButtons: true,
  23175. scrollByContent: false
  23176. }
  23177. }, {
  23178. device: function(device) {
  23179. return DX.devices.real().generic && !DX.devices.isSimulator()
  23180. },
  23181. options: {
  23182. hoverStateEnabled: true,
  23183. focusStateEnabled: true
  23184. }
  23185. }])
  23186. },
  23187. _init: function() {
  23188. this.callBase();
  23189. this._renderMultiple();
  23190. this.element().addClass(TABS_CLASS);
  23191. this._feedbackHideTimeout = FEEDBACK_HIDE_TIMEOUT
  23192. },
  23193. _itemClass: function() {
  23194. return TABS_ITEM_CLASS
  23195. },
  23196. _selectedItemClass: function() {
  23197. return TABS_ITEM_SELECTED_CLASS
  23198. },
  23199. _itemDataKey: function() {
  23200. return TABS_ITEM_DATA_KEY
  23201. },
  23202. _render: function() {
  23203. this.element().removeClass(TABS_EXPANDED_CLASS);
  23204. this.callBase();
  23205. this._renderWrapper();
  23206. if (this._allowScrolling()) {
  23207. this._renderScrollable();
  23208. this._renderNavButtons();
  23209. this._updateNavButtons()
  23210. }
  23211. else {
  23212. this.element().removeClass(TABS_NAV_BUTTONS_CLASS);
  23213. this.element().addClass(TABS_EXPANDED_CLASS)
  23214. }
  23215. this.setAria("role", "tablist");
  23216. var that = this;
  23217. this.itemElements().each(function(_, item) {
  23218. that.setAria("role", "tab", $(item))
  23219. });
  23220. this.element().addClass(ACTIVE_STATE_CLASS).removeClass(ACTIVE_STATE_CLASS)
  23221. },
  23222. _renderMultiple: function() {
  23223. if (this.option("selectionMode") === "multi")
  23224. this.option("selectOnFocus", false)
  23225. },
  23226. _renderWrapper: function() {
  23227. this.element().wrapInner($("<div>").addClass(TABS_WRAPPER_CLASS))
  23228. },
  23229. _renderScrollable: function() {
  23230. var $itemContainer = this.element().wrapInner($("<div>").addClass(TABS_SCROLLABLE_CLASS)).children();
  23231. this._scrollable = this._createComponent($itemContainer, "dxScrollable", {
  23232. direction: "horizontal",
  23233. showScrollbar: false,
  23234. useKeyboard: false,
  23235. useNative: false,
  23236. scrollByContent: this.option("scrollByContent"),
  23237. onScroll: $.proxy(this._updateNavButtonsVisibility, this)
  23238. });
  23239. this.element().append(this._scrollable.element())
  23240. },
  23241. _allowScrolling: function() {
  23242. if (this.option("wordWrap"))
  23243. return false;
  23244. if (!this.option("scrollingEnabled"))
  23245. return false;
  23246. var tabItemsWidth = 0;
  23247. this.itemElements().each(function(_, tabItem) {
  23248. tabItemsWidth += $(tabItem).outerWidth(true)
  23249. });
  23250. return tabItemsWidth - 1 > this.element().width()
  23251. },
  23252. _renderNavButtons: function() {
  23253. this.element().toggleClass(TABS_NAV_BUTTONS_CLASS, this.option("showNavButtons"));
  23254. if (this.option("showNavButtons")) {
  23255. this._leftButton = this._createNavButton(-TAB_OFFSET, "chevronprev");
  23256. var $leftButton = this._leftButton.element();
  23257. $leftButton.addClass(TABS_LEFT_NAV_BUTTON_CLASS);
  23258. this.element().prepend($leftButton);
  23259. this._rightButton = this._createNavButton(TAB_OFFSET, "chevronnext");
  23260. var $rightButton = this._rightButton.element();
  23261. $rightButton.addClass(TABS_RIGHT_NAV_BUTTON_CLASS);
  23262. this.element().append($rightButton);
  23263. this._updateNavButtonsVisibility();
  23264. this._scrollable.update();
  23265. if (this.option("rtlEnabled"))
  23266. this._scrollable.scrollTo({left: this._scrollable.scrollWidth() - this._scrollable.clientWidth()})
  23267. }
  23268. },
  23269. _updateNavButtonsVisibility: function() {
  23270. this._leftButton && this._leftButton.option("disabled", this._scrollable.scrollLeft() <= 0);
  23271. this._rightButton && this._rightButton.option("disabled", this._scrollable.scrollLeft() >= this._scrollable.scrollWidth() - this._scrollable.clientWidth())
  23272. },
  23273. _updateScrollPosition: function(offset, duration) {
  23274. this._scrollable.update();
  23275. this._scrollable.scrollBy(offset / duration)
  23276. },
  23277. _createNavButton: function(offset, icon) {
  23278. var that = this;
  23279. var holdAction = that._createAction(function() {
  23280. that._holdInterval = setInterval(function() {
  23281. that._updateScrollPosition(offset, FEEDBACK_DURATION_INTERVAL)
  23282. }, FEEDBACK_DURATION_INTERVAL)
  23283. }),
  23284. holdEventName = events.addNamespace('dxhold', "dxButton"),
  23285. pointerUpEventName = events.addNamespace('dxpointerup', "dxButton"),
  23286. pointerOutEventName = events.addNamespace('dxpointerout', "dxButton");
  23287. var navButton = this._createComponent($("<div>").addClass(TABS_NAV_BUTTON_CLASS), "dxButton", {
  23288. focusStateEnabled: false,
  23289. icon: icon,
  23290. onClick: function() {
  23291. that._updateScrollPosition(offset, 1)
  23292. },
  23293. _templates: {}
  23294. });
  23295. navButton.element().on(holdEventName, {timeout: FEEDBACK_SCROLL_TIMEOUT}, $.proxy(function(e) {
  23296. holdAction({jQueryEvent: e})
  23297. }, this)).on(pointerUpEventName, function() {
  23298. that._clearInterval()
  23299. }).on(pointerOutEventName, function() {
  23300. that._clearInterval()
  23301. });
  23302. return navButton
  23303. },
  23304. _clearInterval: function() {
  23305. if (this._holdInterval)
  23306. clearInterval(this._holdInterval)
  23307. },
  23308. _updateNavButtons: function() {
  23309. var $element = this.element(),
  23310. tabsHeight = $element.height();
  23311. $element.find("." + TABS_LEFT_NAV_BUTTON_CLASS).css({height: tabsHeight});
  23312. $element.find("." + TABS_RIGHT_NAV_BUTTON_CLASS).css({
  23313. height: tabsHeight,
  23314. "margin-top": -tabsHeight
  23315. })
  23316. },
  23317. _renderSelection: function(addedSelection) {
  23318. this._scrollable && this._scrollable.scrollToElement(this.itemElements().eq(addedSelection[0]))
  23319. },
  23320. _visibilityChanged: function(visible) {
  23321. if (visible)
  23322. this._dimensionChanged()
  23323. },
  23324. _dimensionChanged: function() {
  23325. this._refresh()
  23326. },
  23327. _itemSelectHandler: function(e) {
  23328. if (this.option("selectionMode") === "single" && this.isItemSelected(e.currentTarget))
  23329. return;
  23330. this.callBase(e)
  23331. },
  23332. _optionChanged: function(args) {
  23333. switch (args.name) {
  23334. case"wordWrap":
  23335. case"scrollingEnabled":
  23336. case"showNavButtons":
  23337. this._invalidate();
  23338. break;
  23339. case"scrollByContent":
  23340. this._scrollable && this._scrollable.option(args.name, args.value);
  23341. break;
  23342. case"selectionMode":
  23343. this._renderMultiple();
  23344. this.callBase(args);
  23345. break;
  23346. default:
  23347. this.callBase(args)
  23348. }
  23349. }
  23350. }))
  23351. })(jQuery, DevExpress);
  23352. /*! Module widgets-base, file ui.navBar.js */
  23353. (function($, DX, undefined) {
  23354. var ui = DX.ui,
  23355. NAVBAR_CLASS = "dx-navbar",
  23356. ITEM_CLASS = "dx-item-content",
  23357. NAVBAR_ITEM_CLASS = "dx-nav-item",
  23358. NAVBAR_ITEM_CONTENT_CLASS = "dx-nav-item-content";
  23359. DX.registerComponent("dxNavBar", ui, ui.dxTabs.inherit({
  23360. _setDefaultOptions: function() {
  23361. this.callBase();
  23362. this.option({scrollingEnabled: false})
  23363. },
  23364. _render: function() {
  23365. this.callBase();
  23366. this.element().addClass(NAVBAR_CLASS)
  23367. },
  23368. _postprocessRenderItem: function(args) {
  23369. this.callBase(args);
  23370. var $itemElement = args.itemElement,
  23371. itemData = args.itemData;
  23372. $itemElement.addClass(NAVBAR_ITEM_CLASS);
  23373. $itemElement.find("." + ITEM_CLASS).addClass(NAVBAR_ITEM_CONTENT_CLASS);
  23374. if (!itemData.icon && !itemData.iconSrc)
  23375. $itemElement.addClass("dx-navbar-text-item")
  23376. }
  23377. }))
  23378. })(jQuery, DevExpress);
  23379. /*! Module widgets-base, file ui.toolbar.js */
  23380. (function($, DX, undefined) {
  23381. var ui = DX.ui,
  23382. fx = DX.fx,
  23383. translator = DX.translator;
  23384. var TOOLBAR_CLASS = "dx-toolbar",
  23385. TOOLBAR_BOTTOM_CLASS = "dx-toolbar-bottom",
  23386. TOOLBAR_MINI_CLASS = "dx-toolbar-mini",
  23387. TOOLBAR_ITEM_CLASS = "dx-toolbar-item",
  23388. TOOLBAR_LABEL_CLASS = "dx-toolbar-label",
  23389. TOOLBAR_BUTTON_CLASS = "dx-toolbar-button",
  23390. TOOLBAR_MENU_CONTAINER_CLASS = "dx-toolbar-menu-container",
  23391. TOOLBAR_MENU_BUTTON_CLASS = "dx-toolbar-menu-button",
  23392. TOOLBAR_ITEMS_CONTAINER_CLASS = "dx-toolbar-items-container",
  23393. TOOLBAR_LABEL_SELECTOR = "." + TOOLBAR_LABEL_CLASS,
  23394. TOOLBAR_ITEM_DATA_KEY = "dxToolbarItemDataKey",
  23395. SUBMENU_SWIPE_EASING = "easeOutCubic",
  23396. SUBMENU_HIDE_DURATION = 200,
  23397. SUBMENU_SHOW_DURATION = 400;
  23398. var slideSubmenu = function($element, position, isShowAnimation) {
  23399. var duration = isShowAnimation ? SUBMENU_SHOW_DURATION : SUBMENU_HIDE_DURATION;
  23400. fx.animate($element, {
  23401. type: "slide",
  23402. to: {top: position},
  23403. easing: SUBMENU_SWIPE_EASING,
  23404. duration: duration
  23405. })
  23406. };
  23407. DX.registerComponent("dxToolbar", ui, ui.CollectionWidget.inherit({
  23408. _setDeprecatedOptions: function() {
  23409. this.callBase();
  23410. $.extend(this._deprecatedOptions, {menuItemRender: {
  23411. since: "14.2",
  23412. alias: "menuItemTemplate"
  23413. }})
  23414. },
  23415. _setDefaultOptions: function() {
  23416. this.callBase();
  23417. this.option({
  23418. menuItemTemplate: "menuItem",
  23419. submenuType: "dxDropDownMenu",
  23420. renderAs: "topToolbar"
  23421. })
  23422. },
  23423. _defaultOptionsRules: function() {
  23424. return this.callBase().concat([{
  23425. device: {platform: "ios"},
  23426. options: {submenuType: "dxActionSheet"}
  23427. }, {
  23428. device: {platform: "android"},
  23429. options: {submenuType: "dxDropDownMenu"}
  23430. }, {
  23431. device: {platform: "win8"},
  23432. options: {submenuType: "dxList"}
  23433. }])
  23434. },
  23435. _itemContainer: function() {
  23436. return this._$toolbarItemsContainer.find([".dx-toolbar-before", ".dx-toolbar-center", ".dx-toolbar-after"].join(","))
  23437. },
  23438. _itemClass: function() {
  23439. return TOOLBAR_ITEM_CLASS
  23440. },
  23441. _itemDataKey: function() {
  23442. return TOOLBAR_ITEM_DATA_KEY
  23443. },
  23444. _dimensionChanged: function() {
  23445. if (this._menu)
  23446. this._toggleMenuVisibility(false, true);
  23447. this._arrangeTitle()
  23448. },
  23449. _render: function() {
  23450. this._renderToolbar();
  23451. this._renderSections();
  23452. this.callBase();
  23453. this._renderMenu();
  23454. this._arrangeTitle();
  23455. this.setAria("role", "toolbar")
  23456. },
  23457. _renderToolbar: function() {
  23458. this.element().addClass(TOOLBAR_CLASS).toggleClass(TOOLBAR_BOTTOM_CLASS, this.option("renderAs") === "bottomToolbar");
  23459. this._$toolbarItemsContainer = $("<div>").appendTo(this.element());
  23460. this._$toolbarItemsContainer.addClass(TOOLBAR_ITEMS_CONTAINER_CLASS)
  23461. },
  23462. _renderSections: function() {
  23463. var $container = this._$toolbarItemsContainer,
  23464. that = this;
  23465. $.each(["before", "center", "after"], function() {
  23466. var sectionClass = "dx-toolbar-" + this,
  23467. $section = $container.find("." + sectionClass);
  23468. if (!$section.length)
  23469. that["_$" + this + "Section"] = $section = $("<div>").addClass(sectionClass).appendTo($container)
  23470. })
  23471. },
  23472. _arrangeTitle: function() {
  23473. if (this.element().is(":hidden"))
  23474. return;
  23475. var $section = this._$toolbarItemsContainer.find(TOOLBAR_LABEL_SELECTOR).eq(0).parent(),
  23476. $label = $section.children(TOOLBAR_LABEL_SELECTOR).eq(0);
  23477. if (!$label.length)
  23478. return;
  23479. var containerWidth = this._$toolbarItemsContainer.width(),
  23480. labelOffset = this._$beforeSection.outerWidth() ? this._$beforeSection.outerWidth() : $label.position().left,
  23481. widthBeforeSection = $section.hasClass("dx-toolbar-before") ? 0 : labelOffset,
  23482. widthAfterSection = $section.hasClass("dx-toolbar-after") ? 0 : this._$afterSection.outerWidth(),
  23483. elemsAtSectionWidth = 10;
  23484. $section.children().not(TOOLBAR_LABEL_SELECTOR).each(function() {
  23485. elemsAtSectionWidth += $(this).outerWidth()
  23486. });
  23487. var maxLabelWidth = containerWidth - widthBeforeSection - widthAfterSection - elemsAtSectionWidth,
  23488. labelLongerThanMax = $label.outerWidth() > maxLabelWidth;
  23489. $section.css({
  23490. marginLeft: labelLongerThanMax ? widthBeforeSection : "",
  23491. marginRight: labelLongerThanMax ? widthAfterSection : ""
  23492. });
  23493. $label.css("max-width", maxLabelWidth)
  23494. },
  23495. _renderItem: function(index, item) {
  23496. var location = item.location || "center",
  23497. container = this._$toolbarItemsContainer.find(".dx-toolbar-" + location),
  23498. itemHasTest = Boolean(item.text),
  23499. itemElement = this.callBase(index, item, container);
  23500. itemElement.toggleClass(TOOLBAR_BUTTON_CLASS, !itemHasTest).toggleClass(TOOLBAR_LABEL_CLASS, itemHasTest);
  23501. return itemElement
  23502. },
  23503. _hasVisibleMenuItems: function() {
  23504. var menuItems = this._getMenuItems(),
  23505. result = false;
  23506. var optionGetter = DevExpress.data.utils.compileGetter("visible");
  23507. $.each(menuItems, function(index, item) {
  23508. var itemVisible = optionGetter(item, {functionsAsIs: true});
  23509. if (itemVisible !== false)
  23510. result = true
  23511. });
  23512. return result
  23513. },
  23514. _getToolbarItems: function() {
  23515. return $.grep(this.option("items") || [], function(item) {
  23516. return item.location !== "menu"
  23517. })
  23518. },
  23519. _getMenuItems: function() {
  23520. return $.grep(this.option("items") || [], function(item) {
  23521. return item.location === "menu"
  23522. })
  23523. },
  23524. _renderContentImpl: function() {
  23525. var items = this._getToolbarItems();
  23526. this.element().toggleClass(TOOLBAR_MINI_CLASS, items.length === 0);
  23527. if (this._renderedItemsCount)
  23528. this._renderItems(items.slice(this._renderedItemsCount));
  23529. else
  23530. this._renderItems(items)
  23531. },
  23532. _renderMenu: function() {
  23533. var that = this,
  23534. itemClickAction = this._createActionByOption("onItemClick");
  23535. var options = {
  23536. itemTemplate: function() {
  23537. if (that._menuType === "dxActionSheet")
  23538. return that._getTemplate("actionSheetItem");
  23539. return that._getTemplateByOption("menuItemTemplate")
  23540. },
  23541. onItemClick: function(e) {
  23542. that._toggleMenuVisibility(false, true);
  23543. itemClickAction(e)
  23544. }
  23545. };
  23546. this._menuType = this.option("submenuType");
  23547. if (this._menuType === "dxList" && this.option("renderAs") === "topToolbar")
  23548. this._menuType = "dxDropDownMenu";
  23549. switch (this._menuType) {
  23550. case"dxActionSheet":
  23551. this._renderActionSheet(options);
  23552. break;
  23553. case"dxDropDownMenu":
  23554. this._renderDropDown(options);
  23555. break;
  23556. case"dxList":
  23557. this._renderList(options);
  23558. break
  23559. }
  23560. },
  23561. _renderMenuButton: function(options) {
  23562. var buttonOptions = $.extend({onClick: $.proxy(this._menuButtonClickHandler, this)}, options);
  23563. this._renderMenuButtonContainer();
  23564. this._$button = $("<div>").appendTo(this._$menuButtonContainer).addClass(TOOLBAR_MENU_BUTTON_CLASS);
  23565. this._createComponent(this._$button, "dxButton", buttonOptions)
  23566. },
  23567. _renderMenuButtonContainer: function() {
  23568. var $afterSection = this._$afterSection;
  23569. this._$menuButtonContainer = $("<div>").appendTo($afterSection).addClass(TOOLBAR_BUTTON_CLASS).addClass(TOOLBAR_MENU_CONTAINER_CLASS)
  23570. },
  23571. _renderDropDown: function(options) {
  23572. if (!this._hasVisibleMenuItems())
  23573. return;
  23574. this._renderMenuButtonContainer();
  23575. var $menu = $("<div>").appendTo(this._$menuButtonContainer);
  23576. this._menu = this._createComponent($menu, "dxDropDownMenu", options);
  23577. this._renderMenuItems()
  23578. },
  23579. _renderActionSheet: function(options) {
  23580. if (!this._hasVisibleMenuItems())
  23581. return;
  23582. this._renderMenuButton({icon: "overflow"});
  23583. var actionSheetOptions = $.extend({
  23584. target: this._$button,
  23585. showTitle: false
  23586. }, options);
  23587. var $menu = $("<div>").appendTo(this.element());
  23588. this._menu = this._createComponent($menu, "dxActionSheet", actionSheetOptions);
  23589. this._renderMenuItems()
  23590. },
  23591. _renderList: function(options) {
  23592. this._renderMenuButton({
  23593. activeStateEnabled: false,
  23594. text: "..."
  23595. });
  23596. var listOptions = $.extend({
  23597. width: "100%",
  23598. indicateLoading: false
  23599. }, options);
  23600. this._renderListOverlay();
  23601. this._renderContainerSwipe();
  23602. if (this._hasVisibleMenuItems()) {
  23603. var $menu = $("<div>").appendTo(this._listOverlay.content());
  23604. this._menu = this._createComponent($menu, "dxList", listOptions);
  23605. this._renderMenuItems()
  23606. }
  23607. this._changeListVisible(this.option("visible"))
  23608. },
  23609. _renderMenuItems: function() {
  23610. this._menu.option("items", this._getMenuItems())
  23611. },
  23612. _getListHeight: function() {
  23613. var listHeight = this._listOverlay.content().find(".dx-list").height(),
  23614. semiHiddenHeight = this._$toolbarItemsContainer.height() - this.element().height();
  23615. return listHeight + semiHiddenHeight
  23616. },
  23617. _renderListOverlay: function() {
  23618. var $listOverlay = $("<div>").appendTo(this.element());
  23619. this._listOverlay = this._createComponent($listOverlay, "dxOverlay", {
  23620. container: false,
  23621. deferRendering: false,
  23622. shading: false,
  23623. height: "auto",
  23624. width: "100%",
  23625. showTitle: false,
  23626. closeOnOutsideClick: $.proxy(this._listOutsideClickHandler, this),
  23627. position: null,
  23628. animation: null,
  23629. closeOnBackButton: false
  23630. })
  23631. },
  23632. _hideTopOverlayHandler: function() {
  23633. this._toggleMenuVisibility(false, true)
  23634. },
  23635. _toggleHideTopOverlayCallback: function() {
  23636. if (this._closeCallback)
  23637. DX.hideTopOverlayCallback.remove(this._closeCallback);
  23638. if (this._menuShown) {
  23639. this._closeCallback = $.proxy(this._hideTopOverlayHandler, this);
  23640. DX.hideTopOverlayCallback.add(this._closeCallback)
  23641. }
  23642. },
  23643. _renderContainerSwipe: function() {
  23644. this._createComponent(this._$toolbarItemsContainer.appendTo(this._listOverlay.content()), "dxSwipeable", {
  23645. elastic: false,
  23646. onStart: $.proxy(this._swipeStartHandler, this),
  23647. onUpdated: $.proxy(this._swipeUpdateHandler, this),
  23648. onEnd: $.proxy(this._swipeEndHandler, this),
  23649. itemSizeFunc: $.proxy(this._getListHeight, this),
  23650. direction: "vertical"
  23651. })
  23652. },
  23653. _listOutsideClickHandler: function(e) {
  23654. if (!$(e.target).closest(this._listOverlay.content()).length)
  23655. this._toggleMenuVisibility(false, true)
  23656. },
  23657. _calculatePixelOffset: function(offset) {
  23658. offset = (offset || 0) - 1;
  23659. var maxOffset = this._getListHeight();
  23660. return offset * maxOffset
  23661. },
  23662. _swipeStartHandler: function(e) {
  23663. e.jQueryEvent.maxTopOffset = this._menuShown ? 0 : 1;
  23664. e.jQueryEvent.maxBottomOffset = this._menuShown ? 1 : 0
  23665. },
  23666. _swipeUpdateHandler: function(e) {
  23667. var offset = this._menuShown ? e.jQueryEvent.offset : 1 + e.jQueryEvent.offset;
  23668. this._renderMenuPosition(offset, false)
  23669. },
  23670. _swipeEndHandler: function(e) {
  23671. var targetOffset = e.jQueryEvent.targetOffset;
  23672. targetOffset -= this._menuShown - 1;
  23673. this._toggleMenuVisibility(targetOffset === 0, true)
  23674. },
  23675. _renderMenuPosition: function(offset, animate) {
  23676. var pos = this._calculatePixelOffset(offset),
  23677. element = this._listOverlay.content();
  23678. if (animate)
  23679. slideSubmenu(element, pos, this._menuShown);
  23680. else
  23681. translator.move(element, {top: pos})
  23682. },
  23683. _menuButtonClickHandler: function() {
  23684. this._toggleMenuVisibility(!this._menuShown, true)
  23685. },
  23686. _toggleMenuVisibility: function(visible, animate) {
  23687. this._menuShown = visible;
  23688. switch (this._menuType) {
  23689. case"dxList":
  23690. this._toggleHideTopOverlayCallback();
  23691. this._renderMenuPosition(this._menuShown ? 0 : 1, animate);
  23692. break;
  23693. case"dxActionSheet":
  23694. this._menu.toggle(this._menuShown);
  23695. this._menuShown = false;
  23696. break
  23697. }
  23698. },
  23699. _renderEmptyMessage: $.noop,
  23700. _clean: function() {
  23701. this._$toolbarItemsContainer.children().empty();
  23702. this.element().empty()
  23703. },
  23704. _changeMenuOption: function(name, value) {
  23705. if (this._menu)
  23706. this._menu.option(name, value)
  23707. },
  23708. _changeListVisible: function(value) {
  23709. if (this._listOverlay) {
  23710. this._listOverlay.option("visible", value);
  23711. this._toggleMenuVisibility(false, false)
  23712. }
  23713. },
  23714. _visibilityChanged: function(visible) {
  23715. if (visible)
  23716. this._arrangeTitle()
  23717. },
  23718. _renderDimensions: function() {
  23719. this.callBase();
  23720. this._arrangeTitle()
  23721. },
  23722. _optionChanged: function(args) {
  23723. var name = args.name;
  23724. var value = args.value;
  23725. switch (name) {
  23726. case"renderAs":
  23727. case"submenuType":
  23728. this._invalidate();
  23729. break;
  23730. case"visible":
  23731. this.callBase.apply(this, arguments);
  23732. this._changeListVisible(value);
  23733. break;
  23734. case"menuItemTemplate":
  23735. this._changeMenuOption("itemTemplate", this._getTemplate(value));
  23736. break;
  23737. case"onItemClick":
  23738. this._changeMenuOption(name, value);
  23739. this.callBase.apply(this, arguments);
  23740. break;
  23741. default:
  23742. this.callBase.apply(this, arguments)
  23743. }
  23744. }
  23745. }))
  23746. })(jQuery, DevExpress);
  23747. /*! Module widgets-base, file ui.list.js */
  23748. (function($, DX, undefined) {
  23749. var ui = DX.ui,
  23750. events = ui.events,
  23751. utils = DX.utils;
  23752. var LIST_CLASS = "dx-list",
  23753. LIST_ITEM_CLASS = "dx-list-item",
  23754. LIST_ITEM_SELECTOR = "." + LIST_ITEM_CLASS,
  23755. LIST_GROUP_CLASS = "dx-list-group",
  23756. LIST_GROUP_HEADER_CLASS = "dx-list-group-header",
  23757. LIST_GROUP_BODY_CLASS = "dx-list-group-body",
  23758. LIST_COLLAPSIBLE_GROUPS_CLASS = "dx-list-collapsible-groups",
  23759. LIST_GROUP_COLLAPSED_CLASS = "dx-list-group-collapsed",
  23760. LIST_HAS_NEXT_CLASS = "dx-has-next",
  23761. LIST_NEXT_BUTTON_CLASS = "dx-list-next-button",
  23762. LIST_ITEM_DATA_KEY = "dxListItemData",
  23763. LIST_FEEDBACK_SHOW_TIMEOUT = 70;
  23764. var groupItemsGetter = DX.data.utils.compileGetter("items");
  23765. DX.registerComponent("dxList", ui, ui.CollectionWidget.inherit({
  23766. _activeStateUnit: LIST_ITEM_SELECTOR,
  23767. _supportedKeys: function() {
  23768. var that = this;
  23769. var moveFocusPerPage = function(direction) {
  23770. var $item = getEdgeVisibleItem(direction),
  23771. isFocusedItem = $item.is(that.option("focusedElement"));
  23772. if (isFocusedItem) {
  23773. scrollListTo($item, direction);
  23774. $item = getEdgeVisibleItem(direction)
  23775. }
  23776. that.option("focusedElement", $item);
  23777. that.scrollToItem($item)
  23778. };
  23779. var getEdgeVisibleItem = function(direction) {
  23780. var scrollTop = that.scrollTop(),
  23781. containerHeight = that.element().height();
  23782. var $item = that.option("focusedElement"),
  23783. isItemVisible = true;
  23784. if (!$item)
  23785. return;
  23786. while (isItemVisible) {
  23787. var $nextItem = $item[direction]();
  23788. if (!$nextItem.length)
  23789. break;
  23790. var nextItemLocation = $nextItem.position().top + $nextItem.outerHeight() / 2;
  23791. isItemVisible = nextItemLocation < containerHeight + scrollTop && nextItemLocation > scrollTop;
  23792. if (isItemVisible)
  23793. $item = $nextItem
  23794. }
  23795. return $item
  23796. };
  23797. var scrollListTo = function($item, direction) {
  23798. var resultPosition = $item.position().top;
  23799. if (direction === "prev")
  23800. resultPosition = $item.position().top - that.element().height() + $item.outerHeight();
  23801. that.scrollTo(resultPosition)
  23802. };
  23803. return $.extend(this.callBase(), {
  23804. leftArrow: $.noop,
  23805. rightArrow: $.noop,
  23806. pageUp: function() {
  23807. moveFocusPerPage("prev");
  23808. return false
  23809. },
  23810. pageDown: function() {
  23811. moveFocusPerPage("next");
  23812. return false
  23813. }
  23814. })
  23815. },
  23816. _setDeprecatedOptions: function() {
  23817. this.callBase();
  23818. $.extend(this._deprecatedOptions, {
  23819. itemSwipeAction: {
  23820. since: "14.2",
  23821. alias: "onItemSwipe"
  23822. },
  23823. scrollAction: {
  23824. since: "14.2",
  23825. alias: "onScroll"
  23826. },
  23827. pullRefreshAction: {
  23828. since: "14.2",
  23829. alias: "onPullRefresh"
  23830. },
  23831. pageLoadingAction: {
  23832. since: "14.2",
  23833. alias: "onPageLoading"
  23834. },
  23835. groupRender: {
  23836. since: "14.2",
  23837. alias: "groupTemplate"
  23838. },
  23839. autoPagingEnabled: {
  23840. since: "15.1",
  23841. message: "Use the 'pageLoadMode' option instead"
  23842. },
  23843. showNextButton: {
  23844. since: "15.1",
  23845. message: "Use the 'pageLoadMode' option instead"
  23846. }
  23847. })
  23848. },
  23849. _setDefaultOptions: function() {
  23850. this.callBase();
  23851. this.option({
  23852. pullRefreshEnabled: false,
  23853. scrollingEnabled: true,
  23854. showScrollbar: "onScroll",
  23855. useNative: true,
  23856. bounceEnabled: true,
  23857. scrollByContent: true,
  23858. scrollByThumb: false,
  23859. pullingDownText: Globalize.localize("dxList-pullingDownText"),
  23860. pulledDownText: Globalize.localize("dxList-pulledDownText"),
  23861. refreshingText: Globalize.localize("dxList-refreshingText"),
  23862. pageLoadingText: Globalize.localize("dxList-pageLoadingText"),
  23863. onScroll: null,
  23864. onPullRefresh: null,
  23865. onPageLoading: null,
  23866. pageLoadMode: "scrollBottom",
  23867. nextButtonText: Globalize.localize("dxList-nextButtonText"),
  23868. onItemSwipe: null,
  23869. grouped: false,
  23870. onGroupRendered: null,
  23871. collapsibleGroups: false,
  23872. groupTemplate: "group",
  23873. indicateLoading: true,
  23874. activeStateEnabled: true,
  23875. _itemAttributes: {role: "option"}
  23876. })
  23877. },
  23878. _defaultOptionsRules: function() {
  23879. return this.callBase().concat(ui.dxScrollable.deviceDependentOptions(), [{
  23880. device: function(device) {
  23881. return !DX.support.nativeScrolling && !DX.devices.isSimulator() && DX.devices.real().platform === "generic" && device.platform === "generic"
  23882. },
  23883. options: {
  23884. showScrollbar: "onHover",
  23885. pageLoadMode: "nextButton"
  23886. }
  23887. }, {
  23888. device: function(device) {
  23889. return DX.devices.real().generic && !DX.devices.isSimulator()
  23890. },
  23891. options: {
  23892. hoverStateEnabled: true,
  23893. focusStateEnabled: true
  23894. }
  23895. }])
  23896. },
  23897. _getOptionAliases: function() {
  23898. return $.extend(this.callBase(), {useNative: "useNativeScrolling"})
  23899. },
  23900. _itemClass: function() {
  23901. return LIST_ITEM_CLASS
  23902. },
  23903. _itemDataKey: function() {
  23904. return LIST_ITEM_DATA_KEY
  23905. },
  23906. _itemContainer: function() {
  23907. return this._$container
  23908. },
  23909. _allowDinamicItemsAppend: function() {
  23910. return true
  23911. },
  23912. _init: function() {
  23913. this.callBase();
  23914. this._$container = this.element();
  23915. this._initScrollView();
  23916. this._feedbackShowTimeout = LIST_FEEDBACK_SHOW_TIMEOUT;
  23917. this._createGroupRenderAction()
  23918. },
  23919. _dataSourceOptions: function() {
  23920. this._suppressDeprecatedWarnings();
  23921. var pagingEnabled = this.option("autoPagingEnabled");
  23922. pagingEnabled = utils.isDefined(this.option("showNextButton")) ? pagingEnabled || this.option("showNextButton") : pagingEnabled;
  23923. this._resumeDeprecatedWarnings();
  23924. return $.extend(this.callBase(), {paginate: utils.isDefined(pagingEnabled) ? pagingEnabled : true})
  23925. },
  23926. _initScrollView: function() {
  23927. this._suppressDeprecatedWarnings();
  23928. var scrollingEnabled = this.option("scrollingEnabled"),
  23929. pullRefreshEnabled = scrollingEnabled && this.option("pullRefreshEnabled"),
  23930. autoPagingEnabled = scrollingEnabled && utils.ensureDefined(this.option("autoPagingEnabled"), this.option("pageLoadMode") === "scrollBottom") && !!this._dataSource;
  23931. this._resumeDeprecatedWarnings();
  23932. this._scrollView = this._createComponent(this.element(), "dxScrollView", {
  23933. disabled: this.option("disabled") || !scrollingEnabled,
  23934. onScroll: $.proxy(this._scrollHandler, this),
  23935. onPullDown: pullRefreshEnabled ? $.proxy(this._pullDownHandler, this) : null,
  23936. onReachBottom: autoPagingEnabled ? $.proxy(this._scrollBottomHandler, this) : null,
  23937. showScrollbar: this.option("showScrollbar"),
  23938. useNative: this.option("useNativeScrolling"),
  23939. bounceEnabled: this.option("bounceEnabled"),
  23940. scrollByContent: this.option("scrollByContent"),
  23941. scrollByThumb: this.option("scrollByThumb"),
  23942. pullingDownText: this.option("pullingDownText"),
  23943. pulledDownText: this.option("pulledDownText"),
  23944. refreshingText: this.option("refreshingText"),
  23945. reachBottomText: this.option("pageLoadingText"),
  23946. useKeyboard: false
  23947. });
  23948. this._$container = this._scrollView.content();
  23949. this._createScrollViewActions()
  23950. },
  23951. _createScrollViewActions: function() {
  23952. this._scrollAction = this._createActionByOption("onScroll");
  23953. this._pullRefreshAction = this._createActionByOption("onPullRefresh");
  23954. this._pageLoadingAction = this._createActionByOption("onPageLoading")
  23955. },
  23956. _scrollHandler: function(e) {
  23957. this._scrollAction(e)
  23958. },
  23959. _updateLoadingState: function(tryLoadMore) {
  23960. this._suppressDeprecatedWarnings();
  23961. var isDataLoaded = !tryLoadMore || this._isLastPage(),
  23962. autoPagingEnabled = utils.ensureDefined(this.option("autoPagingEnabled"), this.option("pageLoadMode") === "scrollBottom"),
  23963. stopLoading = isDataLoaded || !autoPagingEnabled,
  23964. hideLoadIndicator = stopLoading && !this._isDataSourceLoading();
  23965. this._resumeDeprecatedWarnings();
  23966. if (stopLoading || this._scrollViewIsFull()) {
  23967. this._scrollView.release(hideLoadIndicator);
  23968. this._toggleNextButton(this._shouldRenderNextButton() && !isDataLoaded);
  23969. this._loadIndicationSuppressed(false)
  23970. }
  23971. else
  23972. this._infiniteDataLoading()
  23973. },
  23974. _shouldRenderNextButton: function() {
  23975. this._suppressDeprecatedWarnings();
  23976. var result = utils.ensureDefined(this.option("showNextButton"), this.option("pageLoadMode") === "nextButton") && this._dataSource && this._dataSource.isLoaded();
  23977. this._resumeDeprecatedWarnings();
  23978. return result
  23979. },
  23980. _dataSourceLoadingChangedHandler: function(isLoading) {
  23981. if (this._loadIndicationSuppressed())
  23982. return;
  23983. if (isLoading && this.option("indicateLoading"))
  23984. this._showLoadingIndicatorTimer = setTimeout($.proxy(function() {
  23985. this._scrollView && this._scrollView.startLoading()
  23986. }, this));
  23987. else {
  23988. clearTimeout(this._showLoadingIndicatorTimer);
  23989. this._scrollView && this._scrollView.finishLoading()
  23990. }
  23991. },
  23992. _hideLoadingIfLoadIndicationOff: function() {
  23993. if (!this.option("indicateLoading"))
  23994. this._dataSourceLoadingChangedHandler(false)
  23995. },
  23996. _loadIndicationSuppressed: function(value) {
  23997. if (!arguments.length)
  23998. return this._isLoadIndicationSuppressed;
  23999. this._isLoadIndicationSuppressed = value
  24000. },
  24001. _scrollViewIsFull: function() {
  24002. return !this._scrollView || this._scrollView.isFull()
  24003. },
  24004. _pullDownHandler: function(e) {
  24005. this._pullRefreshAction(e);
  24006. if (this._dataSource && !this._isDataSourceLoading()) {
  24007. this._dataSource.pageIndex(0);
  24008. this._dataSource.load()
  24009. }
  24010. else
  24011. this._updateLoadingState()
  24012. },
  24013. _infiniteDataLoading: function() {
  24014. if (!this._scrollViewIsFull() && !this._isDataSourceLoading() && !this._isLastPage()) {
  24015. clearTimeout(this._loadNextPageTimer);
  24016. this._loadNextPageTimer = setTimeout($.proxy(this._loadNextPage, this))
  24017. }
  24018. },
  24019. _scrollBottomHandler: function(e) {
  24020. this._pageLoadingAction(e);
  24021. if (!this._isDataSourceLoading())
  24022. this._loadNextPage();
  24023. else
  24024. this._updateLoadingState()
  24025. },
  24026. _renderItems: function(items) {
  24027. if (this.option("grouped")) {
  24028. $.each(items, $.proxy(this._renderGroup, this));
  24029. this._attachGroupCollapseEvent();
  24030. this._renderEmptyMessage()
  24031. }
  24032. else
  24033. this.callBase.apply(this, arguments);
  24034. this._updateLoadingState(true)
  24035. },
  24036. _attachGroupCollapseEvent: function() {
  24037. var eventName = events.addNamespace("dxclick", this.NAME),
  24038. selector = "." + LIST_GROUP_HEADER_CLASS,
  24039. $element = this.element(),
  24040. collapsibleGroups = this.option("collapsibleGroups");
  24041. $element.toggleClass(LIST_COLLAPSIBLE_GROUPS_CLASS, collapsibleGroups);
  24042. $element.off(eventName, selector);
  24043. if (collapsibleGroups)
  24044. $element.on(eventName, selector, $.proxy(function(e) {
  24045. this._createAction($.proxy(function(e) {
  24046. this._collapseGroupHandler($(e.jQueryEvent.currentTarget).parent())
  24047. }, this), {validatingTargetName: "element"})({jQueryEvent: e})
  24048. }, this))
  24049. },
  24050. _collapseGroupHandler: function($group, toggle) {
  24051. var deferred = $.Deferred(),
  24052. $groupBody = $group.children("." + LIST_GROUP_BODY_CLASS);
  24053. $group.toggleClass(LIST_GROUP_COLLAPSED_CLASS, toggle);
  24054. var slideMethod = "slideToggle";
  24055. if (toggle === true)
  24056. slideMethod = "slideUp";
  24057. if (toggle === false)
  24058. slideMethod = "slideDown";
  24059. $groupBody[slideMethod]({
  24060. duration: 200,
  24061. complete: $.proxy(function() {
  24062. this.updateDimensions();
  24063. deferred.resolve()
  24064. }, this)
  24065. });
  24066. return deferred.promise()
  24067. },
  24068. _dataSourceLoadErrorHandler: function() {
  24069. this._forgetNextPageLoading();
  24070. if (this._initialized) {
  24071. this._renderEmptyMessage();
  24072. this._updateLoadingState()
  24073. }
  24074. },
  24075. _render: function() {
  24076. this.element().addClass(LIST_CLASS);
  24077. this.callBase();
  24078. this.setAria("role", "listbox")
  24079. },
  24080. _postprocessRenderItem: function(args) {
  24081. this.callBase.apply(this, arguments);
  24082. if (this.option("onItemSwipe"))
  24083. this._attachSwipeEvent($(args.itemElement))
  24084. },
  24085. _attachSwipeEvent: function($itemElement) {
  24086. var endEventName = events.addNamespace("dxswipeend", this.NAME);
  24087. $itemElement.on(endEventName, $.proxy(this._itemSwipeEndHandler, this))
  24088. },
  24089. _itemSwipeEndHandler: function(e) {
  24090. this._itemJQueryEventHandler(e, "onItemSwipe", {direction: e.offset < 0 ? "left" : "right"})
  24091. },
  24092. _nextButtonHandler: function() {
  24093. var source = this._dataSource;
  24094. if (source && !source.isLoading()) {
  24095. this._scrollView.toggleLoading(true);
  24096. this._$nextButton.detach();
  24097. this._loadIndicationSuppressed(true);
  24098. this._loadNextPage()
  24099. }
  24100. },
  24101. _renderGroup: function(index, group) {
  24102. var $groupElement = $("<div>").addClass(LIST_GROUP_CLASS).appendTo(this._itemContainer());
  24103. var $groupHeaderElement = $("<div>").addClass(LIST_GROUP_HEADER_CLASS).appendTo($groupElement);
  24104. var groupTemplateName = this.option("groupTemplate"),
  24105. groupTemplate = this._getTemplate(group.template || groupTemplateName, group, index, $groupHeaderElement),
  24106. renderArgs = {
  24107. index: index,
  24108. item: group,
  24109. container: $groupHeaderElement
  24110. };
  24111. this._createItemByTemplate(groupTemplate, renderArgs);
  24112. this._renderingGroupIndex = index;
  24113. var $groupBody = $("<div>").addClass(LIST_GROUP_BODY_CLASS).appendTo($groupElement);
  24114. $.each(groupItemsGetter(group) || [], $.proxy(function(index, item) {
  24115. this._renderItem(index, item, $groupBody)
  24116. }, this));
  24117. this._groupRenderAction({
  24118. groupElement: $groupElement,
  24119. groupIndex: index,
  24120. groupData: group
  24121. })
  24122. },
  24123. _createGroupRenderAction: function() {
  24124. this._groupRenderAction = this._createActionByOption("onGroupRendered")
  24125. },
  24126. _clean: function() {
  24127. if (this._$nextButton) {
  24128. this._$nextButton.remove();
  24129. this._$nextButton = null
  24130. }
  24131. this.callBase.apply(this, arguments)
  24132. },
  24133. _dispose: function() {
  24134. clearTimeout(this._holdTimer);
  24135. clearTimeout(this._loadNextPageTimer);
  24136. clearTimeout(this._showLoadingIndicatorTimer);
  24137. this.callBase()
  24138. },
  24139. _toggleDisabledState: function(value) {
  24140. this.callBase(value);
  24141. this._scrollView.option("disabled", value || !this.option("scrollingEnabled"))
  24142. },
  24143. _toggleNextButton: function(value) {
  24144. var dataSource = this._dataSource,
  24145. $nextButton = this._getNextButton();
  24146. this.element().toggleClass(LIST_HAS_NEXT_CLASS, value);
  24147. if (value && dataSource && dataSource.isLoaded())
  24148. $nextButton.appendTo(this._itemContainer());
  24149. if (!value)
  24150. $nextButton.detach()
  24151. },
  24152. _getNextButton: function() {
  24153. if (!this._$nextButton)
  24154. this._$nextButton = this._createNextButton();
  24155. return this._$nextButton
  24156. },
  24157. _createNextButton: function() {
  24158. var $result = $("<div>").addClass(LIST_NEXT_BUTTON_CLASS);
  24159. var $button = $("<div>").appendTo($result);
  24160. this._createComponent($button, "dxButton", {
  24161. text: this.option("nextButtonText"),
  24162. onClick: $.proxy(this._nextButtonHandler, this),
  24163. _templates: {}
  24164. });
  24165. return $result
  24166. },
  24167. _moveFocus: function(location) {
  24168. this.callBase.apply(this, arguments);
  24169. this.scrollToItem(this.option("focusedElement"))
  24170. },
  24171. _optionChanged: function(args) {
  24172. switch (args.name) {
  24173. case"pageLoadMode":
  24174. this._toggleNextButton(args.value);
  24175. this._initScrollView();
  24176. break;
  24177. case"showNextButton":
  24178. this._toggleNextButton(args.value);
  24179. break;
  24180. case"dataSource":
  24181. this.callBase(args);
  24182. this._initScrollView();
  24183. break;
  24184. case"pullingDownText":
  24185. case"pulledDownText":
  24186. case"refreshingText":
  24187. case"pageLoadingText":
  24188. case"useNative":
  24189. case"showScrollbar":
  24190. case"bounceEnabled":
  24191. case"scrollByContent":
  24192. case"scrollByThumb":
  24193. case"scrollingEnabled":
  24194. case"pullRefreshEnabled":
  24195. case"autoPagingEnabled":
  24196. this._initScrollView();
  24197. break;
  24198. case"nextButtonText":
  24199. case"onItemSwipe":
  24200. this._invalidate();
  24201. break;
  24202. case"onScroll":
  24203. case"onPullRefresh":
  24204. case"onPageLoading":
  24205. this._createScrollViewActions();
  24206. this._invalidate();
  24207. break;
  24208. case"grouped":
  24209. case"collapsibleGroups":
  24210. case"groupTemplate":
  24211. this._invalidate();
  24212. break;
  24213. case"onGroupRendered":
  24214. this._createGroupRenderAction();
  24215. break;
  24216. case"items":
  24217. this._invalidate();
  24218. break;
  24219. case"width":
  24220. case"height":
  24221. this.callBase(args);
  24222. this._scrollView.update();
  24223. break;
  24224. case"indicateLoading":
  24225. this._hideLoadingIfLoadIndicationOff();
  24226. break;
  24227. case"visible":
  24228. this.callBase(args);
  24229. this._scrollView.update();
  24230. break;
  24231. case"rtlEnabled":
  24232. this._initScrollView();
  24233. this.callBase(args);
  24234. break;
  24235. default:
  24236. this.callBase(args)
  24237. }
  24238. },
  24239. _extendActionArgs: function($itemElement) {
  24240. if (!this.option("grouped"))
  24241. return this.callBase($itemElement);
  24242. var $group = $itemElement.closest("." + LIST_GROUP_CLASS);
  24243. var $item = $group.find("." + LIST_ITEM_CLASS);
  24244. return $.extend(this.callBase($itemElement), {itemIndex: {
  24245. group: $group.index(),
  24246. item: $item.index($itemElement)
  24247. }})
  24248. },
  24249. expandGroup: function(groupIndex) {
  24250. var deferred = $.Deferred(),
  24251. $group = this._itemContainer().find("." + LIST_GROUP_CLASS).eq(groupIndex);
  24252. this._collapseGroupHandler($group, false).done($.proxy(function() {
  24253. deferred.resolveWith(this)
  24254. }, this));
  24255. return deferred.promise()
  24256. },
  24257. collapseGroup: function(groupIndex) {
  24258. var deferred = $.Deferred(),
  24259. $group = this._itemContainer().find("." + LIST_GROUP_CLASS).eq(groupIndex);
  24260. this._collapseGroupHandler($group, true).done($.proxy(function() {
  24261. deferred.resolveWith(this)
  24262. }, this));
  24263. return deferred
  24264. },
  24265. updateDimensions: function() {
  24266. var that = this,
  24267. deferred = $.Deferred();
  24268. if (that._scrollView)
  24269. that._scrollView.update().done(function() {
  24270. deferred.resolveWith(that)
  24271. });
  24272. else
  24273. deferred.resolveWith(that);
  24274. return deferred.promise()
  24275. },
  24276. reload: function() {
  24277. this.scrollTo(0);
  24278. this._pullDownHandler()
  24279. },
  24280. scrollTop: function() {
  24281. return this._scrollView.scrollOffset().top
  24282. },
  24283. clientHeight: function() {
  24284. return this._scrollView.clientHeight()
  24285. },
  24286. scrollHeight: function() {
  24287. return this._scrollView.scrollHeight()
  24288. },
  24289. scrollBy: function(distance) {
  24290. this._scrollView.scrollBy(distance)
  24291. },
  24292. scrollTo: function(location) {
  24293. this._scrollView.scrollTo(location)
  24294. },
  24295. scrollToItem: function(itemElement) {
  24296. var $item = this._editStrategy.getItemElement(itemElement);
  24297. this._scrollView.scrollToElement($item)
  24298. }
  24299. }))
  24300. })(jQuery, DevExpress);
  24301. /*! Module widgets-base, file ui.list.edit.js */
  24302. (function($, DX, undefined) {
  24303. var ui = DX.ui;
  24304. var LIST_ITEM_SELECTED_CLASS = "dx-list-item-selected",
  24305. LIST_ITEM_RESPONSE_WAIT_CLASS = "dx-list-item-response-wait";
  24306. DX.registerComponent("dxList", ui, ui.dxList.inherit({
  24307. _supportedKeys: function() {
  24308. var that = this,
  24309. parent = this.callBase();
  24310. var deleteFocusedItem = function(e) {
  24311. if (that.option("allowItemDeleting")) {
  24312. e.preventDefault();
  24313. that.deleteItem(that.option("focusedElement"))
  24314. }
  24315. };
  24316. var moveFocusedItemUp = function(e) {
  24317. if (e.shiftKey && that.option("allowItemReordering")) {
  24318. e.preventDefault();
  24319. var focusedItemIndex = that._editStrategy.getNormalizedIndex(that.option("focusedElement")),
  24320. $prevItem = that._editStrategy.getItemElement(focusedItemIndex - 1);
  24321. that.reorderItem(that.option("focusedElement"), $prevItem);
  24322. that.scrollToItem(that.option("focusedElement"))
  24323. }
  24324. else
  24325. parent.upArrow(e)
  24326. };
  24327. var moveFocusedItemDown = function(e) {
  24328. if (e.shiftKey && that.option("allowItemReordering")) {
  24329. e.preventDefault();
  24330. var focusedItemIndex = that._editStrategy.getNormalizedIndex(that.option("focusedElement")),
  24331. $nextItem = that._editStrategy.getItemElement(focusedItemIndex + 1);
  24332. that.reorderItem(that.option("focusedElement"), $nextItem);
  24333. that.scrollToItem(that.option("focusedElement"))
  24334. }
  24335. else
  24336. parent.downArrow(e)
  24337. };
  24338. return $.extend({}, parent, {
  24339. del: deleteFocusedItem,
  24340. upArrow: moveFocusedItemUp,
  24341. downArrow: moveFocusedItemDown
  24342. })
  24343. },
  24344. _setDeprecatedOptions: function() {
  24345. this.callBase();
  24346. $.extend(this._deprecatedOptions, {
  24347. itemDeleteAction: {
  24348. since: "14.2",
  24349. alias: "onItemDeleted"
  24350. },
  24351. itemReorderAction: {
  24352. since: "14.2",
  24353. alias: "onItemReordered"
  24354. },
  24355. itemUnselectAction: {
  24356. since: "14.2",
  24357. message: "Use the 'onSelectionChanged' option instead"
  24358. }
  24359. })
  24360. },
  24361. _setDefaultOptions: function() {
  24362. this.callBase();
  24363. this.option({
  24364. showSelectionControls: false,
  24365. selectionMode: 'none',
  24366. selectAllText: Globalize.localize("dxList-selectAll"),
  24367. menuItems: [],
  24368. menuMode: "context",
  24369. allowItemDeleting: false,
  24370. itemDeleteMode: "toggle",
  24371. allowItemReordering: false
  24372. })
  24373. },
  24374. _defaultOptionsRules: function() {
  24375. return this.callBase().concat([{
  24376. device: function(device) {
  24377. return device.platform === "ios"
  24378. },
  24379. options: {
  24380. menuMode: "slide",
  24381. itemDeleteMode: "slideItem"
  24382. }
  24383. }, {
  24384. device: {platform: "android"},
  24385. options: {itemDeleteMode: "swipe"}
  24386. }, {
  24387. device: {platform: "win8"},
  24388. options: {itemDeleteMode: "context"}
  24389. }, {
  24390. device: {platform: "generic"},
  24391. options: {itemDeleteMode: "static"}
  24392. }])
  24393. },
  24394. _init: function() {
  24395. this.callBase();
  24396. this._initEditProvider()
  24397. },
  24398. _initEditProvider: function() {
  24399. this._editProvider = new ui.dxList.EditProvider(this)
  24400. },
  24401. _disposeEditProvider: function() {
  24402. if (this._editProvider)
  24403. this._editProvider.dispose()
  24404. },
  24405. _refreshEditProvider: function() {
  24406. this._disposeEditProvider();
  24407. this._initEditProvider()
  24408. },
  24409. _initEditStrategy: function(grouped) {
  24410. if (this.option("grouped"))
  24411. this._editStrategy = new ui.dxList.GroupedEditStrategy(this);
  24412. else
  24413. this.callBase()
  24414. },
  24415. _render: function() {
  24416. this._refreshEditProvider();
  24417. this.callBase()
  24418. },
  24419. _renderItems: function() {
  24420. this.callBase.apply(this, arguments);
  24421. this._editProvider.afterItemsRendered()
  24422. },
  24423. _selectedItemClass: function() {
  24424. return LIST_ITEM_SELECTED_CLASS
  24425. },
  24426. _itemResponseWaitClass: function() {
  24427. return LIST_ITEM_RESPONSE_WAIT_CLASS
  24428. },
  24429. _itemClickHandler: function(e) {
  24430. var $itemElement = $(e.currentTarget);
  24431. if ($itemElement.is(".dx-state-disabled, .dx-state-disabled *"))
  24432. return;
  24433. var handledByEditProvider = this._editProvider.handleClick($itemElement, e);
  24434. if (handledByEditProvider)
  24435. return;
  24436. this.callBase.apply(this, arguments)
  24437. },
  24438. _shouldAttachContextMenuEvent: function() {
  24439. return this.callBase.apply(this, arguments) || this._editProvider.contextMenuHandlerExists()
  24440. },
  24441. _itemHoldHandler: function(e) {
  24442. var $itemElement = $(e.currentTarget);
  24443. if ($itemElement.is(".dx-state-disabled, .dx-state-disabled *"))
  24444. return;
  24445. var isTouchEvent = ui.events.isTouchEvent(e),
  24446. handledByEditProvider = isTouchEvent && this._editProvider.handleContextMenu($itemElement, e);
  24447. if (handledByEditProvider) {
  24448. e.handledByEditProvider = true;
  24449. return
  24450. }
  24451. this.callBase.apply(this, arguments)
  24452. },
  24453. _itemContextMenuHandler: function(e) {
  24454. var $itemElement = $(e.currentTarget);
  24455. if ($itemElement.is(".dx-state-disabled, .dx-state-disabled *"))
  24456. return;
  24457. var handledByEditProvider = !e.handledByEditProvider && this._editProvider.handleContextMenu($itemElement, e);
  24458. if (handledByEditProvider)
  24459. return;
  24460. this.callBase.apply(this, arguments)
  24461. },
  24462. _postprocessRenderItem: function(args) {
  24463. this.callBase.apply(this, arguments);
  24464. this._editProvider.modifyItemElement(args)
  24465. },
  24466. _clean: function() {
  24467. this._disposeEditProvider();
  24468. this.callBase()
  24469. },
  24470. _optionChanged: function(args) {
  24471. switch (args.name) {
  24472. case"items":
  24473. this._clearSelectedItems();
  24474. this.callBase(args);
  24475. break;
  24476. case"grouped":
  24477. this._clearSelectedItems();
  24478. delete this._renderingGroupIndex;
  24479. this._initEditStrategy(args.value);
  24480. this.callBase(args);
  24481. break;
  24482. case"showSelectionControls":
  24483. case"menuItems":
  24484. case"menuMode":
  24485. case"allowItemDeleting":
  24486. case"itemDeleteMode":
  24487. case"allowItemReordering":
  24488. case"selectAllText":
  24489. this._invalidate();
  24490. break;
  24491. default:
  24492. this.callBase(args)
  24493. }
  24494. },
  24495. getFlatIndexByItemElement: function(itemElement) {
  24496. return this._itemElements().index(itemElement)
  24497. },
  24498. getItemElementByFlatIndex: function(flatIndex) {
  24499. var $itemElements = this._itemElements();
  24500. if (flatIndex < 0 || flatIndex >= $itemElements.length)
  24501. return $();
  24502. return $itemElements.eq(flatIndex)
  24503. },
  24504. getItemByIndex: function(index) {
  24505. return this._getItemData(this._itemElements().eq(index))
  24506. }
  24507. }))
  24508. })(jQuery, DevExpress);
  24509. /*! Module widgets-base, file ui.list.edit.strategy.grouped.js */
  24510. (function($, DX, undefined) {
  24511. var ui = DX.ui;
  24512. var LIST_ITEM_CLASS = "dx-list-item",
  24513. LIST_GROUP_CLASS = "dx-list-group";
  24514. var SELECTION_SHIFT = 20,
  24515. SELECTION_MASK = 0x8FF;
  24516. var combineIndex = function(indices) {
  24517. return (indices.group << SELECTION_SHIFT) + indices.item
  24518. };
  24519. var splitIndex = function(combinedIndex) {
  24520. return {
  24521. group: combinedIndex >> SELECTION_SHIFT,
  24522. item: combinedIndex & SELECTION_MASK
  24523. }
  24524. };
  24525. var createGroupSelection = function(group, selectedItems) {
  24526. var groupItems = group.items,
  24527. groupSelection = {
  24528. key: group.key,
  24529. items: []
  24530. };
  24531. $.each(selectedItems, function(_, itemIndex) {
  24532. groupSelection.items.push(groupItems[itemIndex])
  24533. });
  24534. return groupSelection
  24535. };
  24536. var groupByKey = function(groups, key) {
  24537. var length = groups.length;
  24538. for (var i = 0; i < length; i++)
  24539. if (groups[i].key === key)
  24540. return groups[i]
  24541. };
  24542. ui.dxList.GroupedEditStrategy = ui.CollectionWidget.EditStrategy.inherit({
  24543. _groupElements: function() {
  24544. return this._collectionWidget._itemContainer().find("." + LIST_GROUP_CLASS)
  24545. },
  24546. _groupItemElements: function($group) {
  24547. return $group.find("." + LIST_ITEM_CLASS)
  24548. },
  24549. getIndexByItemData: function(itemData) {
  24550. return null
  24551. },
  24552. getItemDataByIndex: function(index) {
  24553. return null
  24554. },
  24555. deleteItemAtIndex: function(index) {
  24556. var indices = splitIndex(index),
  24557. itemGroup = this._collectionWidget.option("items")[indices.group].items;
  24558. itemGroup.splice(indices.item, 1)
  24559. },
  24560. updateSelectionAfterDelete: function(fromIndex) {
  24561. var deletedIndices = splitIndex(fromIndex),
  24562. selectedItemIndices = this._collectionWidget._selectedItemIndices;
  24563. $.each(selectedItemIndices, function(i, index) {
  24564. var indices = splitIndex(index);
  24565. if (indices.group === deletedIndices.group && indices.item > deletedIndices.item)
  24566. selectedItemIndices[i] -= 1
  24567. })
  24568. },
  24569. fetchSelectedItems: function(indices) {
  24570. indices = indices || this._collectionWidget._selectedItemIndices;
  24571. var items = this._collectionWidget.option("items"),
  24572. selectedItems = [];
  24573. indices.sort(function(a, b) {
  24574. return a - b
  24575. });
  24576. var currentGroupIndex = 0,
  24577. groupSelectedIndices = [];
  24578. $.each(indices, function(_, combinedIndex) {
  24579. var index = splitIndex(combinedIndex);
  24580. if (index.group !== currentGroupIndex && groupSelectedIndices.length) {
  24581. selectedItems.push(createGroupSelection(items[currentGroupIndex], groupSelectedIndices));
  24582. groupSelectedIndices.length = 0
  24583. }
  24584. currentGroupIndex = index.group;
  24585. groupSelectedIndices.push(index.item)
  24586. });
  24587. if (groupSelectedIndices.length)
  24588. selectedItems.push(createGroupSelection(items[currentGroupIndex], groupSelectedIndices));
  24589. return selectedItems
  24590. },
  24591. selectedItemIndices: function() {
  24592. var selectedIndices = [],
  24593. items = this._collectionWidget.option("items"),
  24594. selected = this._collectionWidget.option("selectedItems");
  24595. $.each(selected, function(_, selectionInGroup) {
  24596. var group = groupByKey(items, selectionInGroup.key),
  24597. groupIndex = $.inArray(group, items);
  24598. if (!group) {
  24599. DX.log("W1003", selectionInGroup.key);
  24600. return
  24601. }
  24602. $.each(selectionInGroup.items, function(_, selectedGroupItem) {
  24603. var itemIndex = $.inArray(selectedGroupItem, group.items);
  24604. if (itemIndex !== -1)
  24605. selectedIndices.push(combineIndex({
  24606. group: groupIndex,
  24607. item: itemIndex
  24608. }));
  24609. else
  24610. DX.log("W1004", selectedGroupItem, selectionInGroup.key)
  24611. })
  24612. });
  24613. return selectedIndices
  24614. },
  24615. moveItemAtIndexToIndex: function(movingIndex, destinationIndex) {
  24616. var items = this._collectionWidget.option("items"),
  24617. movingIndices = splitIndex(movingIndex),
  24618. destinationIndices = splitIndex(destinationIndex),
  24619. movingItemGroup = items[movingIndices.group].items,
  24620. destinationItemGroup = items[destinationIndices.group].items,
  24621. movedItemData = movingItemGroup[movingIndices.item];
  24622. movingItemGroup.splice(movingIndices.item, 1);
  24623. destinationItemGroup.splice(destinationIndices.item, 0, movedItemData)
  24624. },
  24625. getSelectedItemsAfterReorderItem: function(movingIndex, destinationIndex) {
  24626. if (this._itemsFromSameParent(movingIndex, destinationIndex) || $.inArray(movingIndex, this._collectionWidget._selectedItemIndices))
  24627. return this.callBase();
  24628. var items = this._collectionWidget.option("items"),
  24629. selectedItems = this._collectionWidget.option("selectedItems"),
  24630. movingIndices = splitIndex(movingIndex),
  24631. destinationIndices = splitIndex(destinationIndex),
  24632. movingSelectedItemGroup = selectedItems[movingIndices.group].items,
  24633. destinationSelectedItemGroup = selectedItems[destinationIndices.group].items,
  24634. movedItemData = items[movingIndices.group].items[movingIndices.item],
  24635. movedItemSelectedIndex = $.inArray(movedItemData, movingSelectedItemGroup);
  24636. movingSelectedItemGroup.splice(movedItemSelectedIndex, 1);
  24637. destinationSelectedItemGroup.push(movedItemData);
  24638. return selectedItems
  24639. },
  24640. _isItemIndex: function(index) {
  24641. return $.isNumeric(index.group) && $.isNumeric(index.item)
  24642. },
  24643. _getNormalizedItemIndex: function(itemElement) {
  24644. var $item = $(itemElement),
  24645. $group = $item.closest("." + LIST_GROUP_CLASS);
  24646. return combineIndex({
  24647. group: this._groupElements().index($group),
  24648. item: this._groupItemElements($group).index($item)
  24649. })
  24650. },
  24651. _normalizeItemIndex: function(index) {
  24652. return combineIndex(index)
  24653. },
  24654. _denormalizeItemIndex: function(index) {
  24655. return splitIndex(index)
  24656. },
  24657. _getItemByNormalizedIndex: function(index) {
  24658. var indices = splitIndex(index),
  24659. $group = this._groupElements().eq(indices.group);
  24660. return this._groupItemElements($group).eq(indices.item)
  24661. },
  24662. _itemsFromSameParent: function(firstIndex, secondIndex) {
  24663. return splitIndex(firstIndex).group === splitIndex(secondIndex).group
  24664. }
  24665. })
  24666. })(jQuery, DevExpress);
  24667. /*! Module widgets-base, file ui.list.edit.decorator.js */
  24668. (function($, DX, undefined) {
  24669. var ui = DX.ui,
  24670. events = ui.events;
  24671. ui.dxList.EditDecoratorsRegistry = {};
  24672. ui.dxList.registerEditDecorator = function(option, type, decoratorClass) {
  24673. var decoratorsRegistry = ui.dxList.EditDecoratorsRegistry;
  24674. var decoratorConfig = {};
  24675. decoratorConfig[option] = decoratorsRegistry[option] ? decoratorsRegistry[option] : {};
  24676. decoratorConfig[option][type] = decoratorClass;
  24677. decoratorsRegistry = $.extend(decoratorsRegistry, decoratorConfig)
  24678. };
  24679. var LIST_EDIT_DECORATOR = "dxListEditDecorator",
  24680. SWIPE_START_EVENT_NAME = events.addNamespace("dxswipestart", LIST_EDIT_DECORATOR),
  24681. SWIPE_UPDATE_EVENT_NAME = events.addNamespace("dxswipe", LIST_EDIT_DECORATOR),
  24682. SWIPE_END_EVENT_NAME = events.addNamespace("dxswipeend", LIST_EDIT_DECORATOR);
  24683. ui.dxList.EditDecorator = DX.Class.inherit({
  24684. ctor: function(list) {
  24685. this._list = list;
  24686. this._init()
  24687. },
  24688. _init: $.noop,
  24689. _shouldHandleSwipe: false,
  24690. _attachSwipeEvent: function(config) {
  24691. var swipeConfig = {itemSizeFunc: $.proxy(function() {
  24692. if (this._clearSwipeCache) {
  24693. this._itemWidthCache = this._list.element().width();
  24694. this._clearSwipeCache = false
  24695. }
  24696. return this._itemWidthCache
  24697. }, this)};
  24698. config.$itemElement.on(SWIPE_START_EVENT_NAME, swipeConfig, $.proxy(this._itemSwipeStartHandler, this)).on(SWIPE_UPDATE_EVENT_NAME, $.proxy(this._itemSwipeUpdateHandler, this)).on(SWIPE_END_EVENT_NAME, $.proxy(this._itemSwipeEndHandler, this))
  24699. },
  24700. _itemSwipeStartHandler: function(e) {
  24701. var $itemElement = $(e.currentTarget);
  24702. if ($itemElement.is(".dx-state-disabled, .dx-state-disabled *")) {
  24703. e.cancel = true;
  24704. return
  24705. }
  24706. this._swipeStartHandler($itemElement, e)
  24707. },
  24708. _itemSwipeUpdateHandler: function(e) {
  24709. var $itemElement = $(e.currentTarget);
  24710. this._swipeUpdateHandler($itemElement, e)
  24711. },
  24712. _itemSwipeEndHandler: function(e) {
  24713. var $itemElement = $(e.currentTarget);
  24714. this._swipeEndHandler($itemElement, e);
  24715. this._clearSwipeCache = true
  24716. },
  24717. beforeBag: $.noop,
  24718. afterBag: $.noop,
  24719. _commonOptions: function() {
  24720. return {
  24721. activeStateEnabled: this._list.option("activeStateEnabled"),
  24722. hoverStateEnabled: this._list.option("hoverStateEnabled"),
  24723. focusStateEnabled: this._list.option("focusStateEnabled")
  24724. }
  24725. },
  24726. modifyElement: function(config) {
  24727. if (this._shouldHandleSwipe) {
  24728. this._attachSwipeEvent(config);
  24729. this._clearSwipeCache = true
  24730. }
  24731. },
  24732. afterRender: $.noop,
  24733. handleClick: $.noop,
  24734. handleContextMenu: $.noop,
  24735. _swipeStartHandler: $.noop,
  24736. _swipeUpdateHandler: $.noop,
  24737. _swipeEndHandler: $.noop,
  24738. visibilityChange: $.noop,
  24739. dispose: $.noop
  24740. })
  24741. })(jQuery, DevExpress);
  24742. /*! Module widgets-base, file ui.list.edit.decoratorMenuHelper.js */
  24743. (function($, DX, undefined) {
  24744. var ui = DX.ui;
  24745. ui.dxList.EditDecoratorMenuHelperMixin = {
  24746. _menuEnabled: function() {
  24747. return !!this._menuItems().length
  24748. },
  24749. _menuItems: function() {
  24750. return this._list.option("menuItems")
  24751. },
  24752. _deleteEnabled: function() {
  24753. return this._list.option("allowItemDeleting")
  24754. },
  24755. _fireMenuAction: function($itemElement, action) {
  24756. this._list._itemEventHandlerByHandler($itemElement, action, {}, {excludeValidators: ["disabled", "readOnly"]})
  24757. }
  24758. }
  24759. })(jQuery, DevExpress);
  24760. /*! Module widgets-base, file ui.list.edit.decorator.static.js */
  24761. (function($, DX, undefined) {
  24762. var ui = DX.ui;
  24763. var STATIC_DELETE_BUTTON_CONTAINER_CLASS = "dx-list-static-delete-button-container",
  24764. STATIC_DELETE_BUTTON_CLASS = "dx-list-static-delete-button";
  24765. ui.dxList.registerEditDecorator("delete", "static", ui.dxList.EditDecorator.inherit({
  24766. afterBag: function(config) {
  24767. var $itemElement = config.$itemElement,
  24768. $container = config.$container;
  24769. var $button = $("<div>").addClass(STATIC_DELETE_BUTTON_CLASS);
  24770. this._list._createComponent($button, "dxButton", {
  24771. icon: "remove",
  24772. type: "danger",
  24773. onClick: $.proxy(function(e) {
  24774. this._deleteItem($itemElement)
  24775. }, this),
  24776. _templates: {}
  24777. });
  24778. $container.addClass(STATIC_DELETE_BUTTON_CONTAINER_CLASS).append($button)
  24779. },
  24780. _deleteItem: function($itemElement) {
  24781. if ($itemElement.is(".dx-state-disabled, .dx-state-disabled *"))
  24782. return;
  24783. this._list.deleteItem($itemElement)
  24784. }
  24785. }))
  24786. })(jQuery, DevExpress);
  24787. /*! Module widgets-base, file ui.list.edit.decorator.switchable.js */
  24788. (function($, DX, undefined) {
  24789. var ui = DX.ui,
  24790. events = ui.events;
  24791. var LIST_EDIT_DECORATOR = "dxListEditDecorator",
  24792. POINTER_DOWN_EVENT_NAME = events.addNamespace("dxpointerdown", LIST_EDIT_DECORATOR),
  24793. LIST_ITEM_CONTENT_CLASS = "dx-list-item-content",
  24794. SWITCHABLE_DELETE_READY_CLASS = "dx-list-switchable-delete-ready",
  24795. SWITCHABLE_MENU_SHIELD_POSITIONING_CLASS = "dx-list-switchable-menu-shield-positioning",
  24796. SWITCHABLE_DELETE_TOP_SHIELD_CLASS = "dx-list-switchable-delete-top-shield",
  24797. SWITCHABLE_DELETE_BOTTOM_SHIELD_CLASS = "dx-list-switchable-delete-bottom-shield",
  24798. SWITCHABLE_MENU_ITEM_SHIELD_POSITIONING_CLASS = "dx-list-switchable-menu-item-shield-positioning",
  24799. SWITCHABLE_DELETE_ITEM_CONTENT_SHIELD_CLASS = "dx-list-switchable-delete-item-content-shield";
  24800. ui.dxList.SwitchableEditDecorator = ui.dxList.EditDecorator.inherit({
  24801. _init: function() {
  24802. this._$topShield = $("<div />").addClass(SWITCHABLE_DELETE_TOP_SHIELD_CLASS);
  24803. this._$bottomShield = $("<div />").addClass(SWITCHABLE_DELETE_BOTTOM_SHIELD_CLASS);
  24804. this._$itemContentShield = $("<div />").addClass(SWITCHABLE_DELETE_ITEM_CONTENT_SHIELD_CLASS);
  24805. this._$topShield.on(POINTER_DOWN_EVENT_NAME, $.proxy(this._cancelDeleteReadyItem, this));
  24806. this._$bottomShield.on(POINTER_DOWN_EVENT_NAME, $.proxy(this._cancelDeleteReadyItem, this));
  24807. this._list.element().append(this._$topShield.toggle(false)).append(this._$bottomShield.toggle(false))
  24808. },
  24809. handleClick: function($itemElement) {
  24810. return this._cancelDeleteReadyItem()
  24811. },
  24812. _cancelDeleteReadyItem: function() {
  24813. if (!this._$readyToDeleteItem)
  24814. return false;
  24815. this._cancelDelete(this._$readyToDeleteItem);
  24816. return true
  24817. },
  24818. _cancelDelete: function($itemElement) {
  24819. this._toggleDeleteReady($itemElement, false)
  24820. },
  24821. _toggleDeleteReady: function($itemElement, readyToDelete) {
  24822. if (readyToDelete === undefined)
  24823. readyToDelete = !this._isReadyToDelete($itemElement);
  24824. this._toggleShields($itemElement, readyToDelete);
  24825. this._toggleScrolling(readyToDelete);
  24826. this._cacheReadyToDeleteItem($itemElement, readyToDelete);
  24827. this._animateToggleDelete($itemElement, readyToDelete)
  24828. },
  24829. _isReadyToDelete: function($itemElement) {
  24830. return $itemElement.hasClass(SWITCHABLE_DELETE_READY_CLASS)
  24831. },
  24832. _toggleShields: function($itemElement, enabled) {
  24833. this._list.element().toggleClass(SWITCHABLE_MENU_SHIELD_POSITIONING_CLASS, enabled);
  24834. this._$topShield.toggle(enabled);
  24835. this._$bottomShield.toggle(enabled);
  24836. if (enabled)
  24837. this._updateShieldsHeight($itemElement);
  24838. this._toggleContentShield($itemElement, enabled)
  24839. },
  24840. _updateShieldsHeight: function($itemElement) {
  24841. var $list = this._list.element(),
  24842. listTopOffset = $list.offset().top,
  24843. listHeight = $list.outerHeight(),
  24844. itemTopOffset = $itemElement.offset().top,
  24845. itemHeight = $itemElement.outerHeight(),
  24846. dirtyTopShieldHeight = itemTopOffset - listTopOffset,
  24847. dirtyBottomShieldHeight = listHeight - itemHeight - dirtyTopShieldHeight;
  24848. this._$topShield.height(Math.max(dirtyTopShieldHeight, 0));
  24849. this._$bottomShield.height(Math.max(dirtyBottomShieldHeight, 0))
  24850. },
  24851. _toggleContentShield: function($itemElement, enabled) {
  24852. if (enabled)
  24853. $itemElement.find("." + LIST_ITEM_CONTENT_CLASS).append(this._$itemContentShield);
  24854. else
  24855. this._$itemContentShield.detach()
  24856. },
  24857. _toggleScrolling: function(readyToDelete) {
  24858. var scrollView = this._list.element().dxScrollView("instance");
  24859. if (readyToDelete) {
  24860. this._scrollViewDisabled = scrollView.option("disabled");
  24861. scrollView.option("disabled", true)
  24862. }
  24863. else
  24864. scrollView.option("disabled", this._scrollViewDisabled)
  24865. },
  24866. _cacheReadyToDeleteItem: function($itemElement, cache) {
  24867. if (cache)
  24868. this._$readyToDeleteItem = $itemElement;
  24869. else
  24870. delete this._$readyToDeleteItem
  24871. },
  24872. _animateToggleDelete: function($itemElement, readyToDelete) {
  24873. if (readyToDelete) {
  24874. this._enablePositioning($itemElement);
  24875. this._prepareDeleteReady($itemElement);
  24876. this._animatePrepareDeleteReady($itemElement)
  24877. }
  24878. else {
  24879. this._forgetDeleteReady($itemElement);
  24880. this._animateForgetDeleteReady($itemElement).done($.proxy(this._disablePositioning, this, $itemElement))
  24881. }
  24882. },
  24883. _enablePositioning: function($itemElement) {
  24884. $itemElement.addClass(SWITCHABLE_MENU_ITEM_SHIELD_POSITIONING_CLASS)
  24885. },
  24886. _disablePositioning: function($itemElement) {
  24887. $itemElement.removeClass(SWITCHABLE_MENU_ITEM_SHIELD_POSITIONING_CLASS)
  24888. },
  24889. _prepareDeleteReady: function($itemElement) {
  24890. $itemElement.addClass(SWITCHABLE_DELETE_READY_CLASS)
  24891. },
  24892. _forgetDeleteReady: function($itemElement) {
  24893. $itemElement.removeClass(SWITCHABLE_DELETE_READY_CLASS)
  24894. },
  24895. _animatePrepareDeleteReady: DX.abstract,
  24896. _animateForgetDeleteReady: DX.abstract,
  24897. _deleteItem: function($itemElement) {
  24898. $itemElement = $itemElement || this._$readyToDeleteItem;
  24899. if ($itemElement.is(".dx-state-disabled, .dx-state-disabled *"))
  24900. return;
  24901. this._list.deleteItem($itemElement).always($.proxy(this._cancelDelete, this, $itemElement))
  24902. },
  24903. _isRtlEnabled: function() {
  24904. return this._list.option("rtlEnabled")
  24905. },
  24906. dispose: function() {
  24907. if (this._$topShield)
  24908. this._$topShield.remove();
  24909. if (this._$bottomShield)
  24910. this._$bottomShield.remove();
  24911. this.callBase.apply(this, arguments)
  24912. }
  24913. })
  24914. })(jQuery, DevExpress);
  24915. /*! Module widgets-base, file ui.list.edit.decorator.switchable.button.js */
  24916. (function($, DX, undefined) {
  24917. var ui = DX.ui,
  24918. fx = DX.fx;
  24919. var SWITCHABLE_DELETE_BUTTON_CONTAINER_CLASS = "dx-list-switchable-delete-button-container",
  24920. SWITCHABLE_DELETE_BUTTON_WRAPPER_CLASS = "dx-list-switchable-delete-button-wrapper",
  24921. SWITCHABLE_DELETE_BUTTON_INNER_WRAPPER_CLASS = "dx-list-switchable-delete-button-inner-wrapper",
  24922. SWITCHABLE_DELETE_BUTTON_CLASS = "dx-list-switchable-delete-button",
  24923. SWITCHABLE_DELETE_BUTTON_ANIMATION_DURATION = 200;
  24924. ui.dxList.SwitchableButtonEditDecorator = ui.dxList.SwitchableEditDecorator.inherit({
  24925. _init: function() {
  24926. this.callBase.apply(this, arguments);
  24927. var $buttonContainer = $("<div >").addClass(SWITCHABLE_DELETE_BUTTON_CONTAINER_CLASS),
  24928. $buttonWrapper = $("<div />").addClass(SWITCHABLE_DELETE_BUTTON_WRAPPER_CLASS),
  24929. $buttonInnerWrapper = $("<div />").addClass(SWITCHABLE_DELETE_BUTTON_INNER_WRAPPER_CLASS),
  24930. $button = $("<div />").addClass(SWITCHABLE_DELETE_BUTTON_CLASS);
  24931. this._list._createComponent($button, "dxButton", {
  24932. text: Globalize.localize("dxListEditDecorator-delete"),
  24933. type: "danger",
  24934. onClick: $.proxy(function(e) {
  24935. this._deleteItem();
  24936. e.jQueryEvent.stopPropagation()
  24937. }, this),
  24938. _templates: {}
  24939. });
  24940. $buttonContainer.append($buttonWrapper);
  24941. $buttonWrapper.append($buttonInnerWrapper);
  24942. $buttonInnerWrapper.append($button);
  24943. this._$buttonContainer = $buttonContainer
  24944. },
  24945. _enablePositioning: function($itemElement) {
  24946. this.callBase.apply(this, arguments);
  24947. fx.stop(this._$buttonContainer, true);
  24948. this._$buttonContainer.appendTo($itemElement)
  24949. },
  24950. _disablePositioning: function() {
  24951. this.callBase.apply(this, arguments);
  24952. this._$buttonContainer.detach()
  24953. },
  24954. _animatePrepareDeleteReady: function() {
  24955. var rtl = this._isRtlEnabled(),
  24956. listWidth = this._list.element().width(),
  24957. buttonWidth = this._buttonWidth(),
  24958. fromValue = rtl ? listWidth : -buttonWidth,
  24959. toValue = rtl ? listWidth - buttonWidth : 0;
  24960. return fx.animate(this._$buttonContainer, {
  24961. type: "custom",
  24962. duration: SWITCHABLE_DELETE_BUTTON_ANIMATION_DURATION,
  24963. from: {right: fromValue},
  24964. to: {right: toValue}
  24965. })
  24966. },
  24967. _animateForgetDeleteReady: function() {
  24968. var rtl = this._isRtlEnabled(),
  24969. listWidth = this._list.element().width(),
  24970. buttonWidth = this._buttonWidth(),
  24971. fromValue = rtl ? listWidth - buttonWidth : 0,
  24972. toValue = rtl ? listWidth : -buttonWidth;
  24973. return fx.animate(this._$buttonContainer, {
  24974. type: "custom",
  24975. duration: SWITCHABLE_DELETE_BUTTON_ANIMATION_DURATION,
  24976. from: {right: fromValue},
  24977. to: {right: toValue}
  24978. })
  24979. },
  24980. _buttonWidth: function() {
  24981. if (!this._buttonContainerWidth)
  24982. this._buttonContainerWidth = this._$buttonContainer.outerWidth();
  24983. return this._buttonContainerWidth
  24984. },
  24985. dispose: function() {
  24986. if (this._$buttonContainer)
  24987. this._$buttonContainer.remove();
  24988. this.callBase.apply(this, arguments)
  24989. }
  24990. });
  24991. var TOGGLE_DELETE_SWITCH_CONTAINER_CLASS = "dx-list-toggle-delete-switch-container",
  24992. TOGGLE_DELETE_SWITCH_CLASS = "dx-list-toggle-delete-switch";
  24993. ui.dxList.registerEditDecorator("delete", "toggle", ui.dxList.SwitchableButtonEditDecorator.inherit({beforeBag: function(config) {
  24994. var $itemElement = config.$itemElement,
  24995. $container = config.$container;
  24996. var $toggle = $("<div />").addClass(TOGGLE_DELETE_SWITCH_CLASS);
  24997. this._list._createComponent($toggle, "dxButton", {
  24998. icon: "toggle-delete",
  24999. onClick: $.proxy(function(e) {
  25000. this._toggleDeleteReady($itemElement);
  25001. e.jQueryEvent.stopPropagation()
  25002. }, this),
  25003. _templates: {}
  25004. });
  25005. $container.addClass(TOGGLE_DELETE_SWITCH_CONTAINER_CLASS);
  25006. $container.append($toggle)
  25007. }}));
  25008. ui.dxList.registerEditDecorator("delete", "slideButton", ui.dxList.SwitchableButtonEditDecorator.inherit({
  25009. _shouldHandleSwipe: true,
  25010. _swipeEndHandler: function($itemElement, args) {
  25011. if (args.targetOffset !== 0)
  25012. this._toggleDeleteReady($itemElement);
  25013. return true
  25014. }
  25015. }))
  25016. })(jQuery, DevExpress);
  25017. /*! Module widgets-base, file ui.list.edit.decorator.switchable.slide.js */
  25018. (function($, DX, undefined) {
  25019. var ui = DX.ui,
  25020. events = ui.events,
  25021. translator = DX.translator,
  25022. fx = DX.fx;
  25023. var LIST_EDIT_DECORATOR = "dxListEditDecorator",
  25024. CLICK_EVENT_NAME = events.addNamespace("dxclick", LIST_EDIT_DECORATOR),
  25025. SLIDE_MENU_CLASS = "dx-list-slide-menu",
  25026. SLIDE_MENU_WRAPPER_CLASS = "dx-list-slide-menu-wrapper",
  25027. SLIDE_MENU_CONTENT_CLASS = "dx-list-slide-menu-content",
  25028. SLIDE_MENU_BUTTONS_CONTAINER_CLASS = "dx-list-slide-menu-buttons-container",
  25029. SLIDE_MENU_BUTTONS_CLASS = "dx-list-slide-menu-buttons",
  25030. SLIDE_MENU_BUTTON_CLASS = "dx-list-slide-menu-button",
  25031. SLIDE_MENU_BUTTON_MENU_CLASS = "dx-list-slide-menu-button-menu",
  25032. SLIDE_MENU_BUTTON_DELETE_CLASS = "dx-list-slide-menu-button-delete";
  25033. ui.dxList.registerEditDecorator("menu", "slide", ui.dxList.SwitchableEditDecorator.inherit({
  25034. _shouldHandleSwipe: true,
  25035. _init: function() {
  25036. this.callBase.apply(this, arguments);
  25037. this._$buttonsContainer = $("<div/>").addClass(SLIDE_MENU_BUTTONS_CONTAINER_CLASS);
  25038. this._$buttons = $("<div/>").addClass(SLIDE_MENU_BUTTONS_CLASS).appendTo(this._$buttonsContainer);
  25039. this._renderMenu();
  25040. this._renderDeleteButton()
  25041. },
  25042. _renderMenu: function() {
  25043. if (!this._menuEnabled())
  25044. return;
  25045. var menuItems = this._menuItems();
  25046. if (menuItems.length === 1) {
  25047. var menuItem = menuItems[0];
  25048. this._renderMenuButton(menuItem.text, $.proxy(function() {
  25049. this._fireAction(menuItem)
  25050. }, this))
  25051. }
  25052. else {
  25053. var $menu = $("<div />").addClass(SLIDE_MENU_CLASS);
  25054. this._menu = this._list._createComponent($menu, "dxActionSheet", {
  25055. showTitle: false,
  25056. items: menuItems,
  25057. onItemClick: $.proxy(function(args) {
  25058. this._fireAction(args.itemData)
  25059. }, this),
  25060. _templates: {}
  25061. });
  25062. $menu.appendTo(this._list.element());
  25063. var $menuButton = this._renderMenuButton(Globalize.localize("dxListEditDecorator-more"), $.proxy(this._menu.show, this._menu));
  25064. this._menu.option("target", $menuButton)
  25065. }
  25066. },
  25067. _renderMenuButton: function(text, action) {
  25068. var $menuButton = $("<div/>").addClass(SLIDE_MENU_BUTTON_CLASS).addClass(SLIDE_MENU_BUTTON_MENU_CLASS).text(text);
  25069. this._$buttons.append($menuButton);
  25070. $menuButton.on(CLICK_EVENT_NAME, action);
  25071. return $menuButton
  25072. },
  25073. _renderDeleteButton: function() {
  25074. if (!this._deleteEnabled())
  25075. return;
  25076. var $deleteButton = $("<div/>").addClass(SLIDE_MENU_BUTTON_CLASS).addClass(SLIDE_MENU_BUTTON_DELETE_CLASS).text(Globalize.localize("dxListEditDecorator-delete"));
  25077. $deleteButton.on(CLICK_EVENT_NAME, $.proxy(function() {
  25078. this._deleteItem()
  25079. }, this));
  25080. this._$buttons.append($deleteButton)
  25081. },
  25082. _fireAction: function(menuItem) {
  25083. this._fireMenuAction($(this._cachedNode), menuItem.action);
  25084. this._cancelDeleteReadyItem()
  25085. },
  25086. modifyElement: function(config) {
  25087. this.callBase.apply(this, arguments);
  25088. var $itemElement = config.$itemElement;
  25089. $itemElement.addClass(SLIDE_MENU_WRAPPER_CLASS);
  25090. var $slideMenuContent = $("<div/>").addClass(SLIDE_MENU_CONTENT_CLASS);
  25091. $itemElement.wrapInner($slideMenuContent)
  25092. },
  25093. handleClick: function(_, e) {
  25094. if ($(e.target).closest("." + SLIDE_MENU_CONTENT_CLASS).length)
  25095. return this.callBase.apply(this, arguments);
  25096. return false
  25097. },
  25098. _swipeStartHandler: function($itemElement) {
  25099. this._enablePositioning($itemElement);
  25100. this._cacheItemData($itemElement)
  25101. },
  25102. _swipeUpdateHandler: function($itemElement, args) {
  25103. var rtl = this._isRtlEnabled(),
  25104. signCorrection = rtl ? -1 : 1,
  25105. offset = this._cachedItemWidth * args.offset,
  25106. startOffset = this._isReadyToDelete($itemElement) ? -this._cachedButtonWidth * signCorrection : 0,
  25107. correctedOffset = (offset + startOffset) * signCorrection,
  25108. contentPosition = correctedOffset < 0 ? offset + startOffset : 0,
  25109. buttonPosition = correctedOffset < 0 ? correctedOffset : 0;
  25110. translator.move(this._$cachedContent, {left: contentPosition});
  25111. this._$buttonsContainer.css(rtl ? "right" : "left", Math.max(this._cachedItemWidth + buttonPosition, this._minButtonContainerLeftOffset()));
  25112. return true
  25113. },
  25114. _cacheItemData: function($itemElement) {
  25115. if ($itemElement[0] === this._cachedNode)
  25116. return;
  25117. this._$cachedContent = $itemElement.find("." + SLIDE_MENU_CONTENT_CLASS);
  25118. this._cachedItemWidth = $itemElement.outerWidth();
  25119. this._cachedButtonWidth = this._cachedButtonWidth || $itemElement.find("." + SLIDE_MENU_BUTTONS_CLASS).outerWidth();
  25120. if (this._$cachedContent.length)
  25121. this._cachedNode = $itemElement[0]
  25122. },
  25123. _minButtonContainerLeftOffset: function() {
  25124. return this._cachedItemWidth - this._cachedButtonWidth
  25125. },
  25126. _swipeEndHandler: function($itemElement, args) {
  25127. this._cacheItemData($itemElement);
  25128. var signCorrection = this._isRtlEnabled() ? 1 : -1,
  25129. offset = this._cachedItemWidth * args.offset,
  25130. endedAtReadyToDelete = !this._isReadyToDelete($itemElement) && offset * signCorrection > this._cachedButtonWidth * 0.2,
  25131. readyToDelete = args.targetOffset === signCorrection || endedAtReadyToDelete;
  25132. this._toggleDeleteReady($itemElement, readyToDelete);
  25133. return true
  25134. },
  25135. _enablePositioning: function($itemElement) {
  25136. this.callBase.apply(this, arguments);
  25137. this._$buttonsContainer.appendTo($itemElement)
  25138. },
  25139. _disablePositioning: function($itemElement) {
  25140. this.callBase.apply(this, arguments);
  25141. this._$buttonsContainer.detach()
  25142. },
  25143. _animatePrepareDeleteReady: function() {
  25144. var rtl = this._isRtlEnabled(),
  25145. directionCorrection = rtl ? 1 : -1;
  25146. this._$buttonsContainer.css(rtl ? "left" : "right", "0");
  25147. var contentAnimation = fx.animate(this._$cachedContent, {
  25148. to: {left: this._cachedButtonWidth * directionCorrection},
  25149. type: "slide",
  25150. duration: 200
  25151. });
  25152. var direction = rtl ? "right" : "left",
  25153. buttonToAnimation = {};
  25154. buttonToAnimation[direction] = this._minButtonContainerLeftOffset();
  25155. var buttonAnimation = fx.animate(this._$buttonsContainer, {
  25156. to: buttonToAnimation,
  25157. duration: 200
  25158. });
  25159. return $.when(contentAnimation, buttonAnimation).promise()
  25160. },
  25161. _animateForgetDeleteReady: function($itemElement) {
  25162. this._cacheItemData($itemElement);
  25163. var rtl = this._isRtlEnabled();
  25164. this._$buttonsContainer.css(rtl ? "left" : "right", "0");
  25165. var contentAnimation = fx.animate(this._$cachedContent, {
  25166. to: {left: 0},
  25167. type: "slide",
  25168. duration: 200
  25169. });
  25170. var direction = rtl ? "right" : "left",
  25171. buttonToAnimation = {};
  25172. buttonToAnimation[direction] = this._cachedItemWidth;
  25173. var buttonAnimation = fx.animate(this._$buttonsContainer, {
  25174. to: buttonToAnimation,
  25175. duration: 200,
  25176. complete: $.proxy(function() {
  25177. this._$buttonsContainer.css(direction, "100%")
  25178. }, this)
  25179. });
  25180. return $.when(contentAnimation, buttonAnimation).promise()
  25181. },
  25182. dispose: function() {
  25183. if (this._menu)
  25184. this._menu.element().remove();
  25185. if (this._$buttonsContainer)
  25186. this._$buttonsContainer.remove();
  25187. this.callBase.apply(this, arguments)
  25188. }
  25189. }).include(ui.dxList.EditDecoratorMenuHelperMixin))
  25190. })(jQuery, DevExpress);
  25191. /*! Module widgets-base, file ui.list.edit.decorator.swipe.js */
  25192. (function($, DX, undefined) {
  25193. var ui = DX.ui,
  25194. translator = DX.translator,
  25195. fx = DX.fx;
  25196. ui.dxList.registerEditDecorator("delete", "swipe", ui.dxList.EditDecorator.inherit({
  25197. _shouldHandleSwipe: true,
  25198. _renderItemPosition: function($itemElement, offset, animate) {
  25199. var deferred = $.Deferred(),
  25200. itemOffset = offset * this._itemElementWidth;
  25201. if (animate)
  25202. fx.animate($itemElement, {
  25203. to: {left: itemOffset},
  25204. type: "slide",
  25205. complete: function() {
  25206. deferred.resolve($itemElement, offset)
  25207. }
  25208. });
  25209. else {
  25210. translator.move($itemElement, {left: itemOffset});
  25211. deferred.resolve()
  25212. }
  25213. return deferred.promise()
  25214. },
  25215. _swipeStartHandler: function($itemElement) {
  25216. this._itemElementWidth = $itemElement.width();
  25217. return true
  25218. },
  25219. _swipeUpdateHandler: function($itemElement, args) {
  25220. this._renderItemPosition($itemElement, args.offset);
  25221. return true
  25222. },
  25223. _swipeEndHandler: function($itemElement, args) {
  25224. var offset = args.targetOffset;
  25225. this._renderItemPosition($itemElement, offset, true).done($.proxy(function($itemElement, offset) {
  25226. if (Math.abs(offset))
  25227. this._list.deleteItem($itemElement).fail($.proxy(function() {
  25228. this._renderItemPosition($itemElement, 0, true)
  25229. }, this))
  25230. }, this));
  25231. return true
  25232. }
  25233. }))
  25234. })(jQuery, DevExpress);
  25235. /*! Module widgets-base, file ui.list.edit.decorator.context.js */
  25236. (function($, DX, undefined) {
  25237. var ui = DX.ui;
  25238. var CONTEXTMENU_CLASS = "dx-list-context-menu",
  25239. CONTEXTMENU_MENUCONTENT_CLASS = "dx-list-context-menucontent";
  25240. ui.dxList.registerEditDecorator("menu", "context", ui.dxList.EditDecorator.inherit({
  25241. _init: function() {
  25242. var $menu = $("<div/>").addClass(CONTEXTMENU_CLASS);
  25243. this._list.element().append($menu);
  25244. this._menu = this._renderOverlay($menu)
  25245. },
  25246. _renderOverlay: function($element) {
  25247. return this._list._createComponent($element, "dxOverlay", {
  25248. shading: false,
  25249. deferRendering: true,
  25250. closeOnTargetScroll: true,
  25251. closeOnOutsideClick: function(e) {
  25252. return !$(e.target).closest("." + CONTEXTMENU_CLASS).length
  25253. },
  25254. animation: {
  25255. show: {
  25256. type: "slide",
  25257. duration: 300,
  25258. from: {
  25259. height: 0,
  25260. opacity: 1
  25261. },
  25262. to: {
  25263. height: $.proxy(function() {
  25264. return this._$menuList.outerHeight()
  25265. }, this),
  25266. opacity: 1
  25267. }
  25268. },
  25269. hide: {
  25270. type: "slide",
  25271. duration: 0,
  25272. from: {opacity: 1},
  25273. to: {opacity: 0}
  25274. }
  25275. },
  25276. height: $.proxy(function() {
  25277. return this._$menuList ? this._$menuList.outerHeight() : 0
  25278. }, this),
  25279. width: $.proxy(function() {
  25280. return this._list.element().outerWidth()
  25281. }, this),
  25282. onContentReady: $.proxy(this._renderMenuContent, this)
  25283. })
  25284. },
  25285. _renderMenuContent: function(e) {
  25286. var $overlayContent = e.component.content();
  25287. var items = this._menuItems().slice();
  25288. if (this._deleteEnabled())
  25289. items.push({
  25290. text: Globalize.localize("dxListEditDecorator-delete"),
  25291. action: $.proxy(this._deleteItem, this)
  25292. });
  25293. this._$menuList = $("<div>");
  25294. this._list._createComponent(this._$menuList, "dxList", {
  25295. items: items,
  25296. onItemClick: $.proxy(this._menuItemClickHandler, this),
  25297. height: "auto",
  25298. _templates: {}
  25299. });
  25300. $overlayContent.addClass(CONTEXTMENU_MENUCONTENT_CLASS);
  25301. $overlayContent.append(this._$menuList)
  25302. },
  25303. _menuItemClickHandler: function(args) {
  25304. this._menu.hide();
  25305. this._fireMenuAction(this._$itemWithMenu, args.itemData.action)
  25306. },
  25307. _deleteItem: function() {
  25308. this._list.deleteItem(this._$itemWithMenu)
  25309. },
  25310. handleContextMenu: function($itemElement) {
  25311. this._$itemWithMenu = $itemElement;
  25312. this._menu.option({position: {
  25313. my: "top",
  25314. at: "bottom",
  25315. of: $itemElement,
  25316. collision: "flip"
  25317. }});
  25318. this._menu.show();
  25319. return true
  25320. },
  25321. dispose: function() {
  25322. if (this._menu)
  25323. this._menu.element().remove();
  25324. this.callBase.apply(this, arguments)
  25325. }
  25326. }).include(ui.dxList.EditDecoratorMenuHelperMixin))
  25327. })(jQuery, DevExpress);
  25328. /*! Module widgets-base, file ui.list.edit.decorator.selection.js */
  25329. (function($, DX, undefined) {
  25330. var ui = DX.ui,
  25331. events = ui.events;
  25332. var SELECT_DECORATOR_ENABLED_CLASS = "dx-list-select-decorator-enabled",
  25333. SELECT_DECORATOR_SELECT_ALL_CLASS = "dx-list-select-all",
  25334. SELECT_DECORATOR_SELECT_ALL_CHECKBOX_CLASS = "dx-list-select-all-checkbox",
  25335. SELECT_DECORATOR_SELECT_ALL_LABEL_CLASS = "dx-list-select-all-label",
  25336. SELECT_CHECKBOX_CONTAINER_CLASS = "dx-list-select-checkbox-container",
  25337. SELECT_CHECKBOX_CLASS = "dx-list-select-checkbox",
  25338. SELECT_RADIO_BUTTON_CONTAINER_CLASS = "dx-list-select-radiobutton-container",
  25339. SELECT_RADIO_BUTTON_CLASS = "dx-list-select-radiobutton";
  25340. var CLICK_EVENT_NAME = events.addNamespace("dxclick", "dxListEditDecorator");
  25341. ui.dxList.registerEditDecorator("selection", "default", ui.dxList.EditDecorator.inherit({
  25342. _init: function() {
  25343. this.callBase.apply(this, arguments);
  25344. var selectionMode = this._list.option("selectionMode");
  25345. this._singleStrategy = selectionMode === "single";
  25346. this._containerClass = this._singleStrategy ? SELECT_RADIO_BUTTON_CONTAINER_CLASS : SELECT_CHECKBOX_CONTAINER_CLASS;
  25347. this._controlClass = this._singleStrategy ? SELECT_RADIO_BUTTON_CLASS : SELECT_CHECKBOX_CLASS;
  25348. this._controlWidget = this._singleStrategy ? "dxRadioButton" : "dxCheckBox";
  25349. this._list.element().addClass(SELECT_DECORATOR_ENABLED_CLASS)
  25350. },
  25351. beforeBag: function(config) {
  25352. var $itemElement = config.$itemElement,
  25353. $container = config.$container;
  25354. var $control = $("<div />").addClass(this._controlClass);
  25355. $control[this._controlWidget]($.extend(this._commonOptions(), {
  25356. value: this._isSelected($itemElement),
  25357. focusStateEnabled: false,
  25358. hoverStateEnabled: false,
  25359. onValueChanged: $.proxy(function(e) {
  25360. this._processCheckedState($itemElement, e.value);
  25361. e.jQueryEvent && e.jQueryEvent.stopPropagation()
  25362. }, this)
  25363. }));
  25364. $container.addClass(this._containerClass);
  25365. $container.append($control)
  25366. },
  25367. modifyElement: function(config) {
  25368. this.callBase.apply(this, arguments);
  25369. var $itemElement = config.$itemElement,
  25370. control = $itemElement.find("." + this._controlClass)[this._controlWidget]("instance");
  25371. $itemElement.on("stateChanged", $.proxy(function() {
  25372. control.option("value", this._isSelected($itemElement));
  25373. this._updateSelectAllState()
  25374. }, this))
  25375. },
  25376. _updateSelectAllState: function() {
  25377. if (!this._$selectAll)
  25378. return;
  25379. var items = this._list.option("items");
  25380. var selectedItems = this._list.option("selectedItems");
  25381. var isSelectedAll = items.length === selectedItems.length ? true : selectedItems.length === 0 ? false : undefined;
  25382. this._selectAllCheckBox.option("value", isSelectedAll)
  25383. },
  25384. afterRender: function() {
  25385. if (this._list.option("selectionMode") !== "all")
  25386. return;
  25387. if (!this._$selectAll)
  25388. this._renderSelectAll();
  25389. if (this._selectAllCheckBox.option("value"))
  25390. this._selectAllItems()
  25391. },
  25392. _renderSelectAll: function() {
  25393. var $selectAll = this._$selectAll = $("<div>").addClass(SELECT_DECORATOR_SELECT_ALL_CLASS);
  25394. this._selectAllCheckBox = this._list._createComponent($("<div>").addClass(SELECT_DECORATOR_SELECT_ALL_CHECKBOX_CLASS).appendTo($selectAll), "dxCheckBox");
  25395. $("<div>").addClass(SELECT_DECORATOR_SELECT_ALL_LABEL_CLASS).text(this._list.option("selectAllText")).appendTo($selectAll);
  25396. this._list.itemsContainer().prepend($selectAll);
  25397. this._updateSelectAllState();
  25398. this._attachSelectAllHandler()
  25399. },
  25400. _attachSelectAllHandler: function() {
  25401. this._selectAllCheckBox.option("onValueChanged", $.proxy(this._selectAllHandler, this));
  25402. this._$selectAll.off(CLICK_EVENT_NAME).on(CLICK_EVENT_NAME, $.proxy(this._selectAllClickHandler, this))
  25403. },
  25404. _selectAllHandler: function(e) {
  25405. var isSelectedAll = this._selectAllCheckBox.option("value");
  25406. if (isSelectedAll === true)
  25407. this._selectAllItems();
  25408. else if (isSelectedAll === false)
  25409. this._unselectAllItems();
  25410. e.jQueryEvent && e.jQueryEvent.stopPropagation()
  25411. },
  25412. _selectAllItems: function() {
  25413. this._list.option("selectedItems", this._list.option("items").slice())
  25414. },
  25415. _unselectAllItems: function() {
  25416. this._list.option("selectedItems", [])
  25417. },
  25418. _selectAllClickHandler: function() {
  25419. this._selectAllCheckBox.option("value", !this._selectAllCheckBox.option("value"))
  25420. },
  25421. _isSelected: function($itemElement) {
  25422. return this._list.isItemSelected($itemElement)
  25423. },
  25424. _processCheckedState: function($itemElement, checked) {
  25425. if (checked)
  25426. this._list.selectItem($itemElement);
  25427. else
  25428. this._list.unselectItem($itemElement)
  25429. },
  25430. dispose: function() {
  25431. this._disposeSelectAll();
  25432. this._list.element().removeClass(SELECT_DECORATOR_ENABLED_CLASS);
  25433. this.callBase.apply(this, arguments)
  25434. },
  25435. _disposeSelectAll: function() {
  25436. if (this._$selectAll) {
  25437. this._$selectAll.remove();
  25438. this._$selectAll = null
  25439. }
  25440. },
  25441. handleClick: function($itemElement) {
  25442. var newState = !this._isSelected($itemElement) || this._singleStrategy;
  25443. this._processCheckedState($itemElement, newState);
  25444. return true
  25445. }
  25446. }))
  25447. })(jQuery, DevExpress);
  25448. /*! Module widgets-base, file ui.list.edit.decorator.reorder.js */
  25449. (function($, DX, undefined) {
  25450. var ui = DX.ui,
  25451. events = ui.events,
  25452. translator = DX.translator,
  25453. fx = DX.fx,
  25454. support = DX.support,
  25455. utils = DX.utils,
  25456. fitIntoRange = utils.fitIntoRange;
  25457. var ReorderScrollAnimator = DX.Animator.inherit({
  25458. ctor: function(strategy) {
  25459. this.callBase();
  25460. this._strategy = strategy
  25461. },
  25462. _isFinished: function() {
  25463. return this._strategy.scrollFinished()
  25464. },
  25465. _step: function() {
  25466. this._strategy.scrollByStep()
  25467. }
  25468. });
  25469. var LIST_EDIT_DECORATOR = "dxListEditDecorator",
  25470. DRAG_START_EVENT_NAME = events.addNamespace("dxdragstart", LIST_EDIT_DECORATOR),
  25471. DRAG_UPDATE_EVENT_NAME = events.addNamespace("dxdrag", LIST_EDIT_DECORATOR),
  25472. DRAG_END_EVENT_NAME = events.addNamespace("dxdragend", LIST_EDIT_DECORATOR),
  25473. REORDER_HANDLE_CONTAINER_CLASS = "dx-list-reorder-handle-container",
  25474. REORDER_HANDLE_CLASS = "dx-list-reorder-handle",
  25475. REOREDERING_ITEM_CLASS = "dx-list-item-reordering",
  25476. REOREDERING_ITEM_GHOST_CLASS = "dx-list-item-ghost-reordering",
  25477. LIST_REORDER_COMPATIBILITY_MODE_CLASS = "dx-list-reorder-compatibility-mode";
  25478. ui.dxList.registerEditDecorator("reorder", "default", ui.dxList.EditDecorator.inherit({
  25479. _init: function() {
  25480. this._groupedEnabled = this._list.option("grouped");
  25481. this._initAnimator()
  25482. },
  25483. _initAnimator: function() {
  25484. this._scrollAnimator = new ReorderScrollAnimator(this)
  25485. },
  25486. _startAnimator: function() {
  25487. if (!this._scrollAnimator.inProgress())
  25488. this._scrollAnimator.start()
  25489. },
  25490. _stopAnimator: function() {
  25491. this._scrollAnimator.stop()
  25492. },
  25493. afterBag: function(config) {
  25494. var $itemElement = config.$itemElement,
  25495. $container = config.$container;
  25496. var $handle = $("<div>").addClass(REORDER_HANDLE_CLASS);
  25497. $handle.on(DRAG_START_EVENT_NAME, {
  25498. direction: "vertical",
  25499. immediate: true
  25500. }, $.proxy(this._dragStartHandler, this, $itemElement));
  25501. $handle.on(DRAG_UPDATE_EVENT_NAME, $.proxy(this._dragHandler, this, $itemElement));
  25502. $handle.on(DRAG_END_EVENT_NAME, $.proxy(this._dragEndHandler, this, $itemElement));
  25503. $container.addClass(REORDER_HANDLE_CONTAINER_CLASS);
  25504. $container.append($handle)
  25505. },
  25506. _dragStartHandler: function($itemElement, e) {
  25507. if ($itemElement.is(".dx-state-disabled, .dx-state-disabled *")) {
  25508. e.cancel = true;
  25509. return
  25510. }
  25511. this._stopPreviousAnimation();
  25512. e.targetElements = [];
  25513. this._cacheItemsPositions();
  25514. this._startPointerOffset = e.pageY - $itemElement.offset().top;
  25515. this._elementHeight = $itemElement.outerHeight();
  25516. var itemIndex = this._list.getFlatIndexByItemElement($itemElement);
  25517. this._startIndex = itemIndex;
  25518. this._lastIndex = itemIndex;
  25519. this._cacheScrollData();
  25520. this._createGhost($itemElement);
  25521. $itemElement.addClass(REOREDERING_ITEM_CLASS);
  25522. this._toggleCompatibilityMode(true)
  25523. },
  25524. _stopPreviousAnimation: function() {
  25525. fx.stop(this._$ghostItem, true)
  25526. },
  25527. _toggleCompatibilityMode: function(enabled) {
  25528. this._list.element().toggleClass(LIST_REORDER_COMPATIBILITY_MODE_CLASS, !support.transform && enabled)
  25529. },
  25530. _cacheItemsPositions: function() {
  25531. this._itemPositions = [];
  25532. $.each(this._list.itemElements(), $.proxy(function(index, item) {
  25533. this._itemPositions.push($(item).position().top)
  25534. }, this))
  25535. },
  25536. _getDraggingElementPosition: function() {
  25537. return this._itemPositions[this._startIndex]
  25538. },
  25539. _getLastElementPosition: function() {
  25540. return this._itemPositions[this._lastIndex]
  25541. },
  25542. _cacheScrollData: function() {
  25543. this._list.updateDimensions();
  25544. this._startScrollTop = this._list.scrollTop();
  25545. this._scrollOffset = 0;
  25546. this._scrollHeight = this._list.scrollHeight();
  25547. this._clientHeight = this._list.clientHeight()
  25548. },
  25549. _scrollTop: function() {
  25550. return this._startScrollTop + this._scrollOffset
  25551. },
  25552. _createGhost: function($itemElement) {
  25553. this._$ghostItem = $itemElement.clone();
  25554. this._$ghostItem.addClass(REOREDERING_ITEM_GHOST_CLASS).appendTo(this._list.itemsContainer());
  25555. this._startGhostPosition = this._getDraggingElementPosition() - this._$ghostItem.position().top;
  25556. translator.move(this._$ghostItem, {top: this._startGhostPosition})
  25557. },
  25558. _dragHandler: function($itemElement, e) {
  25559. this._topOffset = e.offset.y;
  25560. this._updateItemPositions();
  25561. var pointerPosition = this._getPonterPosition();
  25562. this._toggleScroll(pointerPosition)
  25563. },
  25564. _getPonterPosition: function() {
  25565. return this._getDraggingElementPosition() + this._startPointerOffset + this._scrollOffset + this._topOffset
  25566. },
  25567. _toggleScroll: function(pointerPosition) {
  25568. if (this._scrollHeight <= this._clientHeight)
  25569. return;
  25570. var minOffset = this._elementHeight * 0.7,
  25571. topOffset = this._clientHeight - (pointerPosition - this._scrollTop()),
  25572. topOffsetRatio = topOffset / minOffset,
  25573. bottomOffset = pointerPosition - this._scrollTop(),
  25574. bottomOffsetRatio = bottomOffset / minOffset;
  25575. if (topOffsetRatio < 1) {
  25576. this._stepSize = this._adjustRationIntoRange(topOffsetRatio);
  25577. this._startAnimator()
  25578. }
  25579. else if (bottomOffsetRatio < 1) {
  25580. this._stepSize = -this._adjustRationIntoRange(bottomOffsetRatio);
  25581. this._startAnimator()
  25582. }
  25583. else
  25584. this._stopAnimator()
  25585. },
  25586. _adjustRationIntoRange: function(ratio) {
  25587. return fitIntoRange(Math.round(Math.abs(ratio - 1) * 7), 1, 7)
  25588. },
  25589. _updateItemPositions: function() {
  25590. this._updateGhostPosition();
  25591. this._updateOthersPositions()
  25592. },
  25593. _updateGhostPosition: function() {
  25594. translator.move(this._$ghostItem, {top: this._startGhostPosition + this._scrollOffset + this._topOffset})
  25595. },
  25596. _updateOthersPositions: function() {
  25597. var currentIndex = this._findItemIndexByPosition(this._getPonterPosition());
  25598. if (this._lastIndex === currentIndex || this._groupedEnabled && !this._sameParent(currentIndex))
  25599. return;
  25600. var currentIndexOffset = currentIndex - this._startIndex,
  25601. currentDirection = utils.sign(currentIndexOffset),
  25602. minIndex = Math.min(currentIndex, this._lastIndex),
  25603. maxIndex = Math.max(currentIndex, this._lastIndex);
  25604. for (var itemIndex = minIndex; itemIndex <= maxIndex; itemIndex++) {
  25605. if (itemIndex === this._startIndex)
  25606. continue;
  25607. var $item = this._list.getItemElementByFlatIndex(itemIndex),
  25608. itemIndexOffset = itemIndex - this._startIndex,
  25609. itemDirection = utils.sign(itemIndexOffset),
  25610. offsetsDifference = Math.abs(itemIndexOffset) <= Math.abs(currentIndexOffset),
  25611. sameDirections = currentDirection === itemDirection,
  25612. setupPosition = offsetsDifference && sameDirections,
  25613. resetPosition = !offsetsDifference || !sameDirections;
  25614. fx.stop($item);
  25615. if (setupPosition)
  25616. fx.animate($item, {
  25617. type: "slide",
  25618. to: {top: this._elementHeight * -currentDirection},
  25619. duration: 300
  25620. });
  25621. if (resetPosition)
  25622. fx.animate($item, {
  25623. type: "slide",
  25624. to: {top: 0},
  25625. duration: 300
  25626. })
  25627. }
  25628. this._lastIndex = currentIndex
  25629. },
  25630. _sameParent: function(index) {
  25631. var $dragging = this._list.getItemElementByFlatIndex(this._startIndex),
  25632. $over = this._list.getItemElementByFlatIndex(index);
  25633. return $over.parent().get(0) === $dragging.parent().get(0)
  25634. },
  25635. scrollByStep: function() {
  25636. this._scrollOffset += this._stepSize;
  25637. this._list.scrollBy(this._stepSize);
  25638. this._updateItemPositions()
  25639. },
  25640. scrollFinished: function() {
  25641. var scrollTop = this._scrollTop(),
  25642. rejectScrollTop = scrollTop <= 0 && this._stepSize < 0,
  25643. rejectScrollBottom = scrollTop >= this._scrollHeight - this._clientHeight && this._stepSize > 0;
  25644. return rejectScrollTop || rejectScrollBottom
  25645. },
  25646. _dragEndHandler: function($itemElement) {
  25647. this._scrollAnimator.stop();
  25648. fx.animate(this._$ghostItem, {
  25649. type: "slide",
  25650. to: {top: this._startGhostPosition + this._getLastElementPosition() - this._getDraggingElementPosition()},
  25651. duration: 300
  25652. }).done($.proxy(function() {
  25653. $itemElement.removeClass(REOREDERING_ITEM_CLASS);
  25654. this._resetPositions();
  25655. this._list.reorderItem($itemElement, this._list.getItemElementByFlatIndex(this._lastIndex));
  25656. this._deleteGhost();
  25657. this._toggleCompatibilityMode(false)
  25658. }, this))
  25659. },
  25660. _deleteGhost: function() {
  25661. this._$ghostItem.remove()
  25662. },
  25663. _resetPositions: function() {
  25664. var minIndex = Math.min(this._startIndex, this._lastIndex),
  25665. maxIndex = Math.max(this._startIndex, this._lastIndex);
  25666. for (var itemIndex = minIndex; itemIndex <= maxIndex; itemIndex++) {
  25667. var $item = this._list.getItemElementByFlatIndex(itemIndex);
  25668. translator.resetPosition($item)
  25669. }
  25670. },
  25671. _findItemIndexByPosition: function(position) {
  25672. var minIndex = 0;
  25673. var maxIndex = this._itemPositions.length - 1;
  25674. var currentIndex;
  25675. var currentPosition;
  25676. while (minIndex <= maxIndex) {
  25677. currentIndex = (minIndex + maxIndex) / 2 | 0;
  25678. currentPosition = this._itemPositions[currentIndex];
  25679. if (currentPosition < position)
  25680. minIndex = currentIndex + 1;
  25681. else if (currentPosition > position)
  25682. maxIndex = currentIndex - 1;
  25683. else
  25684. return currentIndex
  25685. }
  25686. return fitIntoRange(minIndex, 0, Math.max(maxIndex, 0))
  25687. }
  25688. }))
  25689. })(jQuery, DevExpress);
  25690. /*! Module widgets-base, file ui.list.edit.provider.js */
  25691. (function($, DX, undefined) {
  25692. var ui = DX.ui;
  25693. var editOptionsRegistry = [];
  25694. var registerOption = function(enabledFunc, decoratorTypeFunc, decoratorSubTypeFunc) {
  25695. editOptionsRegistry.push({
  25696. enabled: enabledFunc,
  25697. decoratorType: decoratorTypeFunc,
  25698. decoratorSubType: decoratorSubTypeFunc
  25699. })
  25700. };
  25701. registerOption(function() {
  25702. return this.option("menuItems").length
  25703. }, function() {
  25704. return "menu"
  25705. }, function() {
  25706. return this.option("menuMode")
  25707. });
  25708. registerOption(function() {
  25709. return !this.option("menuItems").length && this.option("allowItemDeleting")
  25710. }, function() {
  25711. var mode = this.option("itemDeleteMode");
  25712. return mode === "toggle" || mode === "slideButton" || mode === "swipe" || mode === "static" ? "delete" : "menu"
  25713. }, function() {
  25714. var mode = this.option("itemDeleteMode");
  25715. if (mode === "slideItem")
  25716. mode = "slide";
  25717. if (mode === "hold")
  25718. mode = "context";
  25719. return mode
  25720. });
  25721. registerOption(function() {
  25722. return this.option("selectionMode") !== "none" && this.option("showSelectionControls")
  25723. }, function() {
  25724. return "selection"
  25725. }, function() {
  25726. return "default"
  25727. });
  25728. registerOption(function() {
  25729. return this.option("allowItemReordering")
  25730. }, function() {
  25731. return "reorder"
  25732. }, function() {
  25733. return "default"
  25734. });
  25735. var LIST_ITEM_BEFORE_BAG_CLASS = "dx-list-item-before-bag",
  25736. LIST_ITEM_AFTER_BAG_CLASS = "dx-list-item-after-bag",
  25737. DECORATOR_BEFORE_BAG_CREATE_METHOD = "beforeBag",
  25738. DECORATOR_AFTER_BAG_CREATE_METHOD = "afterBag",
  25739. DECORATOR_MODIFY_ELEMENT_METHOD = "modifyElement",
  25740. DECORATOR_AFTER_RENDER_METHOD = "afterRender";
  25741. ui.dxList.EditProvider = DX.Class.inherit({
  25742. ctor: function(list) {
  25743. this._list = list;
  25744. this._fetchRequiredDecorators()
  25745. },
  25746. dispose: function() {
  25747. if (this._decorators && this._decorators.length)
  25748. $.each(this._decorators, function(_, decorator) {
  25749. decorator.dispose()
  25750. })
  25751. },
  25752. _fetchRequiredDecorators: function() {
  25753. this._decorators = [];
  25754. $.each(editOptionsRegistry, $.proxy(function(_, option) {
  25755. var optionEnabled = option.enabled.call(this._list);
  25756. if (optionEnabled) {
  25757. var decoratorType = option.decoratorType.call(this._list),
  25758. decoratorSubType = option.decoratorSubType.call(this._list),
  25759. decorator = this._createDecorator(decoratorType, decoratorSubType);
  25760. this._decorators.push(decorator)
  25761. }
  25762. }, this))
  25763. },
  25764. _createDecorator: function(type, subType) {
  25765. var decoratorClass = this._findDecorator(type, subType);
  25766. return new decoratorClass(this._list)
  25767. },
  25768. _findDecorator: function(type, subType) {
  25769. var foundDecorator = ui.dxList.EditDecoratorsRegistry[type][subType];
  25770. if (!foundDecorator)
  25771. throw DX.Error("E1012", type, subType);
  25772. return foundDecorator
  25773. },
  25774. modifyItemElement: function(args) {
  25775. var $itemElement = $(args.itemElement);
  25776. var config = {$itemElement: $itemElement};
  25777. this._prependBeforeBags($itemElement, config);
  25778. this._appendAfterBags($itemElement, config);
  25779. this._applyDecorators(DECORATOR_MODIFY_ELEMENT_METHOD, config)
  25780. },
  25781. afterItemsRendered: function() {
  25782. this._applyDecorators(DECORATOR_AFTER_RENDER_METHOD)
  25783. },
  25784. _prependBeforeBags: function($itemElement, config) {
  25785. var $beforeBags = this._collectDecoratorsMarkup(DECORATOR_BEFORE_BAG_CREATE_METHOD, config, LIST_ITEM_BEFORE_BAG_CLASS);
  25786. $itemElement.prepend($beforeBags)
  25787. },
  25788. _appendAfterBags: function($itemElement, config) {
  25789. var $afterBags = this._collectDecoratorsMarkup(DECORATOR_AFTER_BAG_CREATE_METHOD, config, LIST_ITEM_AFTER_BAG_CLASS);
  25790. $itemElement.append($afterBags)
  25791. },
  25792. _collectDecoratorsMarkup: function(method, config, containerClass) {
  25793. var $collector = $("<div />");
  25794. $.each(this._decorators, function() {
  25795. var $container = $("<div />").addClass(containerClass);
  25796. this[method]($.extend({$container: $container}, config));
  25797. if ($container.children().length)
  25798. $collector.append($container)
  25799. });
  25800. return $collector.children()
  25801. },
  25802. _applyDecorators: function(method, config) {
  25803. $.each(this._decorators, function() {
  25804. this[method](config)
  25805. })
  25806. },
  25807. _handlerExists: function(name) {
  25808. if (!this._decorators)
  25809. return false;
  25810. var decorators = this._decorators,
  25811. length = decorators.length;
  25812. for (var i = 0; i < length; i++)
  25813. if (decorators[i][name] !== $.noop)
  25814. return true;
  25815. return false
  25816. },
  25817. _eventHandler: function(name, $itemElement, e) {
  25818. if (!this._decorators)
  25819. return false;
  25820. var response = false,
  25821. decorators = this._decorators,
  25822. length = decorators.length;
  25823. for (var i = 0; i < length; i++) {
  25824. response = decorators[i][name]($itemElement, e);
  25825. if (response)
  25826. break
  25827. }
  25828. return response
  25829. },
  25830. handleClick: function($itemElement, e) {
  25831. return this._eventHandler("handleClick", $itemElement, e)
  25832. },
  25833. contextMenuHandlerExists: function() {
  25834. return this._handlerExists("handleContextMenu")
  25835. },
  25836. handleContextMenu: function($itemElement, e) {
  25837. return this._eventHandler("handleContextMenu", $itemElement, e)
  25838. }
  25839. })
  25840. })(jQuery, DevExpress);
  25841. /*! Module widgets-base, file ui.tileView.js */
  25842. (function($, DX, undefined) {
  25843. var ui = DX.ui;
  25844. var TILEVIEW_CLASS = "dx-tileview",
  25845. TILEVIEW_CONTAINER_CLASS = "dx-tileview-wrapper",
  25846. TILEVIEW_ITEM_CLASS = "dx-tile",
  25847. TILEVIEW_ITEM_SELECTOR = "." + TILEVIEW_ITEM_CLASS,
  25848. TILEVIEW_ITEM_DATA_KEY = "dxTileData";
  25849. DX.registerComponent("dxTileView", ui, ui.CollectionWidget.inherit({
  25850. _activeStateUnit: TILEVIEW_ITEM_SELECTOR,
  25851. _setDefaultOptions: function() {
  25852. this.callBase();
  25853. this.option({
  25854. items: null,
  25855. showScrollbar: false,
  25856. height: 500,
  25857. baseItemWidth: 100,
  25858. baseItemHeight: 100,
  25859. itemMargin: 20,
  25860. activeStateEnabled: true,
  25861. indicateLoading: true
  25862. })
  25863. },
  25864. _defaultOptionsRules: function() {
  25865. return this.callBase().concat([{
  25866. device: function(device) {
  25867. return DX.devices.real().generic && !DX.devices.isSimulator()
  25868. },
  25869. options: {
  25870. hoverStateEnabled: true,
  25871. focusStateEnabled: true
  25872. }
  25873. }])
  25874. },
  25875. _itemClass: function() {
  25876. return TILEVIEW_ITEM_CLASS
  25877. },
  25878. _itemDataKey: function() {
  25879. return TILEVIEW_ITEM_DATA_KEY
  25880. },
  25881. _itemContainer: function() {
  25882. return this._$container
  25883. },
  25884. _init: function() {
  25885. this.callBase();
  25886. this._initScrollView()
  25887. },
  25888. _dataSourceLoadingChangedHandler: function(isLoading) {
  25889. var scrollView = this._scrollView;
  25890. if (!scrollView)
  25891. return;
  25892. if (isLoading && this.option("indicateLoading"))
  25893. scrollView.startLoading();
  25894. else
  25895. scrollView.finishLoading()
  25896. },
  25897. _hideLoadingIfLoadIndicationOff: function() {
  25898. if (!this.option("indicateLoading"))
  25899. this._dataSourceLoadingChangedHandler(false)
  25900. },
  25901. _initScrollView: function() {
  25902. this._scrollView = this._createComponent(this.element(), "dxScrollView", {
  25903. direction: "horizontal",
  25904. scrollByContent: true,
  25905. useKeyboard: false,
  25906. showScrollbar: this.option("showScrollbar"),
  25907. disabled: this.option("disabled")
  25908. });
  25909. this._$container = this._scrollView.content();
  25910. this._$container.addClass(TILEVIEW_CONTAINER_CLASS);
  25911. this._scrollView.option("onUpdated", $.proxy(this._renderGeometry, this))
  25912. },
  25913. _render: function() {
  25914. this.callBase();
  25915. this.element().addClass(TILEVIEW_CLASS);
  25916. this.cellsPerColumn = 1;
  25917. this._updateScrollView();
  25918. this._fireContentReadyAction()
  25919. },
  25920. _renderContent: function() {
  25921. this._renderContentImpl()
  25922. },
  25923. _updateScrollView: function() {
  25924. this._scrollView.option("rtlEnabled", this.option("rtlEnabled"));
  25925. this._renderGeometry();
  25926. this._scrollView.update();
  25927. this._indicateLoadingIfAlreadyStarted()
  25928. },
  25929. _indicateLoadingIfAlreadyStarted: function() {
  25930. if (this._isDataSourceLoading())
  25931. this._dataSourceLoadingChangedHandler(true)
  25932. },
  25933. _renderGeometry: function() {
  25934. var items = this.option("items") || [],
  25935. maxItemHeight = Math.max.apply(Math, $.map(items || [], function(item) {
  25936. return Math.round(item.heightRatio || 1)
  25937. }));
  25938. this.cellsPerColumn = Math.floor(this.element().height() / (this.option("baseItemHeight") + this.option("itemMargin")));
  25939. this.cellsPerColumn = Math.max(this.cellsPerColumn, maxItemHeight);
  25940. this.cells = [];
  25941. this.cells.push(new Array(this.cellsPerColumn));
  25942. this._arrangeItems(items);
  25943. this._$container.width(this.cells.length * this.option("baseItemWidth") + (this.cells.length + 1) * this.option("itemMargin"))
  25944. },
  25945. _arrangeItems: function(items) {
  25946. var that = this;
  25947. this._itemsPositions = [];
  25948. $.each(items, function(index, item) {
  25949. var currentItem = {};
  25950. currentItem.widthRatio = item.widthRatio || 1;
  25951. currentItem.heightRatio = item.heightRatio || 1;
  25952. currentItem.index = index;
  25953. currentItem.widthRatio = currentItem.widthRatio <= 0 ? 0 : Math.round(currentItem.widthRatio);
  25954. currentItem.heightRatio = currentItem.heightRatio <= 0 ? 0 : Math.round(currentItem.heightRatio);
  25955. var itemPosition = that._getItemPosition(currentItem);
  25956. if (itemPosition.x === -1)
  25957. itemPosition.x = that.cells.push(new Array(that.cellsPerColumn)) - 1;
  25958. that._occupyCells(currentItem, itemPosition);
  25959. that._arrangeItem(currentItem, itemPosition);
  25960. that._itemsPositions.push(itemPosition)
  25961. })
  25962. },
  25963. _getItemPosition: function(item) {
  25964. var position = {
  25965. x: -1,
  25966. y: 0
  25967. };
  25968. for (var col = 0; col < this.cells.length; col++) {
  25969. for (var row = 0; row < this.cellsPerColumn; row++)
  25970. if (this._itemFit(col, row, item)) {
  25971. position.x = col;
  25972. position.y = row;
  25973. break
  25974. }
  25975. if (position.x > -1)
  25976. break
  25977. }
  25978. return position
  25979. },
  25980. _itemFit: function(column, row, item) {
  25981. var result = true;
  25982. if (row + item.heightRatio > this.cellsPerColumn)
  25983. return false;
  25984. for (var columnIndex = column; columnIndex < column + item.widthRatio; columnIndex++)
  25985. for (var rowIndex = row; rowIndex < row + item.heightRatio; rowIndex++)
  25986. if (this.cells.length - 1 < columnIndex)
  25987. this.cells.push(new Array(this.cellsPerColumn));
  25988. else if (this.cells[columnIndex][rowIndex] !== undefined) {
  25989. result = false;
  25990. break
  25991. }
  25992. return result
  25993. },
  25994. _occupyCells: function(item, itemPosition) {
  25995. for (var i = itemPosition.x; i < itemPosition.x + item.widthRatio; i++)
  25996. for (var j = itemPosition.y; j < itemPosition.y + item.heightRatio; j++)
  25997. this.cells[i][j] = item.index
  25998. },
  25999. _arrangeItem: function(item, itemPosition) {
  26000. var baseItemHeight = this.option("baseItemHeight"),
  26001. baseItemWidth = this.option("baseItemWidth"),
  26002. itemMargin = this.option("itemMargin"),
  26003. leftOffset,
  26004. offsetCorrection = this.option("rtlEnabled") ? this._$container.width() : 0,
  26005. $item = this._itemElements().eq(item.index);
  26006. if (!offsetCorrection)
  26007. leftOffset = itemPosition.x * baseItemWidth + (itemPosition.x + 1) * itemMargin;
  26008. else {
  26009. var startOffsetPosition = itemPosition.x * baseItemWidth,
  26010. itemBasePartWidth = baseItemWidth + itemMargin,
  26011. itemWidth = itemBasePartWidth * item.widthRatio,
  26012. subitemMarginsWidth = itemPosition.x * itemMargin;
  26013. leftOffset = offsetCorrection - (startOffsetPosition + itemWidth + subitemMarginsWidth)
  26014. }
  26015. $item.css({
  26016. height: item.heightRatio * baseItemHeight + (item.heightRatio - 1) * itemMargin,
  26017. width: item.widthRatio * baseItemWidth + (item.widthRatio - 1) * itemMargin,
  26018. top: itemPosition.y * baseItemHeight + (itemPosition.y + 1) * itemMargin,
  26019. left: leftOffset,
  26020. display: item.widthRatio <= 0 || item.heightRatio <= 0 ? "none" : ""
  26021. })
  26022. },
  26023. _moveFocus: function(location) {
  26024. var FOCUS_UP = "up",
  26025. FOCUS_DOWN = "down",
  26026. FOCUS_LEFT = this.option("rtlEnabled") ? "right" : "left",
  26027. FOCUS_RIGHT = this.option("rtlEnabled") ? "left" : "right",
  26028. FOCUS_PAGE_UP = "pageup",
  26029. FOCUS_PAGE_DOWN = "pagedown";
  26030. var cells = this.cells,
  26031. index = this.option("focusedElement").index(),
  26032. newTargetCol = this._itemsPositions[index].x,
  26033. targetRow = this._itemsPositions[index].y,
  26034. newTargetIndex;
  26035. switch (location) {
  26036. case FOCUS_PAGE_UP:
  26037. case FOCUS_UP:
  26038. while (targetRow > 0 && index === cells[newTargetCol][targetRow])
  26039. targetRow--;
  26040. if (targetRow < 0)
  26041. targetRow = 0;
  26042. break;
  26043. case FOCUS_PAGE_DOWN:
  26044. case FOCUS_DOWN:
  26045. while (targetRow < cells[0].length && index === cells[newTargetCol][targetRow])
  26046. targetRow++;
  26047. if (targetRow === cells[0].length)
  26048. targetRow = cells[0].length - 1;
  26049. break;
  26050. case FOCUS_RIGHT:
  26051. while (newTargetCol < cells.length && index === cells[newTargetCol][targetRow])
  26052. newTargetCol++;
  26053. if (newTargetCol === cells.length)
  26054. newTargetCol = cells.length - 1;
  26055. break;
  26056. case FOCUS_LEFT:
  26057. while (newTargetCol >= 0 && index === cells[newTargetCol][targetRow])
  26058. newTargetCol--;
  26059. if (newTargetCol < 0)
  26060. newTargetCol = 0;
  26061. break;
  26062. default:
  26063. this.callBase.apply(this, arguments);
  26064. return
  26065. }
  26066. newTargetIndex = cells[newTargetCol][targetRow];
  26067. var $newTarget = this._itemElements().eq(newTargetIndex);
  26068. this.option("focusedElement", $newTarget);
  26069. this._scrollToItem($newTarget)
  26070. },
  26071. _scrollToItem: function($itemElement) {
  26072. if (!$itemElement.length)
  26073. return;
  26074. var itemPosition = $itemElement.position().left,
  26075. itemWidth = $itemElement.outerWidth(),
  26076. itemRight = itemPosition + itemWidth,
  26077. scrollLeft = this._scrollView.scrollLeft(),
  26078. clientWidht = this._scrollView.element().outerWidth();
  26079. if (scrollLeft <= itemPosition && itemRight <= scrollLeft + clientWidht)
  26080. return;
  26081. if (scrollLeft > itemPosition)
  26082. this._scrollView.scrollTo(itemPosition - this.option("itemMargin"));
  26083. else
  26084. this._scrollView.scrollTo(itemPosition + itemWidth - clientWidht + this.option("itemMargin"))
  26085. },
  26086. _optionChanged: function(args) {
  26087. switch (args.name) {
  26088. case"showScrollbar":
  26089. this._initScrollView();
  26090. break;
  26091. case"disabled":
  26092. this._scrollView.option("disabled", args.value);
  26093. break;
  26094. case"baseItemWidth":
  26095. case"baseItemHeight":
  26096. case"itemMargin":
  26097. this._renderGeometry();
  26098. break;
  26099. case"height":
  26100. this.callBase(args);
  26101. this._renderGeometry();
  26102. this._scrollView.update();
  26103. break;
  26104. case"indicateLoading":
  26105. this._hideLoadingIfLoadIndicationOff();
  26106. break;
  26107. default:
  26108. this.callBase(args)
  26109. }
  26110. },
  26111. scrollPosition: function() {
  26112. return this._scrollView.scrollOffset().left
  26113. }
  26114. }))
  26115. })(jQuery, DevExpress);
  26116. /*! Module widgets-base, file ui.trackBar.js */
  26117. (function($, DX, undefined) {
  26118. var ui = DX.ui,
  26119. fx = DX.fx;
  26120. var TRACKBAR_CLASS = "dx-trackbar",
  26121. TRACKBAR_CONTAINER_CLASS = "dx-trackbar-container",
  26122. TRACKBAR_RANGE_CLASS = "dx-trackbar-range",
  26123. TRACKBAR_WRAPPER_CLASS = "dx-trackbar-wrapper";
  26124. DX.registerComponent("dxTrackBar", ui, ui.Editor.inherit({
  26125. _setDefaultOptions: function() {
  26126. this.callBase();
  26127. this.option({
  26128. min: 0,
  26129. max: 100,
  26130. value: 0
  26131. })
  26132. },
  26133. _render: function() {
  26134. this.element().addClass(TRACKBAR_CLASS);
  26135. this._renderWrapper();
  26136. this._renderContainer();
  26137. this._renderRange();
  26138. this.callBase();
  26139. this._renderValue()
  26140. },
  26141. _renderWrapper: function() {
  26142. this._$wrapper = $("<div>").addClass(TRACKBAR_WRAPPER_CLASS).appendTo(this.element())
  26143. },
  26144. _renderContainer: function() {
  26145. this._$bar = $("<div>").addClass(TRACKBAR_CONTAINER_CLASS).appendTo(this._$wrapper)
  26146. },
  26147. _renderRange: function() {
  26148. this._$range = $("<div>").addClass(TRACKBAR_RANGE_CLASS).appendTo(this._$bar)
  26149. },
  26150. _renderValue: function() {
  26151. var val = this.option("value"),
  26152. min = this.option("min"),
  26153. max = this.option("max");
  26154. if (min > max)
  26155. return;
  26156. if (val < min) {
  26157. this.option("value", min);
  26158. this._currentRatio = 0;
  26159. return
  26160. }
  26161. if (val > max) {
  26162. this.option("value", max);
  26163. this._currentRatio = 1;
  26164. return
  26165. }
  26166. var ratio = min === max ? 0 : (val - min) / (max - min);
  26167. this._animateRange({width: ratio * 100 + "%"});
  26168. this.setAria({
  26169. valuemin: this.option("min"),
  26170. valuemax: max,
  26171. valuenow: val
  26172. });
  26173. this._currentRatio = ratio
  26174. },
  26175. _animateRange: function(configTo) {
  26176. fx.stop(this._$range);
  26177. if (!this._needPreventAnimation)
  26178. fx.animate(this._$range, {
  26179. type: "custom",
  26180. duration: 100,
  26181. to: configTo,
  26182. complete: $.proxy(this._rangeAnimationCompleteHandler, this)
  26183. })
  26184. },
  26185. _rangeAnimationCompleteHandler: $.noop,
  26186. _optionChanged: function(args) {
  26187. switch (args.name) {
  26188. case"value":
  26189. this._renderValue();
  26190. this.callBase(args);
  26191. break;
  26192. case"max":
  26193. case"min":
  26194. this._renderValue();
  26195. break;
  26196. default:
  26197. this.callBase(args)
  26198. }
  26199. },
  26200. _dispose: function() {
  26201. fx.stop(this._$range);
  26202. this.callBase()
  26203. }
  26204. }))
  26205. })(jQuery, DevExpress);
  26206. /*! Module widgets-base, file ui.progressBar.js */
  26207. (function($, DX, undefined) {
  26208. var ui = DX.ui;
  26209. var PROGRESSBAR_CLASS = "dx-progressbar",
  26210. PROGRESSBAR_CONTAINER_CLASS = "dx-progressbar-container",
  26211. PROGRESSBAR_RANGE_CONTAINER_CLASS = "dx-progressbar-range-container",
  26212. PROGRESSBAR_RANGE_CLASS = "dx-progressbar-range",
  26213. PROGRESSBAR_WRAPPER_CLASS = "dx-progressbar-wrapper",
  26214. PROGRESSBAR_STATUS_CLASS = "dx-progressbar-status",
  26215. PROGRESSBAR_INDETERMINATE_SEGMENT_CONTAINER = "dx-progressbar-animating-container",
  26216. PROGRESSBAR_INDETERMINATE_SEGMENT = "dx-progressbar-animating-segment";
  26217. DX.registerComponent("dxProgressBar", ui, ui.dxTrackBar.inherit({
  26218. _setDefaultOptions: function() {
  26219. this.callBase();
  26220. this.option({
  26221. statusFormat: function(ratio, value) {
  26222. return "Progress: " + Math.round(ratio * 100) + "%"
  26223. },
  26224. showStatus: true,
  26225. onComplete: null,
  26226. activeStateEnabled: false,
  26227. statusPosition: "bottom left",
  26228. _animatingSegmentCount: 0
  26229. })
  26230. },
  26231. _defaultOptionsRules: function() {
  26232. return this.callBase().concat([{
  26233. device: [{platform: "win8"}],
  26234. options: {_animatingSegmentCount: 5}
  26235. }, {
  26236. device: function(device) {
  26237. return device.platform === "android"
  26238. },
  26239. options: {_animatingSegmentCount: 2}
  26240. }])
  26241. },
  26242. _init: function() {
  26243. this.callBase()
  26244. },
  26245. _render: function() {
  26246. this._createCompleteAction();
  26247. this._renderStatus();
  26248. this.callBase();
  26249. this.element().addClass(PROGRESSBAR_CLASS);
  26250. this.setAria("role", "progressbar");
  26251. this._$wrapper.addClass(PROGRESSBAR_WRAPPER_CLASS);
  26252. this._$bar.addClass(PROGRESSBAR_CONTAINER_CLASS);
  26253. $("<div>").addClass(PROGRESSBAR_RANGE_CONTAINER_CLASS).appendTo(this._$wrapper).append(this._$bar);
  26254. this._$range.addClass(PROGRESSBAR_RANGE_CLASS);
  26255. this._toggleStatus(this.option("showStatus"))
  26256. },
  26257. _createCompleteAction: function() {
  26258. this._completeAction = this._createActionByOption("onComplete")
  26259. },
  26260. _renderStatus: function() {
  26261. this._$status = $("<div>").addClass(PROGRESSBAR_STATUS_CLASS)
  26262. },
  26263. _renderIndeterminateState: function() {
  26264. this._$segmentContainer = $("<div>").addClass(PROGRESSBAR_INDETERMINATE_SEGMENT_CONTAINER);
  26265. var segments = this.option("_animatingSegmentCount");
  26266. for (var i = 0; i < segments; i++)
  26267. $("<div>").addClass(PROGRESSBAR_INDETERMINATE_SEGMENT).addClass(PROGRESSBAR_INDETERMINATE_SEGMENT + "-" + (i + 1)).appendTo(this._$segmentContainer);
  26268. this._$segmentContainer.appendTo(this._$wrapper)
  26269. },
  26270. _toggleStatus: function(value) {
  26271. var splittedPosition = this.option("statusPosition").split(" ");
  26272. if (value)
  26273. if (splittedPosition[0] === "top" || splittedPosition[0] === "left")
  26274. this._$status.prependTo(this._$wrapper);
  26275. else
  26276. this._$status.appendTo(this._$wrapper);
  26277. else
  26278. this._$status.detach();
  26279. this._togglePositionClass()
  26280. },
  26281. _togglePositionClass: function() {
  26282. var position = this.option("statusPosition"),
  26283. splittedPosition = position.split(" ");
  26284. this._$wrapper.removeClass("dx-position-top-left dx-position-top-right dx-position-bottom-left dx-position-bottom-right dx-position-left dx-position-right");
  26285. var positionClass = "dx-position-" + splittedPosition[0];
  26286. if (splittedPosition[1])
  26287. positionClass += "-" + splittedPosition[1];
  26288. this._$wrapper.addClass(positionClass)
  26289. },
  26290. _toggleIndeterminateState: function(value) {
  26291. if (value) {
  26292. this._renderIndeterminateState();
  26293. this._$bar.toggle(false)
  26294. }
  26295. else {
  26296. this._$bar.toggle(true);
  26297. this._$segmentContainer.remove();
  26298. delete this._$segmentContainer
  26299. }
  26300. },
  26301. _renderValue: function() {
  26302. var val = this.option("value"),
  26303. max = this.option("max");
  26304. if (!val && val !== 0) {
  26305. this._toggleIndeterminateState(true);
  26306. return
  26307. }
  26308. if (this._$segmentContainer)
  26309. this._toggleIndeterminateState(false);
  26310. if (val === max)
  26311. this._completeAction();
  26312. this.callBase();
  26313. this._setStatus()
  26314. },
  26315. _setStatus: function() {
  26316. var format = this.option("statusFormat");
  26317. if ($.isFunction(format))
  26318. format = $.proxy(format, this);
  26319. else
  26320. format = function(value) {
  26321. return value
  26322. };
  26323. var statusText = format(this._currentRatio, this.option("value"));
  26324. this._$status.text(statusText)
  26325. },
  26326. _dispose: function() {
  26327. this._$status.remove();
  26328. this.callBase()
  26329. },
  26330. _optionChanged: function(args) {
  26331. switch (args.name) {
  26332. case"statusFormat":
  26333. this._setStatus();
  26334. break;
  26335. case"showStatus":
  26336. this._toggleStatus(args.value);
  26337. break;
  26338. case"statusPosition":
  26339. this._toggleStatus(this.option("showStatus"));
  26340. break;
  26341. case"onComplete":
  26342. this._createCompleteAction();
  26343. break;
  26344. case"_animatingSegmentCount":
  26345. break;
  26346. default:
  26347. this.callBase(args)
  26348. }
  26349. }
  26350. }))
  26351. })(jQuery, DevExpress);
  26352. /*! Module widgets-base, file ui.slider.js */
  26353. (function($, DX, undefined) {
  26354. var ui = DX.ui,
  26355. events = ui.events,
  26356. translator = DX.translator,
  26357. transionEndEventName = DX.support.transitionEndEventName;
  26358. var SLIDER_CLASS = "dx-slider",
  26359. SLIDER_WRAPPER_CLASS = "dx-slider-wrapper",
  26360. SLIDER_HANDLE_CLASS = "dx-slider-handle",
  26361. SLIDER_HANDLE_SELECTOR = ".dx-slider-handle",
  26362. SLIDER_BAR_CLASS = "dx-slider-bar",
  26363. SLIDER_RANGE_CLASS = "dx-slider-range",
  26364. SLIDER_RANGE_VISIBLE_CLASS = "dx-slider-range-visible",
  26365. SLIDER_LABEL_CLASS = "dx-slider-label",
  26366. SLIDER_LABEL_POSITION_CLASS_PREFIX = "dx-slider-label-position-",
  26367. SLIDER_TOOLTIP_POSITION_CLASS_PREFIX = "dx-slider-tooltip-position-";
  26368. var dxSliderHandle = ui.Widget.inherit({
  26369. _setDefaultOptions: function() {
  26370. this.callBase();
  26371. this.option({
  26372. hoverStateEnabled: false,
  26373. value: 50,
  26374. tooltipEnabled: false,
  26375. tooltipFormat: function(v) {
  26376. return v
  26377. },
  26378. tooltipPosition: "top",
  26379. tooltipShowMode: "onHover",
  26380. tooltipFitIn: null
  26381. })
  26382. },
  26383. _render: function() {
  26384. this.callBase();
  26385. this.element().addClass(SLIDER_HANDLE_CLASS);
  26386. this._renderTooltip();
  26387. this.setAria({
  26388. role: "slider",
  26389. valuenow: this.option("value")
  26390. })
  26391. },
  26392. _renderTooltip: function() {
  26393. if (this.option("tooltipEnabled")) {
  26394. if (!this._$tooltip) {
  26395. this._$tooltip = $("<div>").appendTo(this.element());
  26396. this._tooltip = this._createComponent(this._$tooltip, "dxTooltip", {
  26397. visible: true,
  26398. height: undefined,
  26399. target: this.element(),
  26400. closeOnOutsideClick: false,
  26401. container: this.element(),
  26402. closeOnBackButton: false,
  26403. closeOnTargetScroll: false,
  26404. animation: null,
  26405. arrowPosition: null
  26406. })
  26407. }
  26408. this._renderTooltipPosition();
  26409. this._renderTooltipShowMode();
  26410. this._renderValue()
  26411. }
  26412. else
  26413. this._removeTooltip()
  26414. },
  26415. _visibilityChanged: function() {
  26416. this._dimensionChanged()
  26417. },
  26418. _dimensionChanged: function() {
  26419. this._repaintTooltip()
  26420. },
  26421. _removeTooltip: function() {
  26422. if (!this._$tooltip)
  26423. return;
  26424. this._$tooltip.remove();
  26425. delete this._$tooltip;
  26426. delete this._tooltip
  26427. },
  26428. _renderTooltipPosition: function() {
  26429. if (!this._tooltip)
  26430. return;
  26431. var position = this.option("tooltipPosition");
  26432. if ($.type(position) === "string")
  26433. position = position + "None";
  26434. this._tooltip.option("position", position)
  26435. },
  26436. _repaintTooltip: function() {
  26437. if (this._tooltip)
  26438. this._tooltip.repaint()
  26439. },
  26440. _renderValue: function() {
  26441. if (!this._tooltip)
  26442. return;
  26443. var format = this.option("tooltipFormat"),
  26444. value = format(this.option("value"));
  26445. this._tooltip.content().html(value);
  26446. this._fitTooltipPosition()
  26447. },
  26448. _renderTooltipShowMode: function() {
  26449. this.element().toggleClass("dx-slider-tooltip-on-hover", /^onhover$/i.test(this.option("tooltipShowMode")))
  26450. },
  26451. _fitTooltipPosition: function() {
  26452. if (!this._$tooltip)
  26453. return;
  26454. var $tooltipContent = this._tooltip.content().parent(),
  26455. tooltipWidth = $tooltipContent.outerWidth(),
  26456. $boundElement = this.option("tooltipFitIn"),
  26457. boundElementWidth = $boundElement.outerWidth(),
  26458. boundElementLeft = $boundElement.offset().left,
  26459. boundElementRight = boundElementLeft + boundElementWidth,
  26460. $element = this.element(),
  26461. elementWidth = $element.outerWidth(),
  26462. elementLeft = $element.offset().left,
  26463. elementRight = elementLeft + elementWidth,
  26464. idealOffset = Math.round(elementWidth / 2 - tooltipWidth / 2),
  26465. minOffset = Math.ceil(boundElementLeft - elementLeft),
  26466. maxOffset = Math.floor(boundElementRight - elementRight) + idealOffset * 2,
  26467. newOffset = Math.min(Math.max(minOffset, idealOffset), maxOffset);
  26468. translator.move($tooltipContent, {left: newOffset})
  26469. },
  26470. _clean: function() {
  26471. this.callBase();
  26472. delete this._$tooltip;
  26473. delete this._tooltip
  26474. },
  26475. _optionChanged: function(args) {
  26476. switch (args.name) {
  26477. case"tooltipFormat":
  26478. this._renderValue();
  26479. break;
  26480. case"value":
  26481. this._renderValue();
  26482. this.setAria("valuenow", args.value);
  26483. break;
  26484. case"tooltipEnabled":
  26485. this._renderTooltip();
  26486. break;
  26487. case"tooltipPosition":
  26488. this._renderTooltipPosition();
  26489. break;
  26490. case"tooltipShowMode":
  26491. this._renderTooltipShowMode();
  26492. break;
  26493. case"tooltipFitIn":
  26494. this._fitTooltipPosition();
  26495. break;
  26496. case"_templates":
  26497. case"templateProvider":
  26498. break;
  26499. default:
  26500. this.callBase(args)
  26501. }
  26502. },
  26503. fitTooltipPosition: function() {
  26504. this._fitTooltipPosition()
  26505. },
  26506. repaint: function() {
  26507. this._repaintTooltip();
  26508. this._renderTooltipPosition();
  26509. this._fitTooltipPosition()
  26510. }
  26511. });
  26512. DX.registerComponent("dxSlider", ui, ui.dxTrackBar.inherit({
  26513. _activeStateUnit: SLIDER_HANDLE_SELECTOR,
  26514. _supportedKeys: function() {
  26515. var isRTL = this.option("rtlEnabled");
  26516. var that = this,
  26517. moveHandleRight = function(step) {
  26518. var val = that.option("value");
  26519. step = that._valueStep(step);
  26520. val = isRTL ? val - step : val + step;
  26521. that.option("value", val)
  26522. },
  26523. moveHandleLeft = function(step) {
  26524. var val = that.option("value");
  26525. step = that._valueStep(step);
  26526. val = isRTL ? val + step : val - step;
  26527. that.option("value", val)
  26528. };
  26529. return $.extend(this.callBase(), {
  26530. leftArrow: function(e) {
  26531. e.preventDefault();
  26532. e.stopPropagation();
  26533. moveHandleLeft(this.option("step"))
  26534. },
  26535. rightArrow: function(e) {
  26536. e.preventDefault();
  26537. e.stopPropagation();
  26538. moveHandleRight(this.option("step"))
  26539. },
  26540. pageUp: function(e) {
  26541. e.preventDefault();
  26542. e.stopPropagation();
  26543. moveHandleRight(this.option("step") * this.option("keyStep"))
  26544. },
  26545. pageDown: function(e) {
  26546. e.preventDefault();
  26547. e.stopPropagation();
  26548. moveHandleLeft(this.option("step") * this.option("keyStep"))
  26549. },
  26550. home: function(e) {
  26551. e.preventDefault();
  26552. e.stopPropagation();
  26553. var min = this.option("min");
  26554. this.option("value", min)
  26555. },
  26556. end: function(e) {
  26557. e.preventDefault();
  26558. e.stopPropagation();
  26559. var max = this.option("max");
  26560. this.option("value", max)
  26561. }
  26562. })
  26563. },
  26564. _setDefaultOptions: function() {
  26565. this.callBase();
  26566. this.option({
  26567. step: 1,
  26568. value: 50,
  26569. showRange: true,
  26570. tooltip: {
  26571. enabled: false,
  26572. format: function(value) {
  26573. return value
  26574. },
  26575. position: "top",
  26576. showMode: "onHover"
  26577. },
  26578. label: {
  26579. visible: false,
  26580. position: "bottom",
  26581. format: function(value) {
  26582. return value
  26583. }
  26584. },
  26585. keyStep: 1
  26586. })
  26587. },
  26588. _defaultOptionsRules: function() {
  26589. return this.callBase().concat([{
  26590. device: function(device) {
  26591. return DX.devices.real().generic && !DX.devices.isSimulator()
  26592. },
  26593. options: {
  26594. focusStateEnabled: true,
  26595. hoverStateEnabled: true
  26596. }
  26597. }])
  26598. },
  26599. _render: function() {
  26600. this.element().addClass(SLIDER_CLASS);
  26601. this.callBase();
  26602. this._renderLabels();
  26603. this._renderStartHandler();
  26604. this._renderAriaMinAndMax()
  26605. },
  26606. _visibilityChanged: function() {
  26607. this.repaint()
  26608. },
  26609. _renderWrapper: function() {
  26610. this.callBase();
  26611. this._$wrapper.addClass(SLIDER_WRAPPER_CLASS);
  26612. this._createComponent(this._$wrapper, "dxSwipeable", {
  26613. elastic: false,
  26614. immediate: true,
  26615. onStart: $.proxy(this._swipeStartHandler, this),
  26616. onUpdated: $.proxy(this._swipeUpdateHandler, this),
  26617. onEnd: $.proxy(this._swipeEndHandler, this),
  26618. itemSizeFunc: $.proxy(this._itemWidthFunc, this)
  26619. })
  26620. },
  26621. _renderContainer: function() {
  26622. this.callBase();
  26623. this._$bar.addClass(SLIDER_BAR_CLASS);
  26624. this._$bar.off(transionEndEventName + "." + this.NAME).on(transionEndEventName, $.proxy(this._fitHandleTooltipPosition, this))
  26625. },
  26626. _renderRange: function() {
  26627. this.callBase();
  26628. this._$range.addClass(SLIDER_RANGE_CLASS);
  26629. this._renderHandle();
  26630. this._renderRangeVisibility()
  26631. },
  26632. _renderRangeVisibility: function() {
  26633. this._$range.toggleClass(SLIDER_RANGE_VISIBLE_CLASS, Boolean(this.option("showRange")))
  26634. },
  26635. _renderHandle: function() {
  26636. this._$handle = this._renderHandleImpl(this.option("value"), this._$handle)
  26637. },
  26638. _renderHandleImpl: function(value, $element) {
  26639. var $handle = $element || $("<div>").appendTo(this._$range),
  26640. format = this._normalizeFormat(this.option("tooltip.format")),
  26641. tooltipEnabled = this.option("tooltip.enabled"),
  26642. tooltipPosition = this.option("tooltip.position");
  26643. this.element().toggleClass(SLIDER_TOOLTIP_POSITION_CLASS_PREFIX + "bottom", tooltipEnabled && tooltipPosition === "bottom").toggleClass(SLIDER_TOOLTIP_POSITION_CLASS_PREFIX + "top", tooltipEnabled && tooltipPosition === "top");
  26644. this._createComponent($handle, "dxSliderHandle", {
  26645. value: value,
  26646. tooltipEnabled: tooltipEnabled,
  26647. tooltipPosition: tooltipPosition,
  26648. tooltipFormat: format,
  26649. tooltipShowMode: this.option("tooltip.showMode"),
  26650. tooltipFitIn: this.element()
  26651. });
  26652. return $handle
  26653. },
  26654. _renderAriaMinAndMax: function() {
  26655. this.setAria({
  26656. valuemin: this.option("min"),
  26657. valuemax: this.option("max")
  26658. }, this._$handle)
  26659. },
  26660. _renderLabels: function() {
  26661. this.element().removeClass(SLIDER_LABEL_POSITION_CLASS_PREFIX + "bottom").removeClass(SLIDER_LABEL_POSITION_CLASS_PREFIX + "top");
  26662. if (this.option("label.visible")) {
  26663. var min = this.option("min"),
  26664. max = this.option("max"),
  26665. position = this.option("label.position"),
  26666. format = this._normalizeFormat(this.option("label.format"));
  26667. if (!this._$minLabel)
  26668. this._$minLabel = $("<div>").addClass(SLIDER_LABEL_CLASS).appendTo(this._$wrapper);
  26669. this._$minLabel.html(format(min));
  26670. if (!this._$maxLabel)
  26671. this._$maxLabel = $("<div>").addClass(SLIDER_LABEL_CLASS).appendTo(this._$wrapper);
  26672. this._$maxLabel.html(format(max));
  26673. this.element().addClass(SLIDER_LABEL_POSITION_CLASS_PREFIX + position)
  26674. }
  26675. else {
  26676. if (this._$minLabel) {
  26677. this._$minLabel.remove();
  26678. delete this._$minLabel
  26679. }
  26680. if (this._$maxLabel) {
  26681. this._$maxLabel.remove();
  26682. delete this._$maxLabel
  26683. }
  26684. }
  26685. },
  26686. _normalizeFormat: function(formatSource) {
  26687. var format = formatSource;
  26688. if (typeof formatSource === "string")
  26689. format = function(value) {
  26690. return Globalize.format(value, formatSource)
  26691. };
  26692. else if ($.isFunction(formatSource))
  26693. format = $.proxy(format, this);
  26694. else
  26695. format = function(value) {
  26696. return value
  26697. };
  26698. return format
  26699. },
  26700. _renderDimensions: function() {
  26701. this.callBase();
  26702. if (this._$bar) {
  26703. var barMarginWidth = this._$bar.outerWidth(true) - this._$bar.outerWidth();
  26704. this._$bar.width(this.option("width") - barMarginWidth)
  26705. }
  26706. },
  26707. _renderStartHandler: function() {
  26708. var pointerDownEventName = events.addNamespace("dxpointerdown", this.NAME),
  26709. clickEventName = events.addNamespace("dxclick", this.NAME),
  26710. startAction = this._createAction($.proxy(this._startHandler, this));
  26711. this.element().off(pointerDownEventName).on(pointerDownEventName, function(e) {
  26712. if (events.isMouseEvent(e))
  26713. startAction({jQueryEvent: e})
  26714. }).off(clickEventName).on(clickEventName, $.proxy(function(e) {
  26715. var handle = this._activeHandle();
  26716. handle && handle.focusin() && handle.focus();
  26717. startAction({jQueryEvent: e})
  26718. }, this))
  26719. },
  26720. _itemWidthFunc: function() {
  26721. return this.element().width() / this._swipePixelRatio()
  26722. },
  26723. _swipeStartHandler: function(e) {
  26724. var rtlEnabled = this.option("rtlEnabled"),
  26725. startOffset,
  26726. endOffset;
  26727. if (events.isTouchEvent(e.jQueryEvent))
  26728. this._createAction($.proxy(this._startHandler, this))({jQueryEvent: e.jQueryEvent});
  26729. this._feedbackDeferred = $.Deferred();
  26730. ui.events.lockFeedback(this._feedbackDeferred);
  26731. this._toggleActiveState(this._activeHandle(), true);
  26732. this._startOffset = this._currentRatio;
  26733. startOffset = this._startOffset * this._swipePixelRatio();
  26734. endOffset = (1 - this._startOffset) * this._swipePixelRatio();
  26735. e.jQueryEvent.maxLeftOffset = rtlEnabled ? endOffset : startOffset;
  26736. e.jQueryEvent.maxRightOffset = rtlEnabled ? startOffset : endOffset;
  26737. this._needPreventAnimation = true
  26738. },
  26739. _swipeEndHandler: function(e) {
  26740. this._feedbackDeferred.resolve();
  26741. this._toggleActiveState(this._activeHandle(), false);
  26742. var offsetDirection = this.option("rtlEnabled") ? -1 : 1;
  26743. delete this._needPreventAnimation;
  26744. this._changeValueOnSwipe(this._startOffset + offsetDirection * e.jQueryEvent.targetOffset / this._swipePixelRatio());
  26745. delete this._startOffset;
  26746. this._renderValue()
  26747. },
  26748. _activeHandle: function() {
  26749. return this._$handle
  26750. },
  26751. _swipeUpdateHandler: function(e) {
  26752. this._saveValueChangeEvent(e);
  26753. this._updateHandlePosition(e)
  26754. },
  26755. _updateHandlePosition: function(e) {
  26756. var offsetDirection = this.option("rtlEnabled") ? -1 : 1;
  26757. var newRatio = this._startOffset + offsetDirection * e.jQueryEvent.offset / this._swipePixelRatio();
  26758. this._$range.width(newRatio * 100 + "%");
  26759. this._changeValueOnSwipe(newRatio)
  26760. },
  26761. _swipePixelRatio: function() {
  26762. var min = this.option("min"),
  26763. max = this.option("max"),
  26764. step = this._valueStep(this.option("step"));
  26765. return (max - min) / step
  26766. },
  26767. _valueStep: function(step) {
  26768. if (!step || isNaN(step))
  26769. step = 1;
  26770. step = parseFloat(step.toFixed(5));
  26771. if (step === 0)
  26772. step = 0.00001;
  26773. return step
  26774. },
  26775. _changeValueOnSwipe: function(ratio) {
  26776. var min = this.option("min"),
  26777. max = this.option("max"),
  26778. step = this._valueStep(this.option("step")),
  26779. newChange = ratio * (max - min),
  26780. newValue = min + newChange;
  26781. if (step < 0)
  26782. return;
  26783. if (newValue === max || newValue === min)
  26784. this.option("value", newValue);
  26785. else {
  26786. var stepExponent = (step + "").split(".")[1];
  26787. var minExponent = (min + "").split(".")[1];
  26788. var exponentLength = Math.max(stepExponent && stepExponent.length || 0, minExponent && minExponent.length || 0);
  26789. var stepCount = Math.round((newValue - min) / step);
  26790. newValue = Number((stepCount * step + min).toFixed(exponentLength));
  26791. this.option("value", Math.max(Math.min(newValue, max), min))
  26792. }
  26793. },
  26794. _startHandler: function(args) {
  26795. var e = args.jQueryEvent;
  26796. this._currentRatio = (ui.events.eventData(e).x - this._$bar.offset().left) / this._$bar.width();
  26797. if (this.option("rtlEnabled"))
  26798. this._currentRatio = 1 - this._currentRatio;
  26799. this._saveValueChangeEvent(e);
  26800. this._changeValueOnSwipe(this._currentRatio)
  26801. },
  26802. _renderValue: function() {
  26803. this.callBase();
  26804. this._activeHandle().dxSliderHandle("option", "value", this.option("value"))
  26805. },
  26806. _rangeAnimationCompleteHandler: function() {
  26807. this._fitHandleTooltipPosition()
  26808. },
  26809. _fitHandleTooltipPosition: function() {
  26810. if (this._activeHandle())
  26811. this._activeHandle().dxSliderHandle("fitTooltipPosition")
  26812. },
  26813. _repaintHandle: function() {
  26814. this._$handle.dxSliderHandle("repaint")
  26815. },
  26816. _optionChanged: function(args) {
  26817. switch (args.name) {
  26818. case"visible":
  26819. this.callBase(args);
  26820. this._renderHandle();
  26821. this._repaintHandle();
  26822. DX.utils.triggerShownEvent(this.element());
  26823. break;
  26824. case"min":
  26825. case"max":
  26826. this._renderLabels();
  26827. this._renderAriaMinAndMax();
  26828. this.callBase(args);
  26829. break;
  26830. case"step":
  26831. this._renderValue();
  26832. break;
  26833. case"keyStep":
  26834. break;
  26835. case"showRange":
  26836. this._renderRangeVisibility();
  26837. break;
  26838. case"tooltip":
  26839. this._renderHandle();
  26840. break;
  26841. case"label":
  26842. this._renderLabels();
  26843. break;
  26844. case"rtlEnabled":
  26845. this._toggleRTLDirection();
  26846. this._renderValue();
  26847. break;
  26848. default:
  26849. this.callBase(args)
  26850. }
  26851. },
  26852. _refresh: function() {
  26853. this._renderDimensions();
  26854. this._renderValue();
  26855. this._renderHandle();
  26856. this._repaintHandle()
  26857. }
  26858. }));
  26859. DX.registerComponent("dxSliderHandle", ui.dxSlider, dxSliderHandle)
  26860. })(jQuery, DevExpress);
  26861. /*! Module widgets-base, file ui.rangeSlider.js */
  26862. (function($, DX, undefined) {
  26863. var ui = DX.ui,
  26864. utils = DX.utils,
  26865. events = ui.events;
  26866. var RANGE_SLIDER_CLASS = "dx-rangeslider",
  26867. RANGE_SLIDER_START_HANDLE_CLASS = RANGE_SLIDER_CLASS + "-start-handle",
  26868. RANGE_SLIDER_END_HANDLE_CLASS = RANGE_SLIDER_CLASS + "-end-handle";
  26869. DX.registerComponent("dxRangeSlider", ui, ui.dxSlider.inherit({
  26870. _supportedKeys: function() {
  26871. var isRTL = this.option("rtlEnabled");
  26872. var that = this,
  26873. _changeHandle = function(e, capturedHandle) {
  26874. if (that.option("start") === that.option("end")) {
  26875. that._capturedHandle = capturedHandle;
  26876. e.target = that._capturedHandle;
  26877. that._capturedHandle.focus()
  26878. }
  26879. },
  26880. _setHandleValue = function(e, step, sign) {
  26881. var isStart = $(e.target).hasClass(RANGE_SLIDER_START_HANDLE_CLASS),
  26882. valueOption = isStart ? "start" : "end",
  26883. val = that.option(valueOption);
  26884. step = that._valueStep(step);
  26885. val += sign * (isRTL ? -step : step);
  26886. that.option(valueOption, val)
  26887. },
  26888. moveHandleRight = function(e, step) {
  26889. _changeHandle(e, isRTL ? that._$handleStart : that._$handleEnd);
  26890. _setHandleValue(e, step, 1)
  26891. },
  26892. moveHandleLeft = function(e, step) {
  26893. _changeHandle(e, isRTL ? that._$handleEnd : that._$handleStart);
  26894. _setHandleValue(e, step, -1)
  26895. };
  26896. return $.extend(this.callBase(), {
  26897. leftArrow: function(e) {
  26898. e.preventDefault();
  26899. e.stopPropagation();
  26900. moveHandleLeft(e, this.option("step"))
  26901. },
  26902. rightArrow: function(e) {
  26903. e.preventDefault();
  26904. e.stopPropagation();
  26905. moveHandleRight(e, this.option("step"))
  26906. },
  26907. pageUp: function(e) {
  26908. e.preventDefault();
  26909. e.stopPropagation();
  26910. moveHandleRight(e, this.option("step") * this.option("keyStep"))
  26911. },
  26912. pageDown: function(e) {
  26913. e.preventDefault();
  26914. e.stopPropagation();
  26915. moveHandleLeft(e, this.option("step") * this.option("keyStep"))
  26916. },
  26917. home: function(e) {
  26918. e.preventDefault();
  26919. e.stopPropagation();
  26920. var isStart = $(e.target).hasClass(RANGE_SLIDER_START_HANDLE_CLASS),
  26921. valueOption = isStart ? "start" : "end",
  26922. startOption = isStart ? "min" : "start",
  26923. val = this.option(startOption);
  26924. this.option(valueOption, val)
  26925. },
  26926. end: function(e) {
  26927. e.preventDefault();
  26928. e.stopPropagation();
  26929. var isStart = $(e.target).hasClass(RANGE_SLIDER_START_HANDLE_CLASS),
  26930. valueOption = isStart ? "start" : "end",
  26931. endOption = isStart ? "end" : "max",
  26932. val = this.option(endOption);
  26933. this.option(valueOption, val)
  26934. }
  26935. })
  26936. },
  26937. _setDefaultOptions: function() {
  26938. this.callBase();
  26939. this.option({
  26940. start: 40,
  26941. end: 60
  26942. })
  26943. },
  26944. _render: function() {
  26945. this.callBase();
  26946. this.element().addClass(RANGE_SLIDER_CLASS)
  26947. },
  26948. _renderHandle: function() {
  26949. this._$handleStart = this._renderHandleImpl(this.option("start"), this._$handleStart).addClass(RANGE_SLIDER_START_HANDLE_CLASS);
  26950. this._$handleEnd = this._renderHandleImpl(this.option("end"), this._$handleEnd).addClass(RANGE_SLIDER_END_HANDLE_CLASS);
  26951. this._updateHandleAriaLabels()
  26952. },
  26953. _startHandler: function(args) {
  26954. var e = args.jQueryEvent,
  26955. $range = this._$range,
  26956. rangeWidth = $range.width(),
  26957. eventOffsetX = events.eventData(e).x - this._$bar.offset().left,
  26958. startHandleX = $range.position().left,
  26959. endHandleX = $range.position().left + rangeWidth,
  26960. rtlEnabled = this.option("rtlEnabled"),
  26961. startHandleIsClosest = (rtlEnabled ? -1 : 1) * ((startHandleX + endHandleX) / 2 - eventOffsetX) > 0;
  26962. this._capturedHandle = startHandleIsClosest ? this._$handleStart : this._$handleEnd;
  26963. this.callBase(args)
  26964. },
  26965. _updateHandleAriaLabels: function() {
  26966. this.setAria("label", utils.stringFormat(Globalize.localize("dxRangeSlider-ariaFrom"), this.option("start")), this._$handleStart);
  26967. this.setAria("label", utils.stringFormat(Globalize.localize("dxRangeSlider-ariaTill"), this.option("end")), this._$handleEnd)
  26968. },
  26969. _activeHandle: function() {
  26970. return this._capturedHandle
  26971. },
  26972. _updateHandlePosition: function(e) {
  26973. var rtlEnabled = this.option("rtlEnabled"),
  26974. offsetDirection = rtlEnabled ? -1 : 1,
  26975. max = this.option("max"),
  26976. min = this.option("min");
  26977. var newRatio = this._startOffset + offsetDirection * e.jQueryEvent.offset / this._swipePixelRatio();
  26978. newRatio = newRatio.toPrecision(12);
  26979. var newValue = newRatio * (max - min) + min;
  26980. this._updateSelectedRangePosition(newRatio, newRatio);
  26981. this._changeValueOnSwipe(newRatio);
  26982. var startValue = this.option("start"),
  26983. endValue = this.option("end"),
  26984. $nextHandle;
  26985. if (startValue === endValue) {
  26986. if (newValue < startValue)
  26987. $nextHandle = this._$handleStart;
  26988. else
  26989. $nextHandle = this._$handleEnd;
  26990. $nextHandle.focus();
  26991. if ($nextHandle && $nextHandle !== this._capturedHandle) {
  26992. this._updateSelectedRangePosition((startValue - min) / (max - min), (endValue - min) / (max - min));
  26993. this._toggleActiveState(this._activeHandle(), false);
  26994. this._toggleActiveState($nextHandle, true);
  26995. this._capturedHandle = $nextHandle
  26996. }
  26997. this._updateSelectedRangePosition(newRatio, newRatio);
  26998. this._changeValueOnSwipe(newRatio)
  26999. }
  27000. },
  27001. _updateSelectedRangePosition: function(leftRatio, rightRatio) {
  27002. var rtlEnabled = this.option("rtlEnabled"),
  27003. moveRight = this._capturedHandle === this._$handleStart && rtlEnabled || this._capturedHandle === this._$handleEnd && !rtlEnabled;
  27004. var prop = moveRight ? "right" : "left";
  27005. if (rtlEnabled ^ moveRight)
  27006. this._$range.css(prop, 100 - rightRatio * 100 + "%");
  27007. else
  27008. this._$range.css(prop, leftRatio * 100 + "%")
  27009. },
  27010. _changeValueOnSwipe: function(ratio) {
  27011. this._suppressValueChangeAction();
  27012. this.callBase(ratio);
  27013. this._resumeValueChangeAction();
  27014. var option = this._capturedHandle === this._$handleStart ? "start" : "end",
  27015. start = this.option("start"),
  27016. end = this.option("end"),
  27017. newValue = this.option("value"),
  27018. max = this.option("max"),
  27019. min = this.option("min");
  27020. if (start > max) {
  27021. start = max;
  27022. this.option("start", max)
  27023. }
  27024. if (start < min) {
  27025. start = min;
  27026. this.option("start", min)
  27027. }
  27028. if (end > max) {
  27029. end = max;
  27030. this.option("end", max)
  27031. }
  27032. if (newValue > end && option === "start")
  27033. newValue = end;
  27034. if (newValue < start && option === "end")
  27035. newValue = start;
  27036. this.option(option, newValue)
  27037. },
  27038. _renderValue: function() {
  27039. var valStart = this.option("start"),
  27040. valEnd = this.option("end"),
  27041. min = this.option("min"),
  27042. max = this.option("max"),
  27043. rtlEnabled = this.option("rtlEnabled");
  27044. valStart = Math.max(min, Math.min(valStart, max));
  27045. valEnd = Math.max(valStart, Math.min(valEnd, max));
  27046. this.option("start", valStart);
  27047. this.option("end", valEnd);
  27048. var ratio1 = max === min ? 0 : (valStart - min) / (max - min),
  27049. ratio2 = max === min ? 0 : (valEnd - min) / (max - min);
  27050. var startOffset = parseFloat((ratio1 * 100).toPrecision(12)) + "%",
  27051. endOffset = parseFloat(((1 - ratio2) * 100).toPrecision(12)) + "%";
  27052. this._animateRange({
  27053. right: rtlEnabled ? startOffset : endOffset,
  27054. left: rtlEnabled ? endOffset : startOffset
  27055. });
  27056. this._renderHandle()
  27057. },
  27058. _repaintHandle: function() {
  27059. this._$handleStart.dxSliderHandle("repaint");
  27060. this._$handleEnd.dxSliderHandle("repaint")
  27061. },
  27062. _optionChanged: function(args) {
  27063. switch (args.name) {
  27064. case"start":
  27065. case"end":
  27066. this._renderValue();
  27067. this._createActionByOption("onValueChanged")({
  27068. start: this.option("start"),
  27069. end: this.option("end"),
  27070. jQueryEvent: this._valueChangeEventInstance
  27071. });
  27072. this._saveValueChangeEvent(undefined);
  27073. break;
  27074. default:
  27075. this.callBase(args)
  27076. }
  27077. }
  27078. }))
  27079. })(jQuery, DevExpress);
  27080. /*! Module widgets-base, file ui.gallery.js */
  27081. (function($, DX, undefined) {
  27082. var ui = DX.ui,
  27083. events = ui.events,
  27084. fx = DX.fx,
  27085. translator = DX.translator,
  27086. GALLERY_CLASS = "dx-gallery",
  27087. GALLERY_WRAPPER_CLASS = GALLERY_CLASS + "-wrapper",
  27088. GALLERY_LOOP_CLASS = "dx-gallery-loop",
  27089. GALLERY_ITEM_CONTAINER_CLASS = GALLERY_CLASS + "-container",
  27090. GALLERY_ACTIVE_CLASS = GALLERY_CLASS + "-active",
  27091. GALLERY_ITEM_CLASS = GALLERY_CLASS + "-item",
  27092. GALLERY_LOOP_ITEM_CLASS = GALLERY_ITEM_CLASS + "-loop",
  27093. GALLERY_ITEM_SELECTOR = "." + GALLERY_ITEM_CLASS,
  27094. GALLERY_ITEM_SELECTED_CLASS = GALLERY_ITEM_CLASS + "-selected",
  27095. GALLERY_INDICATOR_CLASS = GALLERY_CLASS + "-indicator",
  27096. GALLERY_INDICATOR_ITEM_CLASS = GALLERY_INDICATOR_CLASS + "-item",
  27097. GALLERY_INDICATOR_ITEM_SELECTOR = "." + GALLERY_INDICATOR_ITEM_CLASS,
  27098. GALLERY_INDICATOR_ITEM_SELECTED_CLASS = GALLERY_INDICATOR_ITEM_CLASS + "-selected",
  27099. GALLERY_ITEM_DATA_KEY = "dxGalleryItemData";
  27100. var dxGalleryNavButton = ui.Widget.inherit({
  27101. _supportedKeys: function() {
  27102. return $.extend(this.callBase(), {
  27103. pageUp: $.noop,
  27104. pageDown: $.noop
  27105. })
  27106. },
  27107. _setDefaultOptions: function() {
  27108. this.callBase();
  27109. this.option({
  27110. direction: "next",
  27111. onClick: null,
  27112. hoverStateEnabled: true,
  27113. activeStateEnabled: true
  27114. })
  27115. },
  27116. _render: function() {
  27117. this.callBase();
  27118. var that = this,
  27119. $element = this.element(),
  27120. eventName = events.addNamespace("dxclick", this.NAME);
  27121. $element.addClass(GALLERY_CLASS + "-nav-button-" + this.option("direction")).off(eventName).on(eventName, function(e) {
  27122. that._createActionByOption("onClick")({jQueryEvent: e})
  27123. })
  27124. },
  27125. _optionChanged: function(args) {
  27126. switch (args.name) {
  27127. case"onClick":
  27128. case"direction":
  27129. this._invalidate();
  27130. break;
  27131. default:
  27132. this.callBase(args)
  27133. }
  27134. }
  27135. });
  27136. DX.registerComponent("dxGallery", ui, ui.CollectionWidget.inherit({
  27137. _activeStateUnit: GALLERY_ITEM_SELECTOR,
  27138. _setDefaultOptions: function() {
  27139. this.callBase();
  27140. this.option({
  27141. activeStateEnabled: false,
  27142. animationDuration: 400,
  27143. animationEnabled: true,
  27144. loop: false,
  27145. swipeEnabled: true,
  27146. indicatorEnabled: true,
  27147. showIndicator: true,
  27148. selectedIndex: 0,
  27149. slideshowDelay: 0,
  27150. showNavButtons: false,
  27151. wrapAround: false,
  27152. initialItemWidth: undefined,
  27153. stretchImages: false,
  27154. _itemAttributes: {role: "option"},
  27155. loopItemFocus: false,
  27156. selectOnFocus: true,
  27157. selectionMode: "single",
  27158. selectionRequired: true,
  27159. selectionByClick: false
  27160. })
  27161. },
  27162. _defaultOptionsRules: function() {
  27163. return this.callBase().concat([{
  27164. device: function(device) {
  27165. return DX.devices.real().generic && !DX.devices.isSimulator()
  27166. },
  27167. options: {focusStateEnabled: true}
  27168. }])
  27169. },
  27170. _init: function() {
  27171. this.callBase();
  27172. this.option("loopItemFocus", this.option("loop"))
  27173. },
  27174. _dataSourceOptions: function() {
  27175. return {paginate: false}
  27176. },
  27177. _itemContainer: function() {
  27178. return this._$container
  27179. },
  27180. _itemClass: function() {
  27181. return GALLERY_ITEM_CLASS
  27182. },
  27183. _itemDataKey: function() {
  27184. return GALLERY_ITEM_DATA_KEY
  27185. },
  27186. _itemWidth: function() {
  27187. if (!this._itemWidthCache)
  27188. this._itemWidthCache = this.option("initialItemWidth") || this.element().outerWidth();
  27189. return this._itemWidthCache
  27190. },
  27191. _actualItemWidth: function() {
  27192. var itemPerPage = this.option("wrapAround") ? this._itemsPerPage() + 1 : this._itemsPerPage();
  27193. if (this.option("stretchImages"))
  27194. return this.element().outerWidth() / itemPerPage;
  27195. if (this.option("wrapAround"))
  27196. return this._itemWidth() * this._itemsPerPage() / (this._itemsPerPage() + 1);
  27197. return this._itemWidth()
  27198. },
  27199. _itemsPerPage: function() {
  27200. var itemsPerPage = Math.floor(this.element().outerWidth() / this._itemWidth()) || 1;
  27201. return Math.min(itemsPerPage, this._itemsCount())
  27202. },
  27203. _pagesCount: function() {
  27204. return Math.ceil(this._itemsCount() / this._itemsPerPage())
  27205. },
  27206. _clearItemWidthCache: function() {
  27207. delete this._itemWidthCache
  27208. },
  27209. _itemsCount: function() {
  27210. return (this.option("items") || []).length
  27211. },
  27212. _offsetDirection: function() {
  27213. return this.option("rtlEnabled") ? -1 : 1
  27214. },
  27215. _render: function() {
  27216. this.element().addClass(GALLERY_CLASS);
  27217. this.element().toggleClass(GALLERY_LOOP_CLASS, this.option("loop"));
  27218. this._renderDragHandler();
  27219. this._renderWrapper();
  27220. this._renderItemsContainer();
  27221. this.callBase();
  27222. this._renderContainerPosition();
  27223. this._renderItemSizes();
  27224. this._renderItemPositions();
  27225. this._renderNavButtons();
  27226. this._renderIndicator();
  27227. this._renderSelectedItem();
  27228. this._renderUserInteraction();
  27229. this._setupSlideShow();
  27230. this._reviseDimensions();
  27231. this.setAria({
  27232. role: "listbox",
  27233. label: "gallery"
  27234. })
  27235. },
  27236. _dimensionChanged: function() {
  27237. var selectedIndex = this.option("selectedIndex") || 0;
  27238. this._clearItemWidthCache();
  27239. this._renderDuplicateItems();
  27240. this._renderItemSizes();
  27241. this._renderItemPositions();
  27242. this._renderIndicator();
  27243. this._renderContainerPosition(this._calculateIndexOffset(selectedIndex))
  27244. },
  27245. _renderDragHandler: function() {
  27246. var eventName = events.addNamespace("dragstart", this.NAME);
  27247. this.element().off(eventName).on(eventName, "img", function() {
  27248. return false
  27249. })
  27250. },
  27251. _renderWrapper: function() {
  27252. if (this._$wrapper)
  27253. return;
  27254. this._$wrapper = $("<div />").addClass(GALLERY_WRAPPER_CLASS).appendTo(this.element())
  27255. },
  27256. _renderItems: function(items) {
  27257. this.callBase(items);
  27258. this._loadNextPageIfNeeded()
  27259. },
  27260. _renderItemsContainer: function() {
  27261. if (this._$container)
  27262. return;
  27263. this._$container = $("<div>").addClass(GALLERY_ITEM_CONTAINER_CLASS).appendTo(this._$wrapper)
  27264. },
  27265. _renderDuplicateItems: function() {
  27266. if (!this.option("loop"))
  27267. return;
  27268. var items = this.option("items") || [],
  27269. itemsCount = items.length,
  27270. lastItemIndex = itemsCount - 1,
  27271. i;
  27272. if (!itemsCount)
  27273. return;
  27274. this.element().find("." + GALLERY_LOOP_ITEM_CLASS).remove();
  27275. var duplicateCount = Math.min(this._itemsPerPage(), itemsCount);
  27276. for (i = 0; i < duplicateCount; i++)
  27277. this._renderItem(0, items[i]).addClass(GALLERY_LOOP_ITEM_CLASS);
  27278. for (i = 0; i < duplicateCount; i++)
  27279. this._renderItem(0, items[lastItemIndex - i]).addClass(GALLERY_LOOP_ITEM_CLASS)
  27280. },
  27281. _renderItemSizes: function(startIndex) {
  27282. var $items = this._itemElements(),
  27283. itemWidth = this._actualItemWidth();
  27284. if (startIndex !== undefined)
  27285. $items = $items.slice(startIndex);
  27286. $items.each(function(index) {
  27287. $($items[index]).outerWidth(itemWidth)
  27288. })
  27289. },
  27290. _renderItemPositions: function() {
  27291. var itemWidth = this._actualItemWidth(),
  27292. itemsCount = this._itemsCount(),
  27293. itemsPerPage = this._itemsPerPage(),
  27294. loopItemsCount = this.element().find("." + GALLERY_LOOP_ITEM_CLASS).length,
  27295. lastItemDuplicateIndex = itemsCount + loopItemsCount - 1,
  27296. offsetDirection = this._offsetDirection(),
  27297. offsetRatio = this.option("wrapAround") ? 0.5 : 0,
  27298. freeSpace = this._itemFreeSpace();
  27299. this._itemElements().each(function(index) {
  27300. var realIndex = index;
  27301. if (index > itemsCount + itemsPerPage - 1)
  27302. realIndex = lastItemDuplicateIndex - realIndex - itemsPerPage;
  27303. var itemPosition = offsetDirection * itemWidth * (realIndex + offsetRatio) + freeSpace * (realIndex + 1 - offsetRatio);
  27304. translator.move($(this), {left: itemPosition})
  27305. });
  27306. this._relocateItems(this.option("selectedIndex"), this.option("selectedIndex"), true)
  27307. },
  27308. _itemFreeSpace: function() {
  27309. var itemsPerPage = this._itemsPerPage();
  27310. if (this.option("wrapAround"))
  27311. itemsPerPage = itemsPerPage + 1;
  27312. return (this.element().outerWidth() - this._actualItemWidth() * itemsPerPage) / (itemsPerPage + 1)
  27313. },
  27314. _renderContainerPosition: function(offset, animate) {
  27315. offset = offset || 0;
  27316. var that = this,
  27317. itemWidth = this._actualItemWidth(),
  27318. targetIndex = offset,
  27319. targetPosition = this._offsetDirection() * targetIndex * (itemWidth + this._itemFreeSpace()),
  27320. positionReady;
  27321. if (DX.utils.isDefined(this._animationOverride)) {
  27322. animate = this._animationOverride;
  27323. delete this._animationOverride
  27324. }
  27325. if (animate) {
  27326. that._startSwipe();
  27327. positionReady = that._animate(targetPosition).done($.proxy(that._endSwipe, that))
  27328. }
  27329. else {
  27330. translator.move(this._$container, {left: targetPosition});
  27331. positionReady = $.Deferred().resolveWith(that)
  27332. }
  27333. if (this._deferredAnimate)
  27334. positionReady.done(function() {
  27335. that._deferredAnimate.resolveWith(that)
  27336. });
  27337. return positionReady.promise()
  27338. },
  27339. _startSwipe: function() {
  27340. this.element().addClass(GALLERY_ACTIVE_CLASS)
  27341. },
  27342. _endSwipe: function() {
  27343. this.element().removeClass(GALLERY_ACTIVE_CLASS)
  27344. },
  27345. _animate: function(targetPosition, extraConfig) {
  27346. var that = this,
  27347. animationComplete = $.Deferred();
  27348. fx.animate(this._$container, $.extend({
  27349. type: "slide",
  27350. to: {left: targetPosition},
  27351. duration: that.option("animationDuration"),
  27352. complete: function() {
  27353. if (that._needMoveContainerForward())
  27354. translator.move(that._$container, {left: 0});
  27355. if (that._needMoveContainerBack())
  27356. translator.move(that._$container, {left: that._maxContainerOffset()});
  27357. animationComplete.resolveWith(that)
  27358. }
  27359. }, extraConfig || {}));
  27360. return animationComplete
  27361. },
  27362. _needMoveContainerForward: function() {
  27363. return this._$container.position().left * this._offsetDirection() <= -this._maxItemWidth() * this._itemsCount()
  27364. },
  27365. _needMoveContainerBack: function() {
  27366. return this._$container.position().left * this._offsetDirection() >= this._actualItemWidth()
  27367. },
  27368. _maxContainerOffset: function() {
  27369. return -this._maxItemWidth() * (this._itemsCount() - this._itemsPerPage()) * this._offsetDirection()
  27370. },
  27371. _maxItemWidth: function() {
  27372. return this._actualItemWidth() + this._itemFreeSpace()
  27373. },
  27374. _reviseDimensions: function() {
  27375. var that = this,
  27376. $firstItem = that._itemElements().first().find(".dx-item-content");
  27377. if (!$firstItem || $firstItem.is(":hidden"))
  27378. return;
  27379. if (!that.option("height"))
  27380. that.option("height", $firstItem.outerHeight());
  27381. if (!that.option("width"))
  27382. that.option("width", $firstItem.outerWidth());
  27383. this._dimensionChanged()
  27384. },
  27385. _renderIndicator: function() {
  27386. this._cleanIndicators();
  27387. if (!this.option("showIndicator"))
  27388. return;
  27389. var indicator = this._$indicator = $("<div>").addClass(GALLERY_INDICATOR_CLASS).appendTo(this._$wrapper);
  27390. for (var i = 0; i < this._pagesCount(); i++)
  27391. $("<div>").addClass(GALLERY_INDICATOR_ITEM_CLASS).appendTo(indicator);
  27392. this._renderSelectedPageIndicator()
  27393. },
  27394. _cleanIndicators: function() {
  27395. if (this._$indicator)
  27396. this._$indicator.remove()
  27397. },
  27398. _renderSelectedItem: function() {
  27399. var selectedIndex = this.option("selectedIndex");
  27400. this._itemElements().removeClass(GALLERY_ITEM_SELECTED_CLASS).eq(selectedIndex).addClass(GALLERY_ITEM_SELECTED_CLASS)
  27401. },
  27402. _renderSelectedPageIndicator: function() {
  27403. if (!this._$indicator)
  27404. return;
  27405. var itemIndex = this.option("selectedIndex"),
  27406. lastIndex = this._pagesCount() - 1,
  27407. pageIndex = Math.ceil(itemIndex / this._itemsPerPage());
  27408. pageIndex = Math.min(lastIndex, pageIndex);
  27409. this._$indicator.find(GALLERY_INDICATOR_ITEM_SELECTOR).removeClass(GALLERY_INDICATOR_ITEM_SELECTED_CLASS).eq(pageIndex).addClass(GALLERY_INDICATOR_ITEM_SELECTED_CLASS)
  27410. },
  27411. _renderUserInteraction: function() {
  27412. var that = this,
  27413. rootElement = that.element(),
  27414. swipeEnabled = that.option("swipeEnabled") && this._itemsCount() > 1;
  27415. this._createComponent(rootElement, "dxSwipeable", {
  27416. disabled: this.option("disabled") || !swipeEnabled,
  27417. onStart: $.proxy(that._swipeStartHandler, that),
  27418. onUpdated: $.proxy(that._swipeUpdateHandler, that),
  27419. onEnd: $.proxy(that._swipeEndHandler, that),
  27420. itemSizeFunc: $.proxy(that._actualItemWidth(), that)
  27421. });
  27422. var indicatorSelectAction = this._createAction(this._indicatorSelectHandler);
  27423. rootElement.off(events.addNamespace("dxclick", this.NAME), GALLERY_INDICATOR_ITEM_SELECTOR).on(events.addNamespace("dxclick", this.NAME), GALLERY_INDICATOR_ITEM_SELECTOR, function(e) {
  27424. indicatorSelectAction({jQueryEvent: e})
  27425. })
  27426. },
  27427. _indicatorSelectHandler: function(args) {
  27428. var e = args.jQueryEvent,
  27429. instance = args.component;
  27430. if (!instance.option("indicatorEnabled"))
  27431. return;
  27432. var indicatorIndex = $(e.target).index(),
  27433. itemIndex = instance._fitPaginatedIndex(indicatorIndex * instance._itemsPerPage());
  27434. instance._needLongMove = true;
  27435. instance.option("selectedIndex", itemIndex);
  27436. instance._loadNextPageIfNeeded(itemIndex)
  27437. },
  27438. _renderNavButtons: function() {
  27439. var that = this;
  27440. if (!that.option("showNavButtons")) {
  27441. that._cleanNavButtons();
  27442. return
  27443. }
  27444. that._prevNavButton = $("<div>").appendTo(this._$wrapper);
  27445. that._createComponent(that._prevNavButton, "dxGalleryNavButton", {
  27446. direction: "prev",
  27447. onClick: function() {
  27448. that._prevPage()
  27449. }
  27450. });
  27451. that._nextNavButton = $("<div>").appendTo(this._$wrapper);
  27452. that._createComponent(that._nextNavButton, "dxGalleryNavButton", {
  27453. direction: "next",
  27454. onClick: function() {
  27455. that._nextPage()
  27456. }
  27457. });
  27458. this._renderNavButtonsVisibility()
  27459. },
  27460. _prevPage: function() {
  27461. var visiblePageSize = this._itemsPerPage(),
  27462. newSelectedIndex = this.option("selectedIndex") - visiblePageSize;
  27463. if (newSelectedIndex === -visiblePageSize && visiblePageSize === this._itemsCount())
  27464. return this._relocateItems(newSelectedIndex, 0);
  27465. else
  27466. return this.goToItem(this._fitPaginatedIndex(newSelectedIndex))
  27467. },
  27468. _nextPage: function() {
  27469. var visiblePageSize = this._itemsPerPage(),
  27470. newSelectedIndex = this.option("selectedIndex") + visiblePageSize;
  27471. if (newSelectedIndex === visiblePageSize && visiblePageSize === this._itemsCount())
  27472. return this._relocateItems(newSelectedIndex, 0);
  27473. else
  27474. return this.goToItem(this._fitPaginatedIndex(newSelectedIndex)).done(this._loadNextPageIfNeeded)
  27475. },
  27476. _loadNextPageIfNeeded: function(selectedIndex) {
  27477. selectedIndex = selectedIndex === undefined ? this.option("selectedIndex") : selectedIndex;
  27478. if (this._dataSource && this._dataSource.paginate() && this._shouldLoadNextPage(selectedIndex) && !this._isDataSourceLoading() && !this._isLastPage())
  27479. this._loadNextPage().done($.proxy(function() {
  27480. this._renderIndicator();
  27481. this._renderItemPositions();
  27482. this._renderNavButtonsVisibility();
  27483. this._renderItemSizes(selectedIndex)
  27484. }, this))
  27485. },
  27486. _shouldLoadNextPage: function(selectedIndex) {
  27487. var visiblePageSize = this._itemsPerPage();
  27488. return selectedIndex + 2 * visiblePageSize > this.option("items").length
  27489. },
  27490. _allowDinamicItemsAppend: function() {
  27491. return true
  27492. },
  27493. _fitPaginatedIndex: function(itemIndex) {
  27494. var itemsPerPage = this._itemsPerPage();
  27495. var restItemsCount = itemIndex < 0 ? itemsPerPage + itemIndex : this._itemsCount() - itemIndex;
  27496. if (itemIndex > this._itemsCount() - 1) {
  27497. itemIndex = 0;
  27498. this._goToGhostItem = true
  27499. }
  27500. else if (restItemsCount < itemsPerPage && restItemsCount > 0)
  27501. if (itemIndex > 0)
  27502. itemIndex = itemIndex - (itemsPerPage - restItemsCount);
  27503. else
  27504. itemIndex = itemIndex + (itemsPerPage - restItemsCount);
  27505. return itemIndex
  27506. },
  27507. _cleanNavButtons: function() {
  27508. if (this._prevNavButton) {
  27509. this._prevNavButton.remove();
  27510. delete this._prevNavButton
  27511. }
  27512. if (this._nextNavButton) {
  27513. this._nextNavButton.remove();
  27514. delete this._nextNavButton
  27515. }
  27516. },
  27517. _renderNavButtonsVisibility: function() {
  27518. if (!this.option("showNavButtons") || !this._prevNavButton || !this._nextNavButton)
  27519. return;
  27520. var selectedIndex = this.option("selectedIndex"),
  27521. loop = this.option("loop"),
  27522. itemsCount = this._itemsCount();
  27523. this._prevNavButton.show();
  27524. this._nextNavButton.show();
  27525. if (loop)
  27526. return;
  27527. var nextHidden = selectedIndex === itemsCount - this._itemsPerPage(),
  27528. prevHidden = itemsCount < 2 || selectedIndex === 0;
  27529. if (this._dataSource && this._dataSource.paginate())
  27530. nextHidden = nextHidden && this._isLastPage();
  27531. else
  27532. nextHidden = nextHidden || itemsCount < 2;
  27533. if (prevHidden)
  27534. this._prevNavButton.hide();
  27535. if (nextHidden)
  27536. this._nextNavButton.hide()
  27537. },
  27538. _setupSlideShow: function() {
  27539. var that = this,
  27540. slideshowDelay = that.option("slideshowDelay");
  27541. clearTimeout(that._slideshowTimer);
  27542. if (!slideshowDelay)
  27543. return;
  27544. that._slideshowTimer = setTimeout(function() {
  27545. if (that._userInteraction) {
  27546. that._setupSlideShow();
  27547. return
  27548. }
  27549. that.nextItem(true).done(that._setupSlideShow)
  27550. }, slideshowDelay)
  27551. },
  27552. _swipeStartHandler: function(e) {
  27553. var itemsCount = this._itemsCount();
  27554. if (!itemsCount) {
  27555. e.jQueryEvent.cancel = true;
  27556. return
  27557. }
  27558. this._stopItemAnimations();
  27559. this._startSwipe();
  27560. this._userInteraction = true;
  27561. if (!this.option("loop")) {
  27562. var selectedIndex = this.option("selectedIndex"),
  27563. startOffset = itemsCount - selectedIndex - this._itemsPerPage(),
  27564. endOffset = selectedIndex,
  27565. rtlEnabled = this.option("rtlEnabled");
  27566. e.jQueryEvent.maxLeftOffset = rtlEnabled ? endOffset : startOffset;
  27567. e.jQueryEvent.maxRightOffset = rtlEnabled ? startOffset : endOffset
  27568. }
  27569. },
  27570. _stopItemAnimations: function() {
  27571. fx.stop(this._$container, true)
  27572. },
  27573. _swipeUpdateHandler: function(e) {
  27574. var wrapAroundRatio = this.option("wrapAround") ? 1 : 0;
  27575. var offset = this._offsetDirection() * e.jQueryEvent.offset * (this._itemsPerPage() + wrapAroundRatio) - this.option("selectedIndex");
  27576. if (offset < 0)
  27577. this._loadNextPageIfNeeded(Math.ceil(Math.abs(offset)));
  27578. this._renderContainerPosition(offset)
  27579. },
  27580. _swipeEndHandler: function(e) {
  27581. var targetOffset = e.jQueryEvent.targetOffset * this._offsetDirection() * this._itemsPerPage(),
  27582. selectedIndex = this.option("selectedIndex"),
  27583. newIndex = this._fitIndex(selectedIndex - targetOffset),
  27584. paginatedIndex = this._fitPaginatedIndex(newIndex);
  27585. if (Math.abs(targetOffset) < this._itemsPerPage()) {
  27586. this._relocateItems(selectedIndex);
  27587. return
  27588. }
  27589. if (this._itemsPerPage() === this._itemsCount()) {
  27590. if (targetOffset > 0)
  27591. this._relocateItems(-targetOffset);
  27592. else
  27593. this._relocateItems(0);
  27594. return
  27595. }
  27596. this.option("selectedIndex", paginatedIndex)
  27597. },
  27598. _setFocusOnSelect: function() {
  27599. this._userInteraction = true;
  27600. var selectedItem = this.itemElements().filter("." + GALLERY_ITEM_SELECTED_CLASS);
  27601. this.option("focusedElement", selectedItem);
  27602. this._userInteraction = false
  27603. },
  27604. _flipIndex: function(index) {
  27605. var itemsCount = this._itemsCount();
  27606. index = index % itemsCount;
  27607. if (index > (itemsCount + 1) / 2)
  27608. index -= itemsCount;
  27609. if (index < -(itemsCount - 1) / 2)
  27610. index += itemsCount;
  27611. return index
  27612. },
  27613. _fitIndex: function(index) {
  27614. if (!this.option("loop"))
  27615. return index;
  27616. var itemsCount = this._itemsCount();
  27617. if (index >= itemsCount || index < 0)
  27618. this._goToGhostItem = true;
  27619. if (index >= itemsCount)
  27620. index = itemsCount - index;
  27621. index = index % itemsCount;
  27622. if (index < 0)
  27623. index += itemsCount;
  27624. return index
  27625. },
  27626. _clean: function() {
  27627. this.callBase();
  27628. this._cleanIndicators();
  27629. this._cleanNavButtons()
  27630. },
  27631. _dispose: function() {
  27632. clearTimeout(this._slideshowTimer);
  27633. this.callBase()
  27634. },
  27635. _updateSelection: function(addedSelection, removedSelection) {
  27636. this._stopItemAnimations();
  27637. this._renderNavButtonsVisibility();
  27638. this._renderSelectedItem();
  27639. this._relocateItems(addedSelection[0], removedSelection[0]);
  27640. this._renderSelectedPageIndicator()
  27641. },
  27642. _relocateItems: function(newIndex, prevIndex, withoutAnimation) {
  27643. if (prevIndex === undefined)
  27644. prevIndex = newIndex;
  27645. var indexOffset = this._calculateIndexOffset(newIndex, prevIndex);
  27646. this._renderContainerPosition(indexOffset, this.option("animationEnabled") && !withoutAnimation).done(function() {
  27647. this._setFocusOnSelect();
  27648. this._userInteraction = false;
  27649. this._setupSlideShow()
  27650. })
  27651. },
  27652. _focusInHandler: function(e) {
  27653. if (fx.isAnimating(this._$container) || this._userInteraction)
  27654. return;
  27655. this.callBase.apply(this, arguments)
  27656. },
  27657. _focusOutHandler: function(e) {
  27658. if (fx.isAnimating(this._$container) || this._userInteraction)
  27659. return;
  27660. this.callBase.apply(this, arguments)
  27661. },
  27662. _selectFocusedItem: $.noop,
  27663. _moveFocus: function(location) {
  27664. this._stopItemAnimations();
  27665. this.callBase.apply(this, arguments);
  27666. var index = this.itemElements().index(this.option("focusedElement"));
  27667. this.goToItem(index, this.option("animationEnabled"))
  27668. },
  27669. _visibilityChanged: function(visible) {
  27670. if (visible)
  27671. this._reviseDimensions()
  27672. },
  27673. _calculateIndexOffset: function(newIndex, lastIndex) {
  27674. if (lastIndex === undefined)
  27675. lastIndex = newIndex;
  27676. var indexOffset = lastIndex - newIndex;
  27677. if (this.option("loop") && !this._needLongMove && this._goToGhostItem) {
  27678. if (this._isItemOnFirstPage(newIndex) && this._isItemOnLastPage(lastIndex))
  27679. indexOffset = -this._itemsPerPage();
  27680. else if (this._isItemOnLastPage(newIndex) && this._isItemOnFirstPage(lastIndex))
  27681. indexOffset = this._itemsPerPage();
  27682. this._goToGhostItem = false
  27683. }
  27684. this._needLongMove = false;
  27685. indexOffset = indexOffset - lastIndex;
  27686. return indexOffset
  27687. },
  27688. _isItemOnLastPage: function(itemIndex) {
  27689. return itemIndex >= this._itemsCount() - this._itemsPerPage()
  27690. },
  27691. _isItemOnFirstPage: function(itemIndex) {
  27692. return itemIndex <= this._itemsPerPage()
  27693. },
  27694. _optionChanged: function(args) {
  27695. var value = args.value;
  27696. switch (args.name) {
  27697. case"width":
  27698. case"initialItemWidth":
  27699. this.callBase.apply(this, arguments);
  27700. this._dimensionChanged();
  27701. break;
  27702. case"animationDuration":
  27703. this._renderNavButtonsVisibility();
  27704. break;
  27705. case"animationEnabled":
  27706. break;
  27707. case"loop":
  27708. this.option("loopItemFocus", value);
  27709. this.element().toggleClass(GALLERY_LOOP_CLASS, value);
  27710. this._renderDuplicateItems();
  27711. this._renderItemPositions();
  27712. this._renderNavButtonsVisibility();
  27713. return;
  27714. case"showIndicator":
  27715. this._renderIndicator();
  27716. return;
  27717. case"showNavButtons":
  27718. this._renderNavButtons();
  27719. return;
  27720. case"slideshowDelay":
  27721. this._setupSlideShow();
  27722. return;
  27723. case"wrapAround":
  27724. case"stretchImages":
  27725. this._renderItemSizes();
  27726. this._renderItemPositions();
  27727. break;
  27728. case"swipeEnabled":
  27729. case"indicatorEnabled":
  27730. this._renderUserInteraction();
  27731. return;
  27732. default:
  27733. this.callBase(args)
  27734. }
  27735. },
  27736. goToItem: function(itemIndex, animation) {
  27737. var selectedIndex = this.option("selectedIndex"),
  27738. itemsCount = this._itemsCount();
  27739. if (animation !== undefined)
  27740. this._animationOverride = animation;
  27741. itemIndex = this._fitIndex(itemIndex);
  27742. this._deferredAnimate = $.Deferred();
  27743. if (itemIndex > itemsCount - 1 || itemIndex < 0 || selectedIndex === itemIndex)
  27744. return this._deferredAnimate.resolveWith(this).promise();
  27745. this.option("selectedIndex", itemIndex);
  27746. return this._deferredAnimate.promise()
  27747. },
  27748. prevItem: function(animation) {
  27749. return this.goToItem(this.option("selectedIndex") - 1, animation)
  27750. },
  27751. nextItem: function(animation) {
  27752. return this.goToItem(this.option("selectedIndex") + 1, animation)
  27753. }
  27754. }));
  27755. DX.registerComponent("dxGalleryNavButton", ui.dxGallery, dxGalleryNavButton)
  27756. })(jQuery, DevExpress);
  27757. /*! Module widgets-base, file ui.overlay.js */
  27758. (function($, DX, undefined) {
  27759. var ui = DX.ui,
  27760. utils = DX.utils,
  27761. events = ui.events,
  27762. fx = DX.fx,
  27763. translator = DX.translator;
  27764. var OVERLAY_CLASS = "dx-overlay",
  27765. OVERLAY_WRAPPER_CLASS = "dx-overlay-wrapper",
  27766. OVERLAY_CONTENT_CLASS = "dx-overlay-content",
  27767. OVERLAY_SHADER_CLASS = "dx-overlay-shader",
  27768. OVERLAY_MODAL_CLASS = "dx-overlay-modal",
  27769. ANONYMOUS_TEMPLATE_NAME = "content",
  27770. RTL_DIRECTION_CLASS = "dx-rtl",
  27771. ACTIONS = ["onShowing", "onShown", "onHiding", "onHidden", "onPositioning", "onPositioned"],
  27772. FIRST_Z_INDEX = 1000,
  27773. Z_INDEX_STACK = [],
  27774. DISABLED_STATE_CLASS = "dx-state-disabled",
  27775. TAB_KEY = 9;
  27776. var realDevice = DX.devices.real(),
  27777. realVersion = realDevice.version,
  27778. iOS7_0andBelow = realDevice.platform === "ios" && DX.compareVersions(realVersion, [7, 1]) < 0,
  27779. android4_0nativeBrowser = realDevice.platform === "android" && DX.compareVersions(realVersion, [4, 0], 2) === 0 && navigator.userAgent.indexOf("Chrome") === -1;
  27780. var forceRepaint = function($element) {
  27781. if (iOS7_0andBelow)
  27782. $element.width();
  27783. if (android4_0nativeBrowser) {
  27784. var $parents = $element.parents(),
  27785. inScrollView = $parents.is(".dx-scrollable-native");
  27786. if (!inScrollView) {
  27787. $parents.css("backface-visibility", "hidden");
  27788. $parents.css("backface-visibility");
  27789. $parents.css("backface-visibility", "visible")
  27790. }
  27791. }
  27792. };
  27793. var getElement = function(value) {
  27794. return value && $(value instanceof $.Event ? value.target : value)
  27795. };
  27796. DX.registerComponent("dxOverlay", ui, ui.Widget.inherit({
  27797. _supportedKeys: function() {
  27798. var offsetSize = 5,
  27799. move = function(top, left, e) {
  27800. if (!this.option("dragEnabled"))
  27801. return;
  27802. e.preventDefault();
  27803. e.stopPropagation();
  27804. var offset = {
  27805. top: top,
  27806. left: left
  27807. };
  27808. this._changePosition(offset)
  27809. };
  27810. return $.extend(this.callBase(), {
  27811. escape: function(e) {
  27812. this.hide()
  27813. },
  27814. downArrow: $.proxy(move, this, offsetSize, 0),
  27815. upArrow: $.proxy(move, this, -offsetSize, 0),
  27816. leftArrow: $.proxy(move, this, 0, -offsetSize),
  27817. rightArrow: $.proxy(move, this, 0, offsetSize)
  27818. })
  27819. },
  27820. _setDeprecatedOptions: function() {
  27821. this.callBase();
  27822. $.extend(this._deprecatedOptions, {
  27823. shownAction: {
  27824. since: "14.2",
  27825. alias: "onShown"
  27826. },
  27827. showingAction: {
  27828. since: "14.2",
  27829. alias: "onShowing"
  27830. },
  27831. hidingAction: {
  27832. since: "14.2",
  27833. alias: "onHiding"
  27834. },
  27835. hiddenAction: {
  27836. since: "14.2",
  27837. alias: "onHidden"
  27838. }
  27839. })
  27840. },
  27841. _setDefaultOptions: function() {
  27842. this.callBase();
  27843. this.option({
  27844. activeStateEnabled: false,
  27845. visible: false,
  27846. deferRendering: true,
  27847. shading: true,
  27848. shadingColor: "",
  27849. position: {
  27850. my: "center",
  27851. at: "center"
  27852. },
  27853. width: function() {
  27854. return $(window).width() * 0.8
  27855. },
  27856. height: function() {
  27857. return $(window).height() * 0.8
  27858. },
  27859. animation: {
  27860. show: {
  27861. type: "pop",
  27862. duration: 400
  27863. },
  27864. hide: {
  27865. type: "pop",
  27866. duration: 400,
  27867. to: {
  27868. opacity: 0,
  27869. scale: 0
  27870. },
  27871. from: {
  27872. opacity: 1,
  27873. scale: 1
  27874. }
  27875. }
  27876. },
  27877. closeOnOutsideClick: false,
  27878. closeOnBackButton: true,
  27879. onShowing: null,
  27880. onShown: null,
  27881. onHiding: null,
  27882. onHidden: null,
  27883. contentTemplate: "content",
  27884. dragEnabled: false,
  27885. resizeEnabled: false,
  27886. target: undefined,
  27887. container: undefined,
  27888. hideTopOverlayHandler: undefined,
  27889. closeOnTargetScroll: false,
  27890. onPositioning: null,
  27891. onPositioned: null,
  27892. boundaryOffset: {
  27893. h: 0,
  27894. v: 0
  27895. }
  27896. })
  27897. },
  27898. _defaultOptionsRules: function() {
  27899. return this.callBase().concat([{
  27900. device: function(device) {
  27901. var realDevice = DX.devices.real(),
  27902. realPlatform = realDevice.platform,
  27903. realVersion = realDevice.version;
  27904. return realPlatform === "android" && DX.compareVersions(realVersion, [4, 2]) < 0
  27905. },
  27906. options: {animation: {
  27907. show: {
  27908. type: "fade",
  27909. duration: 400
  27910. },
  27911. hide: {
  27912. type: "fade",
  27913. duration: 400,
  27914. to: {opacity: 0},
  27915. from: {opacity: 1}
  27916. }
  27917. }}
  27918. }])
  27919. },
  27920. _setOptionsByReference: function() {
  27921. this.callBase();
  27922. $.extend(this._optionsByReference, {animation: true})
  27923. },
  27924. _getAnonimousTemplateName: function() {
  27925. return ANONYMOUS_TEMPLATE_NAME
  27926. },
  27927. _wrapper: function() {
  27928. return this._$wrapper
  27929. },
  27930. _container: function() {
  27931. return this._$content
  27932. },
  27933. _init: function() {
  27934. this.callBase();
  27935. this._initActions();
  27936. this._initCloseOnOutsideClickHandler();
  27937. this._$wrapper = $("<div>").addClass(OVERLAY_WRAPPER_CLASS);
  27938. this._$content = $("<div>").addClass(OVERLAY_CONTENT_CLASS);
  27939. var $element = this.element();
  27940. this._$wrapper.addClass($element.attr("class"));
  27941. $element.addClass(OVERLAY_CLASS);
  27942. this._$wrapper.attr("data-bind", "dxControlsDescendantBindings: true");
  27943. this._$wrapper.on("MSPointerDown", $.noop);
  27944. this._toggleViewPortSubscriptiion(true)
  27945. },
  27946. _initOptions: function(options) {
  27947. this._initTarget(options.target);
  27948. this._initContainer(options.container);
  27949. this._initHideTopOverlayHandler(options.hideTopOverlayHandler);
  27950. this.callBase(options)
  27951. },
  27952. _initTarget: function(target) {
  27953. if (!utils.isDefined(target))
  27954. return;
  27955. var options = this.option();
  27956. $.each(["position.of", "animation.show.from.position.of", "animation.show.to.position.of", "animation.hide.from.position.of", "animation.hide.to.position.of"], function(_, path) {
  27957. var pathParts = path.split(".");
  27958. var option = options;
  27959. while (option)
  27960. if (pathParts.length === 1) {
  27961. if ($.isPlainObject(option))
  27962. option[pathParts.shift()] = target;
  27963. break
  27964. }
  27965. else
  27966. option = option[pathParts.shift()]
  27967. })
  27968. },
  27969. _initContainer: function(container) {
  27970. container = container === undefined ? DX.viewPort() : container;
  27971. var $element = this.element(),
  27972. $container = $element.closest(container);
  27973. if (!$container.length)
  27974. $container = $(container).first();
  27975. this._$container = $container.length ? $container : $element.parent()
  27976. },
  27977. _initHideTopOverlayHandler: function(handler) {
  27978. this._hideTopOverlayHandler = handler !== undefined ? handler : $.proxy(this._defaultHideTopOverlayHandler, this)
  27979. },
  27980. _defaultHideTopOverlayHandler: function() {
  27981. this.hide()
  27982. },
  27983. _initActions: function() {
  27984. this._actions = {};
  27985. $.each(ACTIONS, $.proxy(function(_, action) {
  27986. this._actions[action] = this._createActionByOption(action) || $.noop
  27987. }, this))
  27988. },
  27989. _initCloseOnOutsideClickHandler: function() {
  27990. this._proxiedDocumentDownHandler = $.proxy(function() {
  27991. this._documentDownHandler.apply(this, arguments)
  27992. }, this)
  27993. },
  27994. _documentDownHandler: function(e) {
  27995. if (!this._isTopOverlay())
  27996. return;
  27997. var closeOnOutsideClick = this.option("closeOnOutsideClick");
  27998. if ($.isFunction(closeOnOutsideClick))
  27999. closeOnOutsideClick = closeOnOutsideClick(e);
  28000. if (closeOnOutsideClick) {
  28001. var $container = this._$content,
  28002. outsideClick = !$container.is(e.target) && !$.contains($container.get(0), e.target);
  28003. if (outsideClick) {
  28004. if (this.option("shading"))
  28005. e.preventDefault();
  28006. this.hide()
  28007. }
  28008. }
  28009. },
  28010. _isTopOverlay: function() {
  28011. var zIndexStack = this._zIndexStack();
  28012. return zIndexStack[zIndexStack.length - 1] === this._zIndex
  28013. },
  28014. _zIndexStack: function() {
  28015. return Z_INDEX_STACK
  28016. },
  28017. _zIndexInitValue: function() {
  28018. return FIRST_Z_INDEX
  28019. },
  28020. _toggleViewPortSubscriptiion: function(toggle) {
  28021. DX.viewPortChanged.remove(this._viewPortChangeHandle);
  28022. if (toggle) {
  28023. this._viewPortChangeHandle = $.proxy(this._viewPortChangeHandler, this);
  28024. DX.viewPortChanged.add(this._viewPortChangeHandle)
  28025. }
  28026. },
  28027. _viewPortChangeHandler: function() {
  28028. this._initContainer(this.option("container"));
  28029. this._refresh()
  28030. },
  28031. _renderVisibilityAnimate: function() {
  28032. var visible = this.option("visible");
  28033. this._stopAnimation();
  28034. if (visible)
  28035. return this._show();
  28036. else
  28037. return this._hide()
  28038. },
  28039. _normalizePosition: function() {
  28040. this._position = this.option("position")
  28041. },
  28042. _show: function() {
  28043. if (this._isParentHidden())
  28044. return $.Deferred().resolve();
  28045. this._normalizePosition();
  28046. var that = this,
  28047. deferred = $.Deferred(),
  28048. animation = that.option("animation") || {},
  28049. showAnimation = this._normalizeAnimation(animation.show, "to"),
  28050. completeShowAnimation = showAnimation && showAnimation.complete || $.noop;
  28051. if (this._isHidingActionCancelled) {
  28052. delete this._isHidingActionCancelled;
  28053. deferred.resolve()
  28054. }
  28055. else {
  28056. this._toggleVisibility(true);
  28057. this._animate(showAnimation, function() {
  28058. if (that.option("focusStateEnabled"))
  28059. that._focusTarget().focus();
  28060. completeShowAnimation.apply(this, arguments);
  28061. that._actions.onShown();
  28062. deferred.resolve()
  28063. })
  28064. }
  28065. return deferred.promise()
  28066. },
  28067. _normalizeAnimation: function(animation, prop) {
  28068. if (animation && animation[prop]) {
  28069. animation = $.extend({type: "slide"}, animation);
  28070. $.extend(animation[prop], {position: this._position})
  28071. }
  28072. return animation
  28073. },
  28074. _hide: function() {
  28075. var that = this,
  28076. deferred = $.Deferred(),
  28077. animation = this.option("animation") || {},
  28078. hideAnimation = this._normalizeAnimation(animation.hide, "from"),
  28079. completeHideAnimation = hideAnimation && hideAnimation.complete || $.noop,
  28080. hidingArgs = {cancel: false};
  28081. this._actions.onHiding(hidingArgs);
  28082. if (hidingArgs.cancel) {
  28083. this._isHidingActionCancelled = true;
  28084. this.option("visible", true);
  28085. deferred.resolve()
  28086. }
  28087. else {
  28088. this._toggleShading(false);
  28089. this._animate(hideAnimation, function() {
  28090. that._toggleVisibility(false);
  28091. completeHideAnimation.apply(this, arguments);
  28092. that._actions.onHidden();
  28093. deferred.resolve()
  28094. })
  28095. }
  28096. return deferred.promise()
  28097. },
  28098. _animate: function(animation, completeCallback) {
  28099. if (animation) {
  28100. var startCallback = animation.start || $.noop,
  28101. $content = this._$content;
  28102. fx.animate(this._$content, $.extend({}, animation, {
  28103. start: function() {
  28104. $content.css("pointer-events", "none");
  28105. startCallback.apply(this, arguments)
  28106. },
  28107. complete: function() {
  28108. $content.css("pointer-events", "");
  28109. completeCallback.apply(this, arguments)
  28110. }
  28111. }))
  28112. }
  28113. else
  28114. completeCallback()
  28115. },
  28116. _stopAnimation: function() {
  28117. fx.stop(this._$content, true)
  28118. },
  28119. _toggleVisibility: function(visible) {
  28120. if (visible && this._isParentHidden())
  28121. return;
  28122. this._stopAnimation();
  28123. if (!visible)
  28124. utils.triggerHidingEvent(this._$content);
  28125. this.callBase.apply(this, arguments);
  28126. this._$content.toggle(visible);
  28127. this._updateZIndexStackPosition(visible);
  28128. if (visible) {
  28129. this._renderContent();
  28130. this._actions.onShowing();
  28131. this._moveToContainer();
  28132. this._renderGeometry();
  28133. utils.triggerShownEvent(this._$content)
  28134. }
  28135. else
  28136. this._moveFromContainer();
  28137. this._toggleShading(visible);
  28138. this._toggleSubscriptions(visible)
  28139. },
  28140. _updateZIndexStackPosition: function(pushToStack) {
  28141. var zIndexStack = this._zIndexStack();
  28142. if (pushToStack) {
  28143. if (!this._zIndex) {
  28144. var length = zIndexStack.length;
  28145. this._zIndex = (length ? zIndexStack[length - 1] : this._zIndexInitValue()) + 1;
  28146. zIndexStack.push(this._zIndex)
  28147. }
  28148. this._$wrapper.css("z-index", this._zIndex);
  28149. this._$content.css("z-index", this._zIndex)
  28150. }
  28151. else if (this._zIndex) {
  28152. var index = $.inArray(this._zIndex, zIndexStack);
  28153. zIndexStack.splice(index, 1);
  28154. delete this._zIndex
  28155. }
  28156. },
  28157. _toggleShading: function(visible) {
  28158. this._$wrapper.toggleClass(OVERLAY_MODAL_CLASS, this.option("shading") && !this.option("container"));
  28159. this._$wrapper.toggleClass(OVERLAY_SHADER_CLASS, visible && this.option("shading"));
  28160. this._$wrapper.css("background-color", this.option("shading") ? this.option("shadingColor") : "");
  28161. this._toggleTabTerminator(visible && this.option("shading"))
  28162. },
  28163. _toggleTabTerminator: function(enabled) {
  28164. var eventName = events.addNamespace("keydown", this.NAME);
  28165. if (enabled)
  28166. $(document).on(eventName, $.proxy(this._tabKeyHandler, this));
  28167. else
  28168. $(document).off(eventName)
  28169. },
  28170. _tabKeyHandler: function(e) {
  28171. if (e.keyCode !== TAB_KEY)
  28172. return;
  28173. var tabbableElements = this._$wrapper.find(":dx-tabbable"),
  28174. $firstTabbable = tabbableElements.first(),
  28175. $lastTabbable = tabbableElements.last(),
  28176. isTabOnLast = !e.shiftKey && e.target === $lastTabbable.get(0),
  28177. isShiftTabOnFirst = e.shiftKey && e.target === $firstTabbable.get(0),
  28178. isEmptyTabList = tabbableElements.length === 0,
  28179. isOutsideTarget = $.inArray(e.target, tabbableElements) === -1;
  28180. if (isTabOnLast || isShiftTabOnFirst || isEmptyTabList || isOutsideTarget) {
  28181. e.preventDefault();
  28182. (e.shiftKey ? $lastTabbable : $firstTabbable).focusin().focus()
  28183. }
  28184. },
  28185. _toggleSubscriptions: function(enabled) {
  28186. this._toggleHideTopOverlayCallback(enabled);
  28187. this._toggleDocumentDownHandler(enabled);
  28188. this._toggleParentsScrollSubscription(enabled)
  28189. },
  28190. _toggleHideTopOverlayCallback: function(subscribe) {
  28191. if (!this._hideTopOverlayHandler)
  28192. return;
  28193. if (subscribe && this.option("closeOnBackButton"))
  28194. DX.hideTopOverlayCallback.add(this._hideTopOverlayHandler);
  28195. else
  28196. DX.hideTopOverlayCallback.remove(this._hideTopOverlayHandler)
  28197. },
  28198. _toggleDocumentDownHandler: function(enabled) {
  28199. var eventName = events.addNamespace("dxpointerdown", this.NAME);
  28200. if (enabled)
  28201. $(document).on(eventName, this._proxiedDocumentDownHandler);
  28202. else
  28203. $(document).off(eventName, this._proxiedDocumentDownHandler)
  28204. },
  28205. _toggleParentsScrollSubscription: function(subscribe) {
  28206. if (!this._position)
  28207. return;
  28208. var that = this,
  28209. target = that._position.of || $(),
  28210. closeOnScroll = this.option("closeOnTargetScroll"),
  28211. $parents = getElement(target).parents();
  28212. if (DX.devices.real().platform === "generic")
  28213. $parents = $parents.add(window);
  28214. $().add(this._$prevTargetParents).off(events.addNamespace("scroll dxscroll", that.NAME));
  28215. if (subscribe && closeOnScroll) {
  28216. $parents.on(events.addNamespace("scroll dxscroll", that.NAME), function(e) {
  28217. if (e.overlayProcessed)
  28218. return;
  28219. e.overlayProcessed = true;
  28220. var closeHandled = false;
  28221. if ($.isFunction(closeOnScroll))
  28222. closeHandled = closeOnScroll(e);
  28223. if (!closeHandled)
  28224. that.hide()
  28225. });
  28226. this._$prevTargetParents = $parents
  28227. }
  28228. },
  28229. _renderContent: function() {
  28230. var shouldDeferRendering = !this.option("visible") && this.option("deferRendering");
  28231. var isParentHidden = this.option("visible") && this._isParentHidden();
  28232. if (this._contentAlreadyRendered || shouldDeferRendering || isParentHidden)
  28233. return;
  28234. this._contentAlreadyRendered = true;
  28235. this.callBase()
  28236. },
  28237. _isParentHidden: function() {
  28238. var $parent = this.element().parent();
  28239. if ($parent.is(":visible"))
  28240. return false;
  28241. var isHidden = false;
  28242. $parent.add($parent.parents()).each(function() {
  28243. var $element = $(this);
  28244. if ($element.css("display") === "none") {
  28245. isHidden = true;
  28246. return false
  28247. }
  28248. });
  28249. return isHidden || !$.contains(document, $parent.get(0))
  28250. },
  28251. _renderContentImpl: function() {
  28252. var $element = this.element();
  28253. this._$content.appendTo($element);
  28254. var contentTemplate = this._getTemplate(this.option("contentTemplate"));
  28255. contentTemplate && contentTemplate.render(this.content());
  28256. this._renderDrag();
  28257. this._renderResize();
  28258. this._renderScrollTerminator()
  28259. },
  28260. _renderDrag: function() {
  28261. var $dragTarget = this._getDragTarget();
  28262. if (!$dragTarget)
  28263. return;
  28264. var startEventName = events.addNamespace("dxdragstart", this.NAME),
  28265. updateEventName = events.addNamespace("dxdrag", this.NAME);
  28266. $dragTarget.off(startEventName).off(updateEventName);
  28267. if (!this.option("dragEnabled"))
  28268. return;
  28269. $dragTarget.on(startEventName, $.proxy(this._dragStartHandler, this)).on(updateEventName, $.proxy(this._dragUpdateHandler, this))
  28270. },
  28271. _renderResize: function() {
  28272. this._createComponent(this._$content, "dxResizable", {
  28273. handles: this.option("resizeEnabled") ? "all" : "none",
  28274. onResizeEnd: $.proxy(this._resizeEndHandler, this),
  28275. minHeight: 100,
  28276. minWidth: 100,
  28277. area: this._$container
  28278. })
  28279. },
  28280. _resizeEndHandler: function() {
  28281. this._geometryChangeHandled = true
  28282. },
  28283. _renderScrollTerminator: function() {
  28284. var $scrollTerminator = this._wrapper();
  28285. var scrollEventName = events.addNamespace("dxscroll", this.NAME);
  28286. $scrollTerminator.off(scrollEventName).on(scrollEventName, {
  28287. validate: function() {
  28288. return true
  28289. },
  28290. getDirection: function() {
  28291. return "both"
  28292. },
  28293. _togglePointerAddons: $.noop,
  28294. _clearSelection: $.noop,
  28295. isNative: true
  28296. }, function(e) {
  28297. if (e.originalEvent.originalEvent.type !== "mousemove")
  28298. e.preventDefault()
  28299. })
  28300. },
  28301. _getDragTarget: function() {
  28302. return this.content()
  28303. },
  28304. _dragStartHandler: function(e) {
  28305. e.targetElements = [];
  28306. this._prevOffset = {
  28307. x: 0,
  28308. y: 0
  28309. };
  28310. var position = translator.locate(this._$content),
  28311. allowedOffsets = this._allowedOffsets();
  28312. var deltaSize = this._deltaSize();
  28313. var isAllowedDrag = deltaSize.height >= 0 && deltaSize.width >= 0;
  28314. this._geometryChangeHandled = isAllowedDrag;
  28315. e.maxLeftOffset = isAllowedDrag ? position.left + allowedOffsets.left : 0;
  28316. e.maxRightOffset = isAllowedDrag ? -position.left + allowedOffsets.right : 0;
  28317. e.maxTopOffset = isAllowedDrag ? position.top + allowedOffsets.top : 0;
  28318. e.maxBottomOffset = isAllowedDrag ? -position.top + allowedOffsets.bottom : 0
  28319. },
  28320. _deltaSize: function() {
  28321. var $content = this._$content,
  28322. $container = this._$container;
  28323. var contentWidth = $content.outerWidth(),
  28324. contentHeight = $content.outerHeight(),
  28325. containerWidth = $container.width(),
  28326. containerHeight = $container.height();
  28327. return {
  28328. width: containerWidth - contentWidth,
  28329. height: containerHeight - contentHeight
  28330. }
  28331. },
  28332. _dragUpdateHandler: function(e) {
  28333. var offset = e.offset,
  28334. prevOffset = this._prevOffset,
  28335. targetOffset = {
  28336. top: offset.y - prevOffset.y,
  28337. left: offset.x - prevOffset.x
  28338. };
  28339. this._changePosition(targetOffset);
  28340. this._prevOffset = offset
  28341. },
  28342. _changePosition: function(offset) {
  28343. var position = translator.locate(this._$content);
  28344. translator.move(this._$content, {
  28345. left: position.left + offset.left,
  28346. top: position.top + offset.top
  28347. })
  28348. },
  28349. _allowedOffsets: function() {
  28350. var deltaSize = this._deltaSize(),
  28351. boundaryOffset = this.option("boundaryOffset");
  28352. return {
  28353. top: boundaryOffset.v,
  28354. bottom: deltaSize.height - boundaryOffset.v,
  28355. left: boundaryOffset.h,
  28356. right: deltaSize.width - boundaryOffset.h
  28357. }
  28358. },
  28359. _fireContentReadyAction: function() {
  28360. if (this.option("visible"))
  28361. this._moveToContainer();
  28362. this.callBase.apply(this, arguments)
  28363. },
  28364. _moveFromContainer: function() {
  28365. this._$content.appendTo(this.element());
  28366. this._detachWrapperToContainer()
  28367. },
  28368. _detachWrapperToContainer: function() {
  28369. this._$wrapper.detach()
  28370. },
  28371. _moveToContainer: function() {
  28372. this._attachWrapperToContainer();
  28373. this._$content.appendTo(this._$wrapper)
  28374. },
  28375. _attachWrapperToContainer: function() {
  28376. var $element = this.element();
  28377. if (this._$container && this._$container[0] !== $element.parent()[0])
  28378. this._$wrapper.appendTo(this._$container);
  28379. else
  28380. this._$wrapper.appendTo($element)
  28381. },
  28382. _renderGeometry: function() {
  28383. if (this.option("visible"))
  28384. this._renderGeometryImpl()
  28385. },
  28386. _renderGeometryImpl: function() {
  28387. this._stopAnimation();
  28388. this._normalizePosition();
  28389. this._renderShading();
  28390. this._renderDimensions();
  28391. this._renderPosition()
  28392. },
  28393. _renderShading: function() {
  28394. var $wrapper = this._$wrapper,
  28395. $container = this._getContainer();
  28396. $wrapper.css("position", this._isWindow($container) ? "fixed" : "absolute");
  28397. if (this.option("shading"))
  28398. $wrapper.show();
  28399. this._renderShadingDimensions();
  28400. this._renderShadingPosition()
  28401. },
  28402. _renderShadingPosition: function() {
  28403. if (this.option("shading")) {
  28404. var $container = this._getContainer();
  28405. DX.position(this._$wrapper, {
  28406. my: "top left",
  28407. at: "top left",
  28408. of: $container
  28409. })
  28410. }
  28411. },
  28412. _renderShadingDimensions: function() {
  28413. if (this.option("shading")) {
  28414. var $container = this._getContainer(),
  28415. wrapperWidth = this._isWindow($container) ? "100%" : $container.outerWidth(),
  28416. wrapperHeight = this._isWindow($container) ? "100%" : $container.outerHeight();
  28417. this._$wrapper.css({
  28418. width: wrapperWidth,
  28419. height: wrapperHeight
  28420. })
  28421. }
  28422. },
  28423. _isWindow: function($element) {
  28424. return !!$element && $.isWindow($element.get(0))
  28425. },
  28426. _getContainer: function() {
  28427. var position = this._position,
  28428. container = this.option("container"),
  28429. positionOf = position ? position.of || window : null;
  28430. return getElement(container || positionOf)
  28431. },
  28432. _renderDimensions: function() {
  28433. if (this._geometryChangeHandled) {
  28434. var $content = this._$content,
  28435. $container = this._$container;
  28436. $content.outerWidth(Math.min($content.outerWidth(), $container.width())).outerHeight(Math.min($content.outerHeight(), $container.height()))
  28437. }
  28438. else
  28439. this._$content.outerWidth(this.option("width")).outerHeight(this.option("height"))
  28440. },
  28441. _renderPosition: function() {
  28442. var position,
  28443. containerPosition,
  28444. allowedOffsets,
  28445. $content;
  28446. if (this._geometryChangeHandled) {
  28447. $content = this._$content;
  28448. position = translator.locate($content);
  28449. allowedOffsets = this._allowedOffsets();
  28450. translator.move($content, {
  28451. top: utils.fitIntoRange(position.top, -allowedOffsets.top, allowedOffsets.bottom),
  28452. left: utils.fitIntoRange(position.left, -allowedOffsets.left, allowedOffsets.right)
  28453. })
  28454. }
  28455. else {
  28456. translator.resetPosition(this._$content);
  28457. this._renderOverlayBoundaryOffset();
  28458. position = this._position;
  28459. containerPosition = DX.calculatePosition(this._$content, position);
  28460. this._actions.onPositioning({position: containerPosition});
  28461. var resultPosition = DX.position(this._$content, containerPosition);
  28462. this._actions.onPositioned({position: resultPosition});
  28463. forceRepaint(this._$content)
  28464. }
  28465. },
  28466. _renderOverlayBoundaryOffset: function() {
  28467. var boundaryOffset = this.option("boundaryOffset");
  28468. this._$content.css("margin", boundaryOffset.v + "px " + boundaryOffset.h + "px")
  28469. },
  28470. _focusTarget: function() {
  28471. return this._$content
  28472. },
  28473. _attachKeyboardEvents: function() {
  28474. this._keyboardProcessor = new ui.KeyboardProcessor({
  28475. element: this._$content,
  28476. handler: this._keyboardHandler,
  28477. context: this
  28478. })
  28479. },
  28480. _keyboardHandler: function(options) {
  28481. var e = options.originalEvent,
  28482. $target = $(e.target);
  28483. if ($target.is(this._$content))
  28484. this.callBase.apply(this, arguments)
  28485. },
  28486. _visibilityChanged: function(visible) {
  28487. if (visible) {
  28488. if (this.option("visible") && this._$content.is(":hidden"))
  28489. this._show();
  28490. this._dimensionChanged()
  28491. }
  28492. else if (this._$content.is(":visible"))
  28493. this._hide()
  28494. },
  28495. _dimensionChanged: function() {
  28496. this._renderGeometry()
  28497. },
  28498. _clean: function() {
  28499. this._cleanFocusState()
  28500. },
  28501. _dispose: function() {
  28502. this._stopAnimation();
  28503. this._toggleViewPortSubscriptiion(false);
  28504. this._toggleSubscriptions(false);
  28505. this._updateZIndexStackPosition(false);
  28506. this._actions = null;
  28507. this.callBase();
  28508. this._$wrapper.remove();
  28509. this._$content.remove()
  28510. },
  28511. _toggleDisabledState: function(value) {
  28512. this.callBase.apply(this, arguments);
  28513. this._$content.toggleClass(DISABLED_STATE_CLASS, value)
  28514. },
  28515. _toggleRTLDirection: function(rtl) {
  28516. this._$content.toggleClass(RTL_DIRECTION_CLASS, rtl)
  28517. },
  28518. _optionChanged: function(args) {
  28519. var value = args.value;
  28520. if ($.inArray(args.name, ACTIONS) > -1) {
  28521. this._initActions();
  28522. return
  28523. }
  28524. switch (args.name) {
  28525. case"dragEnabled":
  28526. this._renderDrag();
  28527. break;
  28528. case"resizeEnabled":
  28529. this._renderResize();
  28530. break;
  28531. case"resizeEnabled":
  28532. this._invalidate();
  28533. break;
  28534. case"shading":
  28535. case"shadingColor":
  28536. this._toggleShading(this.option("visible"));
  28537. break;
  28538. case"width":
  28539. case"height":
  28540. case"position":
  28541. case"boundaryOffset":
  28542. this._renderGeometry();
  28543. break;
  28544. case"visible":
  28545. delete this._geometryChangeHandled;
  28546. this._renderVisibilityAnimate().done($.proxy(function() {
  28547. if (!this._animateDeferred)
  28548. return;
  28549. this._animateDeferred.resolveWith(this)
  28550. }, this));
  28551. break;
  28552. case"target":
  28553. this._initTarget(value);
  28554. this._invalidate();
  28555. break;
  28556. case"container":
  28557. this._initContainer(value);
  28558. this._invalidate();
  28559. break;
  28560. case"deferRendering":
  28561. case"contentTemplate":
  28562. this._invalidate();
  28563. break;
  28564. case"closeOnBackButton":
  28565. this._toggleHideTopOverlayCallback(this.option("visible"));
  28566. break;
  28567. case"closeOnOutsideClick":
  28568. this._toggleDocumentDownHandler(this.option("visible"));
  28569. break;
  28570. case"closeOnTargetScroll":
  28571. this._toggleParentsScrollSubscription(this.option("visible"));
  28572. break;
  28573. case"animation":
  28574. break;
  28575. default:
  28576. this.callBase(args)
  28577. }
  28578. },
  28579. toggle: function(showing) {
  28580. showing = showing === undefined ? !this.option("visible") : showing;
  28581. if (showing === this.option("visible"))
  28582. return $.Deferred().resolve().promise();
  28583. var animateDeferred = $.Deferred();
  28584. this._animateDeferred = animateDeferred;
  28585. this.option("visible", showing);
  28586. return animateDeferred.promise().done($.proxy(function() {
  28587. delete this._animateDeferred
  28588. }, this))
  28589. },
  28590. show: function() {
  28591. return this.toggle(true)
  28592. },
  28593. hide: function() {
  28594. return this.toggle(false)
  28595. },
  28596. content: function() {
  28597. return this._$content
  28598. },
  28599. repaint: function() {
  28600. this._renderGeometry()
  28601. }
  28602. }));
  28603. DevExpress.ui.dxOverlay.baseZIndex = function(zIndex) {
  28604. FIRST_Z_INDEX = zIndex
  28605. };
  28606. ui.dxOverlay.__internals = {
  28607. OVERLAY_CLASS: OVERLAY_CLASS,
  28608. OVERLAY_WRAPPER_CLASS: OVERLAY_WRAPPER_CLASS,
  28609. OVERLAY_CONTENT_CLASS: OVERLAY_CONTENT_CLASS,
  28610. OVERLAY_SHADER_CLASS: OVERLAY_SHADER_CLASS,
  28611. OVERLAY_MODAL_CLASS: OVERLAY_MODAL_CLASS
  28612. }
  28613. })(jQuery, DevExpress);
  28614. /*! Module widgets-base, file ui.toast.js */
  28615. (function($, DX, undefined) {
  28616. var ui = DX.ui;
  28617. var TOAST_CLASS = "dx-toast",
  28618. TOAST_CLASS_PREFIX = TOAST_CLASS + "-",
  28619. TOAST_WRAPPER_CLASS = TOAST_CLASS_PREFIX + "wrapper",
  28620. TOAST_CONTENT_CLASS = TOAST_CLASS_PREFIX + "content",
  28621. TOAST_MESSAGE_CLASS = TOAST_CLASS_PREFIX + "message",
  28622. TOAST_ICON_CLASS = TOAST_CLASS_PREFIX + "icon",
  28623. WIDGET_NAME = "dxToast",
  28624. toastTypes = ["info", "warning", "error", "success"],
  28625. Z_INDEX_STACK = [],
  28626. FIRST_Z_INDEX_OFFSET = 8000,
  28627. visibleToastInstance = null,
  28628. POSITION_ALIASES = {
  28629. top: {
  28630. my: "top",
  28631. at: "top",
  28632. of: window,
  28633. offset: "0 0"
  28634. },
  28635. bottom: {
  28636. my: "bottom",
  28637. at: "bottom",
  28638. of: window,
  28639. offset: "0 -20"
  28640. },
  28641. center: {
  28642. my: "center",
  28643. at: "center",
  28644. of: window,
  28645. offset: "0 0"
  28646. },
  28647. right: {
  28648. my: "center right",
  28649. at: "center right",
  28650. of: window,
  28651. offset: "0 0"
  28652. },
  28653. left: {
  28654. my: "center left",
  28655. at: "center left",
  28656. of: window,
  28657. offset: "0 0"
  28658. }
  28659. };
  28660. DX.registerComponent(WIDGET_NAME, ui, ui.dxOverlay.inherit({
  28661. _setDefaultOptions: function() {
  28662. this.callBase();
  28663. this.option({
  28664. message: "",
  28665. type: "info",
  28666. displayTime: 2000,
  28667. position: "bottom center",
  28668. animation: {
  28669. show: {
  28670. type: "fade",
  28671. duration: 400,
  28672. from: 0,
  28673. to: 1
  28674. },
  28675. hide: {
  28676. type: "fade",
  28677. duration: 400,
  28678. to: 0
  28679. }
  28680. },
  28681. shading: false,
  28682. height: "auto",
  28683. closeOnBackButton: false,
  28684. resizeEnabled: false
  28685. })
  28686. },
  28687. _defaultOptionsRules: function() {
  28688. return this.callBase().concat([{
  28689. device: {platform: "win8"},
  28690. options: {
  28691. position: "top center",
  28692. width: function() {
  28693. return $(window).width()
  28694. }
  28695. }
  28696. }, {
  28697. device: function(device) {
  28698. return device.platform === "android"
  28699. },
  28700. options: {
  28701. closeOnOutsideClick: true,
  28702. width: "auto",
  28703. position: {
  28704. at: "bottom left",
  28705. my: "bottom left",
  28706. offset: "20 -20"
  28707. }
  28708. }
  28709. }, {
  28710. device: function(device) {
  28711. return device.deviceType === "phone" && device.platform === "android"
  28712. },
  28713. options: {
  28714. width: function() {
  28715. return $(window).width()
  28716. },
  28717. position: {
  28718. at: "bottom center",
  28719. my: "bottom center",
  28720. offset: "0 0"
  28721. }
  28722. }
  28723. }])
  28724. },
  28725. _init: function() {
  28726. this.callBase();
  28727. this._posStringToObject()
  28728. },
  28729. _renderContentImpl: function() {
  28730. if (this.option("message"))
  28731. this._message = $("<div>").addClass(TOAST_MESSAGE_CLASS).text(this.option("message")).appendTo(this.content());
  28732. this.setAria("role", "alert", this._message);
  28733. if ($.inArray(this.option("type").toLowerCase(), toastTypes) > -1)
  28734. this.content().prepend($("<div>").addClass(TOAST_ICON_CLASS));
  28735. this.callBase()
  28736. },
  28737. _render: function() {
  28738. this.callBase();
  28739. this.element().addClass(TOAST_CLASS);
  28740. this._wrapper().addClass(TOAST_WRAPPER_CLASS);
  28741. this._$content.addClass(TOAST_CLASS_PREFIX + String(this.option("type")).toLowerCase());
  28742. this.content().addClass(TOAST_CONTENT_CLASS);
  28743. this._$content.off("dxswipe").on("dxswipe", $.proxy(this.hide, this))
  28744. },
  28745. _posStringToObject: function() {
  28746. if (!DX.utils.isString(this.option("position")))
  28747. return;
  28748. var verticalPosition = this.option("position").split(" ")[0],
  28749. horizontalPosition = this.option("position").split(" ")[1];
  28750. this.option("position", $.extend({}, POSITION_ALIASES[verticalPosition]));
  28751. switch (horizontalPosition) {
  28752. case"center":
  28753. case"left":
  28754. case"right":
  28755. this.option("position").at += " " + horizontalPosition;
  28756. this.option("position").my += " " + horizontalPosition;
  28757. break
  28758. }
  28759. },
  28760. _show: function() {
  28761. if (visibleToastInstance) {
  28762. clearTimeout(visibleToastInstance._hideTimeout);
  28763. visibleToastInstance.hide()
  28764. }
  28765. visibleToastInstance = this;
  28766. return this.callBase.apply(this, arguments).done($.proxy(function() {
  28767. clearTimeout(this._hideTimeout);
  28768. this._hideTimeout = setTimeout($.proxy(this.hide, this), this.option("displayTime"))
  28769. }, this))
  28770. },
  28771. _hide: function() {
  28772. visibleToastInstance = null;
  28773. return this.callBase.apply(this, arguments)
  28774. },
  28775. _zIndexStack: function() {
  28776. return Z_INDEX_STACK
  28777. },
  28778. _zIndexInitValue: function() {
  28779. return this.callBase() + FIRST_Z_INDEX_OFFSET
  28780. },
  28781. _dispose: function() {
  28782. clearTimeout(this._hideTimeout);
  28783. visibleToastInstance = null;
  28784. this.callBase()
  28785. },
  28786. _optionChanged: function(args) {
  28787. switch (args.name) {
  28788. case"type":
  28789. this._$content.removeClass(TOAST_CLASS_PREFIX + args.previousValue);
  28790. this._$content.addClass(TOAST_CLASS_PREFIX + String(args.value).toLowerCase());
  28791. break;
  28792. case"message":
  28793. if (this._message)
  28794. this._message.text(args.value);
  28795. break;
  28796. case"displayTime":
  28797. case"position":
  28798. break;
  28799. default:
  28800. this.callBase(args)
  28801. }
  28802. }
  28803. }));
  28804. ui.dxToast.__internals = {
  28805. TOAST_CLASS: TOAST_CLASS,
  28806. TOAST_WRAPPER_CLASS: TOAST_WRAPPER_CLASS,
  28807. TOAST_CONTENT_CLASS: TOAST_CONTENT_CLASS,
  28808. TOAST_MESSAGE_CLASS: TOAST_MESSAGE_CLASS,
  28809. TOAST_ICON_CLASS: TOAST_ICON_CLASS,
  28810. TOAST_CLASS_PREFIX: TOAST_CLASS_PREFIX,
  28811. WIDGET_NAME: WIDGET_NAME
  28812. }
  28813. })(jQuery, DevExpress);
  28814. /*! Module widgets-base, file ui.popup.js */
  28815. (function($, DX, undefined) {
  28816. var ui = DX.ui,
  28817. translator = DX.translator,
  28818. POPUP_CLASS = "dx-popup",
  28819. POPUP_WRAPPER_CLASS = "dx-popup-wrapper",
  28820. POPUP_FULL_SCREEN_CLASS = "dx-popup-fullscreen",
  28821. POPUP_FULL_SCREEN_WIDTH_CLASS = "dx-popup-fullscreen-width",
  28822. POPUP_NORMAL_CLASS = "dx-popup-normal",
  28823. POPUP_CONTENT_CLASS = "dx-popup-content",
  28824. POPUP_DRAGGABLE_CLASS = "dx-popup-draggable",
  28825. POPUP_TITLE_CLASS = "dx-popup-title",
  28826. POPUP_TITLE_CLOSEBUTTON_CLASS = "dx-closebutton",
  28827. POPUP_BOTTOM_CLASS = "dx-popup-bottom",
  28828. TEMPLATE_WRAPPER_CLASS = "dx-template-wrapper",
  28829. ALLOWED_BUTTON_ALIASES = ["cancel", "clear", "done"];
  28830. var getButtonPlace = function(name) {
  28831. var device = DX.devices.current(),
  28832. platform = device.platform,
  28833. toolbar = "bottom",
  28834. location = "before";
  28835. if (platform === "ios")
  28836. switch (name) {
  28837. case"cancel":
  28838. toolbar = "top";
  28839. break;
  28840. case"clear":
  28841. toolbar = "top";
  28842. location = "after";
  28843. break;
  28844. case"done":
  28845. location = "after";
  28846. break
  28847. }
  28848. else if (platform === "win8")
  28849. location = "after";
  28850. else if (platform === "android" && device.version && parseInt(device.version[0]) > 4)
  28851. switch (name) {
  28852. case"cancel":
  28853. location = "after";
  28854. break;
  28855. case"done":
  28856. location = "after";
  28857. break
  28858. }
  28859. else if (platform === "android")
  28860. location = "center";
  28861. return {
  28862. toolbar: toolbar,
  28863. location: location
  28864. }
  28865. };
  28866. DX.registerComponent("dxPopup", ui, ui.dxOverlay.inherit({
  28867. _setDefaultOptions: function() {
  28868. this.callBase();
  28869. this.option({
  28870. fullScreen: false,
  28871. title: "",
  28872. showTitle: true,
  28873. titleTemplate: "title",
  28874. onTitleRendered: null,
  28875. dragEnabled: false,
  28876. buttons: [],
  28877. showCloseButton: false,
  28878. bottomTemplate: "bottom"
  28879. })
  28880. },
  28881. _defaultOptionsRules: function() {
  28882. return this.callBase().concat([{
  28883. device: {platform: "win8"},
  28884. options: {width: function() {
  28885. return $(window).width()
  28886. }}
  28887. }, {
  28888. device: {
  28889. platform: "win8",
  28890. phone: true
  28891. },
  28892. options: {position: {
  28893. my: "top center",
  28894. at: "top center",
  28895. offset: "0 0"
  28896. }}
  28897. }, {
  28898. device: {platform: "ios"},
  28899. options: {animation: this._iosAnimation}
  28900. }, {
  28901. device: {platform: "generic"},
  28902. options: {showCloseButton: true}
  28903. }, {
  28904. device: function(device) {
  28905. return DX.devices.real().platform === "generic" && device.platform === "generic"
  28906. },
  28907. options: {dragEnabled: true}
  28908. }, {
  28909. device: function(device) {
  28910. return DX.devices.real().generic && !DX.devices.isSimulator()
  28911. },
  28912. options: {focusStateEnabled: true}
  28913. }])
  28914. },
  28915. _iosAnimation: {
  28916. show: {
  28917. type: "slide",
  28918. duration: 400,
  28919. from: {position: {
  28920. my: "top",
  28921. at: "bottom"
  28922. }},
  28923. to: {position: {
  28924. my: "center",
  28925. at: "center"
  28926. }}
  28927. },
  28928. hide: {
  28929. type: "slide",
  28930. duration: 400,
  28931. from: {
  28932. opacity: 1,
  28933. position: {
  28934. my: "center",
  28935. at: "center"
  28936. }
  28937. },
  28938. to: {
  28939. opacity: 1,
  28940. position: {
  28941. my: "top",
  28942. at: "bottom"
  28943. }
  28944. }
  28945. }
  28946. },
  28947. _init: function() {
  28948. this.callBase();
  28949. this.element().addClass(POPUP_CLASS);
  28950. this._wrapper().addClass(POPUP_WRAPPER_CLASS);
  28951. this._$popupContent = this._$content.wrapInner($("<div>").addClass(POPUP_CONTENT_CLASS)).children().eq(0)
  28952. },
  28953. _render: function() {
  28954. var isFullscreen = this.option("fullScreen");
  28955. this._$content.toggleClass(POPUP_DRAGGABLE_CLASS, this.option("dragEnabled")).toggleClass(POPUP_FULL_SCREEN_CLASS, isFullscreen).toggleClass(POPUP_NORMAL_CLASS, !isFullscreen);
  28956. this.callBase()
  28957. },
  28958. _renderContentImpl: function() {
  28959. this.callBase();
  28960. this._renderTitle();
  28961. this._renderBottom()
  28962. },
  28963. _renderTitle: function() {
  28964. var items = this._getToolbarItems("top"),
  28965. titleText = this.option("title"),
  28966. showTitle = this.option("showTitle");
  28967. if (showTitle && !!titleText)
  28968. items.unshift({
  28969. location: DX.devices.current().ios ? "center" : "before",
  28970. text: titleText
  28971. });
  28972. if (showTitle || items.length > 0) {
  28973. this._$title && this._$title.remove();
  28974. var $title = $("<div>").addClass(POPUP_TITLE_CLASS).prependTo(this._$content);
  28975. this._$title = this._renderTemplateByType("titleTemplate", items, $title).addClass(POPUP_TITLE_CLASS);
  28976. this._renderDrag();
  28977. this._executeTitleRenderAction(this._$title)
  28978. }
  28979. else if (this._$title)
  28980. this._$title.detach()
  28981. },
  28982. _renderTemplateByType: function(optionName, data, $container) {
  28983. var template = this._getTemplateByOption(optionName),
  28984. toolbarTemplate = template.owner() === this.option("templateProvider"),
  28985. $result;
  28986. if (toolbarTemplate) {
  28987. $result = template.render(data, $container);
  28988. $container.replaceWith($result);
  28989. return $result
  28990. }
  28991. else {
  28992. $result = template.render($container);
  28993. if ($result.hasClass(TEMPLATE_WRAPPER_CLASS)) {
  28994. $container.replaceWith($result);
  28995. $container = $result
  28996. }
  28997. return $container
  28998. }
  28999. },
  29000. _executeTitleRenderAction: function(titleElement) {
  29001. this._getTitleRenderAction()({titleElement: titleElement})
  29002. },
  29003. _getTitleRenderAction: function() {
  29004. return this._titleRenderAction || this._createTitleRenderAction()
  29005. },
  29006. _createTitleRenderAction: function() {
  29007. return this._titleRenderAction = this._createActionByOption("onTitleRendered", {
  29008. element: this.element(),
  29009. excludeValidators: ["designMode", "disabled", "readOnly"]
  29010. })
  29011. },
  29012. _getCloseButton: function() {
  29013. return {
  29014. toolbar: "top",
  29015. location: "after",
  29016. template: this._getCloseButtonRenderer()
  29017. }
  29018. },
  29019. _getCloseButtonRenderer: function() {
  29020. return $.proxy(function(_, __, $container) {
  29021. var $button = $("<div>").addClass(POPUP_TITLE_CLOSEBUTTON_CLASS);
  29022. this._createComponent($button, "dxButton", {
  29023. icon: 'close',
  29024. onClick: this._createButtonAction(undefined),
  29025. _templates: {}
  29026. });
  29027. $container.append($button)
  29028. }, this)
  29029. },
  29030. _getToolbarItems: function(toolbar) {
  29031. var buttons = this.option("buttons");
  29032. var toolbarsItems = [];
  29033. this._buttonsClasses = [];
  29034. var currentPlatform = DX.devices.current().platform,
  29035. index = 0;
  29036. $.each(buttons, $.proxy(function(_, data) {
  29037. var isShortcut = DX.utils.isDefined(data.shortcut),
  29038. item = isShortcut ? getButtonPlace(data.shortcut) : data;
  29039. if (isShortcut && currentPlatform === "ios" && index < 2) {
  29040. item.toolbar = "top";
  29041. index++
  29042. }
  29043. $.extend(item, DX.utils.isDefined(data.toolbar) ? {toolbar: data.toolbar} : {});
  29044. if (item && item.toolbar === toolbar) {
  29045. if (isShortcut)
  29046. $.extend(item, {location: data.location}, this._getButtonByAlias(data));
  29047. var isLTROrder = currentPlatform === "win8" || currentPlatform === "generic";
  29048. if (data.shortcut === "done" && isLTROrder || data.shortcut === "cancel" && !isLTROrder)
  29049. toolbarsItems.unshift(item);
  29050. else
  29051. toolbarsItems.push(item)
  29052. }
  29053. }, this));
  29054. if (toolbar === "top" && this.option("showCloseButton"))
  29055. toolbarsItems.push(this._getCloseButton());
  29056. return toolbarsItems
  29057. },
  29058. _getButtonByAlias: function(data) {
  29059. var buttonType = data.shortcut;
  29060. if ($.inArray(buttonType, ALLOWED_BUTTON_ALIASES) < 0)
  29061. return false;
  29062. var buttonConfig = $.extend({
  29063. text: Globalize.localize(DX.inflector.camelize(buttonType, true)),
  29064. onClick: this._createButtonAction(data.onClick),
  29065. _templates: {}
  29066. }, data.options || {});
  29067. var buttonClass = POPUP_CLASS + "-" + buttonType;
  29068. this._buttonsClasses.push(buttonClass);
  29069. var $button = $("<div>").addClass(buttonClass);
  29070. this._createComponent($button, "dxButton", buttonConfig);
  29071. return {template: function(_, __, $container) {
  29072. $container.append($button)
  29073. }}
  29074. },
  29075. _createButtonAction: function(clickAction) {
  29076. return this._createAction(clickAction, {afterExecute: function(e) {
  29077. e.component.hide()
  29078. }})
  29079. },
  29080. _renderBottom: function() {
  29081. var items = this._getToolbarItems("bottom");
  29082. if (items.length) {
  29083. this._$bottom && this._$bottom.remove();
  29084. var $bottom = $("<div>").addClass(POPUP_BOTTOM_CLASS).appendTo(this._$content);
  29085. this._$bottom = this._renderTemplateByType("bottomTemplate", items, $bottom).addClass(POPUP_BOTTOM_CLASS);
  29086. this._toggleClasses()
  29087. }
  29088. else
  29089. this._$bottom && this._$bottom.detach()
  29090. },
  29091. _toggleClasses: function() {
  29092. var aliases = ALLOWED_BUTTON_ALIASES;
  29093. $.each(aliases, $.proxy(function(_, alias) {
  29094. var className = POPUP_CLASS + "-" + alias;
  29095. if ($.inArray(className, this._buttonsClasses) >= 0) {
  29096. this._wrapper().addClass(className + "-visible");
  29097. this._$bottom.addClass(className)
  29098. }
  29099. else {
  29100. this._wrapper().removeClass(className + "-visible");
  29101. this._$bottom.removeClass(className)
  29102. }
  29103. }, this))
  29104. },
  29105. _getDragTarget: function() {
  29106. return this._$title
  29107. },
  29108. _renderGeometryImpl: function() {
  29109. this._resetContentHeight();
  29110. this.callBase.apply(this, arguments);
  29111. this._setContentHeight()
  29112. },
  29113. _resetContentHeight: function() {
  29114. this._$popupContent.css({
  29115. height: "auto",
  29116. "max-height": "none"
  29117. })
  29118. },
  29119. _renderResize: function() {
  29120. this.callBase();
  29121. this._$content.dxResizable("option", "onResize", $.proxy(this._setContentHeight, this))
  29122. },
  29123. _setContentHeight: function() {
  29124. if (this.option("height") === "auto")
  29125. return;
  29126. var contentHeight = this._$content.height();
  29127. if (this._$title)
  29128. contentHeight -= this._$title.outerHeight(true) || 0;
  29129. if (this._$bottom)
  29130. contentHeight -= this._$bottom.outerHeight(true) || 0;
  29131. this._$popupContent.css({
  29132. height: "100%",
  29133. "max-height": contentHeight
  29134. })
  29135. },
  29136. _renderDimensions: function() {
  29137. if (this.option("fullScreen"))
  29138. this._$content.css({
  29139. width: "100%",
  29140. height: "100%"
  29141. });
  29142. else
  29143. this.callBase.apply(this, arguments);
  29144. this._renderFullscreenWidthClass()
  29145. },
  29146. _renderFullscreenWidthClass: function() {
  29147. this.overlayContent().toggleClass(POPUP_FULL_SCREEN_WIDTH_CLASS, this.overlayContent().outerWidth() === $(window).width())
  29148. },
  29149. _renderShadingDimensions: function() {
  29150. if (this.option("fullScreen"))
  29151. this._wrapper().css({
  29152. width: "100%",
  29153. height: "100%"
  29154. });
  29155. else
  29156. this.callBase.apply(this, arguments)
  29157. },
  29158. _renderPosition: function() {
  29159. if (this.option("fullScreen"))
  29160. translator.move(this._$content, {
  29161. top: 0,
  29162. left: 0
  29163. });
  29164. else
  29165. this.callBase.apply(this, arguments)
  29166. },
  29167. _optionChanged: function(args) {
  29168. switch (args.name) {
  29169. case"showTitle":
  29170. case"title":
  29171. case"titleTemplate":
  29172. this._renderTitle();
  29173. this._renderGeometry();
  29174. break;
  29175. case"bottomTemplate":
  29176. this._renderBottom();
  29177. this._renderGeometry();
  29178. break;
  29179. case"onTitleRendered":
  29180. this._createTitleRenderAction(args.value);
  29181. break;
  29182. case"buttons":
  29183. this._renderTitle();
  29184. this._renderBottom();
  29185. this._renderGeometry();
  29186. break;
  29187. case"dragEnabled":
  29188. this._renderDrag();
  29189. break;
  29190. case"fullScreen":
  29191. this._$content.toggleClass(POPUP_FULL_SCREEN_CLASS, args.value);
  29192. this._refresh();
  29193. break;
  29194. case"showCloseButton":
  29195. this._renderTitle();
  29196. break;
  29197. default:
  29198. this.callBase(args)
  29199. }
  29200. },
  29201. bottomToolbar: function() {
  29202. return this._$bottom
  29203. },
  29204. content: function() {
  29205. return this._$popupContent
  29206. },
  29207. overlayContent: function() {
  29208. return this._$content
  29209. }
  29210. }))
  29211. })(jQuery, DevExpress);
  29212. /*! Module widgets-base, file ui.popover.js */
  29213. (function($, DX, undefined) {
  29214. var ui = DX.ui,
  29215. fx = DX.fx;
  29216. var POPOVER_CLASS = "dx-popover",
  29217. POPOVER_WRAPPER_CLASS = "dx-popover-wrapper",
  29218. POPOVER_ARROW_CLASS = "dx-popover-arrow",
  29219. POPOVER_WITHOUT_TITLE_CLASS = "dx-popover-without-title",
  29220. POSITION_FLIP_MAP = {
  29221. left: "right",
  29222. top: "bottom",
  29223. right: "left",
  29224. bottom: "top",
  29225. center: "center"
  29226. },
  29227. WEIGHT_OF_SIDES = {
  29228. left: -1,
  29229. top: -1,
  29230. center: 0,
  29231. right: 1,
  29232. bottom: 1
  29233. },
  29234. POSITION_ALIASES = {
  29235. top: {
  29236. my: "bottom center",
  29237. at: "top center"
  29238. },
  29239. bottom: {
  29240. my: "top center",
  29241. at: "bottom center"
  29242. },
  29243. right: {
  29244. my: "left center",
  29245. at: "right center"
  29246. },
  29247. left: {
  29248. my: "right center",
  29249. at: "left center"
  29250. },
  29251. topNone: {
  29252. my: "bottom center",
  29253. at: "top center",
  29254. collision: "none"
  29255. },
  29256. bottomNone: {
  29257. my: "top center",
  29258. at: "bottom center",
  29259. collision: "none"
  29260. },
  29261. rightNone: {
  29262. my: "left center",
  29263. at: "right center",
  29264. collision: "none"
  29265. },
  29266. leftNone: {
  29267. my: "right center",
  29268. at: "left center",
  29269. collision: "none"
  29270. }
  29271. },
  29272. ARROW_OFFSET_CORRECTION = {
  29273. top: "0 -1",
  29274. bottom: "0 1",
  29275. left: "-1 0",
  29276. right: "1 0"
  29277. };
  29278. DX.registerComponent("dxPopover", ui, ui.dxPopup.inherit({
  29279. _setDefaultOptions: function() {
  29280. this.callBase();
  29281. this.option({
  29282. target: window,
  29283. shading: false,
  29284. position: 'bottom',
  29285. closeOnOutsideClick: true,
  29286. animation: {
  29287. show: {
  29288. type: "fade",
  29289. from: 0,
  29290. to: 1
  29291. },
  29292. hide: {
  29293. type: "fade",
  29294. to: 0
  29295. }
  29296. },
  29297. showTitle: false,
  29298. width: "auto",
  29299. height: "auto",
  29300. dragEnabled: false,
  29301. resizeEnabled: false,
  29302. fullScreen: false,
  29303. closeOnTargetScroll: true,
  29304. arrowPosition: null,
  29305. boundaryOffset: {
  29306. h: 10,
  29307. v: 10
  29308. }
  29309. })
  29310. },
  29311. _defaultOptionsRules: function() {
  29312. return [{
  29313. device: {platform: "ios"},
  29314. options: {arrowPosition: {
  29315. boundaryOffset: {
  29316. h: 20,
  29317. v: -10
  29318. },
  29319. collision: "fit"
  29320. }}
  29321. }]
  29322. },
  29323. _init: function() {
  29324. this.callBase();
  29325. this._renderArrow();
  29326. this.element().addClass(POPOVER_CLASS);
  29327. this._wrapper().addClass(POPOVER_WRAPPER_CLASS)
  29328. },
  29329. _renderArrow: function() {
  29330. this._$arrow = $("<div>").addClass(POPOVER_ARROW_CLASS).appendTo(this._wrapper())
  29331. },
  29332. _documentDownHandler: function(e) {
  29333. if (this._isOutsideClick(e))
  29334. this.callBase(e)
  29335. },
  29336. _isOutsideClick: function(e) {
  29337. return !$(e.target).closest(this.option("target")).length
  29338. },
  29339. _animate: function(animation) {
  29340. this._animateArrow(animation);
  29341. if (animation && animation.to)
  29342. $.extend(animation.to, {position: this._contentPosition});
  29343. this.callBase.apply(this, arguments)
  29344. },
  29345. _animateArrow: function(animation) {
  29346. if (!animation)
  29347. return;
  29348. DX.fx.animate(this._$arrow, $.extend({}, animation, {complete: $.noop}))
  29349. },
  29350. _stopAnimation: function() {
  29351. this.callBase.apply(this, arguments);
  29352. fx.stop(this._$arrow)
  29353. },
  29354. _renderTitle: function() {
  29355. this._wrapper().toggleClass(POPOVER_WITHOUT_TITLE_CLASS, !this.option("showTitle"));
  29356. this.callBase()
  29357. },
  29358. _renderPosition: function() {
  29359. this.callBase();
  29360. this._renderOverlayPosition();
  29361. this._renderArrowPosition()
  29362. },
  29363. _renderOverlayBoundaryOffset: $.noop,
  29364. _renderOverlayPosition: function() {
  29365. this._setContentHeight(true);
  29366. this._togglePositionClass("dx-position-" + this._positionSide);
  29367. DX.translator.move(this._$content, {
  29368. left: 0,
  29369. top: 0
  29370. });
  29371. var contentPosition = $.extend({}, this._position);
  29372. var containerPosition = this._getContainerPosition();
  29373. var containerLocation = DX.calculatePosition(this._$content, containerPosition);
  29374. var isFlippedByVertical = containerLocation.v.flip;
  29375. var isFlippedByHorizontal = containerLocation.h.flip;
  29376. this._updateContentSize(containerLocation);
  29377. if (this._position.collision === "flip")
  29378. contentPosition.collision = "fit";
  29379. var positionClass = "dx-position-" + (isFlippedByVertical || isFlippedByHorizontal || this._isPopoverInside() ? POSITION_FLIP_MAP[this._positionSide] : this._positionSide);
  29380. this._togglePositionClass(positionClass);
  29381. this._toggleFlippedClass(isFlippedByVertical, isFlippedByHorizontal);
  29382. $.extend(contentPosition, this._applyFlip(contentPosition, isFlippedByVertical, isFlippedByHorizontal));
  29383. contentPosition.offset = this._updateContentOffset(isFlippedByVertical, isFlippedByHorizontal, contentPosition.offset);
  29384. DX.position(this._$content, contentPosition);
  29385. this._contentPosition = contentPosition
  29386. },
  29387. _isPopoverInside: function() {
  29388. var position = this._getPosition();
  29389. var my = DX.position.normalizeAlign(position.my);
  29390. var at = DX.position.normalizeAlign(position.at);
  29391. return my.h === at.h && my.v === at.v
  29392. },
  29393. _getPosition: function() {
  29394. var position = this.option("position");
  29395. if (DX.utils.isString(position))
  29396. position = $.extend({}, POSITION_ALIASES[position]);
  29397. return position
  29398. },
  29399. _setContentHeight: function(fullUpdate) {
  29400. if (fullUpdate)
  29401. this.callBase()
  29402. },
  29403. _updateContentSize: function(containerLocation) {
  29404. if (!this._$popupContent)
  29405. return;
  29406. var positionAt = this._positionSide;
  29407. if (containerLocation.h.oversize > 0 && (positionAt === "left" || positionAt === "right")) {
  29408. var newContainerWidth = this._$content.width() - containerLocation.h.oversize;
  29409. this._$content.width(newContainerWidth)
  29410. }
  29411. if (containerLocation.v.oversize > 0 && (positionAt === "top" || positionAt === "bottom")) {
  29412. var newOverlayContentHeight = this._$content.height() - containerLocation.v.oversize,
  29413. newPopupContentHeight = this._$popupContent.height() - containerLocation.v.oversize;
  29414. this._$content.height(newOverlayContentHeight);
  29415. this._$popupContent.height(newPopupContentHeight)
  29416. }
  29417. },
  29418. _updateContentOffset: function(isFlippedByVertical, isFlippedByHorizontal, offsetString) {
  29419. var position = this._positionSide,
  29420. offset = this._getOffsetObject(offsetString),
  29421. signCorrectionH = isFlippedByHorizontal ? -1 : 1,
  29422. signCorrectionV = isFlippedByVertical ? -1 : 1;
  29423. var offsetSignCorrection = this._isPopoverInside() ? -1 : 1;
  29424. var isTopPosition = position === "top" && !isFlippedByVertical || position === "bottom" && isFlippedByVertical,
  29425. isBottomPosition = position === "bottom" && !isFlippedByVertical || position === "top" && isFlippedByVertical,
  29426. isLeftPosition = position === "left" && !isFlippedByHorizontal || position === "right" && isFlippedByHorizontal,
  29427. isRightPosition = position === "right" && !isFlippedByHorizontal || position === "left" && isFlippedByHorizontal;
  29428. if (isTopPosition)
  29429. return offset.h + " " + (offset.v * signCorrectionV - offsetSignCorrection * (this._$arrow.height() - 1));
  29430. if (isBottomPosition)
  29431. return offset.h + " " + (offset.v * signCorrectionV + offsetSignCorrection * (this._$arrow.height() - 1));
  29432. if (isLeftPosition)
  29433. return offset.h * signCorrectionH - offsetSignCorrection * (this._$arrow.width() - 1) + " " + offset.v;
  29434. if (isRightPosition)
  29435. return offset.h * signCorrectionH + offsetSignCorrection * (this._$arrow.width() - 1) + " " + offset.v
  29436. },
  29437. _getContainerPosition: function() {
  29438. var offset = this._getOffsetObject(this._position.offset || "");
  29439. var arrowConsideredOffset = this._$arrow.width() + offset.h + " " + (this._$arrow.height() + offset.v);
  29440. return $.extend({}, this._position, {offset: arrowConsideredOffset})
  29441. },
  29442. _applyFlip: function(position, isFlippedByVertical, isFlippedByHorizontal) {
  29443. var pairMy = DX.utils.splitPair(position.my),
  29444. pairAt = DX.utils.splitPair(position.at);
  29445. var isVertical = function(location) {
  29446. return location === "bottom" || location === "top"
  29447. };
  29448. var isHorizontal = function(location) {
  29449. return location === "left" || location === "right"
  29450. };
  29451. var flipIfNeeded = function(location) {
  29452. return isFlippedByVertical && isVertical(location) || isFlippedByHorizontal && isHorizontal(location) ? DX.position.inverseAlign(location) : location
  29453. };
  29454. return {
  29455. my: flipIfNeeded(pairMy[0]) + " " + flipIfNeeded(pairMy[1]),
  29456. at: flipIfNeeded(pairAt[0]) + " " + flipIfNeeded(pairAt[1])
  29457. }
  29458. },
  29459. _renderArrowPosition: function() {
  29460. DX.translator.move(this._$arrow, {
  29461. left: 0,
  29462. top: 0
  29463. });
  29464. var arrowPosition = this.option("arrowPosition"),
  29465. position = $.extend({}, this._getDefaultArrowPosition(), arrowPosition);
  29466. var customPositionSpecified = arrowPosition && DX.utils.isDefined(arrowPosition.at) && DX.utils.isDefined(arrowPosition.my);
  29467. if (customPositionSpecified)
  29468. $.extend(position, this._getCustomArrowPosition(arrowPosition));
  29469. DX.position(this._$arrow, position)
  29470. },
  29471. _getCustomArrowPosition: function(arrowPosition) {
  29472. var contentPositionAt = this._contentPosition.at.split(" ")[0],
  29473. arrowPositionAt = arrowPosition.at,
  29474. arrowPositionMy = arrowPosition.my,
  29475. isFlipped = arrowPositionAt && arrowPositionAt.split(" ")[0] === contentPositionAt;
  29476. if (isFlipped) {
  29477. var at = arrowPositionAt;
  29478. arrowPositionAt = arrowPositionMy;
  29479. arrowPositionMy = at
  29480. }
  29481. var correctedOffset = this._mergeOffsets(ARROW_OFFSET_CORRECTION[contentPositionAt], arrowPosition.offset);
  29482. return {
  29483. my: arrowPositionMy,
  29484. at: arrowPositionAt,
  29485. of: this._$content,
  29486. offset: correctedOffset
  29487. }
  29488. },
  29489. _getDefaultArrowPosition: function() {
  29490. var popoverSide = this._getDisplaySide(this._contentPosition),
  29491. flippedSide = POSITION_FLIP_MAP[popoverSide],
  29492. that = this;
  29493. var flipIfInside = function(side) {
  29494. return that._isPopoverInside() ? POSITION_FLIP_MAP[side] : side
  29495. };
  29496. return this._isPopoverLargerThanTarget() ? {
  29497. my: flipIfInside(flippedSide),
  29498. at: popoverSide,
  29499. of: $(this.option("target"))
  29500. } : {
  29501. my: flipIfInside(popoverSide),
  29502. at: flipIfInside(flippedSide),
  29503. of: this._$content,
  29504. offset: ARROW_OFFSET_CORRECTION[flipIfInside(popoverSide)]
  29505. }
  29506. },
  29507. _isPopoverLargerThanTarget: function() {
  29508. if (this._$content.is(':hidden'))
  29509. return true;
  29510. if (this._position.of.target)
  29511. return false;
  29512. var position = this._positionSide,
  29513. $target = $(this._position.of),
  29514. popoverSize,
  29515. targetSize;
  29516. switch (position) {
  29517. case"top":
  29518. case"bottom":
  29519. popoverSize = this._$content.width();
  29520. targetSize = $target.outerWidth() + this._$arrow.width();
  29521. break;
  29522. case"left":
  29523. case"right":
  29524. popoverSize = this._$content.height();
  29525. targetSize = $target.outerHeight() + this._$arrow.height();
  29526. break
  29527. }
  29528. return popoverSize > targetSize
  29529. },
  29530. _mergeOffsets: function(baseOffset, additionalOffset) {
  29531. if (!additionalOffset)
  29532. return baseOffset;
  29533. var base = this._getOffsetObject(baseOffset),
  29534. addition = this._getOffsetObject(additionalOffset);
  29535. return base.h + addition.h + " " + (base.v + addition.v)
  29536. },
  29537. _renderShadingPosition: function() {
  29538. if (this.option("shading"))
  29539. this._$wrapper.css({
  29540. top: 0,
  29541. left: 0
  29542. })
  29543. },
  29544. _renderShadingDimensions: function() {
  29545. if (this.option("shading"))
  29546. this._$wrapper.css({
  29547. width: "100%",
  29548. height: "100%"
  29549. })
  29550. },
  29551. _togglePositionClass: function(positionClass) {
  29552. this._$wrapper.removeClass("dx-position-left dx-position-right dx-position-top dx-position-bottom").addClass(positionClass)
  29553. },
  29554. _toggleFlippedClass: function(isFlippedVertical, isFlippedHorizontal) {
  29555. this._$wrapper.toggleClass("dx-popover-flipped-vertical", isFlippedVertical).toggleClass("dx-popover-flipped-horizontal", isFlippedHorizontal)
  29556. },
  29557. _normalizePosition: function() {
  29558. var position = this._getPosition();
  29559. if (!position.of)
  29560. position.of = this.option("target");
  29561. if (!position.collision)
  29562. position.collision = "flip";
  29563. if (!position.boundaryOffset)
  29564. position.boundaryOffset = this.option("boundaryOffset");
  29565. this._positionSide = this._getDisplaySide(position);
  29566. this._position = position
  29567. },
  29568. _getDisplaySide: function(position) {
  29569. var my = DX.position.normalizeAlign(position.my),
  29570. at = DX.position.normalizeAlign(position.at);
  29571. var weightSign = WEIGHT_OF_SIDES[my.h] === WEIGHT_OF_SIDES[at.h] && WEIGHT_OF_SIDES[my.v] === WEIGHT_OF_SIDES[at.v] ? -1 : 1,
  29572. horizontalWeight = Math.abs(WEIGHT_OF_SIDES[my.h] - weightSign * WEIGHT_OF_SIDES[at.h]),
  29573. verticalWeight = Math.abs(WEIGHT_OF_SIDES[my.v] - weightSign * WEIGHT_OF_SIDES[at.v]);
  29574. return horizontalWeight > verticalWeight ? at.h : at.v
  29575. },
  29576. _getOffsetObject: function(offset) {
  29577. return DX.utils.stringPairToObject(offset)
  29578. },
  29579. _optionChanged: function(args) {
  29580. switch (args.name) {
  29581. case"showTitle":
  29582. case"title":
  29583. case"titleTemplate":
  29584. this.callBase(args);
  29585. this._renderGeometry();
  29586. break;
  29587. case"target":
  29588. case"boundaryOffset":
  29589. case"arrowPosition":
  29590. this._renderGeometry();
  29591. break;
  29592. case"fullScreen":
  29593. if (args.value)
  29594. this.option("fullScreen", false);
  29595. break;
  29596. default:
  29597. this.callBase(args)
  29598. }
  29599. },
  29600. show: function(target) {
  29601. if (target)
  29602. this.option("target", target);
  29603. return this.callBase()
  29604. }
  29605. }));
  29606. ui.dxPopover.__internals = {
  29607. POPOVER_CLASS: POPOVER_CLASS,
  29608. POPOVER_WRAPPER_CLASS: POPOVER_WRAPPER_CLASS,
  29609. POPOVER_ARROW_CLASS: POPOVER_ARROW_CLASS,
  29610. POPOVER_WITHOUT_TITLE_CLASS: POPOVER_WITHOUT_TITLE_CLASS
  29611. }
  29612. })(jQuery, DevExpress);
  29613. /*! Module widgets-base, file ui.tooltip.js */
  29614. (function($, DX, undefined) {
  29615. var ui = DX.ui,
  29616. TOOLTIP_CLASS = "dx-tooltip",
  29617. TOOLTIP_WRAPPER_CLASS = "dx-tooltip-wrapper",
  29618. Z_INDEX_STACK = [],
  29619. FIRST_Z_INDEX_OFFSET = -500;
  29620. DX.registerComponent("dxTooltip", ui, ui.dxPopover.inherit({
  29621. _setDefaultOptions: function() {
  29622. this.callBase();
  29623. this.option({
  29624. showTitle: false,
  29625. title: undefined,
  29626. titleTemplate: undefined,
  29627. bottomTemplate: undefined
  29628. })
  29629. },
  29630. _render: function() {
  29631. this.element().addClass(TOOLTIP_CLASS);
  29632. this._wrapper().addClass(TOOLTIP_WRAPPER_CLASS);
  29633. this.callBase()
  29634. },
  29635. _renderContent: function() {
  29636. this.callBase();
  29637. this._contentId = new DevExpress.data.Guid;
  29638. this._$content.attr({
  29639. id: this._contentId,
  29640. role: "tooltip"
  29641. });
  29642. this._toggleAriaDescription(true)
  29643. },
  29644. _toggleAriaDescription: function(showing) {
  29645. var $target = $(this.option("target")),
  29646. label = showing ? this._contentId : undefined;
  29647. this.setAria("describedby", label, $target)
  29648. },
  29649. _zIndexStack: function() {
  29650. return Z_INDEX_STACK
  29651. },
  29652. _zIndexInitValue: function() {
  29653. return this.callBase() + FIRST_Z_INDEX_OFFSET
  29654. }
  29655. }));
  29656. ui.dxTooltip.__internals = {
  29657. TOOLTIP_CLASS: TOOLTIP_CLASS,
  29658. TOOLTIP_WRAPPER_CLASS: TOOLTIP_WRAPPER_CLASS
  29659. }
  29660. })(jQuery, DevExpress);
  29661. /*! Module widgets-base, file ui.dropDownMenu.js */
  29662. (function($, DX, undefined) {
  29663. var ui = DX.ui;
  29664. var DROP_DOWN_MENU_CLASS = "dx-dropdownmenu",
  29665. DROP_DOWN_MENU_POPUP_CLASS = "dx-dropdownmenu-popup",
  29666. DROP_DOWN_MENU_POPUP_WRAPPER_CLASS = DROP_DOWN_MENU_POPUP_CLASS + "-wrapper",
  29667. DROP_DOWN_MENU_LIST_CLASS = "dx-dropdownmenu-list",
  29668. DROP_DOWN_MENU_BUTTON_CLASS = "dx-dropdownmenu-button";
  29669. var POPUP_OPTION_MAP = {
  29670. popupWidth: "width",
  29671. popupHeight: "height"
  29672. };
  29673. var BUTTON_OPTION_MAP = {
  29674. buttonIcon: "icon",
  29675. buttonText: "text"
  29676. };
  29677. DX.registerComponent("dxDropDownMenu", ui, ui.Widget.inherit({
  29678. _supportedKeys: function() {
  29679. return $.extend(this.callBase(), {tab: function(e) {
  29680. this._popup.hide()
  29681. }})
  29682. },
  29683. _setDeprecatedOptions: function() {
  29684. this.callBase();
  29685. $.extend(this._deprecatedOptions, {
  29686. itemClickAction: {
  29687. since: "14.2",
  29688. alias: "onItemClick"
  29689. },
  29690. buttonClickAction: {
  29691. since: "14.2",
  29692. alias: "onButtonClick"
  29693. },
  29694. itemRender: {
  29695. since: "14.2",
  29696. alias: "itemTemplate"
  29697. },
  29698. buttonIconSrc: {
  29699. since: "15.1",
  29700. alias: "buttonIcon"
  29701. }
  29702. })
  29703. },
  29704. _setDefaultOptions: function() {
  29705. this.callBase();
  29706. this.option({
  29707. items: [],
  29708. onItemClick: null,
  29709. dataSource: null,
  29710. itemTemplate: "item",
  29711. buttonText: "",
  29712. buttonIcon: "overflow",
  29713. onButtonClick: null,
  29714. usePopover: false,
  29715. popupWidth: "auto",
  29716. popupHeight: "auto",
  29717. hoverStateEnabled: true,
  29718. opened: false,
  29719. popupPosition: "bottom",
  29720. popupAnimation: undefined
  29721. })
  29722. },
  29723. _defaultOptionsRules: function() {
  29724. return this.callBase().concat([{
  29725. device: [{platform: "ios"}],
  29726. options: {usePopover: true}
  29727. }, {
  29728. device: function(device) {
  29729. return DX.devices.real().generic && !DX.devices.isSimulator()
  29730. },
  29731. options: {focusStateEnabled: true}
  29732. }, {
  29733. device: function(device) {
  29734. return device.android && (device.version[0] >= 4 && device.version[1] >= 1 || device.version[0] >= 5)
  29735. },
  29736. options: {
  29737. popupPosition: {
  29738. my: "top " + (this.option("rtlEnabled") ? "left" : "right"),
  29739. at: "top " + (this.option("rtlEnabled") ? "left" : "right")
  29740. },
  29741. popupAnimation: {
  29742. show: {
  29743. type: "pop",
  29744. duration: 200,
  29745. from: {scale: 0},
  29746. to: {scale: 1}
  29747. },
  29748. hide: {
  29749. type: "pop",
  29750. duration: 200,
  29751. from: {scale: 1},
  29752. to: {scale: 0}
  29753. }
  29754. }
  29755. }
  29756. }])
  29757. },
  29758. _dataSourceOptions: function() {
  29759. return {paginate: false}
  29760. },
  29761. _init: function() {
  29762. this.callBase();
  29763. this._initDataSource();
  29764. this._initItemClickAction();
  29765. this._initButtonClickAction()
  29766. },
  29767. _initItemClickAction: function() {
  29768. this._itemClickAction = this._createActionByOption("onItemClick")
  29769. },
  29770. _initButtonClickAction: function() {
  29771. this._buttonClickAction = this._createActionByOption("onButtonClick")
  29772. },
  29773. _render: function() {
  29774. this.element().addClass(DROP_DOWN_MENU_CLASS);
  29775. this._renderButton();
  29776. this.callBase();
  29777. this.setAria({
  29778. role: "menubar",
  29779. haspopup: true,
  29780. expanded: this.option("opened")
  29781. })
  29782. },
  29783. _clean: function() {
  29784. this._cleanFocusState();
  29785. this._popup.element().remove()
  29786. },
  29787. _renderContentImpl: function() {
  29788. this._renderPopup()
  29789. },
  29790. _renderButton: function() {
  29791. var that = this;
  29792. var $button = this.element().addClass(DROP_DOWN_MENU_BUTTON_CLASS);
  29793. this._button = this._createComponent($button, "dxButton", {
  29794. text: this.option("buttonText"),
  29795. icon: this.option("buttonIcon"),
  29796. focusStateEnabled: false,
  29797. onClick: function(e) {
  29798. that.option("opened", !that.option("opened"));
  29799. that._buttonClickAction(e)
  29800. },
  29801. _templates: {}
  29802. });
  29803. var keys = this._supportedKeys(),
  29804. buttonKeys = this._button._supportedKeys();
  29805. this._supportedKeys = function() {
  29806. return $.extend(keys, buttonKeys)
  29807. }
  29808. },
  29809. _toggleMenuVisibility: function(opened) {
  29810. var state = opened === undefined ? !this._popup.option("visible") : opened;
  29811. this._popup.toggle(state);
  29812. this.setAria("expanded", state)
  29813. },
  29814. _renderPopup: function() {
  29815. var $popup = this._$popup = $("<div>").appendTo(this.element());
  29816. var popupOptions = {
  29817. onContentReady: $.proxy(this._popupContentReadyHandler, this),
  29818. deferRendering: false,
  29819. position: this.option("popupPosition"),
  29820. animation: this.option("popupAnimation"),
  29821. onOptionChanged: $.proxy(function(args) {
  29822. if (args.name === "visible")
  29823. this.option("opened", args.value)
  29824. }, this)
  29825. };
  29826. this._popup = this._createPopover($popup, popupOptions);
  29827. this._popup._wrapper().addClass(DROP_DOWN_MENU_POPUP_WRAPPER_CLASS);
  29828. this._popup._wrapper().toggleClass(DROP_DOWN_MENU_POPUP_CLASS, !this.option("usePopover"))
  29829. },
  29830. _popupContentReadyHandler: function() {
  29831. var popup = this._$popup.dxPopover("instance");
  29832. this._renderList(popup)
  29833. },
  29834. _createPopover: function($element, popupOptions) {
  29835. return this._createComponent($element, "dxPopover", $.extend(popupOptions, {
  29836. target: this.element(),
  29837. height: this.option("popupHeight"),
  29838. width: this.option("popupWidth")
  29839. }))
  29840. },
  29841. _renderList: function(instance) {
  29842. var $content = instance.content(),
  29843. that = this;
  29844. $content.addClass(DROP_DOWN_MENU_LIST_CLASS);
  29845. that._list = that._createComponent($content, "dxList", {
  29846. _keyboardProcessor: that._listProcessor,
  29847. pageLoadMode: "scrollBottom",
  29848. indicateLoading: false,
  29849. noDataText: "",
  29850. itemTemplate: that._getTemplateByOption("itemTemplate"),
  29851. onItemClick: function(e) {
  29852. that.option("opened", false);
  29853. that._itemClickAction(e)
  29854. },
  29855. tabIndex: -1,
  29856. focusStateEnabled: this.option("focusStateEnabled"),
  29857. _itemAttributes: {role: "menuitem"}
  29858. });
  29859. that._list._getAriaTarget = function() {
  29860. return that.element()
  29861. };
  29862. that._setListDataSource();
  29863. var listMaxHeight = $(window).height() * 0.5;
  29864. if ($content.height() > listMaxHeight)
  29865. $content.height(listMaxHeight)
  29866. },
  29867. _setListDataSource: function() {
  29868. if (this._list)
  29869. this._list.option("dataSource", this._dataSource || this.option("items"))
  29870. },
  29871. _attachKeyboardEvents: function() {
  29872. this.callBase.apply(this, arguments);
  29873. this._listProcessor = this._keyboardProcessor.attachChildProcessor();
  29874. if (this._list)
  29875. this._list.option("_keyboardProcessor", this._listProcessor)
  29876. },
  29877. _cleanFocusState: function() {
  29878. this.callBase.apply(this, arguments);
  29879. delete this._listProcessor
  29880. },
  29881. _toggleVisibility: function(visible) {
  29882. this.callBase(visible);
  29883. this._button.option("visible", visible)
  29884. },
  29885. _optionChanged: function(args) {
  29886. var name = args.name;
  29887. var value = args.value;
  29888. switch (name) {
  29889. case"items":
  29890. case"dataSource":
  29891. this._refreshDataSource();
  29892. this._setListDataSource();
  29893. break;
  29894. case"itemTemplate":
  29895. if (this._list)
  29896. this._list.option(name, this._getTemplate(value));
  29897. break;
  29898. case"onItemClick":
  29899. this._initItemClickAction();
  29900. break;
  29901. case"onButtonClick":
  29902. this._buttonClickAction();
  29903. break;
  29904. case"buttonIcon":
  29905. case"buttonText":
  29906. this._button.option(BUTTON_OPTION_MAP[name], value);
  29907. break;
  29908. case"popupWidth":
  29909. case"popupHeight":
  29910. this._popup.option(POPUP_OPTION_MAP[name], value);
  29911. break;
  29912. case"usePopover":
  29913. this._invalidate();
  29914. break;
  29915. case"focusStateEnabled":
  29916. if (this._list)
  29917. this._list.option(name, value);
  29918. this.callBase(args);
  29919. break;
  29920. case"opened":
  29921. this._toggleMenuVisibility(value);
  29922. break;
  29923. case"popupPosition":
  29924. break;
  29925. default:
  29926. this.callBase(args)
  29927. }
  29928. },
  29929. open: function() {
  29930. this.option("opened", true)
  29931. },
  29932. close: function() {
  29933. this.option("opened", false)
  29934. }
  29935. }).include(ui.DataHelperMixin))
  29936. })(jQuery, DevExpress);
  29937. /*! Module widgets-base, file ui.dateUtils.js */
  29938. (function($, DX, undefined) {
  29939. var dateCopmotents = function() {
  29940. return ["year", "day", "month", "day"]
  29941. };
  29942. var dateUtils = DX.ui.dateUtils = {
  29943. SUPPORTED_FORMATS: ["date", "time", "datetime"],
  29944. DEFAULT_FORMATTER: function(value) {
  29945. return value
  29946. },
  29947. DATE_COMPONENT_TEXT_FORMATTER: function(value, name) {
  29948. var $container = $("<div>").addClass("dx-dateview-formatter-container");
  29949. $("<span>").text(value).addClass("dx-dateview-value-formatter").appendTo($container);
  29950. $("<span>").text(name).addClass("dx-dateview-name-formatter").appendTo($container);
  29951. return $container
  29952. },
  29953. ONE_MINUTE: 1000 * 60,
  29954. ONE_DAY: 1000 * 60 * 60 * 24,
  29955. TEN_YEARS: 1000 * 60 * 60 * 24 * 365 * 10,
  29956. FORMATS_INFO: {
  29957. date: {
  29958. standardPattern: "yyyy-MM-dd",
  29959. components: dateCopmotents()
  29960. },
  29961. time: {
  29962. standardPattern: "HH:mm",
  29963. components: ["hours", "minutes"]
  29964. },
  29965. datetime: {
  29966. standardPattern: "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'",
  29967. components: dateCopmotents().concat(["hours", "minutes", "seconds", "milliseconds"])
  29968. },
  29969. "datetime-local": {
  29970. standardPattern: "yyyy'-'MM'-'dd'T'HH':'mm",
  29971. components: dateCopmotents().concat(["hours", "minutes", "seconds"])
  29972. }
  29973. },
  29974. FORMATS_MAP: {
  29975. date: "d",
  29976. time: "t",
  29977. datetime: "S",
  29978. "datetime-local": "f"
  29979. },
  29980. toStandardDateFormat: function(date, mode, pattern) {
  29981. pattern = pattern || dateUtils.FORMATS_INFO[mode].standardPattern;
  29982. return Globalize.format(date, pattern)
  29983. },
  29984. fromStandardDateFormat: function(date) {
  29985. return Globalize.parseDate(date, dateUtils.FORMATS_INFO["datetime"].standardPattern) || Globalize.parseDate(date, dateUtils.FORMATS_INFO["datetime-local"].standardPattern) || Globalize.parseDate(date, dateUtils.FORMATS_INFO["time"].standardPattern) || Globalize.parseDate(date, dateUtils.FORMATS_INFO["date"].standardPattern) || Date.parse && Date.parse(date) && new Date(Date.parse(date))
  29986. },
  29987. getMaxMonthDay: function(year, month) {
  29988. return new Date(year, month + 1, 0).getDate()
  29989. },
  29990. mergeDates: function(target, source, format) {
  29991. if (!source)
  29992. return undefined;
  29993. if (isNaN(target.getTime()))
  29994. target = new Date(0, 0, 0, 0, 0, 0);
  29995. var formatInfo = dateUtils.FORMATS_INFO[format];
  29996. $.each(formatInfo.components, function() {
  29997. var componentInfo = dateUtils.DATE_COMPONENTS_INFO[this];
  29998. target[componentInfo.setter](source[componentInfo.getter]())
  29999. });
  30000. return target
  30001. },
  30002. getLongestCaptionIndex: function(captionArray) {
  30003. var longestIndex = 0,
  30004. longestCaptionLength = 0,
  30005. i;
  30006. for (i = 0; i < captionArray.length; ++i)
  30007. if (captionArray[i].length > longestCaptionLength) {
  30008. longestIndex = i;
  30009. longestCaptionLength = captionArray[i].length
  30010. }
  30011. return longestIndex
  30012. },
  30013. expandPattern: function(pattern) {
  30014. return pattern.length === 1 ? Globalize.culture().calendar.patterns[pattern] : pattern
  30015. },
  30016. formatUsesMonthName: function(format) {
  30017. return dateUtils.expandPattern(format).indexOf("MMMM") !== -1
  30018. },
  30019. formatUsesDayName: function(format) {
  30020. return dateUtils.expandPattern(format).indexOf("dddd") !== -1
  30021. },
  30022. getLongestDate: function(format, monthNames, dayNames) {
  30023. var longestDate = new Date(1888, dateUtils.formatUsesMonthName(format) ? dateUtils.getLongestCaptionIndex(monthNames) : 9, 28 - 7, 23, 59, 59, 999);
  30024. if (dateUtils.formatUsesDayName(format))
  30025. longestDate.setDate(longestDate.getDate() - longestDate.getDay() + dateUtils.getLongestCaptionIndex(dayNames));
  30026. return longestDate
  30027. },
  30028. calculateMaximumDateFormatWidth: function(format, customFontStyles, rootElement) {
  30029. if (!rootElement || $(rootElement).is(":visible")) {
  30030. var width,
  30031. ieRoundingError = 2,
  30032. longestTextDiv = $("<div>" + Globalize.format(dateUtils.getLongestDate(format, Globalize.culture().calendar.months.names, Globalize.culture().calendar.days.names), format) + "</div>").css({
  30033. visibility: "hidden",
  30034. "white-space": "nowrap",
  30035. position: "absolute",
  30036. float: "left"
  30037. });
  30038. if (customFontStyles)
  30039. longestTextDiv.css(customFontStyles);
  30040. longestTextDiv.appendTo(rootElement ? $(rootElement) : $("body"));
  30041. width = longestTextDiv.width() + ieRoundingError;
  30042. longestTextDiv.remove();
  30043. return width
  30044. }
  30045. }
  30046. };
  30047. dateUtils.DATE_COMPONENTS_INFO = {
  30048. year: {
  30049. getter: "getFullYear",
  30050. setter: "setFullYear",
  30051. possibleFormats: ["yy", "yyyy"],
  30052. formatter: dateUtils.DEFAULT_FORMATTER,
  30053. startValue: undefined,
  30054. endValue: undefined
  30055. },
  30056. day: {
  30057. getter: "getDate",
  30058. setter: "setDate",
  30059. possibleFormats: ["d", "dd"],
  30060. formatter: function(value, showNames, date) {
  30061. if (!showNames)
  30062. return value;
  30063. var formatDate = new Date(date.getTime());
  30064. formatDate.setDate(value);
  30065. return dateUtils.DATE_COMPONENT_TEXT_FORMATTER(value, Globalize.culture().calendar.days.names[formatDate.getDay()])
  30066. },
  30067. startValue: 1,
  30068. endValue: undefined
  30069. },
  30070. month: {
  30071. getter: "getMonth",
  30072. setter: "setMonth",
  30073. possibleFormats: ["M", "MM", "MMM", "MMMM"],
  30074. formatter: function(value, showNames) {
  30075. var monthName = Globalize.culture().calendar.months.names[value];
  30076. return showNames ? dateUtils.DATE_COMPONENT_TEXT_FORMATTER(value + 1, monthName) : monthName
  30077. },
  30078. startValue: 0,
  30079. endValue: 11
  30080. },
  30081. hours: {
  30082. getter: "getHours",
  30083. setter: "setHours",
  30084. possibleFormats: ["H", "HH", "h", "hh"],
  30085. formatter: function(value) {
  30086. return Globalize.format(new Date(0, 0, 0, value), "HH")
  30087. },
  30088. startValue: 0,
  30089. endValue: 23
  30090. },
  30091. minutes: {
  30092. getter: "getMinutes",
  30093. setter: "setMinutes",
  30094. possibleFormats: ["m", "mm"],
  30095. formatter: function(value) {
  30096. return Globalize.format(new Date(0, 0, 0, 0, value), "mm")
  30097. },
  30098. startValue: 0,
  30099. endValue: 59
  30100. },
  30101. seconds: {
  30102. getter: "getSeconds",
  30103. setter: "setSeconds",
  30104. possibleFormats: ["s", "ss"],
  30105. formatter: function(value) {
  30106. return Globalize.format(new Date(0, 0, 0, 0, 0, value), "ss")
  30107. },
  30108. startValue: 0,
  30109. endValue: 59
  30110. },
  30111. milliseconds: {
  30112. getter: "getMilliseconds",
  30113. setter: "setMilliseconds",
  30114. possibleFormats: ["f", "ff", "fff"],
  30115. formatter: function(value) {
  30116. return Globalize.format(new Date(0, 0, 0, 0, 0, 0, value), "fff")
  30117. },
  30118. startValue: 0,
  30119. endValue: 999
  30120. }
  30121. };
  30122. (function androidFormatDetection() {
  30123. var androidFormatPattern = "yyyy'-'MM'-'dd'T'HH':'mm'Z'";
  30124. var $input = $("<input>").attr("type", "datetime");
  30125. $input.val(dateUtils.toStandardDateFormat(new Date, "datetime", androidFormatPattern));
  30126. if ($input.val())
  30127. dateUtils.FORMATS_INFO.datetime.standardPattern = androidFormatPattern
  30128. })()
  30129. })(jQuery, DevExpress);
  30130. /*! Module widgets-base, file ui.calendar.js */
  30131. (function($, DX, undefined) {
  30132. var ui = DX.ui,
  30133. fx = DX.fx,
  30134. utils = DX.utils,
  30135. CALENDAR_CLASS = "dx-calendar",
  30136. CALENDAR_BODY_CLASS = "dx-calendar-body",
  30137. CALENDAR_CELL_CLASS = "dx-calendar-cell",
  30138. CALENDAR_EMPTY_CELL_CLASS = "dx-calendar-empty-cell",
  30139. CALENDAR_FOOTER_CLASS = "dx-calendar-footer",
  30140. CALENDAR_TODAY_BUTTON_CLASS = "dx-calendar-today-button",
  30141. CALENDAR_HAS_FOOTER_CLASS = "dx-calendar-with-footer",
  30142. MONTH_VIEW_ANIMATION_DURATION = 300,
  30143. ANIMATION_DURATION_ILLEGAL_RANGE = 200,
  30144. ANIMATION_DURATION_SHOW_VIEW = 250,
  30145. POP_ANIMATION_FROM = 0.6,
  30146. POP_ANIMATION_TO = 1,
  30147. SHOT_SWIPE_OFFSET = 0.5,
  30148. CALENDAR_DATE_VALUE_KEY = "dxDateValueKey",
  30149. SWIPE_POSITION = {
  30150. left: -1,
  30151. right: 1
  30152. },
  30153. LEVEL_COMPARE_MAP = {
  30154. month: 3,
  30155. year: 2,
  30156. decade: 1,
  30157. century: 0
  30158. };
  30159. DX.registerComponent("dxCalendar", ui, ui.Editor.inherit({
  30160. _activeStateUnit: "." + CALENDAR_CELL_CLASS,
  30161. _supportedKeys: function() {
  30162. var isRTL = this.option("rtlEnabled"),
  30163. offset = utils.getDifferenceInMonth(this.option("zoomLevel"));
  30164. return $.extend(this.callBase(), {
  30165. rightArrow: function(e) {
  30166. if (e.ctrlKey) {
  30167. e.preventDefault();
  30168. this._waitRenderView(offset, isRTL ? -1 : 1)
  30169. }
  30170. else {
  30171. this._change = "key";
  30172. return true
  30173. }
  30174. },
  30175. leftArrow: function(e) {
  30176. if (e.ctrlKey) {
  30177. e.preventDefault();
  30178. this._waitRenderView(offset, isRTL ? 1 : -1)
  30179. }
  30180. else {
  30181. this._change = "key";
  30182. return true
  30183. }
  30184. },
  30185. upArrow: function(e) {
  30186. if (e.ctrlKey) {
  30187. e.preventDefault();
  30188. this._navigateUp()
  30189. }
  30190. else {
  30191. if (fx.isAnimating(this._view.element()))
  30192. return;
  30193. this._change = "upDownArrow";
  30194. return true
  30195. }
  30196. },
  30197. downArrow: function(e) {
  30198. if (e.ctrlKey) {
  30199. e.preventDefault();
  30200. this._navigateDown()
  30201. }
  30202. else {
  30203. if (fx.isAnimating(this._view.element()))
  30204. return;
  30205. this._change = "upDownArrow";
  30206. return true
  30207. }
  30208. },
  30209. pageUp: function(e) {
  30210. e.preventDefault();
  30211. this._waitRenderView(offset, -1)
  30212. },
  30213. pageDown: function(e) {
  30214. e.preventDefault();
  30215. this._waitRenderView(offset, 1)
  30216. },
  30217. tab: $.noop,
  30218. enter: function(e) {
  30219. if (!this._isMaxZoomLevel())
  30220. this._navigateDown();
  30221. else
  30222. return true
  30223. }
  30224. })
  30225. },
  30226. _setDefaultOptions: function() {
  30227. this.callBase();
  30228. this.option({
  30229. currentDate: new Date,
  30230. min: new Date(1000, 0),
  30231. max: new Date(3000, 0),
  30232. firstDayOfWeek: undefined,
  30233. zoomLevel: "month",
  30234. maxZoomLevel: "month",
  30235. minZoomLevel: "century",
  30236. showTodayButton: false,
  30237. cellTemplate: "cell",
  30238. onCellClick: null,
  30239. onContouredChanged: null
  30240. })
  30241. },
  30242. _defaultOptionsRules: function() {
  30243. return this.callBase().concat([{
  30244. device: function() {
  30245. return DX.devices.real().generic && !DX.devices.isSimulator()
  30246. },
  30247. options: {
  30248. focusStateEnabled: true,
  30249. hoverStateEnabled: true
  30250. }
  30251. }])
  30252. },
  30253. _init: function() {
  30254. this.callBase();
  30255. this._correctZoomLevel();
  30256. this._updateCurrentDate(this.option("value"));
  30257. this._initActions()
  30258. },
  30259. _initActions: function() {
  30260. this._cellClickOptionAction = this._createActionByOption("onCellClick")
  30261. },
  30262. _correctZoomLevel: function() {
  30263. var maxZoomLevel = this.option("maxZoomLevel"),
  30264. minZoomLevel = this.option("minZoomLevel"),
  30265. zoomLevel = this.option("zoomLevel");
  30266. if (LEVEL_COMPARE_MAP[maxZoomLevel] < LEVEL_COMPARE_MAP[minZoomLevel])
  30267. return;
  30268. if (LEVEL_COMPARE_MAP[zoomLevel] > LEVEL_COMPARE_MAP[maxZoomLevel])
  30269. this.option("zoomLevel", maxZoomLevel);
  30270. else if (LEVEL_COMPARE_MAP[zoomLevel] < LEVEL_COMPARE_MAP[minZoomLevel])
  30271. this.option("zoomLevel", minZoomLevel)
  30272. },
  30273. _updateCurrentDate: function(value) {
  30274. var min = this.option("min"),
  30275. max = this.option("max");
  30276. if (min && max && min > max) {
  30277. this.option("currentDate", new Date);
  30278. return
  30279. }
  30280. if (min)
  30281. min = new Date(min);
  30282. if (max)
  30283. max = new Date(max);
  30284. var date = value || new Date(this.option("currentDate")),
  30285. normalizedDate = new Date(utils.normalizeDate(date, min, max));
  30286. normalizedDate.setDate(1);
  30287. this.option("currentDate", normalizedDate);
  30288. var zoomLevel = this.option("zoomLevel"),
  30289. isNewView = this._view && !utils.sameView(zoomLevel, normalizedDate, this._view.option("date"));
  30290. if (isNewView) {
  30291. this._view.element().remove();
  30292. delete this._view;
  30293. this._renderView()
  30294. }
  30295. },
  30296. _render: function() {
  30297. this.callBase();
  30298. this.element().addClass(CALENDAR_CLASS);
  30299. this._renderView();
  30300. this._renderFooter();
  30301. this.onContouredChanged = this._createActionByOption("onContouredChanged");
  30302. this.setAria({
  30303. role: "listbox",
  30304. label: Globalize.localize("dxCalendar-ariaWidgetName")
  30305. })
  30306. },
  30307. _renderView: function() {
  30308. this._change = "";
  30309. this._renderBody();
  30310. this._renderSpecificView();
  30311. this._renderNavigator();
  30312. this._renderSwipeable()
  30313. },
  30314. _renderBody: function() {
  30315. if (!this._body) {
  30316. this._body = $("<div>").addClass(CALENDAR_BODY_CLASS);
  30317. this.element().append(this._body)
  30318. }
  30319. },
  30320. _renderSwipeable: function() {
  30321. var that = this;
  30322. if (!this._swipeable)
  30323. this._swipeable = this._createComponent(this.element(), "dxSwipeable", {
  30324. elastic: false,
  30325. onStart: function(e) {
  30326. that._swipeStartHandler(e)
  30327. },
  30328. onUpdated: function(e) {
  30329. that._swipeUpdateHandler(e)
  30330. },
  30331. onEnd: function(e) {
  30332. that._swipeEndHandler(e)
  30333. },
  30334. itemWidthFunc: function() {
  30335. return this.element().width()
  30336. }
  30337. })
  30338. },
  30339. _waitRenderView: function(offset, direction) {
  30340. if (this._alreadyViewRender)
  30341. return;
  30342. this._alreadyViewRender = true;
  30343. this._change = "";
  30344. this._navigate(offset * direction);
  30345. setTimeout($.proxy(function() {
  30346. this._alreadyViewRender = false
  30347. }, this))
  30348. },
  30349. _focusTarget: function() {
  30350. return this.element()
  30351. },
  30352. _focusOutHandler: function() {
  30353. this.callBase.apply(this, arguments);
  30354. this._view.option("contouredDate", undefined)
  30355. },
  30356. _focusInHandler: function() {
  30357. this.callBase.apply(this, arguments);
  30358. this._view.focusInHandler()
  30359. },
  30360. _attachKeyboardEvents: function() {
  30361. this.callBase.apply(this, arguments);
  30362. this._viewKeyboardProcessor = new ui.KeyboardProcessor;
  30363. this._keyboardProcessor.push(this._viewKeyboardProcessor)
  30364. },
  30365. _swipeStartHandler: function(e) {
  30366. if (this._viewsAnimating) {
  30367. e.jQueryEvent.cancel = true;
  30368. return
  30369. }
  30370. this._swipeInProgress = true;
  30371. this._viewsOnLeft = [this._view];
  30372. this._viewsOnRight = [this._view]
  30373. },
  30374. _swipeUpdateHandler: function(e) {
  30375. this._setOffset(e.jQueryEvent.offset);
  30376. if (this._swipeOffset >= 0)
  30377. this._renderViews(this._viewsOnLeft, SWIPE_POSITION.right);
  30378. else
  30379. this._renderViews(this._viewsOnRight, SWIPE_POSITION.left)
  30380. },
  30381. _setOffset: function(offset) {
  30382. var swipeDirection = offset > 0 ? SWIPE_POSITION.right : SWIPE_POSITION.left,
  30383. prevOffset = this._swipeOffset || 0;
  30384. if (swipeDirection * (offset - prevOffset) <= 1)
  30385. this._swipeOffset = offset
  30386. },
  30387. _renderViews: function(viewsArray, swipePosition) {
  30388. var arrayInsertIndex = Math.ceil(swipePosition * this._swipeOffset),
  30389. zoomLevel = this.option("zoomLevel");
  30390. var offset = swipePosition * arrayInsertIndex;
  30391. offset *= utils.getDifferenceInMonth(zoomLevel);
  30392. offset = this.option("rtlEnabled") ? offset : -1 * offset;
  30393. this._initalizeViewDimensions();
  30394. if (!viewsArray[arrayInsertIndex]) {
  30395. this._newDate = new Date(this.option("currentDate"));
  30396. this._newDate.setMonth(this._newDate.getMonth() + offset);
  30397. var $body = this._body,
  30398. $view = $("<div>").appendTo($body);
  30399. viewsArray[arrayInsertIndex] = new ui.dxCalendar.views[zoomLevel]($view, this._viewConfig())
  30400. }
  30401. this._translateViews(viewsArray, swipePosition)
  30402. },
  30403. _translateViews: function(viewsArray, swipePosition) {
  30404. var prevView = viewsArray[Math.floor(swipePosition * this._swipeOffset)],
  30405. nextView = viewsArray[Math.ceil(swipePosition * this._swipeOffset)],
  30406. localOffset = this._swipeOffset % 1;
  30407. this._normalizeViewsPosition();
  30408. DX.translator.move(prevView.element(), {left: this._correctionMovement * localOffset * this._viewWidth});
  30409. if (swipePosition * localOffset >= 0.05)
  30410. DX.translator.move(nextView.element(), {left: this._correctionMovement * (localOffset - swipePosition) * this._viewWidth});
  30411. this._view = this._isInView(prevView, this._viewWidth / 2) ? prevView : nextView;
  30412. this._renderNavigator()
  30413. },
  30414. _normalizeViewsPosition: function() {
  30415. var i;
  30416. for (i = 0; i < this._viewsOnLeft.length; i++)
  30417. DX.translator.move(this._viewsOnLeft[i].element(), {left: -this._correctionMovement * this._viewWidth});
  30418. for (i = 0; i < this._viewsOnRight.length; i++)
  30419. DX.translator.move(this._viewsOnRight[i].element(), {left: this._correctionMovement * this._viewWidth})
  30420. },
  30421. _isDateInInvalidRange: function() {
  30422. if (this._view.isBoundary(this._newDate))
  30423. return;
  30424. var min = this.option("min"),
  30425. max = this.option("max"),
  30426. normalizedDate = utils.normalizeDate(this._newDate, min, max);
  30427. return normalizedDate === min || normalizedDate === max
  30428. },
  30429. _trimUnusedViews: function(viewsArray) {
  30430. var animatedViews = viewsArray.slice(),
  30431. indexCurrentView = $.inArray(this._view, animatedViews) + 1,
  30432. boundaryIndex = this._getBoundaryIndexView(animatedViews);
  30433. animatedViews = animatedViews.splice(0, indexCurrentView + 1);
  30434. animatedViews.splice(0, boundaryIndex);
  30435. this._disposeUnusedViews(viewsArray, indexCurrentView);
  30436. return animatedViews
  30437. },
  30438. _cleanFocusState: function() {
  30439. this.callBase();
  30440. if (this._viewKeyboardProcessor)
  30441. this._viewKeyboardProcessor.dispose()
  30442. },
  30443. _getBoundaryIndexView: function(arrayViews) {
  30444. var length = arrayViews.length;
  30445. for (var i = length - 1; i >= 0; i--) {
  30446. if (!arrayViews[i])
  30447. continue;
  30448. if (this._view.isBoundary(arrayViews[i].option("date")))
  30449. return i
  30450. }
  30451. },
  30452. _disposeUnusedViews: function(arrayViews, index) {
  30453. var length = arrayViews.length;
  30454. for (var i = length - 1; i > index; i--)
  30455. arrayViews[i].element().remove()
  30456. },
  30457. _moveInRange: function(arrayViews, swipePosition) {
  30458. var length = arrayViews.length,
  30459. startOffset = arrayViews[length - 1].element().position().left * swipePosition,
  30460. summaryWidth = startOffset;
  30461. for (var i = length - 1; i >= 0; i--) {
  30462. DX.translator.move(arrayViews[i].element(), {left: this._correctionMovement * summaryWidth * swipePosition});
  30463. summaryWidth += arrayViews[i].element().width()
  30464. }
  30465. summaryWidth -= arrayViews[0].element().width();
  30466. return this._animateToBoundary(arrayViews, summaryWidth, swipePosition)
  30467. },
  30468. _animateToBoundary: function(arrayViews, summaryWidth, swipePosition) {
  30469. this._animation = $.Deferred();
  30470. var length = arrayViews.length;
  30471. for (var i = length - 1; i >= 0; i--) {
  30472. var leftPosition = arrayViews[i].element().position().left;
  30473. this._animateView(arrayViews[i], leftPosition - summaryWidth * swipePosition, ANIMATION_DURATION_ILLEGAL_RANGE * length)
  30474. }
  30475. return this._animation.promise()
  30476. },
  30477. _swipeEndHandler: function(e) {
  30478. var that = this,
  30479. targetOffset = e.jQueryEvent.targetOffset;
  30480. this._viewsAnimating = true;
  30481. var animation,
  30482. isShortSwipe = false;
  30483. if (Math.abs(e.jQueryEvent.offset) < SHOT_SWIPE_OFFSET)
  30484. if (targetOffset === 1 || targetOffset === -1)
  30485. isShortSwipe = true;
  30486. if (this._isDateInInvalidRange()) {
  30487. this._toggleNavigatorDisabled(true);
  30488. this._$footer && this._$footer.toggleClass("dx-state-disabled", true);
  30489. if (this._swipeOffset > 0) {
  30490. animation = this._animatedIllegalRange(that._viewsOnLeft, SWIPE_POSITION.right);
  30491. this._newDate = new Date(this.option("min"))
  30492. }
  30493. else {
  30494. animation = this._animatedIllegalRange(that._viewsOnRight, SWIPE_POSITION.left);
  30495. this._newDate = new Date(this.option("max"))
  30496. }
  30497. }
  30498. else
  30499. animation = this._alignViews(isShortSwipe);
  30500. animation.done(function() {
  30501. that._disposeViews();
  30502. if (!that._isDateInInvalidRange())
  30503. that.option("currentDate", that._view.option("date"));
  30504. that._viewsAnimating = false;
  30505. that._toggleNavigatorDisabled(false);
  30506. that._$footer && that._$footer.toggleClass("dx-state-disabled", false);
  30507. that._normalizedCircledDate(that._view.option("date"))
  30508. });
  30509. this._swipeInProgress = false;
  30510. this._swipeOffset = 0
  30511. },
  30512. _animatedIllegalRange: function(viewsArray, swipeDirection) {
  30513. var animatedViews = this._trimUnusedViews(viewsArray);
  30514. return this._moveInRange(animatedViews, swipeDirection)
  30515. },
  30516. _alignViews: function(isShortSwipe) {
  30517. this._animation = $.Deferred();
  30518. this._swipeOffset = this._swipeOffset || 0;
  30519. var firstVisibleView,
  30520. secondVisibleView;
  30521. if (this._swipeOffset >= 0)
  30522. firstVisibleView = this._viewsOnLeft[Math.floor(Math.abs(this._swipeOffset))],
  30523. secondVisibleView = this._viewsOnLeft[Math.ceil(Math.abs(this._swipeOffset))];
  30524. else
  30525. firstVisibleView = this._viewsOnRight[Math.ceil(Math.abs(this._swipeOffset))],
  30526. secondVisibleView = this._viewsOnRight[Math.floor(Math.abs(this._swipeOffset))];
  30527. if (this._isInView(firstVisibleView, this._viewWidth / 2))
  30528. if (isShortSwipe)
  30529. this._arrangeViews(secondVisibleView, firstVisibleView, SWIPE_POSITION.right);
  30530. else
  30531. this._arrangeViews(firstVisibleView, secondVisibleView, SWIPE_POSITION.left);
  30532. else if (isShortSwipe)
  30533. this._arrangeViews(firstVisibleView, secondVisibleView, SWIPE_POSITION.left);
  30534. else
  30535. this._arrangeViews(secondVisibleView, firstVisibleView, SWIPE_POSITION.right);
  30536. this._renderNavigator();
  30537. return this._animation.promise()
  30538. },
  30539. _arrangeViews: function(firstView, secondView, swipePosition) {
  30540. this._centerView(firstView);
  30541. this._animateView(secondView, swipePosition * this._viewWidth, MONTH_VIEW_ANIMATION_DURATION)
  30542. },
  30543. _animateView: function(view, to, duration) {
  30544. var that = this;
  30545. fx.animate(view.element(), {
  30546. type: "slide",
  30547. from: {left: view.element().position().left},
  30548. to: {left: to},
  30549. duration: duration,
  30550. complete: function() {
  30551. that._animation.resolve()
  30552. }
  30553. })
  30554. },
  30555. _centerView: function(view) {
  30556. this._animateView(view, 0, MONTH_VIEW_ANIMATION_DURATION);
  30557. this._view = view
  30558. },
  30559. _isInView: function(view, point) {
  30560. var $element = view.element(),
  30561. left = $element.position().left;
  30562. return point > left && point <= left + $element.width()
  30563. },
  30564. _disposeViews: function() {
  30565. var i;
  30566. for (i = 0; i < this._viewsOnLeft.length; i++)
  30567. if (this._viewsOnLeft[i] !== this._view)
  30568. this._viewsOnLeft[i].element().remove();
  30569. for (i = 0; i < this._viewsOnRight.length; i++)
  30570. if (this._viewsOnRight[i] !== this._view)
  30571. this._viewsOnRight[i].element().remove();
  30572. this._viewsOnLeft = [];
  30573. this._viewsOnRight = []
  30574. },
  30575. _renderFooter: function() {
  30576. var that = this,
  30577. showTodayButton = this.option("showTodayButton");
  30578. if (showTodayButton) {
  30579. var $todayButton = this._createComponent($("<a>"), "dxButton", {
  30580. focusStateEnabled: false,
  30581. text: Globalize.localize("dxCalendar-todayButtonText"),
  30582. onClick: function() {
  30583. that._toTodayView()
  30584. },
  30585. _templates: {}
  30586. }).element().addClass(CALENDAR_TODAY_BUTTON_CLASS);
  30587. this._$footer = $("<div>").addClass(CALENDAR_FOOTER_CLASS).append($todayButton);
  30588. this.element().append(this._$footer)
  30589. }
  30590. this.element().toggleClass(CALENDAR_HAS_FOOTER_CLASS, showTodayButton)
  30591. },
  30592. _toTodayView: function() {
  30593. var today = new Date;
  30594. if (!this._isMaxZoomLevel()) {
  30595. this.option("currentDate", today);
  30596. this.option("zoomLevel", this.option("maxZoomLevel"));
  30597. this._animateShowView();
  30598. this.option("value", today);
  30599. return
  30600. }
  30601. var currentDate = this._view.option("date"),
  30602. offset = 0;
  30603. offset += (today.getFullYear() - currentDate.getFullYear()) * 12;
  30604. offset += today.getMonth() - currentDate.getMonth();
  30605. if (!offset) {
  30606. this.option("value", today);
  30607. return
  30608. }
  30609. this._addPrevView(today);
  30610. this._animateNavigation(offset).done($.proxy(function() {
  30611. this._clearPrevView();
  30612. this.option("value", new Date)
  30613. }, this))
  30614. },
  30615. _isMaxZoomLevel: function() {
  30616. return this.option("zoomLevel") === this.option("maxZoomLevel")
  30617. },
  30618. _renderNavigator: function() {
  30619. if (!this._navigator) {
  30620. var $navigator = $("<div>").prependTo(this.element());
  30621. this._navigator = new ui.dxCalendar.Navigator($navigator, this._navigatorConfig())
  30622. }
  30623. this._navigator.option("text", this._view._getNavigatorCaption());
  30624. this._updateButtonsVisibility()
  30625. },
  30626. _updateButtonsVisibility: function() {
  30627. var viewType = this.option("zoomLevel"),
  30628. isRTL = this.option("rtlEnabled"),
  30629. difference = isRTL ? -1 * utils.getDifferenceInMonth(viewType) : 1 * utils.getDifferenceInMonth(viewType);
  30630. this._navigator.toggleButton("next", !this._view.canNavigate(difference));
  30631. this._navigator.toggleButton("prev", !this._view.canNavigate(-difference))
  30632. },
  30633. _navigatorConfig: function() {
  30634. return {
  30635. text: this._view._getNavigatorCaption(),
  30636. onClick: $.proxy(this._navigatorClickHandler, this),
  30637. onCaptionClick: $.proxy(this._navigateUp, this),
  30638. rtlEnabled: this.option("rtlEnabled")
  30639. }
  30640. },
  30641. _navigatorClickHandler: function(e) {
  30642. var viewType = this.option("zoomLevel"),
  30643. difference = utils.getDifferenceInMonth(viewType),
  30644. deltaDifference = difference * e.direction;
  30645. this._navigate(deltaDifference)
  30646. },
  30647. _isMinZoomLevel: function(zoomLevel) {
  30648. var min = this.option("min"),
  30649. max = this.option("max");
  30650. return utils.sameView(zoomLevel, min, max) || this.option("minZoomLevel") === zoomLevel
  30651. },
  30652. _navigateUp: function() {
  30653. var zoomLevel = this.option("zoomLevel"),
  30654. nextView = utils.getViewUp(zoomLevel);
  30655. if (!nextView || this._isMinZoomLevel(zoomLevel))
  30656. return;
  30657. this._contouredStack = this._contouredStack || [];
  30658. var contouredDate = this._view.option("contouredDate");
  30659. contouredDate && this._contouredStack.push(contouredDate);
  30660. this.option("currentDate", contouredDate || this._view.option("date"));
  30661. this.option("zoomLevel", nextView);
  30662. this._animateShowView()
  30663. },
  30664. _navigateDown: function(cell) {
  30665. var zoomLevel = this.option("zoomLevel");
  30666. if (this._isMaxZoomLevel())
  30667. return;
  30668. var nextView = utils.getViewDown(zoomLevel);
  30669. if (!nextView)
  30670. return;
  30671. var newCurrentDate = this._view.option("contouredDate") || this._view.option("date");
  30672. if (cell)
  30673. newCurrentDate = $(cell).data(CALENDAR_DATE_VALUE_KEY);
  30674. this.option("currentDate", newCurrentDate);
  30675. this.option("zoomLevel", nextView);
  30676. this._animateShowView();
  30677. if (this._contouredStack && this._contouredStack.length > 0) {
  30678. var circledDate = this._view.getCircledDate(newCurrentDate, this._contouredStack);
  30679. this._normalizedCircledDate(circledDate);
  30680. this._view.option("contouredDate", circledDate);
  30681. return
  30682. }
  30683. this._normalizedCircledDate(newCurrentDate);
  30684. this._view.option("contouredDate", newCurrentDate)
  30685. },
  30686. _animateShowView: function() {
  30687. fx.stop(this._view.element(), true);
  30688. this._viewsAnimating = true;
  30689. this._popAnimationView(this._view, POP_ANIMATION_FROM, POP_ANIMATION_TO, ANIMATION_DURATION_SHOW_VIEW).done($.proxy(function() {
  30690. this._viewsAnimating = false;
  30691. this._view.moveContouredDate(0)
  30692. }, this))
  30693. },
  30694. _toggleNavigatorDisabled: function(state) {
  30695. this._navigator && this._navigator.option("disabled", state)
  30696. },
  30697. _popAnimationView: function(view, from, to, duration) {
  30698. return fx.animate(view.element(), {
  30699. type: "pop",
  30700. from: {
  30701. scale: from,
  30702. opacity: from
  30703. },
  30704. to: {
  30705. scale: to,
  30706. opacity: to
  30707. },
  30708. duration: duration
  30709. })
  30710. },
  30711. _renderSpecificView: function() {
  30712. var specificView = ui.dxCalendar.views[this.option("zoomLevel")],
  30713. $body = this._body,
  30714. $view = $("<div>").appendTo($body);
  30715. this._view = new specificView($view, this._viewConfig());
  30716. this.element().addClass("dx-calendar-view-" + this.option("zoomLevel"));
  30717. this._correctionMovement = DX.browser.msie && this.option("rtlEnabled") ? -1 : 1
  30718. },
  30719. _viewConfig: function() {
  30720. return {
  30721. date: this._swipeInProgress ? this._newDate : this.option("currentDate"),
  30722. min: this.option("min"),
  30723. max: this.option("max"),
  30724. firstDayOfWeek: this.option("firstDayOfWeek"),
  30725. value: this.option("value"),
  30726. rtl: this.option("rtlEnabled"),
  30727. disabled: this.option("disabled") || DevExpress.designMode,
  30728. _keyboardProcessor: this._viewKeyboardProcessor,
  30729. tabIndex: undefined,
  30730. focusStateEnabled: this.option("focusStateEnabled"),
  30731. hoverStateEnabled: this.option("hoverStateEnabled"),
  30732. onValueChanged: $.proxy(this._viewValueChangedHandler, this),
  30733. onContouredDateChanged: $.proxy(this._viewContouredChangedHandler, this),
  30734. onCellClick: $.proxy(this._handlerOnCellClick, this),
  30735. cellTemplate: this._getTemplateByOption("cellTemplate"),
  30736. allowValueSelection: this._isMaxZoomLevel()
  30737. }
  30738. },
  30739. _cellClickHandler: function(e) {
  30740. this._cellClickAction({jQueryEvent: e})
  30741. },
  30742. _handlerOnCellClick: function(e) {
  30743. var zoomLevel = this.option("zoomLevel"),
  30744. nextView = utils.getViewDown(zoomLevel);
  30745. var _isMaxZoomLevel = this._isMaxZoomLevel();
  30746. if (nextView && !_isMaxZoomLevel) {
  30747. var target = e.jQueryEvent.currentTarget;
  30748. this._navigateDown(target)
  30749. }
  30750. else
  30751. this._cellClickOptionAction(e)
  30752. },
  30753. _viewValueChangedHandler: function(e) {
  30754. if (this._isMaxZoomLevel())
  30755. this.option("value", e.value)
  30756. },
  30757. _viewContouredChangedHandler: function(e) {
  30758. var date = e.value,
  30759. currentDate = this.option("currentDate"),
  30760. zoomLevel = this.option("zoomLevel"),
  30761. isSameView = utils.sameView(zoomLevel, currentDate, date);
  30762. this.setAria("activedescendant", e.ariaId);
  30763. this.onContouredChanged && this.onContouredChanged(e.ariaId);
  30764. if (date && !isSameView && !this._isAlreadyNavigated && (this._isMaxZoomLevel() || this._change === "key" || this._change === "upDownArrow")) {
  30765. var dir = utils.getFirstMonthDate(date) > currentDate ? 1 : -1,
  30766. difference = utils.getDifferenceInMonth(zoomLevel) * dir;
  30767. this._isAlreadyNavigated = true;
  30768. this._navigate(difference)
  30769. }
  30770. },
  30771. _normalizedCircledDate: function(date) {
  30772. var $cell;
  30773. if (this._view.isBoundary(date)) {
  30774. var zoomLevel = this.option("zoomLevel"),
  30775. $cells = this._view.$body.find("." + CALENDAR_CELL_CLASS).not("." + CALENDAR_EMPTY_CELL_CLASS);
  30776. var min = this.option("min"),
  30777. max = this.option("max");
  30778. if (utils.sameView(zoomLevel, min, max))
  30779. $cell = Math.abs(min - date) > Math.abs(max - date) ? $cells.last() : $cells.first();
  30780. else if (utils.sameView(zoomLevel, date, min))
  30781. $cell = $cells.first();
  30782. else if (utils.sameView(zoomLevel, date, max))
  30783. $cell = $cells.last();
  30784. date = $cell ? $cell.data(CALENDAR_DATE_VALUE_KEY) : date;
  30785. this._view.option("contouredDate", date);
  30786. return
  30787. }
  30788. var currentDate = this.option("currentDate");
  30789. $cell = this._view._getCellByDate(utils.getShortDate(date));
  30790. if (!$cell.length && !utils.dateInRange(date, this.option("min"), this.option("max"))) {
  30791. this._view.option("contouredDate", currentDate);
  30792. return
  30793. }
  30794. if (!$cell.hasClass(CALENDAR_EMPTY_CELL_CLASS)) {
  30795. this._view.option("contouredDate", date);
  30796. return
  30797. }
  30798. this._view.option("contouredDate", date)
  30799. },
  30800. _initalizeViewDimensions: function() {
  30801. this._viewWidth = this._viewWidth || this._body.width();
  30802. this._viewHeight = this._viewHeight || this._body.height()
  30803. },
  30804. _navigate: function(difference) {
  30805. if (this._view.canNavigate(difference)) {
  30806. var currentDate = this.option("currentDate"),
  30807. newDate = new Date(currentDate);
  30808. var circledDate;
  30809. newDate.setMonth(currentDate.getMonth() + difference);
  30810. utils.fixTimezoneGap(currentDate, newDate);
  30811. circledDate = this._view.getNextCircledDate(difference);
  30812. if (this._change === "upDownArrow")
  30813. circledDate = this._view.option("contouredDate");
  30814. if (this._change === "key") {
  30815. var zoomLevel = this.option("zoomLevel");
  30816. circledDate = difference < 0 ? utils.getLastDateView(zoomLevel, newDate) : utils.getFirstDateView(zoomLevel, newDate)
  30817. }
  30818. this._changeView(newDate, difference);
  30819. this._normalizedCircledDate(circledDate)
  30820. }
  30821. },
  30822. _changeView: function(newDate, difference) {
  30823. var that = this;
  30824. if (fx.isAnimating(this._view.element())) {
  30825. this._stopCurrentAnimation();
  30826. this._prevView && this._prevView.element().remove()
  30827. }
  30828. this._addPrevView(newDate);
  30829. this._animateNavigation(difference).done(function() {
  30830. that._clearPrevView();
  30831. that._isAlreadyNavigated = false
  30832. })
  30833. },
  30834. _clearPrevView: function() {
  30835. this._prevView.element().remove();
  30836. delete this._prevView
  30837. },
  30838. _addPrevView: function(date) {
  30839. var $view = $("<div>");
  30840. this._prevView = new ui.dxCalendar.views[this.option("zoomLevel")]($view, this._viewConfig());
  30841. this._body.append(this._prevView.element());
  30842. this.option("currentDate", date)
  30843. },
  30844. _stopCurrentAnimation: function() {
  30845. this._prevView && fx.stop(this._prevView.element(), true);
  30846. fx.stop(this._view.element(), true)
  30847. },
  30848. _animateNavigation: function(difference) {
  30849. this._animation = $.Deferred();
  30850. this._initalizeViewDimensions();
  30851. var navDirection = difference < 0 ? -1 : 1;
  30852. DX.translator.move(this._view.element(), {left: this._correctionMovement * navDirection * this._viewWidth});
  30853. this._animateView(this._view, 0, MONTH_VIEW_ANIMATION_DURATION);
  30854. this._animateView(this._prevView, -navDirection * this._viewWidth, MONTH_VIEW_ANIMATION_DURATION);
  30855. return this._animation.promise()
  30856. },
  30857. _clean: function() {
  30858. this.callBase();
  30859. delete this._body;
  30860. delete this._navigator;
  30861. delete this._$footer;
  30862. delete this._viewWidth;
  30863. delete this._viewHeight
  30864. },
  30865. _optionChanged: function(args) {
  30866. var value = args.value;
  30867. switch (args.name) {
  30868. case"min":
  30869. case"max":
  30870. case"firstDayOfWeek":
  30871. var date = this.option("value");
  30872. date = date ? new Date(date) : new Date;
  30873. this._updateCurrentDate(date);
  30874. this._view.element().remove();
  30875. this._renderView();
  30876. break;
  30877. case"currentDate":
  30878. this._updateCurrentDate(value);
  30879. break;
  30880. case"zoomLevel":
  30881. this.element().removeClass("dx-calendar-view-" + args.previousValue);
  30882. this._correctZoomLevel();
  30883. this._view.element().remove();
  30884. delete this._view;
  30885. this._renderView();
  30886. this._updateButtonsVisibility();
  30887. break;
  30888. case"minZoomLevel":
  30889. case"maxZoomLevel":
  30890. this._correctZoomLevel();
  30891. this._updateButtonsVisibility();
  30892. break;
  30893. case"value":
  30894. this._updateCurrentDate(value ? new Date(value) : new Date);
  30895. this._view.option("value", value ? new Date(value) : null);
  30896. this.callBase(args);
  30897. break;
  30898. case"disabled":
  30899. this._view.option("disabled", value);
  30900. this.callBase(args);
  30901. break;
  30902. case"showTodayButton":
  30903. this._invalidate();
  30904. break;
  30905. case"onCellClick":
  30906. this._view.option("onCellClick", value);
  30907. break;
  30908. case"onContouredChanged":
  30909. this.onContouredChanged = this._createActionByOption("onContouredChanged");
  30910. break;
  30911. case"cellTemplate":
  30912. this._invalidate();
  30913. break;
  30914. default:
  30915. this.callBase(args)
  30916. }
  30917. }
  30918. }))
  30919. })(jQuery, DevExpress);
  30920. /*! Module widgets-base, file ui.calendar.views.js */
  30921. (function($, DX, undefined) {
  30922. var ui = DX.ui,
  30923. events = ui.events,
  30924. utils = DX.utils,
  30925. CALENDAR_OTHER_MONTH_CLASS = "dx-calendar-other-month",
  30926. CALENDAR_OTHER_VIEW_CLASS = "dx-calendar-other-view",
  30927. CALENDAR_CELL_CLASS = "dx-calendar-cell",
  30928. CALENDAR_EMPTY_CELL_CLASS = "dx-calendar-empty-cell",
  30929. CALENDAR_TODAY_CLASS = "dx-calendar-today",
  30930. CALENDAR_SELECTED_DATE_CLASS = "dx-calendar-selected-date",
  30931. CALENDAR_CONTOURED_DATE_CLASS = "dx-calendar-contoured-date",
  30932. CALENDAR_DXCLICK_EVENT_NAME = events.addNamespace("dxclick", "dxCalendar"),
  30933. CALENDAR_DATE_VALUE_KEY = "dxDateValueKey",
  30934. CALENDAR_VIEW_NAME_PREFIX = "CalendarView";
  30935. ui.dxCalendar.BaseView = ui.Widget.inherit({
  30936. NAME: CALENDAR_VIEW_NAME_PREFIX + "Base",
  30937. _setDefaultOptions: function() {
  30938. this.callBase();
  30939. this.option({
  30940. date: new Date,
  30941. focusStateEnabled: false,
  30942. cellTemplate: null,
  30943. onCellClick: null,
  30944. rowCount: 3,
  30945. colCount: 4,
  30946. allowValueSelection: true,
  30947. onValueChanged: null,
  30948. onContouredDateChanged: null
  30949. })
  30950. },
  30951. _init: function() {
  30952. this.callBase();
  30953. var value = this.option("value"),
  30954. contouredDate = this.option("contouredDate");
  30955. if (contouredDate)
  30956. this.option("contouredDate", this._calculateContouredDate(contouredDate));
  30957. this.option("value", new Date(value));
  30958. if (!this.option("value").valueOf())
  30959. this.option("value", new Date(0, 0, 0, 0, 0, 0));
  30960. this._initActions()
  30961. },
  30962. _initActions: function() {
  30963. this._createCellClickOptionAction();
  30964. this._createCellClickAction();
  30965. this._valueChangedAction = this._createActionByOption("onValueChanged");
  30966. this._contouredDateChangedAction = this._createActionByOption("onContouredDateChanged")
  30967. },
  30968. _render: function() {
  30969. this.callBase();
  30970. this._renderImpl()
  30971. },
  30972. _renderImpl: function() {
  30973. this._$table = $("<table>");
  30974. this._renderBody();
  30975. this._renderContouredDate();
  30976. this._renderValue();
  30977. var cellClickAction = this._createAction($.proxy(function(e) {
  30978. this._cellClickHandler(e.jQueryEvent)
  30979. }, this));
  30980. this._$table.off(CALENDAR_DXCLICK_EVENT_NAME).on(CALENDAR_DXCLICK_EVENT_NAME, "td", function(e) {
  30981. cellClickAction({jQueryEvent: e})
  30982. });
  30983. this.element().off("beforeactivate").on("beforeactivate", function(e) {
  30984. e.preventDefault()
  30985. });
  30986. this.element().append(this._$table)
  30987. },
  30988. _renderBody: function() {
  30989. this.$body = $("<tbody>").appendTo(this._$table);
  30990. var that = this,
  30991. cellTemplate = this.option("cellTemplate");
  30992. function renderCell(cellIndex) {
  30993. var cellDate = that._getCellData(indexRow, cellIndex);
  30994. var $cell = $("<td>").appendTo($row).addClass(CALENDAR_CELL_CLASS).toggleClass(CALENDAR_TODAY_CLASS, that._isTodayCell(cellDate)).toggleClass(CALENDAR_EMPTY_CELL_CLASS, that._isDateOutOfRange(cellDate)).toggleClass(CALENDAR_OTHER_VIEW_CLASS, that._isOtherView(cellDate)).attr("data-value", utils.getShortDate(cellDate)).data(CALENDAR_DATE_VALUE_KEY, cellDate);
  30995. that.setAria({
  30996. role: "option",
  30997. label: that._getCellAriaLabel(cellDate)
  30998. }, $cell);
  30999. if (cellTemplate)
  31000. cellTemplate.render({text: that._getCellText(cellDate)}, $cell, cellIndex);
  31001. else
  31002. $cell.text(that._getCellText(cellDate))
  31003. }
  31004. for (var indexRow = 0, len = this.option("rowCount"); indexRow < len; indexRow++) {
  31005. var $row = $("<tr>").appendTo(this.$body);
  31006. this._iterateCells(renderCell)
  31007. }
  31008. },
  31009. _iterateCells: function(delegate) {
  31010. var rtl = this.option("rtl"),
  31011. colCount = this.option("colCount"),
  31012. i = rtl ? colCount - 1 : 0;
  31013. while (rtl ? i >= 0 : i < colCount) {
  31014. delegate(i);
  31015. rtl ? --i : ++i
  31016. }
  31017. },
  31018. _isTodayCell: DX.abstract,
  31019. _isDateOutOfRange: DX.abstract,
  31020. _isOtherView: DX.abstract,
  31021. _getCellText: DX.abstract,
  31022. _getCellData: DX.abstract,
  31023. _supportedKeys: function() {
  31024. this._difference = utils.getDifferenceInMonthForCells(this._getViewName());
  31025. return $.extend(this.callBase(), {
  31026. leftArrow: this._leftArrowHandler,
  31027. rightArrow: this._rightArrowHandler,
  31028. upArrow: this._upArrowHandler,
  31029. downArrow: this._downArrowHandler,
  31030. enter: this._enterHandler,
  31031. home: this._homeHandler,
  31032. end: this._endHandler
  31033. })
  31034. },
  31035. _homeHandler: function(e) {
  31036. e.preventDefault();
  31037. var date = this.option("date"),
  31038. currentView = this._getViewName();
  31039. if (utils[DX.inflector.camelize("same " + currentView)](date, new Date(this.option("min")))) {
  31040. var $cell = this.$body.find("." + CALENDAR_CELL_CLASS).not("." + CALENDAR_EMPTY_CELL_CLASS).first();
  31041. this.option("contouredDate", $cell.data(CALENDAR_DATE_VALUE_KEY))
  31042. }
  31043. else
  31044. this.option("contouredDate", utils.getFirstDateView(currentView, date));
  31045. this._renderContouredDate()
  31046. },
  31047. _endHandler: function(e) {
  31048. e.preventDefault();
  31049. var date = this.option("date"),
  31050. currentView = this._getViewName();
  31051. if (utils[DX.inflector.camelize("same " + currentView)](date, new Date(this.option("max")))) {
  31052. var $cell = this.$body.find("." + CALENDAR_CELL_CLASS).not("." + CALENDAR_EMPTY_CELL_CLASS).last();
  31053. this.option("contouredDate", $cell.data(CALENDAR_DATE_VALUE_KEY))
  31054. }
  31055. else
  31056. this.option("contouredDate", utils.getLastDateView(currentView, date));
  31057. this._renderContouredDate()
  31058. },
  31059. _getViewName: function() {
  31060. var startPos = CALENDAR_VIEW_NAME_PREFIX.length,
  31061. name = this.NAME;
  31062. name = name.substr(startPos, name.length);
  31063. return name.toLowerCase()
  31064. },
  31065. _leftArrowHandler: function(e) {
  31066. e.preventDefault();
  31067. this.moveContouredDate(this.option("rtl") ? 1 * this._difference : -1 * this._difference)
  31068. },
  31069. _rightArrowHandler: function(e) {
  31070. e.preventDefault();
  31071. this.moveContouredDate(this.option("rtl") ? -1 * this._difference : 1 * this._difference)
  31072. },
  31073. _upArrowHandler: function(e) {
  31074. e.preventDefault();
  31075. this.moveContouredDate(-this.option("colCount") * this._difference)
  31076. },
  31077. _downArrowHandler: function(e) {
  31078. e.preventDefault();
  31079. this.moveContouredDate(this.option("colCount") * this._difference)
  31080. },
  31081. _enterHandler: function() {
  31082. this.option("value", this.option("contouredDate"))
  31083. },
  31084. _renderContouredDate: function() {
  31085. if (!this.option("focusStateEnabled"))
  31086. return;
  31087. var contouredDate = this.option("contouredDate"),
  31088. $oldContouredCell = this._$table.find("." + CALENDAR_CONTOURED_DATE_CLASS),
  31089. $newContouredCell = this._getCellByDate(contouredDate);
  31090. $oldContouredCell.removeClass(CALENDAR_CONTOURED_DATE_CLASS);
  31091. $newContouredCell.addClass(CALENDAR_CONTOURED_DATE_CLASS);
  31092. this._ariaId = new DevExpress.data.Guid;
  31093. this.setAria({
  31094. id: undefined,
  31095. selected: undefined
  31096. }, $oldContouredCell);
  31097. this.setAria({
  31098. id: this._ariaId,
  31099. selected: true
  31100. }, $newContouredCell)
  31101. },
  31102. _dispose: function() {
  31103. this._keyboardProcessor = undefined;
  31104. this.callBase()
  31105. },
  31106. _createCellClickOptionAction: function() {
  31107. this._cellClickOptionAction = this._createActionByOption("onCellClick")
  31108. },
  31109. _cellClickHandler: function(e) {
  31110. this._cellClickAction({jQueryEvent: e})
  31111. },
  31112. _createCellClickAction: function(e) {
  31113. this._cellClickAction = this._createAction($.proxy(function(e) {
  31114. var $currentTarget = $(e.jQueryEvent.currentTarget);
  31115. if (!$currentTarget.hasClass(CALENDAR_EMPTY_CELL_CLASS)) {
  31116. var cellDate = $currentTarget.data(CALENDAR_DATE_VALUE_KEY);
  31117. this._changeValue(cellDate);
  31118. this._cellClickOptionAction(e)
  31119. }
  31120. }, this))
  31121. },
  31122. _fitContouredCell: function(value, prevValue) {
  31123. var $cell = this._getCellByDate(utils.getShortDate(value));
  31124. if ($cell.hasClass(CALENDAR_EMPTY_CELL_CLASS))
  31125. this.option("contouredDate", prevValue)
  31126. },
  31127. _changeValue: function(cellDate) {
  31128. if (cellDate) {
  31129. var value = this.option("value"),
  31130. newValue = value ? new Date(value) : new Date;
  31131. newValue.setDate(cellDate.getDate());
  31132. newValue.setMonth(cellDate.getMonth());
  31133. newValue.setFullYear(cellDate.getFullYear());
  31134. newValue.setDate(cellDate.getDate());
  31135. this.option("value", newValue)
  31136. }
  31137. else
  31138. this.option("value", null)
  31139. },
  31140. _renderValue: function() {
  31141. if (!this.option("allowValueSelection"))
  31142. return;
  31143. var value = this.option("value"),
  31144. selectedCell = this._getCellByDate(value);
  31145. if (this._selectedCell)
  31146. this._selectedCell.removeClass(CALENDAR_SELECTED_DATE_CLASS);
  31147. selectedCell.addClass(CALENDAR_SELECTED_DATE_CLASS);
  31148. this._selectedCell = selectedCell
  31149. },
  31150. _getCellAriaLabel: $.noop,
  31151. getNextCircledDate: function(difference) {
  31152. var circledDate = this.option("contouredDate") && new Date(this.option("contouredDate"));
  31153. if (circledDate)
  31154. circledDate.setMonth(circledDate.getMonth() + difference);
  31155. return circledDate
  31156. },
  31157. focusInHandler: DX.abstract,
  31158. canNavigate: DX.abstract,
  31159. moveContouredDate: DX.abstract,
  31160. isBoundary: DX.abstract,
  31161. _optionChanged: function(args) {
  31162. var name = args.name;
  31163. switch (name) {
  31164. case"value":
  31165. this.option("contouredDate", args.value);
  31166. this._renderValue();
  31167. this._valueChangedAction({
  31168. jQueryEvent: undefined,
  31169. value: args.value,
  31170. previousValue: args.previousValue
  31171. });
  31172. break;
  31173. case"contouredDate":
  31174. this._fitContouredCell(args.value, args.previousValue);
  31175. this._renderContouredDate();
  31176. this._contouredDateChangedAction({
  31177. jQueryEvent: undefined,
  31178. value: args.value,
  31179. previousValue: args.previousValue,
  31180. ariaId: this._ariaId
  31181. });
  31182. break;
  31183. case"onCellClick":
  31184. this._createCellClickOptionAction();
  31185. break;
  31186. case"cellTemplate":
  31187. this._invalidate();
  31188. break;
  31189. case"onValueChanged":
  31190. case"onContouredDateChanged":
  31191. break;
  31192. default:
  31193. this.callBase(args)
  31194. }
  31195. }
  31196. });
  31197. ui.dxCalendar.views = {
  31198. month: ui.dxCalendar.BaseView.inherit({
  31199. NAME: CALENDAR_VIEW_NAME_PREFIX + "Month",
  31200. _setDefaultOptions: function() {
  31201. this.callBase();
  31202. this.option({
  31203. firstDayOfWeek: undefined,
  31204. rowCount: 6,
  31205. colCount: 7
  31206. })
  31207. },
  31208. _renderImpl: function() {
  31209. this.callBase();
  31210. this._renderHeader()
  31211. },
  31212. _renderBody: function() {
  31213. this.callBase();
  31214. this._$table.find("." + CALENDAR_OTHER_VIEW_CLASS).addClass(CALENDAR_OTHER_MONTH_CLASS)
  31215. },
  31216. _renderFocusTarget: $.noop,
  31217. _getCellAriaLabel: function(date) {
  31218. return Globalize.format(date, "D")
  31219. },
  31220. _renderHeader: function() {
  31221. var that = this,
  31222. $header = $("<thead>").prependTo(this._$table),
  31223. $headerRow = $("<tr>").appendTo($header);
  31224. this._iterateCells(function(i) {
  31225. $("<th>").text(that._getDayCaption(that._getFirstDayOfWeek() + i)).appendTo($headerRow)
  31226. })
  31227. },
  31228. _getNavigatorCaption: function() {
  31229. var navigatorMonth = Globalize.culture().calendar.months.names[this.option("date").getMonth()],
  31230. navigatorYear = this.option("date").getFullYear();
  31231. return this.option("rtl") ? navigatorYear + " " + navigatorMonth : navigatorMonth + " " + navigatorYear
  31232. },
  31233. _isTodayCell: function(cellDate) {
  31234. var today = new Date;
  31235. return utils.sameMonthAndYear(cellDate, today) && cellDate.getDate() === today.getDate()
  31236. },
  31237. _isDateOutOfRange: function(cellDate) {
  31238. var minDate = this.option("min"),
  31239. maxDate = this.option("max");
  31240. return !utils.dateInRange(cellDate, minDate, maxDate)
  31241. },
  31242. _isOtherView: function(cellDate) {
  31243. return cellDate.getMonth() !== this.option("date").getMonth()
  31244. },
  31245. _getCellText: function(cellDate) {
  31246. return cellDate.getDate()
  31247. },
  31248. _getDayCaption: function(day) {
  31249. var daysInWeek = this.option("colCount");
  31250. return Globalize.culture().calendar.days.namesAbbr[day % daysInWeek]
  31251. },
  31252. _getCellData: function(week, day) {
  31253. var firstDay = utils.getFirstMonthDate(this.option("date")),
  31254. firstMonthDayPosition = firstDay.getDay() - this._getFirstDayOfWeek(),
  31255. daysInWeek = this.option("colCount"),
  31256. firstWeekDay = daysInWeek * week - firstMonthDayPosition;
  31257. firstWeekDay = firstMonthDayPosition < 0 ? firstWeekDay - daysInWeek : firstWeekDay;
  31258. firstDay.setDate(firstDay.getDate() + firstWeekDay + day);
  31259. return firstDay
  31260. },
  31261. _getFirstDayOfWeek: function() {
  31262. return this.option("firstDayOfWeek") || Globalize.culture().calendar.firstDay
  31263. },
  31264. moveContouredDate: function(difference) {
  31265. var circledDate = this.option("contouredDate"),
  31266. contouredDate = circledDate || this._calculateContouredDate(circledDate),
  31267. newContouredDate = new Date(contouredDate.getFullYear(), contouredDate.getMonth(), contouredDate.getDate() + difference);
  31268. utils.fixTimezoneGap(contouredDate, newContouredDate);
  31269. this.option("contouredDate", newContouredDate)
  31270. },
  31271. _calculateContouredDate: function(contouredDate) {
  31272. var calculatedContouredDate = null,
  31273. date = this.option("date"),
  31274. value = this.option("value");
  31275. if (utils.sameMonthAndYear(contouredDate, date))
  31276. calculatedContouredDate = contouredDate;
  31277. else if (utils.sameMonthAndYear(value, date))
  31278. calculatedContouredDate = value;
  31279. return calculatedContouredDate || utils.getFirstMonthDate(date)
  31280. },
  31281. focusInHandler: function() {
  31282. this.option("contouredDate", this._calculateContouredDate(this.option("contouredDate")))
  31283. },
  31284. canNavigate: function(difference) {
  31285. var date = new Date(this.option("date"));
  31286. var testCurrentDate = difference < 0 ? new Date(date.getFullYear(), date.getMonth() + difference + 1, 0) : new Date(date.getFullYear(), date.getMonth() + difference, 1);
  31287. return utils.dateInRange(testCurrentDate, this.option("min"), this.option("max"))
  31288. },
  31289. _getCellByDate: function(date) {
  31290. return this._$table.find("td[data-value='" + utils.getShortDate(date) + "']")
  31291. },
  31292. isBoundary: function(date) {
  31293. return utils.sameMonthAndYear(date, this.option("min")) || utils.sameMonthAndYear(date, this.option("max"))
  31294. },
  31295. getNextCircledDate: function(difference) {
  31296. var circledDate = this.option("contouredDate") && new Date(this.option("contouredDate"));
  31297. if (circledDate) {
  31298. var currentDay = circledDate.getDate();
  31299. circledDate.setDate(1);
  31300. circledDate.setMonth(circledDate.getMonth() + difference);
  31301. var lastDayMonth = utils.getLastMonthDate(circledDate).getDate();
  31302. currentDay > lastDayMonth ? circledDate.setDate(lastDayMonth) : circledDate.setDate(currentDay)
  31303. }
  31304. return circledDate
  31305. },
  31306. getCircledDate: function(currentDate, contouredStack) {
  31307. var lastContour = contouredStack.pop(),
  31308. day = lastContour.getDate(),
  31309. circled = new Date(currentDate);
  31310. circled.setDate(day);
  31311. return circled
  31312. }
  31313. }),
  31314. year: ui.dxCalendar.BaseView.inherit({
  31315. NAME: CALENDAR_VIEW_NAME_PREFIX + "Year",
  31316. _isTodayCell: function(cellDate) {
  31317. return utils.sameMonthAndYear(cellDate, new Date)
  31318. },
  31319. _isDateOutOfRange: function(cellDate) {
  31320. return !utils.dateInRange(cellDate, utils.getFirstMonthDate(this.option("min")), utils.getLastMonthDate(this.option("max")))
  31321. },
  31322. _isOtherView: function(cellDate) {
  31323. return false
  31324. },
  31325. _getCellText: function(cellDate) {
  31326. return Globalize.culture().calendar.months.names[cellDate.getMonth()].slice(0, 3)
  31327. },
  31328. _getCellData: function(indexRow, cellIndex) {
  31329. var data = new Date(this.option("date")),
  31330. colCount = this.option("colCount");
  31331. data.setDate(1);
  31332. data.setMonth(indexRow * colCount + cellIndex);
  31333. return data
  31334. },
  31335. _getCellByDate: function(date) {
  31336. var foundDate = new Date(date);
  31337. foundDate.setDate(1);
  31338. return this._$table.find("td[data-value='" + utils.getShortDate(foundDate) + "']")
  31339. },
  31340. _getCellAriaLabel: function(date) {
  31341. return Globalize.format(date, "Y")
  31342. },
  31343. _getNavigatorCaption: function() {
  31344. return this.option("date").getFullYear()
  31345. },
  31346. moveContouredDate: function(difference) {
  31347. var contouredDate = this.option("contouredDate") || this.option("date"),
  31348. newContouredDate = new Date(contouredDate.getFullYear(), contouredDate.getMonth() + difference, contouredDate.getDate());
  31349. utils.fixTimezoneGap(contouredDate, newContouredDate);
  31350. this.option("contouredDate", newContouredDate)
  31351. },
  31352. focusInHandler: function() {
  31353. var date = this.option("date");
  31354. this.option("contouredDate", new Date(date.getFullYear(), date.getMonth(), 1))
  31355. },
  31356. canNavigate: function(difference) {
  31357. var date = new Date(this.option("date"));
  31358. var testCurrentDate = difference < 0 ? new Date(date.getFullYear() - 1, 11, 31) : new Date(date.getFullYear() + 1, 1, 1);
  31359. return utils.dateInRange(testCurrentDate, this.option("min"), this.option("max"))
  31360. },
  31361. isBoundary: function(date) {
  31362. return utils.sameYear(date, this.option("min")) || utils.sameYear(date, this.option("max"))
  31363. },
  31364. getCircledDate: function(currentDate, contouredStack) {
  31365. var lastContour = contouredStack.pop(),
  31366. month = lastContour.getMonth(),
  31367. circled = new Date(currentDate);
  31368. circled.setMonth(month);
  31369. circled.setDate(1);
  31370. return circled
  31371. }
  31372. }),
  31373. decade: ui.dxCalendar.BaseView.inherit({
  31374. NAME: CALENDAR_VIEW_NAME_PREFIX + "Decade",
  31375. _isTodayCell: function(cellDate) {
  31376. return utils.sameYear(cellDate, new Date)
  31377. },
  31378. _isDateOutOfRange: function(cellDate) {
  31379. var min = this.option("min"),
  31380. max = this.option("max");
  31381. return !utils.dateInRange(cellDate.getFullYear(), min && min.getFullYear(), max && max.getFullYear())
  31382. },
  31383. _isOtherView: function(cellDate) {
  31384. var date = new Date(cellDate);
  31385. date.setMonth(1);
  31386. return !utils.sameDecade(date, this.option("date"))
  31387. },
  31388. _getCellText: function(cellDate) {
  31389. return cellDate.getFullYear()
  31390. },
  31391. _getCellData: function(indexRow, cellIndex) {
  31392. var colCount = this.option("colCount"),
  31393. year = utils.getFirstYearInDecade(this.option("date")) - 1 + indexRow * colCount + cellIndex;
  31394. return new Date(year, 0, 1)
  31395. },
  31396. _getCellAriaLabel: function(date) {
  31397. return this._getCellText(date)
  31398. },
  31399. _getNavigatorCaption: function() {
  31400. var year = utils.getFirstYearInDecade(this.option("date"));
  31401. return year + "-" + (year + 9)
  31402. },
  31403. moveContouredDate: function(difference) {
  31404. var contouredDate = new Date(this.option("contouredDate") || this.option("date"));
  31405. contouredDate.setMonth(0);
  31406. var newContouredDate = new Date(contouredDate.getFullYear(), contouredDate.getMonth() + difference, contouredDate.getDate());
  31407. utils.fixTimezoneGap(contouredDate, newContouredDate);
  31408. this.option("contouredDate", newContouredDate)
  31409. },
  31410. focusInHandler: function() {
  31411. var date = this.option("date");
  31412. this.option("contouredDate", new Date(date.getFullYear(), 0, 1))
  31413. },
  31414. _getCellByDate: function(date) {
  31415. var foundDate = new Date(date);
  31416. foundDate.setDate(1);
  31417. foundDate.setMonth(0);
  31418. return this._$table.find("td[data-value='" + utils.getShortDate(foundDate) + "']")
  31419. },
  31420. canNavigate: function(difference) {
  31421. var date = new Date(this.option("date"));
  31422. var testCurrentDate = difference < 0 ? new Date(utils.getFirstYearInDecade(date) - 1, 11, 31) : new Date(utils.getFirstYearInDecade(date) + 10, 1, 1);
  31423. return utils.dateInRange(testCurrentDate, this.option("min"), this.option("max"))
  31424. },
  31425. isBoundary: function(date) {
  31426. return utils.sameDecade(date, this.option("min")) || utils.sameDecade(date, this.option("max"))
  31427. },
  31428. getCircledDate: function(currentDate, contouredStack) {
  31429. var lastContour = contouredStack.pop(),
  31430. year = lastContour.getFullYear(),
  31431. circled = new Date(currentDate);
  31432. circled.setFullYear(circled.getFullYear() + year % 10);
  31433. circled.setMonth(0);
  31434. circled.setDate(1);
  31435. return circled
  31436. }
  31437. }),
  31438. century: ui.dxCalendar.BaseView.inherit({
  31439. NAME: CALENDAR_VIEW_NAME_PREFIX + "Century",
  31440. _isTodayCell: function(cellDate) {
  31441. return utils.sameDecade(cellDate, new Date)
  31442. },
  31443. _isDateOutOfRange: function(cellDate) {
  31444. var decade = utils.getFirstYearInDecade(cellDate),
  31445. minDecade = utils.getFirstYearInDecade(this.option("min")),
  31446. maxDecade = utils.getFirstYearInDecade(this.option("max"));
  31447. return !utils.dateInRange(decade, minDecade, maxDecade)
  31448. },
  31449. _isOtherView: function(cellDate) {
  31450. var date = new Date(cellDate);
  31451. date.setMonth(1);
  31452. return !utils.sameCentury(date, this.option("date"))
  31453. },
  31454. _getCellText: function(cellDate) {
  31455. var decade = cellDate.getFullYear();
  31456. return decade + " - " + (decade + 9)
  31457. },
  31458. _getCellData: function(indexRow, cellIndex) {
  31459. var colCount = this.option("colCount"),
  31460. decade = utils.getFirstDecadeInCentury(this.option("date")) + (-1 + indexRow * colCount + cellIndex) * 10;
  31461. return new Date(decade, 0, 1)
  31462. },
  31463. _getCellAriaLabel: function(date) {
  31464. return this._getCellText(date)
  31465. },
  31466. _getCellByDate: function(date) {
  31467. var foundDate = new Date(date);
  31468. foundDate.setDate(1);
  31469. foundDate.setMonth(0);
  31470. foundDate.setFullYear(utils.getFirstYearInDecade(foundDate));
  31471. return this._$table.find("td[data-value='" + utils.getShortDate(foundDate) + "']")
  31472. },
  31473. _getNavigatorCaption: function() {
  31474. var decade = utils.getFirstDecadeInCentury(this.option("date"));
  31475. return decade + "-" + (decade + 99)
  31476. },
  31477. moveContouredDate: function(difference) {
  31478. var contouredDate = this._calculateContouredDate(this.option("contouredDate")),
  31479. newContouredDate = new Date(contouredDate.getFullYear(), contouredDate.getMonth() + difference, contouredDate.getDate());
  31480. utils.fixTimezoneGap(contouredDate, newContouredDate);
  31481. this.option("contouredDate", newContouredDate)
  31482. },
  31483. _calculateContouredDate: function(contouredDate) {
  31484. var calculatedContouredDate = null;
  31485. if (!utils.isDefined(contouredDate)) {
  31486. var date = this.option("date");
  31487. calculatedContouredDate = new Date(date);
  31488. calculatedContouredDate.setFullYear(utils.getFirstYearInDecade(date));
  31489. calculatedContouredDate.setDate(1)
  31490. }
  31491. else {
  31492. calculatedContouredDate = new Date(contouredDate);
  31493. calculatedContouredDate.setFullYear(utils.getFirstYearInDecade(this.option("contouredDate")))
  31494. }
  31495. calculatedContouredDate.setMonth(0);
  31496. return calculatedContouredDate
  31497. },
  31498. focusInHandler: function() {
  31499. var date = this.option("date");
  31500. this.option("contouredDate", new Date(utils.getFirstYearInDecade(date), 0, 1))
  31501. },
  31502. canNavigate: function(difference) {
  31503. var date = new Date(this.option("date"));
  31504. var testCurrentDate = difference < 0 ? new Date(utils.getFirstDecadeInCentury(date) - 1, 11, 31) : new Date(utils.getFirstDecadeInCentury(date) + 100, 1, 1);
  31505. return utils.dateInRange(testCurrentDate, this.option("min"), this.option("max"))
  31506. },
  31507. isBoundary: function(date) {
  31508. return utils.sameCentury(date, this.option("min")) || utils.sameCentury(date, this.option("max"))
  31509. }
  31510. })
  31511. }
  31512. })(jQuery, DevExpress);
  31513. /*! Module widgets-base, file ui.calendar.navigator.js */
  31514. (function($, DX, undefined) {
  31515. var ui = DX.ui,
  31516. CALENDAR_NAVIGATOR_CLASS = "dx-calendar-navigator",
  31517. CALENDAR_NAVIGATOR_PREVIOUS_MONTH_CLASS = "dx-calendar-navigator-previous-month",
  31518. CALENDAR_NAVIGATOR_NEXT_MONTH_CLASS = "dx-calendar-navigator-next-month",
  31519. CALENDAR_NAVIGATOR_PREVIOUS_VIEW_CLASS = "dx-calendar-navigator-previous-view",
  31520. CALENDAR_NAVIGATOR_NEXT_VIEW_CLASS = "dx-calendar-navigator-next-view",
  31521. CALENDAR_NAVIGATOR_DISABLED_LINK_CLASS = "dx-calendar-disabled-navigator-link",
  31522. CALENDAR_NAVIGATOR_CAPTION_BUTTON_CLASS = "dx-calendar-caption-button";
  31523. ui.dxCalendar.Navigator = ui.Widget.inherit({
  31524. _setDefaultOptions: function() {
  31525. this.callBase();
  31526. this.option({
  31527. onClick: null,
  31528. onCaptionClick: null,
  31529. text: ""
  31530. })
  31531. },
  31532. _init: function() {
  31533. this.callBase();
  31534. this._initActions()
  31535. },
  31536. _initActions: function() {
  31537. this._clickAction = this._createActionByOption("onClick");
  31538. this._captionClickAction = this._createActionByOption("onCaptionClick")
  31539. },
  31540. _render: function() {
  31541. this.callBase();
  31542. this.element().addClass(CALENDAR_NAVIGATOR_CLASS);
  31543. this._renderButtons();
  31544. this._renderCaption()
  31545. },
  31546. _renderButtons: function() {
  31547. var that = this,
  31548. direction = this.option("rtlEnabled") ? -1 : 1;
  31549. this._prevButton = this._createComponent($("<a>"), "dxButton", {
  31550. focusStateEnabled: false,
  31551. icon: "chevronleft",
  31552. onClick: function(e) {
  31553. that._clickAction({
  31554. direction: -direction,
  31555. jQueryEvent: e
  31556. })
  31557. },
  31558. _templates: {}
  31559. });
  31560. var $prevButton = this._prevButton.element().addClass(CALENDAR_NAVIGATOR_PREVIOUS_VIEW_CLASS).addClass(CALENDAR_NAVIGATOR_PREVIOUS_MONTH_CLASS);
  31561. this._nextButton = this._createComponent($("<a>"), "dxButton", {
  31562. focusStateEnabled: false,
  31563. icon: "chevronright",
  31564. onClick: function(e) {
  31565. that._clickAction({
  31566. direction: direction,
  31567. jQueryEvent: e
  31568. })
  31569. },
  31570. _templates: {}
  31571. });
  31572. var $nextButton = this._nextButton.element().addClass(CALENDAR_NAVIGATOR_NEXT_VIEW_CLASS).addClass(CALENDAR_NAVIGATOR_NEXT_MONTH_CLASS);
  31573. this._caption = this._createComponent($("<a>").addClass(CALENDAR_NAVIGATOR_CAPTION_BUTTON_CLASS), "dxButton", {
  31574. focusStateEnabled: false,
  31575. onClick: function(e) {
  31576. that._captionClickAction({jQueryEvent: e})
  31577. },
  31578. _templates: {}
  31579. });
  31580. var $caption = this._caption.element();
  31581. this.element().append($prevButton, $caption, $nextButton)
  31582. },
  31583. _renderCaption: function(caption) {
  31584. this._caption.option("text", this.option("text"))
  31585. },
  31586. toggleButton: function(buttonPrefix, value) {
  31587. var buttonName = "_" + buttonPrefix + "Button",
  31588. button = this[buttonName];
  31589. if (button) {
  31590. button.option("disabled", value);
  31591. button.element().toggleClass(CALENDAR_NAVIGATOR_DISABLED_LINK_CLASS, value)
  31592. }
  31593. },
  31594. _optionChanged: function(args) {
  31595. var value = args.value;
  31596. switch (args.name) {
  31597. case"text":
  31598. this._renderCaption(value);
  31599. break;
  31600. default:
  31601. this.callBase(args)
  31602. }
  31603. }
  31604. })
  31605. })(jQuery, DevExpress);
  31606. /*! Module widgets-base, file ui.timeView.js */
  31607. (function($, DX, undefined) {
  31608. var ui = DX.ui,
  31609. browser = DX.browser,
  31610. isBuggyIE = browser.msie && DX.compareVersions(browser.version, 9) < 0;
  31611. var TIMEVIEW_CLASS = "dx-timeview",
  31612. TIMEVIEW_CLOCK_CLASS = "dx-timeview-clock",
  31613. TIMEVIEW_FIELD_CLASS = "dx-timeview-field",
  31614. TIMEVIEW_HOURARROW_CLASS = "dx-timeview-hourarrow",
  31615. TIMEVIEW_MINUTEARROW_CLASS = "dx-timeview-minutearrow";
  31616. var rotateArrow = function($arrow, angle, offset) {
  31617. if (isBuggyIE)
  31618. filterRotate($arrow, angle, offset);
  31619. else
  31620. cssRotate($arrow, angle, offset)
  31621. };
  31622. var filterRotate = function($arrow, angle, offset) {
  31623. angle = angle / 180 * Math.PI;
  31624. var sin = Math.sin(angle),
  31625. cos = Math.cos(angle);
  31626. $arrow.css("filter", "none");
  31627. var originalWidth = $arrow.width(),
  31628. originalHeight = $arrow.height();
  31629. $arrow.css("filter", 'progid:DXImageTransform.Microsoft.Matrix' + '(sizingMethod="auto expand", M11 = ' + cos + ', M12 = ' + -sin + ', M21 = ' + sin + ', M22 = ' + cos + ')');
  31630. var width = $arrow.width(),
  31631. height = $arrow.height();
  31632. var sx = (width - originalWidth) / 2,
  31633. sy = (height - originalHeight) / 2;
  31634. $arrow.css("margin-left", -originalWidth / 2 + (originalHeight / 2 - offset) * sin - sx);
  31635. $arrow.css("margin-top", originalHeight / 2 - (originalHeight / 2 - offset) * cos - sy)
  31636. };
  31637. var cssRotate = function($arrow, angle, offset) {
  31638. $arrow.css("transform", "rotate(" + angle + "deg)" + " translate(0," + offset + "px)")
  31639. };
  31640. DX.registerComponent("dxTimeView", ui, ui.Editor.inherit({
  31641. _setDefaultOptions: function() {
  31642. this.callBase();
  31643. this.option({
  31644. value: new Date($.now()),
  31645. _arrowOffset: 0
  31646. })
  31647. },
  31648. _defaultOptionsRules: function() {
  31649. return this.callBase().concat([{
  31650. device: {platform: "android"},
  31651. options: {_arrowOffset: 15}
  31652. }, {
  31653. device: {platform: "generic"},
  31654. options: {_arrowOffset: 5}
  31655. }])
  31656. },
  31657. _getValue: function() {
  31658. return this.option("value") || new Date
  31659. },
  31660. _init: function() {
  31661. this.callBase();
  31662. this.element().addClass(TIMEVIEW_CLASS)
  31663. },
  31664. _render: function() {
  31665. this.callBase();
  31666. this._renderBox();
  31667. this._updateTime()
  31668. },
  31669. _renderBox: function() {
  31670. var $box = $("<div>").appendTo(this.element());
  31671. this._createComponent($box, "dxBox", {
  31672. height: "100%",
  31673. width: "100%",
  31674. direction: "col",
  31675. items: [{
  31676. ratio: 1,
  31677. shrink: 0,
  31678. baseSize: "auto",
  31679. template: $.proxy(this._renderClock, this)
  31680. }, {
  31681. ratio: 0,
  31682. shrink: 0,
  31683. baseSize: 50,
  31684. template: $.proxy(this._renderField, this)
  31685. }]
  31686. })
  31687. },
  31688. _renderClock: function(_, __, $container) {
  31689. this._$hourArrow = $("<div>").addClass(TIMEVIEW_HOURARROW_CLASS);
  31690. this._$minuteArrow = $("<div>").addClass(TIMEVIEW_MINUTEARROW_CLASS);
  31691. $container.addClass(TIMEVIEW_CLOCK_CLASS).append(this._$hourArrow).append(this._$minuteArrow);
  31692. this.setAria("role", "presentation", $container)
  31693. },
  31694. _updateClock: function() {
  31695. var time = this._getValue(),
  31696. hourArrowAngle = time.getHours() / 12 * 360 + time.getMinutes() / 60 * 30,
  31697. minuteArrowAngle = time.getMinutes() / 60 * 360;
  31698. rotateArrow(this._$hourArrow, hourArrowAngle, this.option("_arrowOffset"));
  31699. rotateArrow(this._$minuteArrow, minuteArrowAngle, this.option("_arrowOffset"))
  31700. },
  31701. _renderField: function() {
  31702. this._createHourBox();
  31703. this._createMinuteBox();
  31704. return this._createComponent($("<div>").addClass(TIMEVIEW_FIELD_CLASS), "dxBox", {
  31705. direction: "row",
  31706. align: "center",
  31707. crossAlign: "center",
  31708. items: [{
  31709. ratio: 0,
  31710. shrink: 0,
  31711. baseSize: "auto",
  31712. template: $.proxy(function() {
  31713. return this._hourBox.element()
  31714. }, this)
  31715. }, {
  31716. ratio: 0,
  31717. shrink: 0,
  31718. baseSize: "auto",
  31719. template: Globalize.culture().calendar[":"]
  31720. }, {
  31721. ratio: 0,
  31722. shrink: 0,
  31723. baseSize: "auto",
  31724. template: $.proxy(function() {
  31725. return this._minuteBox.element()
  31726. }, this)
  31727. }]
  31728. }).element()
  31729. },
  31730. _createHourBox: function() {
  31731. this._hourBox = this._createComponent($("<div>"), "dxNumberBox", $.extend({
  31732. min: -1,
  31733. max: 24,
  31734. value: this._getValue().getHours(),
  31735. onValueChanged: $.proxy(function(args) {
  31736. var newHours = (24 + args.value) % 24;
  31737. this._hourBox.option("value", newHours);
  31738. var time = new Date(this._getValue());
  31739. time.setHours(newHours);
  31740. this.option("value", time)
  31741. }, this)
  31742. }, this._getNumberBoxConfig()));
  31743. this._hourBox.setAria("label", "hours")
  31744. },
  31745. _createMinuteBox: function() {
  31746. this._minuteBox = this._createComponent($("<div>"), "dxNumberBox", $.extend({
  31747. min: -1,
  31748. max: 60,
  31749. value: this._getValue().getMinutes(),
  31750. onValueChanged: $.proxy(function(args) {
  31751. var newMinutes = (60 + args.value) % 60;
  31752. this._minuteBox.option("value", newMinutes);
  31753. var time = new Date(this._getValue());
  31754. time.setMinutes(newMinutes);
  31755. this.option("value", time)
  31756. }, this)
  31757. }, this._getNumberBoxConfig()));
  31758. this._minuteBox.setAria("label", "minutes")
  31759. },
  31760. _getNumberBoxConfig: function() {
  31761. return {
  31762. showSpinButtons: true,
  31763. disabled: this.option("disabled"),
  31764. valueFormat: function(value) {
  31765. return (value < 10 ? "0" : "") + value
  31766. }
  31767. }
  31768. },
  31769. _updateField: function() {
  31770. this._hourBox && this._hourBox.option("value", this._getValue().getHours());
  31771. this._minuteBox && this._minuteBox.option("value", this._getValue().getMinutes())
  31772. },
  31773. _updateTime: function() {
  31774. this._updateClock();
  31775. this._updateField()
  31776. },
  31777. _visibilityChanged: function(visible) {
  31778. if (visible)
  31779. this._updateTime()
  31780. },
  31781. _toggleDisabledState: function(value) {
  31782. this._hourBox && this._hourBox.option("disabled", value);
  31783. this._minuteBox && this._minuteBox.option("disabled", value)
  31784. },
  31785. _optionChanged: function(args) {
  31786. switch (args.name) {
  31787. case"value":
  31788. this._updateTime();
  31789. this.callBase(args);
  31790. break;
  31791. case"_arrowOffset":
  31792. break;
  31793. default:
  31794. this.callBase(args)
  31795. }
  31796. }
  31797. }))
  31798. })(jQuery, DevExpress);
  31799. /*! Module widgets-base, file ui.dateView.js */
  31800. (function($, DX) {
  31801. var ui = DX.ui,
  31802. events = ui.events,
  31803. dateUtils = ui.dateUtils,
  31804. DATEVIEW_CLASS = "dx-dateview",
  31805. DATEVIEW_WRAPPER_CLASS = "dx-dateview-wrapper",
  31806. DATEVIEW_ROLLER_CONTAINER_CLASS = "dx-dateview-rollers",
  31807. DATEVIEW_ROLLER_CLASS = "dx-dateviewroller",
  31808. DATEVIEW_ROLLER_ACTIVE_CLASS = "dx-state-active",
  31809. DATEVIEW_ROLLER_CURRENT_CLASS = "dx-dateviewroller-current",
  31810. DATEVIEW_ROLLER_ITEM_CLASS = "dx-dateview-item",
  31811. DATEVIEW_ROLLER_ITEM_SELECTED_CLASS = "dx-dateview-item-selected",
  31812. DATEVIEW_ROLLER_ITEM_SELECTED_FRAME_CLASS = "dx-dateview-item-selected-frame",
  31813. DATEVIEW_ROLLER_ITEM_SELECTED_BORDER_CLASS = "dx-dateview-item-selected-border",
  31814. DATEVIEW_ROLLER_BUTTON_UP_CLASS = "dx-dateview-button-up",
  31815. DATEVIEW_ROLLER_BUTTON_DOWN_CLASS = "dx-dateview-button-down";
  31816. DX.registerComponent("dxDateViewRoller", ui, ui.dxScrollable.inherit({
  31817. _setDefaultOptions: function() {
  31818. this.callBase();
  31819. this.option({
  31820. clickableItems: false,
  31821. showScrollbar: false,
  31822. useNative: false,
  31823. selectedIndex: 0,
  31824. bounceEnabled: false,
  31825. items: [],
  31826. onClick: null,
  31827. showOnClick: false
  31828. })
  31829. },
  31830. _defaultOptionsRules: function() {
  31831. return this.callBase().concat([{
  31832. device: {platform: "win8"},
  31833. options: {
  31834. clickableItems: true,
  31835. showOnClick: true
  31836. }
  31837. }, {
  31838. device: {platform: "generic"},
  31839. options: {scrollByContent: true}
  31840. }])
  31841. },
  31842. _init: function() {
  31843. this.callBase();
  31844. this._renderSelectedItemFrame();
  31845. this._renderControlButtons()
  31846. },
  31847. _render: function() {
  31848. this.callBase();
  31849. $.each(this._strategy._scrollers, function(index, scroller) {
  31850. scroller._correctLocation = $.noop
  31851. });
  31852. this.element().addClass(DATEVIEW_ROLLER_CLASS);
  31853. this._renderContainerClick();
  31854. this._renderItems();
  31855. this._renderSelectedValue();
  31856. this._renderItemsClick();
  31857. this._wrapAction("_endAction", $.proxy(this._endActionHandler, this))
  31858. },
  31859. _renderContainerClick: function() {
  31860. if (!this.option("showOnClick"))
  31861. return;
  31862. var eventName = events.addNamespace("dxclick", this.NAME);
  31863. var clickAction = this._createActionByOption("onClick");
  31864. this._$container.off(eventName).on(eventName, function(e) {
  31865. clickAction({jQueryEvent: e})
  31866. })
  31867. },
  31868. _wrapAction: function(actionName, callback) {
  31869. var strategy = this._strategy,
  31870. originalAction = strategy[actionName];
  31871. strategy[actionName] = function() {
  31872. callback.apply(this, arguments);
  31873. return originalAction.apply(this, arguments)
  31874. }
  31875. },
  31876. _renderItems: function() {
  31877. var items = this.option("items") || [],
  31878. $items = $();
  31879. this._$content.empty();
  31880. $.each(items, function() {
  31881. $items = $items.add($("<div>").addClass(DATEVIEW_ROLLER_ITEM_CLASS).append(this))
  31882. });
  31883. this._$content.append($items);
  31884. this._$items = $items;
  31885. this.update()
  31886. },
  31887. _renderSelectedItemFrame: function() {
  31888. $("<div>").addClass(DATEVIEW_ROLLER_ITEM_SELECTED_FRAME_CLASS).append($("<div>").addClass(DATEVIEW_ROLLER_ITEM_SELECTED_BORDER_CLASS)).appendTo(this._$container)
  31889. },
  31890. _renderControlButtons: function() {
  31891. this._createComponent($("<div>").addClass(DATEVIEW_ROLLER_BUTTON_UP_CLASS).insertAfter(this._$container), "dxButton", {
  31892. onClick: $.proxy(this._upButtonClickHandler, this),
  31893. _templates: {}
  31894. });
  31895. this._createComponent($("<div>").addClass(DATEVIEW_ROLLER_BUTTON_DOWN_CLASS).insertAfter(this._$container), "dxButton", {
  31896. onClick: $.proxy(this._downButtonClickHandler, this),
  31897. _templates: {}
  31898. })
  31899. },
  31900. _renderSelectedValue: function(selectedIndex) {
  31901. if (selectedIndex === undefined)
  31902. selectedIndex = this.option("selectedIndex");
  31903. selectedIndex = this._fitIndex(selectedIndex);
  31904. var correctedPosition = this._getItemPosition(selectedIndex);
  31905. this.option().selectedIndex = selectedIndex;
  31906. this._moveTo({top: correctedPosition});
  31907. this._renderActiveStateItem()
  31908. },
  31909. _fitIndex: function(index) {
  31910. var items = this.option("items") || [],
  31911. itemCount = items.length;
  31912. if (index >= itemCount)
  31913. return itemCount - 1;
  31914. if (index < 0)
  31915. return 0;
  31916. return index
  31917. },
  31918. _renderItemsClick: function() {
  31919. var itemSelector = "." + DATEVIEW_ROLLER_ITEM_CLASS,
  31920. eventName = events.addNamespace("dxclick", this.NAME);
  31921. this.element().off(eventName, itemSelector);
  31922. if (this.option("clickableItems"))
  31923. this.element().on(eventName, itemSelector, $.proxy(this._itemClickHandler, this))
  31924. },
  31925. _itemClickHandler: function(e) {
  31926. this._renderSelectedValue(this._itemElementIndex(this._closestItemElement(e)))
  31927. },
  31928. _itemElementIndex: function(itemElement) {
  31929. return this._itemElements().index(itemElement)
  31930. },
  31931. _closestItemElement: function(e) {
  31932. return e.currentTarget
  31933. },
  31934. _itemElements: function() {
  31935. return this.element().find("." + DATEVIEW_ROLLER_ITEM_CLASS)
  31936. },
  31937. _renderActiveStateItem: function() {
  31938. var selectedIndex = this.option("selectedIndex");
  31939. $.each(this._$items, function(index) {
  31940. $(this).toggleClass(DATEVIEW_ROLLER_ITEM_SELECTED_CLASS, selectedIndex === index)
  31941. })
  31942. },
  31943. _upButtonClickHandler: function() {
  31944. this._animation = true;
  31945. this.option("selectedIndex", this.option("selectedIndex") - 1)
  31946. },
  31947. _downButtonClickHandler: function() {
  31948. this._animation = true;
  31949. this.option("selectedIndex", this.option("selectedIndex") + 1)
  31950. },
  31951. _getItemPosition: function(index) {
  31952. return Math.round(this._itemHeight() * index)
  31953. },
  31954. _moveTo: function(targetLocation) {
  31955. targetLocation = this._normalizeLocation(targetLocation);
  31956. var location = this._location(),
  31957. delta = {
  31958. x: -(location.left - targetLocation.left),
  31959. y: -(location.top - targetLocation.top)
  31960. };
  31961. if (this._isVisible() && (delta.x || delta.y)) {
  31962. this._strategy._prepareDirections(true);
  31963. if (this._animation) {
  31964. DX.fx.stop(this._$content);
  31965. DX.fx.animate(this._$content, {
  31966. duration: 200,
  31967. type: "slide",
  31968. to: {top: targetLocation.top}
  31969. });
  31970. delete this._animation
  31971. }
  31972. else
  31973. this._strategy.handleMove({delta: delta})
  31974. }
  31975. },
  31976. _validate: function(e) {
  31977. return this._strategy.validate(e)
  31978. },
  31979. _endActionHandler: function() {
  31980. if (this._changedByIndex) {
  31981. this._changedByIndex = false;
  31982. this._renderSelectedValue();
  31983. return
  31984. }
  31985. var ratio = -this._location().top / this._itemHeight(),
  31986. selectedIndex = Math.round(ratio);
  31987. this._animation = true;
  31988. this._renderSelectedValue(selectedIndex)
  31989. },
  31990. _itemHeight: function() {
  31991. var $item = this._$items.first(),
  31992. height = $item.outerHeight() + parseFloat($item.css("margin-top") || 0);
  31993. return height
  31994. },
  31995. _toggleActive: function(state) {
  31996. this.element().toggleClass(DATEVIEW_ROLLER_ACTIVE_CLASS, state)
  31997. },
  31998. _isVisible: function() {
  31999. return this._$container.is(":visible")
  32000. },
  32001. _optionChanged: function(args) {
  32002. switch (args.name) {
  32003. case"selectedIndex":
  32004. this._renderSelectedValue();
  32005. this._changedByIndex = true;
  32006. this._strategy.handleEnd({velocity: {
  32007. x: 0,
  32008. y: 0
  32009. }});
  32010. break;
  32011. case"items":
  32012. this._renderItems();
  32013. this._renderSelectedValue();
  32014. break;
  32015. case"clickableItems":
  32016. this._renderItemsClick();
  32017. break;
  32018. case"onClick":
  32019. case"showOnClick":
  32020. this._renderContainerClick();
  32021. break;
  32022. default:
  32023. this.callBase(args)
  32024. }
  32025. }
  32026. }), ui);
  32027. DX.registerComponent("dxDateView", ui, ui.Editor.inherit({
  32028. _valueOption: function() {
  32029. return new Date(this.option("value")) === "Invalid Date" ? new Date : new Date(this.option("value"))
  32030. },
  32031. _setDefaultOptions: function() {
  32032. this.callBase();
  32033. this.option({
  32034. minDate: new Date(1),
  32035. maxDate: new Date((new Date).setHours(23, 59, 59) + dateUtils.TEN_YEARS),
  32036. format: "date",
  32037. value: new Date,
  32038. culture: Globalize.culture().name,
  32039. activeStateEnabled: true,
  32040. showNames: false
  32041. })
  32042. },
  32043. _defaultOptionsRules: function() {
  32044. return this.callBase().concat([{
  32045. device: {platform: "win8"},
  32046. options: {showNames: true}
  32047. }])
  32048. },
  32049. _render: function() {
  32050. this.callBase();
  32051. this.element().addClass(DATEVIEW_CLASS);
  32052. this._toggleFormatClasses(this.option("format"))
  32053. },
  32054. _toggleFormatClasses: function(currentFormat, previousFormat) {
  32055. this.element().addClass(DATEVIEW_CLASS + "-" + currentFormat);
  32056. previousFormat && this.element().removeClass(DATEVIEW_CLASS + "-" + previousFormat)
  32057. },
  32058. _wrapper: function() {
  32059. return this._$wrapper
  32060. },
  32061. _renderContentImpl: function() {
  32062. this._$wrapper = $("<div>").appendTo(this.element()).addClass(DATEVIEW_WRAPPER_CLASS);
  32063. this._renderRollers()
  32064. },
  32065. _renderRollers: function() {
  32066. var that = this;
  32067. if (!that._$rollersContainer)
  32068. that._$rollersContainer = $("<div>").appendTo(that._wrapper()).addClass(DATEVIEW_ROLLER_CONTAINER_CLASS);
  32069. that._$rollersContainer.empty();
  32070. that._createRollerConfigs();
  32071. that._rollers = {};
  32072. $.each(that._rollerConfigs, function(name) {
  32073. var $roller = $("<div>").appendTo(that._$rollersContainer).addClass(DATEVIEW_ROLLER_CLASS + "-" + that._rollerConfigs[name].type);
  32074. that._rollers[that._rollerConfigs[name].type] = that._createComponent($roller, "dxDateViewRoller", {
  32075. items: that._rollerConfigs[name].displayItems,
  32076. selectedIndex: that._rollerConfigs[name].selectedIndex,
  32077. showScrollbar: false,
  32078. onStart: function(e) {
  32079. var roller = e.component;
  32080. roller._toggleActive(true);
  32081. that._setActiveRoller(that._rollerConfigs[name], roller.option("selectedIndex"))
  32082. },
  32083. onEnd: function(e) {
  32084. var roller = e.component;
  32085. that._setRollerState(that._rollerConfigs[name], roller.option("selectedIndex"));
  32086. roller._toggleActive(false)
  32087. },
  32088. onClick: function(e) {
  32089. var roller = e.component;
  32090. roller._toggleActive(true);
  32091. that._setActiveRoller(that._rollerConfigs[name], roller.option("selectedIndex"));
  32092. that._setRollerState(that._rollerConfigs[name], roller.option("selectedIndex"));
  32093. roller._toggleActive(false)
  32094. }
  32095. })
  32096. })
  32097. },
  32098. _setActiveRoller: function(currentRoller) {
  32099. var activeRoller = currentRoller && this._rollers[currentRoller.type];
  32100. $.each(this._rollers, function() {
  32101. this._$element.toggleClass(DATEVIEW_ROLLER_CURRENT_CLASS, this === activeRoller)
  32102. })
  32103. },
  32104. _updateRollersPosition: function() {
  32105. var that = this;
  32106. $.each(this._rollers, function(type) {
  32107. var correctIndex = that._rollerConfigs[type].getIndex(that._getCurrentDate());
  32108. this.update();
  32109. this._renderSelectedValue(correctIndex)
  32110. })
  32111. },
  32112. _setRollerState: function(roller, selectedIndex) {
  32113. if (selectedIndex !== roller.selectedIndex) {
  32114. var rollerValue = roller.valueItems[selectedIndex],
  32115. setValue = roller.setValue,
  32116. currentValue = new Date(this._getCurrentDate()),
  32117. currentDate = currentValue.getDate();
  32118. if (roller.type === "month")
  32119. currentDate = Math.min(currentDate, dateUtils.getMaxMonthDay(currentValue.getFullYear(), rollerValue));
  32120. else if (roller.type === "year")
  32121. currentDate = Math.min(currentDate, dateUtils.getMaxMonthDay(rollerValue, currentValue.getMonth()));
  32122. currentValue.setDate(currentDate);
  32123. currentValue[setValue](rollerValue);
  32124. this.option("value", currentValue);
  32125. roller.selectedIndex = selectedIndex
  32126. }
  32127. if (roller.type === "year") {
  32128. this._refreshMonthRoller();
  32129. this._refreshDayRoller()
  32130. }
  32131. if (roller.type === "month")
  32132. this._refreshDayRoller()
  32133. },
  32134. _refreshMonthRoller: function() {
  32135. var monthRoller = this._rollers["month"];
  32136. if (monthRoller) {
  32137. this._createRollerConfig("month");
  32138. var monthRollerConfig = this._rollerConfigs["month"];
  32139. if (monthRollerConfig.displayItems.length !== monthRoller.option("items").length)
  32140. monthRoller.option({
  32141. items: monthRollerConfig.displayItems,
  32142. selectedIndex: monthRollerConfig.selectedIndex
  32143. })
  32144. }
  32145. },
  32146. _refreshDayRoller: function() {
  32147. var dayRoller = this._rollers["day"];
  32148. if (dayRoller) {
  32149. this._createRollerConfig("day");
  32150. var dayRollerConfig = this._rollerConfigs["day"];
  32151. if (dayRollerConfig.displayItems.length !== dayRoller.option("items").length)
  32152. dayRoller.option({
  32153. items: dayRollerConfig.displayItems,
  32154. selectedIndex: dayRollerConfig.selectedIndex
  32155. })
  32156. }
  32157. },
  32158. _createRollerConfigs: function(format) {
  32159. var that = this;
  32160. format = format || that.option("format");
  32161. that._rollerConfigs = {};
  32162. $.each(that._getFormatPattern(format).split(/\W+/), function(_, formatPart) {
  32163. $.each(dateUtils.DATE_COMPONENTS_INFO, function(componentName, componentInfo) {
  32164. if ($.inArray(formatPart, componentInfo.possibleFormats) > -1)
  32165. that._createRollerConfig(componentName)
  32166. })
  32167. })
  32168. },
  32169. _getFormatPattern: function(format) {
  32170. var culture = Globalize.culture(this.option("culture")),
  32171. result = "";
  32172. if (format === "date")
  32173. result = culture.calendar.patterns.d;
  32174. else if (format === "time")
  32175. result = culture.calendar.patterns.t;
  32176. else if (format === "datetime")
  32177. result = [culture.calendar.patterns.d, culture.calendar.patterns.t].join(" ");
  32178. return result
  32179. },
  32180. _createRollerConfig: function(componentName) {
  32181. var componentInfo = dateUtils.DATE_COMPONENTS_INFO[componentName],
  32182. valueRange = this._calculateRollerConfigValueRange(componentName),
  32183. startValue = valueRange.startValue,
  32184. endValue = valueRange.endValue,
  32185. formatter = componentInfo.formatter,
  32186. showNames = this.option("showNames"),
  32187. curDate = this._getCurrentDate();
  32188. var config = {
  32189. type: componentName,
  32190. setValue: componentInfo.setter,
  32191. valueItems: [],
  32192. displayItems: [],
  32193. getIndex: function(value) {
  32194. return value[componentInfo.getter]() - startValue
  32195. }
  32196. };
  32197. for (var i = startValue; i <= endValue; i++) {
  32198. config.valueItems.push(i);
  32199. config.displayItems.push(formatter(i, showNames, curDate))
  32200. }
  32201. config.selectedIndex = config.getIndex(curDate);
  32202. this._rollerConfigs[componentName] = config
  32203. },
  32204. _getCurrentDate: function() {
  32205. var curDate = this.option("value"),
  32206. minDate = this.option("minDate"),
  32207. maxDate = this.option("maxDate");
  32208. if (minDate && curDate.getTime() <= minDate.getTime())
  32209. curDate = minDate;
  32210. else if (maxDate && curDate.getTime() >= maxDate.getTime())
  32211. curDate = maxDate;
  32212. return curDate
  32213. },
  32214. _calculateRollerConfigValueRange: function(componentName) {
  32215. var curDate = this._getCurrentDate(),
  32216. minDate = this.option("minDate"),
  32217. maxDate = this.option("maxDate"),
  32218. minYear = curDate.getFullYear() === minDate.getFullYear(),
  32219. minMonth = minYear && curDate.getMonth() === minDate.getMonth(),
  32220. maxYear = curDate.getFullYear() === maxDate.getFullYear(),
  32221. maxMonth = maxYear && curDate.getMonth() === maxDate.getMonth(),
  32222. componentInfo = dateUtils.DATE_COMPONENTS_INFO[componentName],
  32223. startValue = componentInfo.startValue,
  32224. endValue = componentInfo.endValue;
  32225. if (componentName === "year") {
  32226. startValue = minDate.getFullYear();
  32227. endValue = maxDate.getFullYear()
  32228. }
  32229. if (componentName === "month") {
  32230. if (minYear)
  32231. startValue = minDate.getMonth();
  32232. if (maxYear)
  32233. endValue = maxDate.getMonth()
  32234. }
  32235. if (componentName === "day") {
  32236. endValue = dateUtils.getMaxMonthDay(curDate.getFullYear(), curDate.getMonth());
  32237. if (minYear && minMonth)
  32238. startValue = minDate.getDate();
  32239. if (maxYear && maxMonth)
  32240. endValue = maxDate.getDate()
  32241. }
  32242. return {
  32243. startValue: startValue,
  32244. endValue: endValue
  32245. }
  32246. },
  32247. _refreshRollers: function() {
  32248. this._refreshMonthRoller();
  32249. this._refreshDayRoller()
  32250. },
  32251. _optionChanged: function(args) {
  32252. switch (args.name) {
  32253. case"showNames":
  32254. case"minDate":
  32255. case"maxDate":
  32256. case"culture":
  32257. case"format":
  32258. this._renderRollers();
  32259. this._toggleFormatClasses(args.value, args.previousValue);
  32260. break;
  32261. case"visible":
  32262. this.callBase(args);
  32263. if (args.value)
  32264. this._renderRollers();
  32265. break;
  32266. case"value":
  32267. this.option("value", this._valueOption());
  32268. this._refreshRollers();
  32269. this._updateRollersPosition();
  32270. break;
  32271. default:
  32272. this.callBase(args)
  32273. }
  32274. },
  32275. _clean: function() {
  32276. this.callBase();
  32277. delete this._$rollersContainer
  32278. },
  32279. _dispose: function() {
  32280. clearTimeout(this._deferredRenderDayTimeout);
  32281. clearTimeout(this._deferredRenderMonthTimeout);
  32282. this.callBase()
  32283. }
  32284. }))
  32285. })(jQuery, DevExpress);
  32286. /*! Module widgets-base, file ui.dateBox.js */
  32287. (function($, DX, undefined) {
  32288. var ui = DX.ui,
  32289. support = DX.support,
  32290. devices = DX.devices,
  32291. dateUtils = ui.dateUtils,
  32292. utils = DX.utils,
  32293. DATEBOX_CLASS = "dx-datebox",
  32294. DATEBOX_NATIVE_CLASS = "dx-datebox-native",
  32295. DATEBOX_OVERLAY_CLASS = "dx-datebox-overlay",
  32296. IE_ROUNDING_ERROR = 10,
  32297. NATIVE_BUTTONS_WIDTH = 48;
  32298. var realWidthSetted = function($element) {
  32299. var explicitWidth = $element[0].style.width;
  32300. if (explicitWidth && explicitWidth !== "auto" && explicitWidth !== "inherit")
  32301. return true;
  32302. return false
  32303. };
  32304. var calculateWidth = function(value, $input, $element) {
  32305. var $longestValueElement = $("<div>").text(value).css({
  32306. "font-style": $input.css("font-style"),
  32307. "font-variant": $input.css("font-variant"),
  32308. "font-weight": $input.css("font-weight"),
  32309. "font-size": $input.css("font-size"),
  32310. "font-family": $input.css("font-family"),
  32311. "letter-spacing": $input.css("letter-spacing"),
  32312. "padding-left": $input.css("padding-left"),
  32313. "padding-right": $input.css("padding-right"),
  32314. border: $input.css("border"),
  32315. visibility: "hidden",
  32316. "white-space": "nowrap",
  32317. position: "absolute",
  32318. float: "left"
  32319. });
  32320. $longestValueElement.appendTo($element);
  32321. var width = $longestValueElement.outerWidth() + IE_ROUNDING_ERROR + ($input.prop("type") !== "text" ? NATIVE_BUTTONS_WIDTH : 0);
  32322. $longestValueElement.remove();
  32323. return width
  32324. };
  32325. DX.registerComponent("dxDateBox", ui, ui.dxDropDownEditor.inherit({
  32326. ctor: function(element, options) {
  32327. this._userOptions = $.extend({}, options);
  32328. this.callBase(element, options)
  32329. },
  32330. _supportedKeys: function() {
  32331. return $.extend(this.callBase(), this._strategy.supportedKeys())
  32332. },
  32333. _setDeprecatedOptions: function() {
  32334. this.callBase();
  32335. $.extend(this._deprecatedOptions, {
  32336. closeOnValueChange: {
  32337. since: "14.2",
  32338. message: "Use the 'applyValueMode' option instead"
  32339. },
  32340. useNative: {
  32341. since: "15.1",
  32342. message: "'useNative' option is deprecated in 15.1. Use the 'pickerType' option instead"
  32343. },
  32344. useCalendar: {
  32345. since: "15.1",
  32346. message: "'useCalendar' option is deprecated in 15.1. Use the 'pickerType' option instead"
  32347. }
  32348. })
  32349. },
  32350. _setDefaultOptions: function() {
  32351. this.callBase();
  32352. this.option({
  32353. format: "date",
  32354. value: new Date,
  32355. min: undefined,
  32356. max: undefined,
  32357. useCalendar: false,
  32358. maxZoomLevel: "month",
  32359. minZoomLevel: "century",
  32360. useNative: true,
  32361. pickerType: "native"
  32362. })
  32363. },
  32364. _defaultOptionsRules: function() {
  32365. return this.callBase().concat([{
  32366. device: {platform: "ios"},
  32367. options: {showPopupTitle: true}
  32368. }, {
  32369. device: function(device) {
  32370. return device.platform === "android"
  32371. },
  32372. options: {buttonsLocation: "bottom after"}
  32373. }, {
  32374. device: {platform: "win8"},
  32375. options: {buttonsLocation: "bottom after"}
  32376. }, {
  32377. device: function() {
  32378. var realDevice = DX.devices.real(),
  32379. platform = realDevice.platform,
  32380. version = realDevice.version;
  32381. return platform === "generic" || platform === "win8" || platform === "android" && DX.compareVersions(version, [4, 4]) < 0
  32382. },
  32383. options: {pickerType: "rollers"}
  32384. }, {
  32385. device: {platform: "generic"},
  32386. options: {
  32387. pickerType: "calendar",
  32388. buttonsLocation: "bottom after"
  32389. }
  32390. }])
  32391. },
  32392. _initOptions: function(options) {
  32393. if (DX.utils.isDefined(options.closeOnValueChange) && !DX.utils.isDefined(options.applyValueMode)) {
  32394. var applyValueMode = options.closeOnValueChange ? "instantly" : "useButtons";
  32395. $.extend(options, {applyValueMode: applyValueMode})
  32396. }
  32397. this.callBase(options)
  32398. },
  32399. _updatePickerOptions: function() {
  32400. this.option(this._getPickerOptions())
  32401. },
  32402. _getPickerOptions: function() {
  32403. var result = {},
  32404. pickerType;
  32405. if (this._hasPickerTypePriority) {
  32406. pickerType = this.option("pickerType");
  32407. this.option().useNative = pickerType === "native";
  32408. this.option().useCalendar = pickerType === "calendar" || pickerType === "list"
  32409. }
  32410. else {
  32411. var userOptions = this._userOptions;
  32412. if (userOptions) {
  32413. pickerType = this.option("pickerType");
  32414. if (userOptions.useNative === undefined)
  32415. this.option("useNative", pickerType === "native");
  32416. if (userOptions.useCalendar === undefined)
  32417. this.option("useCalendar", pickerType === "list" || pickerType === "calendar")
  32418. }
  32419. var useNative = this.option("useNative"),
  32420. useCalendar = this.option("useCalendar");
  32421. if (userOptions && userOptions.useCalendar === true && userOptions.format === "time")
  32422. result.pickerType = "list";
  32423. else if (useNative)
  32424. result.pickerType = "native";
  32425. else if (useCalendar) {
  32426. var format = this.option("format");
  32427. result.pickerType = format === "date" || format === "datetime" ? "calendar" : "list"
  32428. }
  32429. else
  32430. result.pickerType = "rollers"
  32431. }
  32432. return result
  32433. },
  32434. _init: function() {
  32435. this._hasPickerTypePriority = this._userOptions.pickerType !== undefined || this._userOptions.useNative === undefined && this._userOptions.useCalendar === undefined;
  32436. this._updatePickerOptions();
  32437. this._initStrategy();
  32438. this.option($.extend({}, this._strategy.getDefaultOptions(), this._userOptions));
  32439. delete this._userOptions;
  32440. this.callBase();
  32441. this._strategy.initFormat()
  32442. },
  32443. _initStrategy: function() {
  32444. this._parseFormat(this.option("format"));
  32445. var strategyName = this._getStrategyName(this._formatType),
  32446. strategy = ui.dxDateBox.renderingStrategies[strategyName];
  32447. if (!(this._strategy && this._strategy.NAME === strategyName))
  32448. this._strategy = new strategy(this)
  32449. },
  32450. _getStrategyName: function(format) {
  32451. switch (this.option("pickerType")) {
  32452. case"calendar":
  32453. case"list":
  32454. if (format === "date")
  32455. return "Calendar";
  32456. if (format === "datetime")
  32457. return "CalendarWithTime";
  32458. return "List";
  32459. case"rollers":
  32460. case"native":
  32461. return this.option().useCalendar ? "Calendar" : "DateView"
  32462. }
  32463. },
  32464. _parseFormat: function(format) {
  32465. var isTime = /h|m|s/g.test(format),
  32466. isDate = /d|M|Y/g.test(format),
  32467. formatType = "";
  32468. if (isDate)
  32469. formatType += "date";
  32470. if (isTime)
  32471. formatType += "time";
  32472. switch (format) {
  32473. case"date":
  32474. format = Globalize.culture().calendar.patterns["d"];
  32475. break;
  32476. case"datetime":
  32477. format = Globalize.culture().calendar.patterns["d"] + " " + Globalize.culture().calendar.patterns["t"];
  32478. break;
  32479. case"time":
  32480. format = Globalize.culture().calendar.patterns["t"];
  32481. break
  32482. }
  32483. if (format)
  32484. this._setFormatString(format);
  32485. if (formatType)
  32486. this._setFormatType(formatType)
  32487. },
  32488. _setFormatString: function(formatString) {
  32489. this._formatString = formatString
  32490. },
  32491. _setFormatType: function(formatType) {
  32492. this._formatType = formatType
  32493. },
  32494. _attachChildKeyboardEvents: function() {
  32495. this._strategy.attachKeyboardEvents(this._keyboardProcessor)
  32496. },
  32497. _render: function() {
  32498. this.element().addClass(DATEBOX_CLASS).addClass(DATEBOX_CLASS + "-" + this.option("format"));
  32499. this.callBase();
  32500. this._strategy.render();
  32501. if (this._isNativeView())
  32502. this.element().addClass(DATEBOX_NATIVE_CLASS);
  32503. this._updateSize();
  32504. this._updateDropButtonVisibility()
  32505. },
  32506. _popupShowingHandler: function() {
  32507. this.callBase();
  32508. this._strategy.popupShowingHandler()
  32509. },
  32510. _popupConfig: function() {
  32511. var popupConfig = this.callBase();
  32512. return $.extend(this._strategy.popupConfig(popupConfig), {
  32513. title: this._getPopupTitle(),
  32514. dragEnabled: false
  32515. })
  32516. },
  32517. _renderPopup: function() {
  32518. this.callBase();
  32519. this._popup._$wrapper.addClass(DATEBOX_OVERLAY_CLASS)
  32520. },
  32521. _renderPopupContent: function() {
  32522. this.callBase();
  32523. this._strategy.renderPopupContent()
  32524. },
  32525. _popupHiddenHandler: function() {
  32526. this.callBase();
  32527. this._strategy.popupHiddenHandler()
  32528. },
  32529. _visibilityChanged: function(visible) {
  32530. if (visible)
  32531. this._updateSize()
  32532. },
  32533. _updateSize: function() {
  32534. var $element = this.element(),
  32535. widthOption = this.option("width"),
  32536. isWidthSet = utils.isDefined(widthOption) || realWidthSetted($element) && !this._isSizeUpdatable,
  32537. isElementVisible = $element.is(":visible"),
  32538. pickerType = this.option("pickerType"),
  32539. shouldCalculateWidth = pickerType !== "rollers" && devices.current().platform === "generic";
  32540. if (isWidthSet || !(shouldCalculateWidth && isElementVisible))
  32541. return;
  32542. var $input = this._input(),
  32543. calendar = Globalize.culture().calendar,
  32544. format = this.option("formatString"),
  32545. longestValue = Globalize.format(dateUtils.getLongestDate(format, calendar.months.names, calendar.days.names), format);
  32546. $element.width(calculateWidth(longestValue, $input, this.element()));
  32547. this._isSizeUpdatable = true
  32548. },
  32549. _usingNativeDatePicker: function() {
  32550. return support.inputType(this.option("mode")) && this.option("pickerType") === "native"
  32551. },
  32552. _readOnlyPropValue: function() {
  32553. return this.callBase() || this.option("pickerType") === "rollers"
  32554. },
  32555. _checkIfClearButtonShouldBeRendered: function() {
  32556. return !this._isNativeView() && this.callBase()
  32557. },
  32558. _renderValue: function() {
  32559. var mode = this.option("mode"),
  32560. value = this.option("value"),
  32561. patternKey = dateUtils.FORMATS_MAP[mode],
  32562. pattern = this._getPattern(patternKey);
  32563. this._validateValue(value);
  32564. if (mode !== "text")
  32565. this.option("text", dateUtils.toStandardDateFormat(value, mode, pattern));
  32566. else
  32567. this.option("text", Globalize.format(value, this.option("formatString")));
  32568. this._strategy.renderValue();
  32569. this.callBase();
  32570. this._textHasBeenChanged = false
  32571. },
  32572. _getPattern: function(patternKey) {
  32573. return !support.inputType(this.option("mode")) ? Globalize.culture().calendar.patterns[patternKey] : null
  32574. },
  32575. _valueChangeEventHandler: function(e) {
  32576. var text = this.option("text"),
  32577. date = this._strategy.getParsedText(text, this.option("formatString")),
  32578. value = this.option("value"),
  32579. modelValue = new Date(value && value.valueOf()),
  32580. mode = this.option("mode"),
  32581. newValue = (mode !== "text" ? dateUtils.mergeDates(modelValue, date, mode) : date) || null;
  32582. this._text = text;
  32583. this._textHasBeenChanged = true;
  32584. if (this._validateValue(date))
  32585. this.option("value", newValue);
  32586. else
  32587. this.option().value = null;
  32588. this.validationRequest.fire({
  32589. value: newValue,
  32590. editor: this
  32591. })
  32592. },
  32593. _validateValue: function(value) {
  32594. var text = this.option("text"),
  32595. hasText = !!text,
  32596. isDate = !!value,
  32597. isDateInRange = isDate && utils.dateInRange(value, this.option("min"), this.option("max")),
  32598. isValid = this._textHasBeenChanged && !hasText || !hasText && !value || isDateInRange,
  32599. validationMessage = "";
  32600. if (!isDate)
  32601. validationMessage = Globalize.localize("dxDateBox-validation-datetime");
  32602. else if (!isDateInRange)
  32603. validationMessage = Globalize.localize("validation-range");
  32604. this.option({
  32605. isValid: isValid,
  32606. validationError: isValid ? null : {
  32607. editorSpecific: true,
  32608. message: validationMessage
  32609. }
  32610. });
  32611. return isValid
  32612. },
  32613. _updateDropButtonVisibility: function() {
  32614. this.option("showDropButton", DX.devices.real().platform !== "generic" || this.option("pickerType") !== "native")
  32615. },
  32616. _renderProps: function() {
  32617. this.callBase();
  32618. this._input().attr("autocomplete", "off")
  32619. },
  32620. _renderOpenedState: function() {
  32621. this._openedStateRendering = true;
  32622. if (!this._isNativeView())
  32623. this.callBase();
  32624. this._strategy.renderOpenedState();
  32625. this._openedStateRendering = false
  32626. },
  32627. _isNativeView: function() {
  32628. return this.option("pickerType") === "native"
  32629. },
  32630. _popupShownHandler: function(e) {
  32631. this.callBase.apply(this, arguments);
  32632. this._text = this.option("text")
  32633. },
  32634. _getPopupTitle: function() {
  32635. var result = this.option("placeholder");
  32636. if (!result) {
  32637. var format = this.option("format");
  32638. switch (format) {
  32639. case"time":
  32640. result = Globalize.localize("dxDateBox-simulatedDataPickerTitleTime");
  32641. break;
  32642. case"date":
  32643. case"datetime":
  32644. result = Globalize.localize("dxDateBox-simulatedDataPickerTitleDate");
  32645. break
  32646. }
  32647. }
  32648. return result
  32649. },
  32650. _renderPlaceholder: function() {
  32651. var popupTitle = this._getPopupTitle();
  32652. this._popup && this._popup.option("title", popupTitle);
  32653. this.callBase()
  32654. },
  32655. _refreshStrategy: function() {
  32656. this._strategy.dispose();
  32657. this._initStrategy();
  32658. this._strategy.initFormat();
  32659. this.option(this._strategy.getDefaultOptions());
  32660. this._refresh()
  32661. },
  32662. _applyButtonHandler: function() {
  32663. this.option("value", this._strategy.getValue());
  32664. this.callBase()
  32665. },
  32666. _dispose: function() {
  32667. this._strategy && this._strategy.dispose();
  32668. this.callBase()
  32669. },
  32670. _optionChanged: function(args) {
  32671. switch (args.name) {
  32672. case"useCalendar":
  32673. case"useNative":
  32674. this._hasPickerTypePriority = false;
  32675. this._updatePickerOptions();
  32676. break;
  32677. case"showClearButton":
  32678. this.callBase.apply(this, arguments);
  32679. this._updateSize();
  32680. break;
  32681. case"pickerType":
  32682. this._hasPickerTypePriority = true;
  32683. this._updatePickerOptions();
  32684. this._refreshStrategy();
  32685. this._invalidate();
  32686. break;
  32687. case"format":
  32688. this._updatePickerOptions();
  32689. this._refreshStrategy();
  32690. this._updateSize();
  32691. break;
  32692. case"placeholder":
  32693. this._renderPlaceholder();
  32694. break;
  32695. case"readOnly":
  32696. case"min":
  32697. case"max":
  32698. case"interval":
  32699. case"minZoomLevel":
  32700. case"maxZoomLevel":
  32701. this._invalidate();
  32702. break;
  32703. case"type":
  32704. throw DX.Error("E1020");
  32705. case"formatString":
  32706. case"formatWidthCalculator":
  32707. break;
  32708. case"closeOnValueChange":
  32709. var applyValueMode = args.value ? "instantly" : "useButtons";
  32710. this.option("applyValueMode", applyValueMode);
  32711. break;
  32712. case"applyValueMode":
  32713. this._suppressDeprecatedWarnings();
  32714. this.option("closeOnValueChange", args.value === "instantly");
  32715. this._resumeDeprecatedWarnings();
  32716. this.callBase.apply(this, arguments);
  32717. break;
  32718. case"text":
  32719. this._strategy.textChangedHandler(args.value);
  32720. this.callBase.apply(this, arguments);
  32721. break;
  32722. case"isValid":
  32723. this.callBase.apply(this, arguments);
  32724. this._updateSize();
  32725. break;
  32726. default:
  32727. this.callBase.apply(this, arguments)
  32728. }
  32729. }
  32730. }));
  32731. ui.dxDateBox.renderingStrategies = {}
  32732. })(jQuery, DevExpress);
  32733. /*! Module widgets-base, file ui.dateBox.strategy.js */
  32734. (function($, DX, undefined) {
  32735. var ui = DX.ui;
  32736. ui.dxDateBox.strategy = DX.Class.inherit({
  32737. ctor: function(dateBox) {
  32738. this.dateBox = dateBox
  32739. },
  32740. widgetOption: function() {
  32741. return this._widget && this._widget.option.apply(this._widget, arguments)
  32742. },
  32743. _renderWidget: function(element) {
  32744. element = element || $("<div>");
  32745. this._widget = this._createWidget(element);
  32746. this._widget.element().appendTo(this._getWidgetContainer())
  32747. },
  32748. _createWidget: function(element) {
  32749. return this.dateBox._createComponent(element, this._getWidgetName(), this._getWidgetOptions())
  32750. },
  32751. _getWidgetOptions: DX.abstract,
  32752. _getWidgetName: DX.abstract,
  32753. initFormat: function() {
  32754. this.dateBox.option("mode", "text")
  32755. },
  32756. supportedKeys: $.noop,
  32757. attachKeyboardEvents: function(keyboardProcessor) {
  32758. this._widgetKeyboardProcessor = keyboardProcessor.attachChildProcessor()
  32759. },
  32760. getParsedText: function(text, format) {
  32761. return Globalize.parseDate(text, format)
  32762. },
  32763. getDefaultOptions: DX.abstract,
  32764. _getDateBoxClass: DX.abstract,
  32765. renderOpenedState: function() {
  32766. if (this.dateBox.option("opened"))
  32767. this._updateValue()
  32768. },
  32769. popupConfig: DX.abstract,
  32770. renderPopupContent: function() {
  32771. var popup = this._getPopup();
  32772. popup._wrapper().addClass(this._getPopupWrapperClass());
  32773. this._renderWidget();
  32774. popup.content().parent().off("mousedown").on("mousedown", $.proxy(this._preventFocusOnPopup, this))
  32775. },
  32776. _preventFocusOnPopup: function(e) {
  32777. e.preventDefault()
  32778. },
  32779. _getWidgetContainer: function() {
  32780. return this._getPopup().content()
  32781. },
  32782. _getPopup: function() {
  32783. return this.dateBox._popup
  32784. },
  32785. _getPopupWrapperClass: DX.abstract,
  32786. popupShowingHandler: $.noop,
  32787. popupHiddenHandler: $.noop,
  32788. _getDateBoxValue: function() {
  32789. return this.dateBox.option("value")
  32790. },
  32791. _updateValue: function() {
  32792. this._widget && this._widget.option("value", this._getDateBoxValue())
  32793. },
  32794. _valueChangedHandler: function(args) {
  32795. if (this.dateBox.option("opened") && this.dateBox.option("applyValueMode") === "instantly")
  32796. this.dateBox.option("value", args.value)
  32797. },
  32798. textChangedHandler: $.noop,
  32799. renderValue: function() {
  32800. if (this.dateBox.option("opened"))
  32801. this._updateValue()
  32802. },
  32803. getValue: function() {
  32804. return this._widget.option("value")
  32805. },
  32806. render: function() {
  32807. this.dateBox.element().addClass(this._getDateBoxClass())
  32808. },
  32809. dispose: function() {
  32810. this.dateBox.element().removeClass(this._getDateBoxClass());
  32811. var popup = this._getPopup();
  32812. if (popup) {
  32813. popup._wrapper().removeClass(this._getPopupWrapperClass());
  32814. popup.content().empty()
  32815. }
  32816. }
  32817. })
  32818. })(jQuery, DevExpress);
  32819. /*! Module widgets-base, file ui.dateBox.strategy.calendar.js */
  32820. (function($, DX, undefined) {
  32821. var ui = DX.ui,
  32822. utils = DX.utils,
  32823. DATEBOX_WITH_CALENDAR_CLASS = "dx-datebox-with-calendar",
  32824. DATEBOX_CALENDAR_OVERLAY_CLASS = "dx-datebox-calendar-overlay";
  32825. ui.dxDateBox.renderingStrategies["Calendar"] = ui.dxDateBox.strategy.inherit({
  32826. NAME: "Calendar",
  32827. supportedKeys: function() {
  32828. return {
  32829. tab: function() {
  32830. this.close()
  32831. },
  32832. rightArrow: function() {
  32833. if (this.option("opened"))
  32834. return true
  32835. },
  32836. leftArrow: function() {
  32837. if (this.option("opened"))
  32838. return true
  32839. },
  32840. enter: $.proxy(function(e) {
  32841. if (this.dateBox.option("opened")) {
  32842. if (this.dateBox._text !== e.target.value) {
  32843. this.dateBox._valueChangeEventHandler(e);
  32844. return false
  32845. }
  32846. if (this._widget.option("zoomLevel") === this._widget.option("maxZoomLevel")) {
  32847. var contouredDate = this._widget._view.option("contouredDate");
  32848. contouredDate && this.dateBox.option("value", contouredDate);
  32849. this.dateBox.close();
  32850. this.dateBox._valueChangeEventHandler(e)
  32851. }
  32852. else
  32853. return true
  32854. }
  32855. }, this)
  32856. }
  32857. },
  32858. getDefaultOptions: function() {
  32859. return {formatString: Globalize.culture().calendar.patterns["d"]}
  32860. },
  32861. _getDateBoxClass: function() {
  32862. return DATEBOX_WITH_CALENDAR_CLASS
  32863. },
  32864. _getPopupWrapperClass: function() {
  32865. return DATEBOX_CALENDAR_OVERLAY_CLASS
  32866. },
  32867. _getWidgetName: function() {
  32868. return "dxCalendar"
  32869. },
  32870. _getWidgetOptions: function() {
  32871. return $.extend(this.dateBox.option("calendarOptions"), {
  32872. value: this._getDateBoxValue(),
  32873. _keyboardProcessor: this._widgetKeyboardProcessor,
  32874. min: this.dateBox.option("min"),
  32875. max: this.dateBox.option("max"),
  32876. onValueChanged: $.proxy(this._valueChangedHandler, this),
  32877. onCellClick: $.proxy(this._cellClickHandler, this),
  32878. tabIndex: null,
  32879. maxZoomLevel: this.dateBox.option("maxZoomLevel"),
  32880. minZoomLevel: this.dateBox.option("minZoomLevel"),
  32881. onContouredChanged: $.proxy(this._refreshActiveDescendant, this)
  32882. })
  32883. },
  32884. _refreshActiveDescendant: function(e) {
  32885. this.dateBox.setAria("activedescendant", e.actionValue)
  32886. },
  32887. popupConfig: function(popupConfig) {
  32888. var buttons = popupConfig.buttons,
  32889. buttonsLocation = this.dateBox.option("buttonsLocation");
  32890. var position = [];
  32891. if (buttonsLocation !== "default")
  32892. position = DX.utils.splitPair(buttonsLocation);
  32893. else
  32894. position = ["bottom", "center"];
  32895. if (this.dateBox.option("applyValueMode") === "useButtons")
  32896. buttons.unshift({
  32897. widget: "button",
  32898. toolbar: position[0],
  32899. location: position[1] === "after" ? "before" : position[1],
  32900. options: {
  32901. onClick: $.proxy(function() {
  32902. this._widget._toTodayView()
  32903. }, this),
  32904. text: Globalize.localize("dxCalendar-todayButtonText"),
  32905. type: "today"
  32906. }
  32907. });
  32908. return $.extend(popupConfig, {buttons: buttons})
  32909. },
  32910. _valueChangedHandler: function(e) {
  32911. if (this.dateBox._openedStateRendering)
  32912. return;
  32913. var dateBox = this.dateBox,
  32914. value = e.value,
  32915. prevValue = e.previousValue;
  32916. var isSameDate = utils.sameMonthAndYear(value, prevValue) && value.getDate() === prevValue.getDate();
  32917. if (isSameDate)
  32918. return;
  32919. if (dateBox.option("applyValueMode") === "instantly")
  32920. dateBox.option("value", this.getValue())
  32921. },
  32922. _getParsedValue: function() {
  32923. return this.getParsedText(this.dateBox.option("text"), this.dateBox.option("formatString"))
  32924. },
  32925. _updateValue: function(preventDefaultValue) {
  32926. var parsedValue = this._getParsedValue();
  32927. if (!parsedValue && !preventDefaultValue)
  32928. parsedValue = new Date;
  32929. if (this._widget) {
  32930. var value = this.dateBox.option("value");
  32931. if (parsedValue) {
  32932. if (value)
  32933. parsedValue.setHours(value.getHours(), value.getMinutes(), value.getSeconds());
  32934. this._widget.option("value", parsedValue)
  32935. }
  32936. }
  32937. },
  32938. textChangedHandler: function() {
  32939. if (this.dateBox.option("opened") && this._widget)
  32940. this._updateValue(true)
  32941. },
  32942. _cellClickHandler: function() {
  32943. var dateBox = this.dateBox;
  32944. if (dateBox.option("applyValueMode") === "instantly")
  32945. dateBox.option({
  32946. opened: dateBox._textHasBeenChanged,
  32947. value: this.getValue()
  32948. })
  32949. },
  32950. dispose: function() {
  32951. this.dateBox.off("optionChanged");
  32952. this.callBase()
  32953. }
  32954. })
  32955. })(jQuery, DevExpress);
  32956. /*! Module widgets-base, file ui.dateBox.strategy.calendarWithTime.js */
  32957. (function($, DX, undefined) {
  32958. var ui = DX.ui,
  32959. CALENDAR_WITH_TIME_PICKER_CLASS = "dx-calendar-with-time-picker",
  32960. CALENDAR_WITH_TIME_PICKER_CONTAINER_CLASS = "dx-calendar-with-time-picker-container";
  32961. ui.dxDateBox.renderingStrategies["CalendarWithTime"] = ui.dxDateBox.renderingStrategies["Calendar"].inherit({
  32962. NAME: "CalendarWithTime",
  32963. supportedKeys: function() {
  32964. return $.extend(this.callBase(), {tab: function(e) {
  32965. if (this.option("opened") === true) {
  32966. e.preventDefault();
  32967. this._strategy._timeView._hourBox.focus()
  32968. }
  32969. }})
  32970. },
  32971. getDefaultOptions: function() {
  32972. return $.extend(this.callBase(), {
  32973. formatString: Globalize.culture().calendar.patterns["d"] + " " + Globalize.culture().calendar.patterns["t"],
  32974. applyValueMode: "useButtons",
  32975. buttonsLocation: "bottom after",
  32976. showPopupTitle: false
  32977. })
  32978. },
  32979. _renderWidget: function() {
  32980. this.callBase();
  32981. this._timeView = this.dateBox._createComponent($("<div>"), "dxTimeView", {
  32982. value: this.dateBox.option("value"),
  32983. onValueChanged: $.proxy(this._valueChangedHandler, this)
  32984. })
  32985. },
  32986. _updateValue: function(preventDefaultValue) {
  32987. var date = this._getParsedValue();
  32988. if (!date && !preventDefaultValue)
  32989. date = new Date;
  32990. this.callBase.apply(this, arguments);
  32991. if (this._timeView && date)
  32992. this._timeView.option("value", date)
  32993. },
  32994. renderPopupContent: function() {
  32995. this.callBase();
  32996. var $popupContent = this._getPopup().content().addClass(CALENDAR_WITH_TIME_PICKER_CONTAINER_CLASS);
  32997. var box = this.dateBox._createComponent($("<div>").appendTo($popupContent), "dxBox", {
  32998. direction: "row",
  32999. crossAlign: "start",
  33000. items: [{
  33001. ratio: 0,
  33002. shrink: 0,
  33003. baseSize: "auto",
  33004. name: "calendar"
  33005. }, {
  33006. ratio: 0,
  33007. shrink: 0,
  33008. baseSize: "auto",
  33009. name: "time"
  33010. }],
  33011. itemTemplate: $.proxy(function(data) {
  33012. switch (data.name) {
  33013. case"calendar":
  33014. return $("<div>").append(this._widget.element());
  33015. case"time":
  33016. return $("<div>").append(this._timeView.element())
  33017. }
  33018. }, this)
  33019. });
  33020. this._removeMinWidthTimer = setTimeout(function() {
  33021. if (box.option("_layoutStrategy") === "fallback")
  33022. $popupContent.find(".dx-timeview-clock").css("minWidth", 0)
  33023. }, 0);
  33024. this._attachTabHandler()
  33025. },
  33026. _attachTabHandler: function() {
  33027. var dateBox = this.dateBox,
  33028. handler = function(e) {
  33029. if (e.shiftKey) {
  33030. e.preventDefault();
  33031. dateBox.focus()
  33032. }
  33033. };
  33034. this._timeView._hourBox.registerKeyHandler("tab", handler)
  33035. },
  33036. _preventFocusOnPopup: function(e) {
  33037. if (!$(e.target).hasClass("dx-texteditor-input")) {
  33038. this.callBase.apply(this, arguments);
  33039. if (!this.dateBox.element().hasClass("dx-state-focused"))
  33040. this.dateBox.focus()
  33041. }
  33042. },
  33043. getValue: function() {
  33044. var date = this._widget.option("value"),
  33045. time = this._timeView.option("value");
  33046. date = date ? new Date(date) : new Date(1970, 0, 1, 0, 0, 0);
  33047. date.setHours(time.getHours(), time.getMinutes(), time.getSeconds());
  33048. return date
  33049. },
  33050. render: function() {
  33051. this.dateBox.element().addClass(CALENDAR_WITH_TIME_PICKER_CLASS);
  33052. this.callBase()
  33053. },
  33054. dispose: function() {
  33055. clearTimeout(this._removeMinWidthTimer);
  33056. this.dateBox.element().removeClass(CALENDAR_WITH_TIME_PICKER_CLASS);
  33057. this.callBase();
  33058. var popup = this._getPopup();
  33059. popup && popup._wrapper().removeClass(this._getPopupWrapperClass())
  33060. }
  33061. })
  33062. })(jQuery, DevExpress);
  33063. /*! Module widgets-base, file ui.dateBox.strategy.dateView.js */
  33064. var DATEVIEW_PICKER_OVERLAY_CLASS = "dx-dateview-picker-overlay";
  33065. (function($, DX, undefined) {
  33066. var ui = DX.ui,
  33067. support = DX.support,
  33068. dateUtils = ui.dateUtils,
  33069. DATEBOX_DATEVIEW_CLASS = "dx-datebox-dateview";
  33070. ui.dxDateBox.renderingStrategies["DateView"] = ui.dxDateBox.strategy.inherit({
  33071. NAME: "DateView",
  33072. popupShowingHandler: function() {
  33073. this._widget.option("visible", true)
  33074. },
  33075. popupHiddenHandler: function() {
  33076. this._widget.option("visible", false)
  33077. },
  33078. getDefaultOptions: function() {
  33079. return {
  33080. openOnFieldClick: true,
  33081. applyButtonText: Globalize.localize("Done")
  33082. }
  33083. },
  33084. _getDateBoxClass: function() {
  33085. return DATEBOX_DATEVIEW_CLASS
  33086. },
  33087. popupConfig: function() {
  33088. return {
  33089. showTitle: true,
  33090. buttons: this.dateBox._popupButtonsConfig(),
  33091. defaultOptionsRules: [{
  33092. device: {platform: "win8"},
  33093. options: {showNames: true}
  33094. }, {
  33095. device: {
  33096. platform: "win8",
  33097. phone: true
  33098. },
  33099. options: {
  33100. fullScreen: true,
  33101. animation: null
  33102. }
  33103. }, {
  33104. device: function(device) {
  33105. return device.platform !== "win8"
  33106. },
  33107. options: {
  33108. width: 333,
  33109. height: 331
  33110. }
  33111. }, {
  33112. device: {platform: "generic"},
  33113. options: {
  33114. width: "auto",
  33115. height: "auto"
  33116. }
  33117. }, {
  33118. device: {platform: "ios"},
  33119. options: {
  33120. width: "auto",
  33121. height: "auto"
  33122. }
  33123. }, {
  33124. device: {
  33125. platform: "ios",
  33126. phone: true
  33127. },
  33128. options: {
  33129. width: "100%",
  33130. position: {
  33131. my: "bottom",
  33132. at: "bottom",
  33133. of: window
  33134. }
  33135. }
  33136. }]
  33137. }
  33138. },
  33139. getParsedText: function(text) {
  33140. return dateUtils.fromStandardDateFormat(text)
  33141. },
  33142. _renderWidget: function() {
  33143. if (this.dateBox._usingNativeDatePicker() || this.dateBox.option("readOnly")) {
  33144. if (this._widget) {
  33145. this._widget.element().remove();
  33146. this._widget = null
  33147. }
  33148. return
  33149. }
  33150. var popup = this._getPopup();
  33151. if (this._widget)
  33152. this._widget.option(this._getWidgetOptions());
  33153. else {
  33154. var element = $("<div>").appendTo(popup.content());
  33155. this._widget = this._createWidget(element)
  33156. }
  33157. this._widget.element().appendTo(this._getWidgetContainer());
  33158. popup._$wrapper.addClass(DATEVIEW_PICKER_OVERLAY_CLASS)
  33159. },
  33160. _getWidgetName: function() {
  33161. return "dxDateView"
  33162. },
  33163. _getDateBoxValue: function() {
  33164. return this.callBase() || new Date
  33165. },
  33166. _getWidgetOptions: function() {
  33167. return {
  33168. value: this._getDateBoxValue(),
  33169. format: this.dateBox.option("format"),
  33170. minDate: this.dateBox.option("min") || new Date(1),
  33171. maxDate: this.dateBox.option("max") || new Date($.now() + dateUtils.TEN_YEARS),
  33172. visible: false,
  33173. onDisposing: $.proxy(function() {
  33174. this._widget = null
  33175. }, this)
  33176. }
  33177. },
  33178. _getPopupWrapperClass: function() {
  33179. return ""
  33180. },
  33181. initFormat: function() {
  33182. var format = this.dateBox.option("format");
  33183. if ($.inArray(format, dateUtils.SUPPORTED_FORMATS) === -1)
  33184. format = "date";
  33185. else if (format === "datetime" && !support.inputType(format))
  33186. format = "datetime-local";
  33187. this.dateBox.option({
  33188. mode: format,
  33189. formatString: dateUtils.FORMATS_MAP[format]
  33190. })
  33191. }
  33192. })
  33193. })(jQuery, DevExpress);
  33194. /*! Module widgets-base, file ui.dateBox.strategy.list.js */
  33195. (function($, DX, undefined) {
  33196. var ui = DX.ui,
  33197. dateUtils = ui.dateUtils,
  33198. DATEBOX_LIST_CLASS = "dx-datebox-list",
  33199. DATEBOX_LIST_POPUP_WRAPPER = "dx-datebox-list-popup-wrapper";
  33200. ui.dxDateBox.renderingStrategies["List"] = ui.dxDateBox.strategy.inherit({
  33201. NAME: "List",
  33202. supportedKeys: function() {
  33203. return {
  33204. tab: function(e) {
  33205. if (this.option("opened"))
  33206. this.close()
  33207. },
  33208. space: $.noop,
  33209. home: $.noop,
  33210. end: $.noop
  33211. }
  33212. },
  33213. getDefaultOptions: function() {
  33214. return {
  33215. formatString: Globalize.culture().calendar.patterns["t"],
  33216. applyValueMode: "instantly",
  33217. interval: 30
  33218. }
  33219. },
  33220. _getDateBoxClass: function() {
  33221. return DATEBOX_LIST_CLASS
  33222. },
  33223. _getPopupWrapperClass: function() {
  33224. return DATEBOX_LIST_POPUP_WRAPPER
  33225. },
  33226. popupConfig: function(popupConfig) {
  33227. return $.extend(popupConfig, {width: this.dateBox.element().outerWidth()})
  33228. },
  33229. popupShowingHandler: function() {
  33230. this._dimensionChanged()
  33231. },
  33232. _renderWidget: function() {
  33233. this.callBase();
  33234. this._refreshItems()
  33235. },
  33236. _getWidgetName: function() {
  33237. return "dxList"
  33238. },
  33239. _getWidgetOptions: function() {
  33240. var keyboardProcessor = this.dateBox._keyboardProcessor;
  33241. return {
  33242. _keyboardProcessor: keyboardProcessor ? keyboardProcessor.attachChildProcessor() : null,
  33243. itemTemplate: $.proxy(this._timeListItemTemplate, this),
  33244. onItemClick: $.proxy(this._listItemClickHandler, this),
  33245. tabIndex: -1,
  33246. onFocusedItemChanged: $.proxy(this._refreshActiveDescendant, this)
  33247. }
  33248. },
  33249. _refreshActiveDescendant: function(e) {
  33250. this.dateBox.setAria("activedescendant", "");
  33251. this.dateBox.setAria("activedescendant", e.actionValue)
  33252. },
  33253. _refreshItems: function() {
  33254. var items = this._getTimeListItems();
  33255. this._widget.option("items", items)
  33256. },
  33257. _getTimeListItems: function() {
  33258. var min = this.dateBox.option("min") || new Date(0, 0, 0, 0, 0),
  33259. max = this.dateBox.option("max") || new Date(0, 0, 0, 23, 59),
  33260. interval = this.dateBox.option("interval"),
  33261. result = [],
  33262. current = new Date(min),
  33263. delta = max - min;
  33264. if (delta < 0)
  33265. return [];
  33266. if (delta > dateUtils.ONE_DAY)
  33267. delta = dateUtils.ONE_DAY;
  33268. while (current - min < delta) {
  33269. result.push(new Date(current));
  33270. current.setMinutes(current.getMinutes() + interval)
  33271. }
  33272. return result
  33273. },
  33274. _timeListItemTemplate: function(itemData) {
  33275. return Globalize.format(itemData, this.dateBox.option("formatString"))
  33276. },
  33277. _listItemClickHandler: function(e) {
  33278. this.dateBox.option("opened", false);
  33279. this.dateBox.option("value", e.itemData)
  33280. },
  33281. attachKeyboardEvents: function(keyboardProcessor) {
  33282. var child = keyboardProcessor.attachChildProcessor();
  33283. if (this._widget)
  33284. this._widget.option("_keyboardProcessor", child)
  33285. },
  33286. _dimensionChanged: function() {
  33287. this._getPopup() && this._updatePopupDimensions()
  33288. },
  33289. _updatePopupDimensions: function() {
  33290. this._updatePopupWidth();
  33291. this._updatePopupHeight()
  33292. },
  33293. _updatePopupWidth: function() {
  33294. this.dateBox._setPopupOption("width", this.dateBox.element().outerWidth())
  33295. },
  33296. _updatePopupHeight: function() {
  33297. this.dateBox._setPopupOption("height", "auto");
  33298. var popupHeight = this.dateBox._popup.overlayContent().outerHeight();
  33299. var maxHeight = $(window).height() * 0.45;
  33300. this.dateBox._setPopupOption("height", Math.min(popupHeight, maxHeight));
  33301. this.dateBox._timeList && this.dateBox._timeList.updateDimensions()
  33302. }
  33303. })
  33304. })(jQuery, DevExpress);
  33305. /*! Module widgets-base, file ui.loadIndicator.js */
  33306. (function($, DX, undefined) {
  33307. var ui = DX.ui;
  33308. var LOADINDICATOR_CLASS = "dx-loadindicator",
  33309. LOADINDICATOR_WRAPPER_CLASS = "dx-loadindicator-wrapper",
  33310. LOADINDICATOR_CONTENT_CLASS = "dx-loadindicator-content",
  33311. LOADINDICATOR_ICON_CLASS = "dx-loadindicator-icon",
  33312. LOADINDICATOR_SEGMENT_CLASS = "dx-loadindicator-segment",
  33313. LOADINDICATOR_SEGMENT_INNER_CLASS = "dx-loadindicator-segment-inner",
  33314. LOADINDICATOR_IMAGE_CLASS = "dx-loadindicator-image";
  33315. DX.registerComponent("dxLoadIndicator", ui, ui.Widget.inherit({
  33316. _setDefaultOptions: function() {
  33317. this.callBase();
  33318. this.option({
  33319. indicatorSrc: "",
  33320. activeStateEnabled: false,
  33321. hoverStateEnabled: false,
  33322. _animatingSegmentCount: 0
  33323. })
  33324. },
  33325. _defaultOptionsRules: function() {
  33326. return this.callBase().concat([{
  33327. device: function() {
  33328. var realDevice = DevExpress.devices.real(),
  33329. obsoleteAndroid = realDevice.platform === "android" && !/chrome/i.test(navigator.userAgent);
  33330. return DevExpress.browser.msie && DevExpress.browser.version < 10 || obsoleteAndroid
  33331. },
  33332. options: {viaImage: true}
  33333. }, {
  33334. device: [{platform: "win8"}],
  33335. options: {_animatingSegmentCount: 5}
  33336. }, {
  33337. device: function(device) {
  33338. return device.platform === "ios"
  33339. },
  33340. options: {_animatingSegmentCount: 11}
  33341. }, {
  33342. device: [{platform: "android"}],
  33343. options: {_animatingSegmentCount: 2}
  33344. }, {
  33345. device: [{platform: "generic"}],
  33346. options: {_animatingSegmentCount: 7}
  33347. }])
  33348. },
  33349. _init: function() {
  33350. this.callBase();
  33351. this.element().addClass(LOADINDICATOR_CLASS)
  33352. },
  33353. _render: function() {
  33354. this._renderWrapper();
  33355. this._renderContent();
  33356. this._renderMarkup();
  33357. this.callBase()
  33358. },
  33359. _renderWrapper: function() {
  33360. this._$wrapper = $("<div>").addClass(LOADINDICATOR_WRAPPER_CLASS);
  33361. this.element().append(this._$wrapper)
  33362. },
  33363. _renderContent: function() {
  33364. this._$content = $("<div>").addClass(LOADINDICATOR_CONTENT_CLASS);
  33365. this._$wrapper.append(this._$content)
  33366. },
  33367. _renderMarkup: function() {
  33368. if (DX.support.animation && !this.option("viaImage") && !this.option("indicatorSrc"))
  33369. this._renderMarkupForAnimation();
  33370. else
  33371. this._renderMarkupForImage()
  33372. },
  33373. _renderMarkupForAnimation: function() {
  33374. var currentDevice = DX.devices.current();
  33375. this._$indicator = $("<div>").addClass(LOADINDICATOR_ICON_CLASS);
  33376. this._$content.append(this._$indicator);
  33377. for (var i = this.option("_animatingSegmentCount"); i >= 0; --i) {
  33378. var $segment = $("<div>").addClass(LOADINDICATOR_SEGMENT_CLASS).addClass(LOADINDICATOR_SEGMENT_CLASS + i);
  33379. if (currentDevice.platform === "android")
  33380. $segment.append($("<div>").addClass(LOADINDICATOR_SEGMENT_INNER_CLASS));
  33381. this._$indicator.append($segment)
  33382. }
  33383. },
  33384. _renderMarkupForImage: function() {
  33385. var indicatorSrc = this.option("indicatorSrc");
  33386. this._$wrapper.addClass(LOADINDICATOR_IMAGE_CLASS);
  33387. if (indicatorSrc)
  33388. this._$wrapper.css("background-image", "url(" + indicatorSrc + ")")
  33389. },
  33390. _renderDimensions: function() {
  33391. this.callBase();
  33392. this._updateContentSizeForAnimation()
  33393. },
  33394. _updateContentSizeForAnimation: function() {
  33395. if (!this._$indicator)
  33396. return;
  33397. var width = this.option("width"),
  33398. height = this.option("height");
  33399. if (width || height) {
  33400. width = this.element().width();
  33401. height = this.element().height();
  33402. var minDimention = Math.min(height, width);
  33403. this._$wrapper.css({
  33404. height: minDimention,
  33405. width: minDimention,
  33406. "font-size": minDimention
  33407. })
  33408. }
  33409. },
  33410. _clean: function() {
  33411. this.callBase();
  33412. this._removeMarkupForAnimation();
  33413. this._removeMarkupForImage()
  33414. },
  33415. _removeMarkupForAnimation: function() {
  33416. if (!this._$indicator)
  33417. return;
  33418. this._$indicator.remove();
  33419. delete this._$indicator
  33420. },
  33421. _removeMarkupForImage: function() {
  33422. this._$wrapper.css("background-image", "none")
  33423. },
  33424. _optionChanged: function(args) {
  33425. switch (args.name) {
  33426. case"_animatingSegmentCount":
  33427. case"indicatorSrc":
  33428. this._invalidate();
  33429. break;
  33430. default:
  33431. this.callBase(args)
  33432. }
  33433. }
  33434. }))
  33435. })(jQuery, DevExpress);
  33436. /*! Module widgets-base, file ui.loadPanel.js */
  33437. (function($, DX, undefined) {
  33438. var ui = DX.ui;
  33439. var LOADPANEL_CLASS = "dx-loadpanel",
  33440. LOADPANEL_WRAPPER_CLASS = "dx-loadpanel-wrapper",
  33441. LOADPANEL_INDICATOR_CLASS = "dx-loadpanel-indicator",
  33442. LOADPANEL_MESSAGE_CLASS = "dx-loadpanel-message",
  33443. LOADPANEL_CONTENT_CLASS = "dx-loadpanel-content",
  33444. LOADPANEL_CONTENT_WRAPPER_CLASS = "dx-loadpanel-content-wrapper",
  33445. LOADPANEL_PANE_HIDDEN_CLASS = "dx-loadpanel-pane-hidden";
  33446. DX.registerComponent("dxLoadPanel", ui, ui.dxOverlay.inherit({
  33447. _setDefaultOptions: function() {
  33448. this.callBase();
  33449. this.option({
  33450. message: Globalize.localize("Loading"),
  33451. width: 222,
  33452. height: 90,
  33453. animation: null,
  33454. showIndicator: true,
  33455. indicatorSrc: "",
  33456. showPane: true,
  33457. delay: 0,
  33458. closeOnBackButton: false,
  33459. resizeEnabled: false
  33460. })
  33461. },
  33462. _init: function() {
  33463. this.callBase.apply(this, arguments);
  33464. this._$contentWrapper = $("<div>").addClass(LOADPANEL_CONTENT_WRAPPER_CLASS);
  33465. this._$contentWrapper.appendTo(this._$content)
  33466. },
  33467. _render: function() {
  33468. this.callBase();
  33469. this.element().addClass(LOADPANEL_CLASS);
  33470. this._wrapper().addClass(LOADPANEL_WRAPPER_CLASS)
  33471. },
  33472. _renderContentImpl: function() {
  33473. this.callBase();
  33474. this.content().addClass(LOADPANEL_CONTENT_CLASS);
  33475. this._togglePaneVisible();
  33476. this._cleanPreviousContent();
  33477. this._renderLoadIndicator();
  33478. this._renderMessage()
  33479. },
  33480. _show: function() {
  33481. var delay = this.option("delay");
  33482. if (!delay)
  33483. return this.callBase();
  33484. var deferred = $.Deferred();
  33485. var callBase = $.proxy(this.callBase, this);
  33486. this._clearShowTimeout();
  33487. this._showTimeout = setTimeout(function() {
  33488. callBase().done(function() {
  33489. deferred.resolve()
  33490. })
  33491. }, delay);
  33492. return deferred.promise()
  33493. },
  33494. _hide: function() {
  33495. this._clearShowTimeout();
  33496. return this.callBase()
  33497. },
  33498. _clearShowTimeout: function() {
  33499. clearTimeout(this._showTimeout)
  33500. },
  33501. _renderMessage: function() {
  33502. var message = this.option("message");
  33503. if (!message)
  33504. return;
  33505. var $message = $("<div>").addClass(LOADPANEL_MESSAGE_CLASS).text(message);
  33506. this._$contentWrapper.append($message)
  33507. },
  33508. _renderLoadIndicator: function() {
  33509. if (!this.option("showIndicator"))
  33510. return;
  33511. this._$indicator = $("<div>").addClass(LOADPANEL_INDICATOR_CLASS).appendTo(this._$contentWrapper);
  33512. this._createComponent(this._$indicator, "dxLoadIndicator", {indicatorSrc: this.option("indicatorSrc")})
  33513. },
  33514. _cleanPreviousContent: function() {
  33515. this.content().find("." + LOADPANEL_MESSAGE_CLASS).remove();
  33516. this.content().find("." + LOADPANEL_INDICATOR_CLASS).remove()
  33517. },
  33518. _togglePaneVisible: function() {
  33519. this.content().toggleClass(LOADPANEL_PANE_HIDDEN_CLASS, !this.option("showPane"))
  33520. },
  33521. _optionChanged: function(args) {
  33522. switch (args.name) {
  33523. case"delay":
  33524. break;
  33525. case"message":
  33526. case"showIndicator":
  33527. this._cleanPreviousContent();
  33528. this._renderLoadIndicator();
  33529. this._renderMessage();
  33530. break;
  33531. case"showPane":
  33532. this._togglePaneVisible();
  33533. break;
  33534. case"indicatorSrc":
  33535. if (this._$indicator)
  33536. this._createComponent(this._$indicator, "dxLoadIndicator", {indicatorSrc: this.option("indicatorSrc")});
  33537. break;
  33538. default:
  33539. this.callBase(args)
  33540. }
  33541. },
  33542. _dispose: function() {
  33543. this._clearShowTimeout();
  33544. this.callBase()
  33545. }
  33546. }));
  33547. ui.dxLoadPanel.__internals = {
  33548. LOADPANEL_CLASS: LOADPANEL_CLASS,
  33549. LOADPANEL_WRAPPER_CLASS: LOADPANEL_WRAPPER_CLASS,
  33550. LOADPANEL_MESSAGE_CLASS: LOADPANEL_MESSAGE_CLASS,
  33551. LOADPANEL_CONTENT_CLASS: LOADPANEL_CONTENT_CLASS,
  33552. LOADPANEL_PANE_HIDDEN_CLASS: LOADPANEL_PANE_HIDDEN_CLASS
  33553. }
  33554. })(jQuery, DevExpress);
  33555. /*! Module widgets-base, file ui.lookup.js */
  33556. (function($, DX, undefined) {
  33557. var ui = DX.ui,
  33558. utils = DX.utils,
  33559. events = ui.events;
  33560. var LOOKUP_CLASS = "dx-lookup",
  33561. LOOKUP_SELECTED_CLASS = "dx-lookup-selected",
  33562. LOOKUP_SEARCH_CLASS = "dx-lookup-search",
  33563. LOOKUP_SEARCH_WRAPPER_CLASS = "dx-lookup-search-wrapper",
  33564. LOOKUP_FIELD_CLASS = "dx-lookup-field",
  33565. LOOKUP_ARROW_CLASS = "dx-lookup-arrow",
  33566. LOOKUP_FIELD_WRAPPER_CLASS = "dx-lookup-field-wrapper",
  33567. LOOKUP_POPUP_CLASS = "dx-lookup-popup",
  33568. LOOKUP_POPUP_WRAPPER_CLASS = "dx-lookup-popup-wrapper",
  33569. LOOKUP_POPUP_SEARCH_CLASS = "dx-lookup-popup-search",
  33570. LOOKUP_POPOVER_MODE = "dx-lookup-popover-mode",
  33571. LOOKUP_EMPTY_CLASS = "dx-lookup-empty",
  33572. LOOKUP_POPUP_VALIDATION_MESSAGE = "dx-lookup-validation-message",
  33573. LOOKUP_POPUP_INVALID_CLASS = "dx-lookup-invalid",
  33574. LIST_ITEM_SELECTOR = ".dx-list-item",
  33575. LIST_ITEM_DATA_KEY = "dxListItemData";
  33576. var POPUP_OPTION_MAP = {
  33577. popupWidth: "width",
  33578. popupHeight: "height"
  33579. };
  33580. DX.registerComponent("dxLookup", ui, ui.dxDropDownList.inherit({
  33581. _supportedKeys: function() {
  33582. return $.extend(this.callBase(), {
  33583. space: function(e) {
  33584. this._validatedOpening()
  33585. },
  33586. enter: function(e) {
  33587. this._validatedOpening()
  33588. }
  33589. })
  33590. },
  33591. _setDeprecatedOptions: function() {
  33592. this.callBase();
  33593. $.extend(this._deprecatedOptions, {
  33594. minFilterLength: {
  33595. since: "14.2",
  33596. alias: "minSearchLength"
  33597. },
  33598. scrollAction: {
  33599. since: "14.2",
  33600. alias: "onScroll"
  33601. },
  33602. autoPagingEnabled: {
  33603. since: "14.2",
  33604. alias: "pagingEnabled"
  33605. },
  33606. pullRefreshAction: {
  33607. since: "14.2",
  33608. alias: "onPullRefresh"
  33609. },
  33610. pageLoadingAction: {
  33611. since: "14.2",
  33612. alias: "onPageLoading"
  33613. },
  33614. contentReadyAction: {
  33615. since: "14.2",
  33616. alias: "onContentReady"
  33617. },
  33618. titleRender: {
  33619. since: "14.2",
  33620. alias: "titleTemplate"
  33621. },
  33622. groupRender: {
  33623. since: "14.2",
  33624. alias: "groupTemplate"
  33625. },
  33626. doneButtonText: {
  33627. since: "14.2",
  33628. alias: "applyButtonText"
  33629. },
  33630. showDoneButton: {
  33631. since: "14.2",
  33632. message: "use the 'applyValueMode' option instead"
  33633. },
  33634. showNextButton: {
  33635. since: "15.1",
  33636. message: "Use the 'pageLoadMode' option instead"
  33637. },
  33638. pagingEnabled: {
  33639. since: "15.1",
  33640. message: "Use the 'dataSource.paginate' option instead"
  33641. }
  33642. })
  33643. },
  33644. _setDefaultOptions: function() {
  33645. this.callBase();
  33646. this.option({
  33647. title: "",
  33648. titleTemplate: "title",
  33649. onTitleRendered: null,
  33650. placeholder: Globalize.localize("Select"),
  33651. searchPlaceholder: Globalize.localize("Search"),
  33652. searchEnabled: true,
  33653. cleanSearchOnOpening: true,
  33654. fullScreen: false,
  33655. showCancelButton: true,
  33656. cancelButtonText: Globalize.localize("Cancel"),
  33657. showClearButton: false,
  33658. clearButtonText: Globalize.localize("Clear"),
  33659. applyButtonText: Globalize.localize("Done"),
  33660. popupWidth: function() {
  33661. return $(window).width() * 0.8
  33662. },
  33663. popupHeight: function() {
  33664. return $(window).height() * 0.8
  33665. },
  33666. shading: true,
  33667. closeOnOutsideClick: false,
  33668. position: undefined,
  33669. animation: undefined,
  33670. pullRefreshEnabled: false,
  33671. useNativeScrolling: true,
  33672. pullingDownText: Globalize.localize("dxList-pullingDownText"),
  33673. pulledDownText: Globalize.localize("dxList-pulledDownText"),
  33674. refreshingText: Globalize.localize("dxList-refreshingText"),
  33675. pageLoadingText: Globalize.localize("dxList-pageLoadingText"),
  33676. onScroll: null,
  33677. onPullRefresh: null,
  33678. onPageLoading: null,
  33679. pageLoadMode: "scrollBottom",
  33680. showNextButton: undefined,
  33681. nextButtonText: Globalize.localize("dxList-nextButtonText"),
  33682. grouped: false,
  33683. groupTemplate: "group",
  33684. usePopover: false,
  33685. showDropButton: false,
  33686. showPopupTitle: true
  33687. })
  33688. },
  33689. _defaultOptionsRules: function() {
  33690. return this.callBase().concat([{
  33691. device: function(device) {
  33692. return !DX.support.nativeScrolling
  33693. },
  33694. options: {useNativeScrolling: false}
  33695. }, {
  33696. device: function(device) {
  33697. return !DX.support.nativeScrolling && !DX.devices.isSimulator() && DX.devices.real().platform === "generic" && device.platform === "generic"
  33698. },
  33699. options: {
  33700. pageLoadMode: "nextButton",
  33701. usePopover: true
  33702. }
  33703. }, {
  33704. device: function(device) {
  33705. var browser = DX.browser;
  33706. return browser.msie && DX.compareVersions(browser.version, 9) < 0
  33707. },
  33708. options: {usePopover: false}
  33709. }, {
  33710. device: {
  33711. platform: "win8",
  33712. phone: true
  33713. },
  33714. options: {
  33715. showCancelButton: false,
  33716. fullScreen: true
  33717. }
  33718. }, {
  33719. device: {
  33720. platform: "win8",
  33721. phone: false
  33722. },
  33723. options: {popupWidth: function() {
  33724. return $(window).width()
  33725. }}
  33726. }, {
  33727. device: {
  33728. platform: "ios",
  33729. phone: true
  33730. },
  33731. options: {fullScreen: true}
  33732. }, {
  33733. device: {
  33734. platform: "ios",
  33735. tablet: true
  33736. },
  33737. options: {
  33738. popupWidth: function() {
  33739. return Math.min($(window).width(), $(window).height()) * 0.4
  33740. },
  33741. popupHeight: function() {
  33742. return Math.min($(window).width(), $(window).height()) * 0.4
  33743. },
  33744. usePopover: true
  33745. }
  33746. }, {
  33747. device: {platform: "generic"},
  33748. options: {buttonsLocation: "bottom center"}
  33749. }])
  33750. },
  33751. _initOptions: function(options) {
  33752. if (DX.utils.isDefined(options.showDoneButton) && !DX.utils.isDefined(options.applyValueMode)) {
  33753. var applyValueMode = options.showDoneButton ? "useButtons" : "instantly";
  33754. $.extend(options, {applyValueMode: applyValueMode})
  33755. }
  33756. this.callBase(options)
  33757. },
  33758. _getAriaTarget: function() {
  33759. return this._$field
  33760. },
  33761. _dataSourceOptions: function() {
  33762. this._suppressDeprecatedWarnings();
  33763. var pagingEnabled = utils.ensureDefined(this.option("pagingEnabled"), true);
  33764. pagingEnabled = utils.isDefined(this.option("showNextButton")) ? pagingEnabled || this.option("showNextButton") : pagingEnabled;
  33765. this._resumeDeprecatedWarnings();
  33766. return $.extend(this.callBase(), {paginate: pagingEnabled})
  33767. },
  33768. _inputWrapper: function() {
  33769. return this.element().find("." + LOOKUP_FIELD_WRAPPER_CLASS)
  33770. },
  33771. _render: function() {
  33772. this.callBase();
  33773. this.element().addClass(LOOKUP_CLASS).toggleClass(LOOKUP_POPOVER_MODE, this.option("usePopover"))
  33774. },
  33775. _fireContentReadyAction: $.noop,
  33776. _popupWrapperClass: function() {
  33777. return ""
  33778. },
  33779. _renderInput: function() {
  33780. var fieldClickAction = this._createAction($.proxy(function() {
  33781. this._validatedOpening()
  33782. }, this));
  33783. this._$field = $("<div>").addClass(LOOKUP_FIELD_CLASS).on(events.addNamespace("dxclick", this.NAME), function(e) {
  33784. fieldClickAction({jQueryEvent: e})
  33785. });
  33786. var $arrow = $("<div>").addClass(LOOKUP_ARROW_CLASS);
  33787. this._$fieldWrapper = $("<div>").addClass(LOOKUP_FIELD_WRAPPER_CLASS).append(this._$field).append($arrow).appendTo(this.element())
  33788. },
  33789. _popupShowingHandler: function() {
  33790. var validationError;
  33791. if (this._$popupValidationMessage) {
  33792. validationError = this.option("validationError");
  33793. if (validationError && validationError.message) {
  33794. this._$popupValidationMessage.text(validationError.message);
  33795. this._popup.content().addClass(LOOKUP_POPUP_INVALID_CLASS)
  33796. }
  33797. else
  33798. this._popup.content().removeClass(LOOKUP_POPUP_INVALID_CLASS)
  33799. }
  33800. this.callBase.apply(this, arguments);
  33801. if (this.option("cleanSearchOnOpening")) {
  33802. if (this.option("searchEnabled") && this._searchBox.option("value")) {
  33803. this._searchBox.option("value", "");
  33804. this._searchCanceled();
  33805. this._searchDataSource()
  33806. }
  33807. this._list && this._list.option("focusedElement", null)
  33808. }
  33809. },
  33810. _popupPositionedHandler: function() {
  33811. if (this.option("usePopover"))
  33812. this._updatePopoverHeight()
  33813. },
  33814. _updatePopoverHeight: function() {
  33815. if (!this._isInitialOptionValue("popupHeight"))
  33816. return;
  33817. var listHeight = 0,
  33818. topSpace = this._popup.content().position().top,
  33819. bottomSpace = this._popup.bottomToolbar() ? this._popup.bottomToolbar().outerHeight(true) : 0,
  33820. contentPaddings = topSpace + bottomSpace;
  33821. if (this._list) {
  33822. listHeight += this._list.element().position().top;
  33823. listHeight += this._list.element().outerHeight() - this._list.clientHeight();
  33824. listHeight += this._list.scrollHeight()
  33825. }
  33826. this._popup.overlayContent().css("maxHeight", "none");
  33827. var popupHeight = Math.min(listHeight + contentPaddings, this._popup.overlayContent().outerHeight());
  33828. this._popup.overlayContent().css("maxHeight", popupHeight);
  33829. this._list && this._list.updateDimensions()
  33830. },
  33831. _renderPopup: function() {
  33832. if (this.option("usePopover") && !this.option("fullScreen"))
  33833. this._renderPopover();
  33834. else
  33835. this.callBase();
  33836. this._$popup.addClass(LOOKUP_POPUP_CLASS);
  33837. this._popup._wrapper().addClass(LOOKUP_POPUP_WRAPPER_CLASS)
  33838. },
  33839. _popupOptionMap: function(optionName) {
  33840. return POPUP_OPTION_MAP[optionName] || optionName
  33841. },
  33842. _renderPopover: function() {
  33843. this._popup = this._createComponent(this._$popup, "dxPopover", $.extend(this._popupConfig(), {
  33844. target: this.element(),
  33845. fullScreen: false,
  33846. shading: false,
  33847. closeOnTargetScroll: true,
  33848. closeOnOutsideClick: true,
  33849. width: this._isInitialOptionValue("popupWidth") ? this.element().width() : this._popupConfig().width
  33850. }));
  33851. this._popup.on({
  33852. showing: $.proxy(this._popupShowingHandler, this),
  33853. shown: $.proxy(this._popupShownHandler, this),
  33854. hiding: $.proxy(this._popupHidingHandler, this),
  33855. hidden: $.proxy(this._popupHiddenHandler, this),
  33856. positioned: $.proxy(this._popupPositionedHandler, this)
  33857. });
  33858. this._popup.option("onContentReady", $.proxy(this._contentReadyHandler, this));
  33859. this._contentReadyHandler()
  33860. },
  33861. _popupHidingHandler: function() {
  33862. this.callBase();
  33863. this.option("focusStateEnabled") && this.focus()
  33864. },
  33865. _preventFocusOnPopup: $.noop,
  33866. _popupConfig: function() {
  33867. var result = $.extend(this.callBase(), {
  33868. onShowing: null,
  33869. showTitle: this.option("showPopupTitle"),
  33870. title: this.option("title"),
  33871. titleTemplate: this._getTemplateByOption("titleTemplate"),
  33872. onTitleRendered: this.option("onTitleRendered"),
  33873. buttons: this._getPopupButtons(),
  33874. fullScreen: this.option("fullScreen"),
  33875. shading: this.option("shading"),
  33876. closeOnTargetScroll: false,
  33877. closeOnOutsideClick: this.option("closeOnOutsideClick")
  33878. });
  33879. delete result.animation;
  33880. delete result.position;
  33881. $.each(["position", "animation", "popupWidth", "popupHeight"], $.proxy(function(_, optionName) {
  33882. if (this.option(optionName) !== undefined)
  33883. result[this._popupOptionMap(optionName)] = this.option(optionName)
  33884. }, this));
  33885. return result
  33886. },
  33887. _getPopupButtons: function() {
  33888. var buttonsConfig = this.option("applyValueMode") === "useButtons" ? this._popupButtonsConfig() : [];
  33889. var cancelButton = this._getCancelButtonConfig();
  33890. if (cancelButton)
  33891. buttonsConfig.push(cancelButton);
  33892. var clearButton = this._getClearButtonConfig();
  33893. if (clearButton)
  33894. buttonsConfig.push(clearButton);
  33895. return this._applyButtonsLocation(buttonsConfig)
  33896. },
  33897. _popupButtonsConfig: function() {
  33898. return [{
  33899. shortcut: "done",
  33900. options: {
  33901. onClick: $.proxy(this._applyButtonHandler, this),
  33902. text: this.option("applyButtonText")
  33903. }
  33904. }]
  33905. },
  33906. _getCancelButtonConfig: function() {
  33907. return this.option("showCancelButton") ? {
  33908. shortcut: "cancel",
  33909. onClick: $.proxy(this._cancelButtonHandler, this),
  33910. options: {text: this.option("cancelButtonText")}
  33911. } : null
  33912. },
  33913. _getClearButtonConfig: function() {
  33914. return this.option("showClearButton") ? {
  33915. shortcut: "clear",
  33916. onClick: $.proxy(this._resetValue, this),
  33917. options: {text: this.option("clearButtonText")}
  33918. } : null
  33919. },
  33920. _applyButtonHandler: function() {
  33921. this.option("value", this._valueGetter(this._currentSelectedItem()));
  33922. this.callBase()
  33923. },
  33924. _cancelButtonHandler: function() {
  33925. this._refreshSelected();
  33926. this.callBase()
  33927. },
  33928. _refreshPopupVisibility: $.noop,
  33929. _dimensionChanged: function() {
  33930. if (this.option("usePopover") && !this.option("popupWidth"))
  33931. this.option("popupWidth", this.element().width())
  33932. },
  33933. _input: function() {
  33934. return this._$searchBox || this.callBase()
  33935. },
  33936. _renderPopupContent: function() {
  33937. if (this._popup.NAME === "dxPopup")
  33938. this._$popupValidationMessage = $("<div>").addClass(LOOKUP_POPUP_VALIDATION_MESSAGE).appendTo(this._popup.content());
  33939. this._renderSearch();
  33940. this.callBase()
  33941. },
  33942. _renderSearch: function() {
  33943. var $searchWrapper = this._$searchWrapper = $("<div>").addClass(LOOKUP_SEARCH_WRAPPER_CLASS);
  33944. var $searchBox = this._$searchBox = $("<div>").addClass(LOOKUP_SEARCH_CLASS).appendTo($searchWrapper);
  33945. var currentDevice = DX.devices.current(),
  33946. searchMode = currentDevice.android && currentDevice.version[0] >= 5 ? "text" : "search";
  33947. this._searchBox = this._createComponent($searchBox, "dxTextBox", {
  33948. mode: searchMode,
  33949. showClearButton: true,
  33950. valueChangeEvent: this.option("valueChangeEvent"),
  33951. onValueChanged: $.proxy(this._search, this)
  33952. });
  33953. this._searchBox.registerKeyHandler("escape", $.proxy(function(e) {
  33954. this.close()
  33955. }, this));
  33956. $searchWrapper.appendTo(this._popup.content());
  33957. this._renderSearchVisibility();
  33958. this._setSearchPlaceholder()
  33959. },
  33960. _renderSearchVisibility: function() {
  33961. if (this._popup) {
  33962. var searchEnabled = this.option("searchEnabled");
  33963. this._popup._wrapper().toggleClass(LOOKUP_POPUP_SEARCH_CLASS, searchEnabled);
  33964. this._$searchWrapper.toggle(searchEnabled)
  33965. }
  33966. },
  33967. _setSearchPlaceholder: function() {
  33968. if (!this._$searchBox)
  33969. return;
  33970. var minSearchLength = this.option("minSearchLength");
  33971. var placeholder = this.option("searchPlaceholder");
  33972. if (minSearchLength && placeholder === Globalize.localize("Search"))
  33973. placeholder = utils.stringFormat(Globalize.localize("dxLookup-searchPlaceholder"), minSearchLength);
  33974. this._searchBox.option("placeholder", placeholder)
  33975. },
  33976. _renderList: function() {
  33977. this.callBase();
  33978. this._list.registerKeyHandler("escape", $.proxy(function(e) {
  33979. this.close()
  33980. }, this))
  33981. },
  33982. _listConfig: function() {
  33983. return $.extend(this.callBase(), {
  33984. tabIndex: 0,
  33985. grouped: this.option("grouped"),
  33986. groupTemplate: this._getTemplateByOption("groupTemplate"),
  33987. pullRefreshEnabled: this.option("pullRefreshEnabled"),
  33988. useNativeScrolling: this.option("useNativeScrolling"),
  33989. pullingDownText: this.option("pullingDownText"),
  33990. pulledDownText: this.option("pulledDownText"),
  33991. refreshingText: this.option("refreshingText"),
  33992. pageLoadingText: this.option("pageLoadingText"),
  33993. onScroll: this.option("onScroll"),
  33994. onPullRefresh: this.option("onPullRefresh"),
  33995. onPageLoading: this.option("onPageLoading"),
  33996. pageLoadMode: this._getPageLoadMode(),
  33997. nextButtonText: this.option("nextButtonText")
  33998. })
  33999. },
  34000. _listContentReadyHandler: function() {
  34001. if (this.option("usePopover"))
  34002. this._popup.repaint();
  34003. this.callBase.apply(this, arguments)
  34004. },
  34005. _getPageLoadMode: function() {
  34006. this._suppressDeprecatedWarnings();
  34007. var result = utils.isDefined(this.option("showNextButton")) ? "nextButton" : this.option("pageLoadMode");
  34008. this._resumeDeprecatedWarnings();
  34009. return result
  34010. },
  34011. _setFocusPolicy: function() {
  34012. if (!this.option("focusStateEnabled"))
  34013. return;
  34014. if (this.option("searchEnabled"))
  34015. this._searchBox.focus();
  34016. else
  34017. this._$list.focus()
  34018. },
  34019. _attachChildKeyboardEvents: $.noop,
  34020. _focusTarget: function() {
  34021. return this._$field
  34022. },
  34023. _keyboardEventBindingTarget: function() {
  34024. return this._$field
  34025. },
  34026. _selectedItemClass: function() {
  34027. return LOOKUP_SELECTED_CLASS
  34028. },
  34029. _listItemClickHandler: function(e) {
  34030. if (this._currentSelectedItem() === e.itemData)
  34031. this._applyButtonHandler();
  34032. this._setCurrentSelectedClass(e.jQueryEvent.target);
  34033. if (this.option("applyValueMode") === "instantly")
  34034. this._applyButtonHandler()
  34035. },
  34036. _currentSelectedItem: function() {
  34037. return this._listSelectedItemElements().data(LIST_ITEM_DATA_KEY)
  34038. },
  34039. _setCurrentSelectedClass: function(target) {
  34040. this._listSelectedItemElements().removeClass(LOOKUP_SELECTED_CLASS);
  34041. $(target).closest(LIST_ITEM_SELECTOR).addClass(LOOKUP_SELECTED_CLASS)
  34042. },
  34043. _resetValue: function() {
  34044. this.option("value", null);
  34045. this.option("opened", false)
  34046. },
  34047. _searchValue: function() {
  34048. return this.option("searchEnabled") ? this._searchBox.option("value") : ""
  34049. },
  34050. _renderInputValue: function() {
  34051. return this.callBase().always($.proxy(function() {
  34052. this._refreshField()
  34053. }, this))
  34054. },
  34055. _refreshField: function() {
  34056. this._$field.text(this.option("displayValue") || this.option("placeholder"));
  34057. this.element().toggleClass(LOOKUP_EMPTY_CLASS, !this.option("selectedItem"))
  34058. },
  34059. _clean: function() {
  34060. this._$fieldWrapper.remove();
  34061. this._$searchBox = null;
  34062. this.callBase()
  34063. },
  34064. _optionChanged: function(args) {
  34065. var name = args.name;
  34066. var value = args.value;
  34067. switch (name) {
  34068. case"searchEnabled":
  34069. this._renderSearchVisibility();
  34070. break;
  34071. case"searchPlaceholder":
  34072. this._setSearchPlaceholder();
  34073. break;
  34074. case"minSearchLength":
  34075. this._setSearchPlaceholder();
  34076. this.callBase.apply(this, arguments);
  34077. break;
  34078. case"title":
  34079. case"titleTemplate":
  34080. case"onTitleRendered":
  34081. case"shading":
  34082. case"animation":
  34083. case"position":
  34084. case"closeOnOutsideClick":
  34085. this._setPopupOption(name);
  34086. break;
  34087. case"fullScreen":
  34088. case"usePopover":
  34089. this._invalidate();
  34090. break;
  34091. case"clearButtonText":
  34092. case"showClearButton":
  34093. case"showCancelButton":
  34094. this._setPopupOption("buttons", this._getPopupButtons());
  34095. break;
  34096. case"showDoneButton":
  34097. this.option("applyValueMode", value ? "useButtons" : "instantly");
  34098. break;
  34099. case"applyValueMode":
  34100. this.option("showDoneButton", value === "useButtons");
  34101. this.callBase.apply(this, arguments);
  34102. break;
  34103. case"popupWidth":
  34104. this._setPopupOption("popupWidth", value === "auto" ? this.initialOption("popupWidth") : value);
  34105. break;
  34106. case"popupHeight":
  34107. this._setPopupOption("popupHeight", value === "auto" ? this.initialOption("popupHeight") : value);
  34108. break;
  34109. case"pullRefreshEnabled":
  34110. case"useNativeScrolling":
  34111. case"pullingDownText":
  34112. case"pulledDownText":
  34113. case"refreshingText":
  34114. case"pageLoadingText":
  34115. case"onScroll":
  34116. case"onPullRefresh":
  34117. case"onPageLoading":
  34118. case"nextButtonText":
  34119. case"grouped":
  34120. case"groupTemplate":
  34121. this._setListOption(name);
  34122. break;
  34123. case"showNextButton":
  34124. case"pageLoadMode":
  34125. this._setListOption("pageLoadMode", this._getPageLoadMode());
  34126. break;
  34127. case"cleanSearchOnOpening":
  34128. break;
  34129. default:
  34130. this.callBase.apply(this, arguments)
  34131. }
  34132. },
  34133. focus: function() {
  34134. this.option("opened") ? this._setFocusPolicy() : this._focusTarget().focus()
  34135. },
  34136. field: function() {
  34137. return this._$field
  34138. }
  34139. }))
  34140. })(jQuery, DevExpress);
  34141. /*! Module widgets-base, file ui.autocomplete.js */
  34142. (function($, DX, undefined) {
  34143. var ui = DX.ui;
  34144. var AUTOCOMPLETE_CLASS = "dx-autocomplete",
  34145. AUTOCOMPLETE_POPUP_WRAPPER_CLASS = "dx-autocomplete-popup-wrapper",
  34146. CONTROL_KEY = {
  34147. "9": "tab",
  34148. "13": "enter",
  34149. "16": "shift",
  34150. "17": "ctrl",
  34151. "18": "alt",
  34152. "27": "escape",
  34153. "33": "pageUp",
  34154. "34": "pageDown",
  34155. "35": "end",
  34156. "36": "home",
  34157. "37": "leftArrow",
  34158. "38": "upArrow",
  34159. "39": "rightArrow",
  34160. "40": "downArrow"
  34161. };
  34162. DX.registerComponent("dxAutocomplete", ui, ui.dxDropDownList.inherit({
  34163. _supportedKeys: function() {
  34164. var item = this._list ? this._list.option("focusedElement") : null;
  34165. return $.extend(this.callBase(), {
  34166. upArrow: function(e) {
  34167. e.preventDefault();
  34168. e.stopPropagation();
  34169. if (item && !item.prev().length) {
  34170. this._clearFocusedItem();
  34171. return false
  34172. }
  34173. return true
  34174. },
  34175. downArrow: function(e) {
  34176. e.preventDefault();
  34177. e.stopPropagation();
  34178. if (item && !item.next().length) {
  34179. this._clearFocusedItem();
  34180. return false
  34181. }
  34182. return true
  34183. },
  34184. enter: function(e) {
  34185. if (!item)
  34186. this.close();
  34187. return true
  34188. }
  34189. })
  34190. },
  34191. _setDeprecatedOptions: function() {
  34192. this.callBase();
  34193. $.extend(this._deprecatedOptions, {displayExpr: {
  34194. since: "14.2",
  34195. alias: "valueExpr"
  34196. }})
  34197. },
  34198. _setDefaultOptions: function() {
  34199. this.callBase();
  34200. this.option({
  34201. minSearchLength: 1,
  34202. maxItemCount: 10,
  34203. noDataText: "",
  34204. showDropButton: false
  34205. })
  34206. },
  34207. _defaultOptionsRules: function() {
  34208. return this.callBase().concat([{
  34209. device: function(device) {
  34210. return device.platform === "android"
  34211. },
  34212. options: {dropPosition: {offset: {
  34213. h: -16,
  34214. v: -9
  34215. }}}
  34216. }])
  34217. },
  34218. _render: function() {
  34219. this.callBase();
  34220. this.element().addClass(AUTOCOMPLETE_CLASS);
  34221. this.setAria("autocomplete", "inline")
  34222. },
  34223. _loadValue: function() {
  34224. return $.Deferred().resolve(this.option("value"))
  34225. },
  34226. _displayGetterExpr: function() {
  34227. return this.option("valueExpr")
  34228. },
  34229. _setSelectedItem: function(item) {
  34230. this.callBase(item);
  34231. this.option("displayValue", this.option("value"))
  34232. },
  34233. _popupConfig: function() {
  34234. return $.extend(this.callBase(), {closeOnOutsideClick: $.proxy(function(e) {
  34235. return !$(e.target).closest(this.element()).length
  34236. }, this)})
  34237. },
  34238. _renderDimensions: function() {
  34239. this.callBase();
  34240. this._setPopupOption("width")
  34241. },
  34242. _hasItemsToShow: function() {
  34243. var resultItems = this._dataSource && this._dataSource.items() || [];
  34244. var value = this.option("value");
  34245. var firstResultValue = this._displayGetter(resultItems[0]) || "";
  34246. var firstResultValueShorterThanValue = firstResultValue.length < (value || "").length;
  34247. return this.callBase() && !firstResultValueShorterThanValue
  34248. },
  34249. _popupWrapperClass: function() {
  34250. return this.callBase() + " " + AUTOCOMPLETE_POPUP_WRAPPER_CLASS
  34251. },
  34252. _listConfig: function() {
  34253. return $.extend(this.callBase(), {
  34254. pageLoadMode: "none",
  34255. indicateLoading: false
  34256. })
  34257. },
  34258. _listItemClickHandler: function(e) {
  34259. var value = this._displayGetter(e.itemData);
  34260. this.option("value", value);
  34261. this.close()
  34262. },
  34263. _refreshSelected: $.noop,
  34264. _searchCanceled: function() {
  34265. this.callBase();
  34266. this.close()
  34267. },
  34268. _dataSourceOptions: function() {
  34269. return {paginate: true}
  34270. },
  34271. _searchDataSource: function() {
  34272. this._dataSource.pageSize(this.option("maxItemCount"));
  34273. this.callBase();
  34274. this._clearFocusedItem()
  34275. },
  34276. _clearFocusedItem: function() {
  34277. if (this._list) {
  34278. this._list.option("focusedElement", null);
  34279. this._list.option("selectedIndex", -1)
  34280. }
  34281. },
  34282. _renderValueEventName: function() {
  34283. return "input keyup"
  34284. },
  34285. _keyUpHandler: function(e) {
  34286. if (CONTROL_KEY[e.which || e.keyCode])
  34287. return;
  34288. this.callBase.apply(this, arguments);
  34289. this._search()
  34290. },
  34291. _optionChanged: function(args) {
  34292. if (args.name === "maxItemCount")
  34293. this._searchDataSource();
  34294. else
  34295. this.callBase(args)
  34296. }
  34297. }))
  34298. })(jQuery, DevExpress);
  34299. /*! Module widgets-base, file ui.selectBox.js */
  34300. (function($, DX, undefined) {
  34301. var ui = DX.ui,
  34302. events = ui.events,
  34303. SELECTBOX = "dxSelectBox",
  34304. SELECTBOX_CLASS = "dx-selectbox",
  34305. SELECTBOX_POPUP_CLASS = "dx-selectbox-popup",
  34306. SELECTBOX_SELECTED_CLASS = "dx-selectbox-selected",
  34307. SELECTBOX_CONTAINER_CLASS = "dx-selectbox-container",
  34308. SELECTBOX_POPUP_WRAPPER_CLASS = "dx-selectbox-popup-wrapper",
  34309. BLUR_EVENT_NAME = events.addNamespace("blur", SELECTBOX),
  34310. CLICK_EVENT_NAME = events.addNamespace("dxclick", SELECTBOX),
  34311. CONTROL_KEY = {
  34312. "9": "tab",
  34313. "13": "enter",
  34314. "16": "shift",
  34315. "17": "ctrl",
  34316. "18": "alt",
  34317. "27": "escape",
  34318. "33": "pageUp",
  34319. "34": "pageDown",
  34320. "35": "end",
  34321. "36": "home",
  34322. "37": "leftArrow",
  34323. "38": "upArrow",
  34324. "39": "rightArrow",
  34325. "40": "downArrow"
  34326. };
  34327. DX.registerComponent(SELECTBOX, ui, ui.dxDropDownList.inherit({
  34328. _supportedKeys: function() {
  34329. var parent = this.callBase(),
  34330. clearSelectBox = function(e) {
  34331. if (this.option("showClearButton")) {
  34332. e.preventDefault();
  34333. this.reset()
  34334. }
  34335. };
  34336. return $.extend({}, parent, {
  34337. upArrow: function(e) {
  34338. if (parent.upArrow.apply(this, arguments)) {
  34339. if (!this.option("opened"))
  34340. this._setNextValue(-1);
  34341. return true
  34342. }
  34343. },
  34344. downArrow: function(e) {
  34345. if (parent.downArrow.apply(this, arguments)) {
  34346. if (!this.option("opened"))
  34347. this._setNextValue(1);
  34348. return true
  34349. }
  34350. },
  34351. enter: function(e) {
  34352. if (parent.enter.apply(this, arguments))
  34353. return this.option("opened")
  34354. },
  34355. backspace: clearSelectBox,
  34356. del: clearSelectBox
  34357. })
  34358. },
  34359. _setDefaultOptions: function() {
  34360. this.callBase();
  34361. this.option({
  34362. placeholder: Globalize.localize("Select"),
  34363. fieldTemplate: null,
  34364. valueChangeEvent: "keyup",
  34365. fieldEditEnabled: false,
  34366. showSelectionControls: false,
  34367. tooltipEnabled: false,
  34368. openOnFieldClick: true,
  34369. showDropButton: true,
  34370. displayCustomValue: false,
  34371. _isAdaptableDropPosition: false
  34372. })
  34373. },
  34374. _defaultOptionsRules: function() {
  34375. return this.callBase().concat([{
  34376. device: {platform: "win8"},
  34377. options: {
  34378. _isAdaptableDropPosition: true,
  34379. dropPosition: {
  34380. at: "left top",
  34381. offset: {
  34382. h: 0,
  34383. v: 0
  34384. }
  34385. }
  34386. }
  34387. }, {
  34388. device: function(device) {
  34389. return device.platform === "android"
  34390. },
  34391. options: {
  34392. _isAdaptableDropPosition: true,
  34393. dropPosition: {
  34394. my: "top left",
  34395. at: "top left",
  34396. offset: {
  34397. h: -16,
  34398. v: -8
  34399. }
  34400. }
  34401. }
  34402. }])
  34403. },
  34404. _selectedItemClass: function() {
  34405. return SELECTBOX_SELECTED_CLASS
  34406. },
  34407. _render: function() {
  34408. this.callBase();
  34409. this.element().addClass(SELECTBOX_CLASS);
  34410. this._renderTooltip()
  34411. },
  34412. _createPopup: function() {
  34413. this.callBase();
  34414. this._updatePopupPosition();
  34415. this._popup.element().addClass(SELECTBOX_POPUP_CLASS)
  34416. },
  34417. _popupWrapperClass: function() {
  34418. return this.callBase() + " " + SELECTBOX_POPUP_WRAPPER_CLASS
  34419. },
  34420. _renderOpenedState: function() {
  34421. this.callBase();
  34422. if (this.option("opened")) {
  34423. this._updatePopupHeight();
  34424. this._scrollToSelectedItem()
  34425. }
  34426. },
  34427. _updatePopupPosition: function() {
  34428. if (!this.option("_isAdaptableDropPosition") || this.option("dropPosition") !== this.initialOption("dropPosition"))
  34429. return;
  34430. if (this.option("fieldEditEnabled") || this.option("searchEnabled")) {
  34431. var adaptablePopupPosition = $.extend(this._getDefaultDropPosition(), {offset: {
  34432. h: this.option("dropPosition").offset.h,
  34433. v: -4
  34434. }});
  34435. this._setPopupOption("position", adaptablePopupPosition)
  34436. }
  34437. else
  34438. this._setPopupOption("position", this.initialOption("dropPosition"))
  34439. },
  34440. _scrollToSelectedItem: function() {
  34441. if (this._dataSource.paginate() && this._isEditable())
  34442. this._list.scrollTo(0);
  34443. else
  34444. this._list.scrollToItem(this._$list.find("." + this._selectedItemClass()))
  34445. },
  34446. _renderInputValue: function() {
  34447. return this.callBase().always($.proxy(function() {
  34448. this._renderTooltip();
  34449. this._renderInputAddons()
  34450. }, this))
  34451. },
  34452. _fitIntoRange: function(value, start, end) {
  34453. if (value > end)
  34454. return start;
  34455. if (value < start)
  34456. return end;
  34457. return value
  34458. },
  34459. _setNextValue: function(step) {
  34460. if (!this._dataSource.isLoaded())
  34461. this._loadDataSource();
  34462. var item = this.option("selectedItem"),
  34463. items = this._dataSource.items(),
  34464. itemIndex = $.inArray(item, items),
  34465. nextIndex = this._fitIntoRange(itemIndex + step, 0, items.length - 1);
  34466. this._setValue(this._valueGetter(items[nextIndex]))
  34467. },
  34468. _setSelectedItem: function(item) {
  34469. var isUnknownItem = !this._isCustomValueAllowed() && item === undefined;
  34470. this.callBase(isUnknownItem ? null : item)
  34471. },
  34472. _isCustomValueAllowed: function() {
  34473. return this.option("fieldEditEnabled") || this.option("displayCustomValue")
  34474. },
  34475. _displayValue: function(item) {
  34476. item = !DX.utils.isDefined(item) && this._isCustomValueAllowed() ? this.option("value") : item;
  34477. return this.callBase(item)
  34478. },
  34479. _listConfig: function() {
  34480. var result = $.extend(this.callBase(), {
  34481. pageLoadMode: "scrollBottom",
  34482. noDataText: "",
  34483. onSelectionChanged: this._getSelectionChangeHandler(),
  34484. selectionMode: "single"
  34485. });
  34486. if (this.option("showSelectionControls"))
  34487. $.extend(result, {showSelectionControls: true});
  34488. return result
  34489. },
  34490. _getSelectionChangeHandler: function() {
  34491. return this.option("showSelectionControls") ? $.proxy(this._selectionChangeHandler, this) : $.noop
  34492. },
  34493. _selectionChangeHandler: function(e) {
  34494. $.each(e.addedItems || [], $.proxy(function(_, addedItem) {
  34495. this._setValue(this._valueGetter(addedItem))
  34496. }, this))
  34497. },
  34498. _toggleOpenState: function() {
  34499. this.callBase.apply(this, arguments);
  34500. if (this.option("opened") && this._isEditable())
  34501. this._filterDataSource("")
  34502. },
  34503. _renderTooltip: function() {
  34504. if (this.option("tooltipEnabled"))
  34505. this.element().attr("title", this.option("displayValue"))
  34506. },
  34507. _renderDimensions: function() {
  34508. this.callBase();
  34509. this._setPopupOption("width")
  34510. },
  34511. _renderInput: function() {
  34512. this.callBase();
  34513. this._$container.addClass(SELECTBOX_CONTAINER_CLASS);
  34514. this._input().off(BLUR_EVENT_NAME).on(BLUR_EVENT_NAME, $.proxy(this._fieldBlurHandler, this))
  34515. },
  34516. _fieldBlurHandler: function() {
  34517. if (this.option("searchEnabled") && !this.option("fieldEditEnabled")) {
  34518. var selectedItem = this.option("selectedItem");
  34519. this._renderInputValue().always($.proxy(function(e) {
  34520. this._setSelectedItem(selectedItem);
  34521. this._renderDisplayText(this._displayGetter(this.option("selectedItem")))
  34522. }, this))
  34523. }
  34524. },
  34525. _renderValueChangeEvent: function() {
  34526. if (this._isEditable())
  34527. this.callBase()
  34528. },
  34529. _isEditable: function() {
  34530. return this.option("fieldEditEnabled") || this.option("searchEnabled")
  34531. },
  34532. _fieldRenderData: function() {
  34533. return this.option("selectedItem")
  34534. },
  34535. _readOnlyPropValue: function() {
  34536. return !this._isEditable() || this.option("readOnly")
  34537. },
  34538. _isSelectedValue: function(value) {
  34539. return this._isValueEquals(value, this.option("value"))
  34540. },
  34541. _listItemClickHandler: function(e) {
  34542. this._completeSelection(this._valueGetter(e.itemData))
  34543. },
  34544. _completeSelection: function(value) {
  34545. if (value === undefined)
  34546. value = this.option("fieldEditEnabled") && this._searchValue() ? this._searchValue() : this.option("value");
  34547. this.option("opened", false);
  34548. this._clearFilter();
  34549. this._setValue(value)
  34550. },
  34551. _setValue: function(value) {
  34552. this.option("value", value)
  34553. },
  34554. _clearValueHandler: function() {
  34555. this.reset()
  34556. },
  34557. _valueChangeEventHandler: function(e) {
  34558. if (CONTROL_KEY[e.which || e.keyCode])
  34559. return;
  34560. if (this.option("fieldEditEnabled")) {
  34561. this._valueUpdateSuppressed = true;
  34562. this.callBase.apply(this, arguments);
  34563. this._valueUpdateSuppressed = false
  34564. }
  34565. if (this.option("searchEnabled"))
  34566. this._search()
  34567. },
  34568. _createClearButton: function() {
  34569. return this.callBase().on(CLICK_EVENT_NAME, function() {
  34570. return false
  34571. })
  34572. },
  34573. _optionChanged: function(args) {
  34574. switch (args.name) {
  34575. case"_isAdaptableDropPosition":
  34576. break;
  34577. case"tooltipEnabled":
  34578. this._renderTooltip();
  34579. break;
  34580. case"displayCustomValue":
  34581. case"fieldEditEnabled":
  34582. case"showSelectionControls":
  34583. this._invalidate();
  34584. break;
  34585. default:
  34586. this.callBase(args)
  34587. }
  34588. }
  34589. }))
  34590. })(jQuery, DevExpress);
  34591. /*! Module widgets-base, file ui.tagBox.js */
  34592. (function($, DX, undefined) {
  34593. var ui = DX.ui,
  34594. events = ui.events,
  34595. TAGBOX = "dxTagBox",
  34596. TAGBOX_TAG_DATA_KEY = "dxTagData",
  34597. TAGBOX_CLASS = "dx-tagbox",
  34598. TAGBOX_TAG_CONTAINER_CLASS = "dx-tag-container",
  34599. TAGBOX_TAG_CLASS = "dx-tag",
  34600. TAGBOX_TAG_CONTENT_CLASS = "dx-tag-content",
  34601. TAGBOX_TAG_REMOVE_BUTTON_CLASS = "dx-tag-remove-button",
  34602. TAGBOX_ONLY_SELECT_CLASS = "dx-tagbox-only-select",
  34603. EMPTY_INPUT_CLASS = "dx-texteditor-empty",
  34604. TAGBOX_TAG_REMOVE_CLICK_EVENT_NAME = events.addNamespace("dxclick", TAGBOX + "TagRemove");
  34605. var dxTagRemoveButton = ui.Widget.inherit({
  34606. _setDefaultOptions: function() {
  34607. this.callBase();
  34608. this.option({activeStateEnabled: true})
  34609. },
  34610. _render: function() {
  34611. this.callBase();
  34612. this.element().addClass(TAGBOX_TAG_REMOVE_BUTTON_CLASS)
  34613. }
  34614. });
  34615. DX.registerComponent(TAGBOX, ui, ui.dxSelectBox.inherit({
  34616. _supportedKeys: function() {
  34617. var parent = this.callBase();
  34618. return $.extend(parent, {
  34619. backspace: function(e) {
  34620. if (this._searchValue().length)
  34621. return;
  34622. e.preventDefault();
  34623. e.stopPropagation();
  34624. var values = this.option("values");
  34625. this._removeTagWithUpdate(values[values.length - 1])
  34626. },
  34627. enter: function(e) {
  34628. if (this.option("fieldEditEnabled") && !this._$list.find(".dx-state-focused").length)
  34629. this._completeSelection();
  34630. else
  34631. this._keyboardProcessor._childProcessors[0].process(e)
  34632. }
  34633. })
  34634. },
  34635. _setNextValue: $.noop,
  34636. _setDefaultOptions: function() {
  34637. this.callBase();
  34638. this.option({
  34639. values: [],
  34640. onValuesChanged: null,
  34641. showDropButton: false,
  34642. tagTemplate: "tag",
  34643. selectAllText: Globalize.localize("dxList-selectAll")
  34644. })
  34645. },
  34646. _init: function() {
  34647. this.callBase();
  34648. this._initValuesChangedAction();
  34649. this._initDynamicTagTemplate()
  34650. },
  34651. _initValuesChangedAction: function() {
  34652. this._valuesChangedAction = this._createActionByOption("onValuesChanged");
  34653. this._removeTagAction = this._createAction($.proxy(this._removeTagHandler, this))
  34654. },
  34655. _initDynamicTagTemplate: function() {
  34656. if (this._displayGetterExpr())
  34657. this._dynamicTemplates["tag"] = new ui.DefaultTemplate($.proxy(function(data) {
  34658. return this._displayGetter(data)
  34659. }, this));
  34660. else
  34661. delete this._dynamicTemplates["tag"]
  34662. },
  34663. _render: function() {
  34664. this.callBase();
  34665. this._updateValues();
  34666. this.element().addClass(TAGBOX_CLASS);
  34667. this.element().toggleClass(TAGBOX_ONLY_SELECT_CLASS, !(this.option("searchEnabled") || this.option("fieldEditEnabled")));
  34668. this.element().find(".dx-texteditor-container").off(TAGBOX_TAG_REMOVE_CLICK_EVENT_NAME).on(TAGBOX_TAG_REMOVE_CLICK_EVENT_NAME, "." + TAGBOX_TAG_REMOVE_BUTTON_CLASS, $.proxy(function(e) {
  34669. this._removeTagAction({jQueryEvent: e})
  34670. }, this))
  34671. },
  34672. _renderInputValue: function() {
  34673. return this.callBase().always($.proxy(function() {
  34674. this._renderMultiSelect()
  34675. }, this))
  34676. },
  34677. _listContentReadyHandler: function() {
  34678. this._suppressingSelectionChanged(function() {
  34679. this._valuesChangedAction = $.noop;
  34680. this._setListOption("selectedItems", this._selectedItems)
  34681. });
  34682. this.callBase();
  34683. this._initValuesChangedAction()
  34684. },
  34685. _suppressingSelectionChanged: function(callback) {
  34686. this._setListOption("onSelectionChanged", $.noop);
  34687. callback.call(this);
  34688. this._setListOption("onSelectionChanged", this._getSelectionChangeHandler())
  34689. },
  34690. _listConfig: function() {
  34691. var config = this.callBase();
  34692. if (this.option("showSelectionControls"))
  34693. $.extend(config, {
  34694. selectionMode: "all",
  34695. selectAllText: this.option("selectAllText")
  34696. });
  34697. return config
  34698. },
  34699. _renderMultiSelect: function() {
  34700. this._$tagsContainer = this.element().find(".dx-texteditor-container").addClass(TAGBOX_TAG_CONTAINER_CLASS);
  34701. this._renderInputSize();
  34702. this._clearFilter();
  34703. this._renderTags();
  34704. this._popup && this._popup.repaint()
  34705. },
  34706. _renderInputSize: function() {
  34707. var $input = this._input();
  34708. $input.prop("size", $input.val() ? $input.val().length + 2 : 1)
  34709. },
  34710. _renderTags: function() {
  34711. this._cleanTags();
  34712. var $tagsBag = $("<div>");
  34713. this._selectedItems = [];
  34714. var itemLoadDeferreds = $.map(this._values(), $.proxy(function(value) {
  34715. return this._renderTag(value, $tagsBag)
  34716. }, this));
  34717. $tagsBag.children().insertBefore(this._input());
  34718. $.when.apply($, itemLoadDeferreds).done($.proxy(this._renderInputAddons, this));
  34719. this._renderEmptyState()
  34720. },
  34721. _renderEmptyState: function() {
  34722. var hasNoValues = !this._values().length;
  34723. this.element().toggleClass(EMPTY_INPUT_CLASS, hasNoValues);
  34724. this._placeholder().toggle(hasNoValues);
  34725. this._renderDisplayText()
  34726. },
  34727. _renderDisplayText: function() {
  34728. this._input().val("");
  34729. this._renderInputSize()
  34730. },
  34731. _cleanTags: function() {
  34732. var $tags = this._tagElements();
  34733. var values = this.option("values");
  34734. $.each($tags, function(_, tag) {
  34735. var $tag = $(tag);
  34736. if ($.inArray($tag.data(TAGBOX_TAG_DATA_KEY), values) < 0)
  34737. $tag.remove()
  34738. })
  34739. },
  34740. _tagElements: function() {
  34741. return this.element().find("." + TAGBOX_TAG_CLASS)
  34742. },
  34743. _renderTag: function(value, $container) {
  34744. if (this._isTagRendered(value))
  34745. return $.Deferred().resolve();
  34746. var $tag = $("<div>").addClass(TAGBOX_TAG_CLASS).data(TAGBOX_TAG_DATA_KEY, value).appendTo($container),
  34747. tagTemplate = this._getTemplateByOption("tagTemplate");
  34748. var $tagContent = $("<div>").addClass(TAGBOX_TAG_CONTENT_CLASS).appendTo($tag);
  34749. $("<div>").dxTagRemoveButton().appendTo($tag);
  34750. return this._loadItem(value).always($.proxy(function(item) {
  34751. item = DX.utils.isDefined(item) ? item : value;
  34752. tagTemplate.render(item, $tagContent);
  34753. this._selectedItems.push(item)
  34754. }, this))
  34755. },
  34756. _isTagRendered: function(value) {
  34757. var $tags = this._tagElements();
  34758. var result = false;
  34759. $.each($tags, function(_, tag) {
  34760. var $tag = $(tag);
  34761. if (value === $tag.data(TAGBOX_TAG_DATA_KEY)) {
  34762. result = true;
  34763. return false
  34764. }
  34765. });
  34766. return result
  34767. },
  34768. _toggleEmptinessEventHandler: function() {
  34769. this._toggleEmptiness(!this.option("values").length && !this._searchValue().length)
  34770. },
  34771. _removeTagHandler: function(args) {
  34772. var e = args.jQueryEvent;
  34773. e.stopPropagation();
  34774. var $tag = $(e.target).closest("." + TAGBOX_TAG_CLASS);
  34775. var itemValue = $tag.data(TAGBOX_TAG_DATA_KEY);
  34776. this._removeTagWithUpdate(itemValue)
  34777. },
  34778. _removeTagWithUpdate: function(itemValue) {
  34779. this._removeTag(itemValue);
  34780. this._suppressingSelectionChanged(function() {
  34781. this._updateValues()
  34782. });
  34783. this.option("values", this.option("values"))
  34784. },
  34785. _selectionChangeHandler: function(e) {
  34786. $.each(e.removedItems || [], $.proxy(function(_, removedItem) {
  34787. this._removeTag(this._valueGetter(removedItem))
  34788. }, this));
  34789. $.each(e.addedItems || [], $.proxy(function(_, addedItem) {
  34790. this._addTag(this._valueGetter(addedItem))
  34791. }, this));
  34792. this.callBase(e);
  34793. this._updateValues();
  34794. this._valuesChangedAction(e)
  34795. },
  34796. _removeTag: function(value) {
  34797. this.option().value = value;
  34798. var values = this.option("values"),
  34799. index = this._valueIndex(value);
  34800. if (index >= 0)
  34801. values.splice(index, 1)
  34802. },
  34803. _addTag: function(value) {
  34804. var values = this.option("values"),
  34805. index = this._valueIndex(value);
  34806. if (index < 0)
  34807. values.push(value)
  34808. },
  34809. _fieldRenderData: function() {
  34810. return this._selectedItems
  34811. },
  34812. _setValue: function(value) {
  34813. if (value === null || this._isSelectedValue(value))
  34814. return;
  34815. var values = this.option("values");
  34816. values.push(value);
  34817. this.option("values", values)
  34818. },
  34819. _isSelectedValue: function(value) {
  34820. return this._valueIndex(value) > -1
  34821. },
  34822. _valueIndex: function(value) {
  34823. var result = -1;
  34824. $.each(this._values(), $.proxy(function(index, selectedValue) {
  34825. if (this._isValueEquals(value, selectedValue)) {
  34826. result = index;
  34827. return false
  34828. }
  34829. }, this));
  34830. return result
  34831. },
  34832. _values: function() {
  34833. return this.option("values") || []
  34834. },
  34835. _optionValuesEqual: function(name, value, prevValue) {
  34836. if (name === "value")
  34837. return false;
  34838. this.callBase(name, value, prevValue)
  34839. },
  34840. reset: function() {
  34841. this.option("values", []);
  34842. this.callBase()
  34843. },
  34844. _updateValues: function() {
  34845. var lastValue = this._lastValue() === undefined ? null : this._lastValue();
  34846. this.option("value", lastValue)
  34847. },
  34848. _lastValue: function() {
  34849. return this._values().slice(-1).pop()
  34850. },
  34851. _valueChangeEventHandler: function(e) {
  34852. this._renderInputSize();
  34853. if (this.option("fieldEditEnabled"))
  34854. return;
  34855. this.callBase(e)
  34856. },
  34857. _valueChangeArgs: function() {
  34858. var result = this.callBase.apply(this, arguments);
  34859. delete result.previousValue;
  34860. return $.extend(result, {values: this.option("values")})
  34861. },
  34862. _optionChanged: function(args) {
  34863. switch (args.name) {
  34864. case"displayExpr":
  34865. this.callBase(args);
  34866. this._initDynamicTagTemplate();
  34867. this._invalidate();
  34868. break;
  34869. case"tagTemplate":
  34870. this._initDynamicTagTemplate();
  34871. this._invalidate();
  34872. break;
  34873. case"values":
  34874. this._updateValues();
  34875. break;
  34876. case"onValuesChanged":
  34877. this._initValuesChangedAction();
  34878. break;
  34879. case"selectAllText":
  34880. this._setListOption("selectAllText", this.option("selectAllText"));
  34881. break;
  34882. default:
  34883. this.callBase(args)
  34884. }
  34885. }
  34886. }));
  34887. DX.registerComponent("dxTagRemoveButton", ui[TAGBOX], dxTagRemoveButton)
  34888. })(jQuery, DevExpress);
  34889. /*! Module widgets-base, file ui.multiView.js */
  34890. (function($, DX, undefined) {
  34891. var ui = DX.ui,
  34892. utils = DX.utils,
  34893. fx = DX.fx,
  34894. translator = DX.translator;
  34895. var MULTIVIEW_CLASS = "dx-multiview",
  34896. MULTIVIEW_WRAPPER_CLASS = "dx-multiview-wrapper",
  34897. MULTIVIEW_ITEM_CONTAINER_CLASS = "dx-multiview-item-container",
  34898. MULTIVIEW_ITEM_CLASS = "dx-multiview-item",
  34899. MULTIVIEW_ITEM_HIDDEN_CLASS = "dx-multiview-item-hidden",
  34900. MULTIVIEW_ITEM_DATA_KEY = "dxMultiViewItemData",
  34901. MULTIVIEW_ANIMATION_DURATION = 200;
  34902. var toNumber = function(value) {
  34903. return +value
  34904. };
  34905. var position = function($element) {
  34906. return translator.locate($element).left
  34907. };
  34908. var move = function($element, position) {
  34909. translator.move($element, {left: position})
  34910. };
  34911. var animation = {
  34912. moveTo: function($element, position, duration, completeAction) {
  34913. fx.animate($element, {
  34914. type: "slide",
  34915. to: {left: position},
  34916. duration: duration,
  34917. complete: completeAction
  34918. })
  34919. },
  34920. complete: function($element) {
  34921. fx.stop($element, true)
  34922. }
  34923. };
  34924. DX.registerComponent("dxMultiView", ui, ui.CollectionWidget.inherit({
  34925. _activeStateUnit: "." + MULTIVIEW_ITEM_CLASS,
  34926. _supportedKeys: function() {
  34927. return $.extend(this.callBase(), {
  34928. pageUp: $.noop,
  34929. pageDown: $.noop
  34930. })
  34931. },
  34932. _setDefaultOptions: function() {
  34933. this.callBase();
  34934. this.option({
  34935. selectedIndex: 0,
  34936. swipeEnabled: true,
  34937. animationEnabled: true,
  34938. loop: false,
  34939. _itemAttributes: {role: "tabpanel"},
  34940. deferRendering: true,
  34941. loopItemFocus: false,
  34942. selectOnFocus: true,
  34943. selectionMode: "single",
  34944. selectionRequired: true,
  34945. selectionByClick: false
  34946. })
  34947. },
  34948. _defaultOptionsRules: function() {
  34949. return this.callBase().concat([{
  34950. device: function(device) {
  34951. return DX.devices.real().generic && !DX.devices.isSimulator()
  34952. },
  34953. options: {focusStateEnabled: true}
  34954. }])
  34955. },
  34956. _itemClass: function() {
  34957. return MULTIVIEW_ITEM_CLASS
  34958. },
  34959. _itemDataKey: function() {
  34960. return MULTIVIEW_ITEM_DATA_KEY
  34961. },
  34962. _itemContainer: function() {
  34963. return this._$itemContainer
  34964. },
  34965. _itemWidth: function() {
  34966. if (!this._itemWidthValue)
  34967. this._itemWidthValue = this._$wrapper.width();
  34968. return this._itemWidthValue
  34969. },
  34970. _clearItemWidthCache: function() {
  34971. delete this._itemWidthValue
  34972. },
  34973. _itemsCount: function() {
  34974. return this.option("items").length
  34975. },
  34976. _normalizeIndex: function(index) {
  34977. var count = this._itemsCount();
  34978. if (index < 0)
  34979. index = index + count;
  34980. if (index >= count)
  34981. index = index - count;
  34982. return index
  34983. },
  34984. _getRTLSignCorrection: function() {
  34985. return this.option("rtlEnabled") ? -1 : 1
  34986. },
  34987. _init: function() {
  34988. this.callBase.apply(this, arguments);
  34989. var $element = this.element();
  34990. $element.addClass(MULTIVIEW_CLASS);
  34991. this._$wrapper = $("<div>").addClass(MULTIVIEW_WRAPPER_CLASS);
  34992. this._$wrapper.appendTo($element);
  34993. this._$itemContainer = $("<div>").addClass(MULTIVIEW_ITEM_CONTAINER_CLASS);
  34994. this._$itemContainer.appendTo(this._$wrapper);
  34995. this.option("loopItemFocus", this.option("loop"));
  34996. this._initSwipeable()
  34997. },
  34998. _render: function() {
  34999. this._deferredItems = [];
  35000. this.callBase()
  35001. },
  35002. _renderItemContent: function(index, itemData, $container) {
  35003. this._deferredItems.push($.Deferred());
  35004. this._deferredItems[index].done($.proxy(function(itemContentRenderer, args) {
  35005. itemContentRenderer.apply(this, args)
  35006. }, this, this.callBase, arguments));
  35007. if (!this.option("deferRendering"))
  35008. this._deferredItems[index].resolve()
  35009. },
  35010. _renderSelection: function(addedSelection) {
  35011. this._updateItems(addedSelection[0])
  35012. },
  35013. _updateItems: function(selectedIndex, newIndex) {
  35014. this._updateItemsPosition(selectedIndex, newIndex);
  35015. this._updateItemsVisibility(selectedIndex, newIndex)
  35016. },
  35017. _renderSpecificItem: function(index) {
  35018. var hasItemContent = this._itemElements().eq(index).find(this._itemContentClass()).length > 0;
  35019. if (DX.utils.isDefined(index) && !hasItemContent)
  35020. this._deferredItems[index].resolve()
  35021. },
  35022. _updateItemsPosition: function(selectedIndex, newIndex) {
  35023. var $itemElements = this._itemElements(),
  35024. positionSign = -this._animationDirection(newIndex, selectedIndex),
  35025. $selectedItem = $itemElements.eq(selectedIndex);
  35026. move($selectedItem, 0);
  35027. move($itemElements.eq(newIndex), positionSign * 100 + "%")
  35028. },
  35029. _updateItemsVisibility: function(selectedIndex, newIndex) {
  35030. var $itemElements = this._itemElements();
  35031. $itemElements.each($.proxy(function(itemIndex, item) {
  35032. var $item = $(item),
  35033. isHidden = itemIndex !== selectedIndex && itemIndex !== newIndex;
  35034. if (!isHidden)
  35035. this._renderSpecificItem(itemIndex);
  35036. $item.toggleClass(MULTIVIEW_ITEM_HIDDEN_CLASS, isHidden);
  35037. this.setAria("hidden", isHidden || undefined, $item)
  35038. }, this))
  35039. },
  35040. _setAriaSelected: $.noop,
  35041. _updateSelection: function(addedSelection, removedSelection) {
  35042. var newIndex = addedSelection[0],
  35043. prevIndex = removedSelection[0];
  35044. animation.complete(this._$itemContainer);
  35045. this._updateItems(prevIndex, newIndex);
  35046. var animationDirection = this._animationDirection(newIndex, prevIndex);
  35047. this._animateItemContainer(animationDirection * this._itemWidth(), $.proxy(function() {
  35048. move(this._$itemContainer, 0);
  35049. this._updateItems(newIndex);
  35050. this._$itemContainer.width()
  35051. }, this))
  35052. },
  35053. _animateItemContainer: function(position, completeCallback) {
  35054. var duration = this.option("animationEnabled") ? MULTIVIEW_ANIMATION_DURATION : 0;
  35055. animation.moveTo(this._$itemContainer, position, duration, completeCallback)
  35056. },
  35057. _animationDirection: function(newIndex, prevIndex) {
  35058. var containerPosition = position(this._$itemContainer),
  35059. indexDifference = (prevIndex - newIndex) * this._getRTLSignCorrection() * this._getItemFocusLoopSignCorrection(),
  35060. isSwipePresent = containerPosition !== 0,
  35061. directionSignVariable = isSwipePresent ? containerPosition : indexDifference;
  35062. return utils.sign(directionSignVariable)
  35063. },
  35064. _initSwipeable: function() {
  35065. this._createComponent(this.element(), "dxSwipeable", {
  35066. disabled: !this.option("swipeEnabled"),
  35067. elastic: false,
  35068. itemSizeFunc: $.proxy(this._itemWidth, this),
  35069. onStart: $.proxy(function(args) {
  35070. this._swipeStartHandler(args.jQueryEvent)
  35071. }, this),
  35072. onUpdated: $.proxy(function(args) {
  35073. this._swipeUpdateHandler(args.jQueryEvent)
  35074. }, this),
  35075. onEnd: $.proxy(function(args) {
  35076. this._swipeEndHandler(args.jQueryEvent)
  35077. }, this)
  35078. })
  35079. },
  35080. _swipeStartHandler: function(e) {
  35081. animation.complete(this._$itemContainer);
  35082. var selectedIndex = this.option("selectedIndex"),
  35083. loop = this.option("loop"),
  35084. lastIndex = this._itemsCount() - 1,
  35085. rtl = this.option("rtlEnabled");
  35086. e.maxLeftOffset = toNumber(loop || (rtl ? selectedIndex > 0 : selectedIndex < lastIndex));
  35087. e.maxRightOffset = toNumber(loop || (rtl ? selectedIndex < lastIndex : selectedIndex > 0));
  35088. this._swipeDirection = null
  35089. },
  35090. _swipeUpdateHandler: function(e) {
  35091. var offset = e.offset,
  35092. swipeDirection = utils.sign(offset) * this._getRTLSignCorrection();
  35093. move(this._$itemContainer, offset * 100 + "%");
  35094. if (swipeDirection !== this._swipeDirection) {
  35095. this._swipeDirection = swipeDirection;
  35096. var selectedIndex = this.option("selectedIndex"),
  35097. newIndex = this._normalizeIndex(selectedIndex - swipeDirection);
  35098. this._updateItems(selectedIndex, newIndex)
  35099. }
  35100. },
  35101. _swipeEndHandler: function(e) {
  35102. var targetOffset = e.targetOffset * this._getRTLSignCorrection();
  35103. if (targetOffset) {
  35104. this.option("selectedIndex", this._normalizeIndex(this.option("selectedIndex") - targetOffset));
  35105. var $selectedElement = this.itemElements().filter(".dx-item-selected");
  35106. this.option("focusedElement", $selectedElement)
  35107. }
  35108. else
  35109. this._animateItemContainer(0, $.noop)
  35110. },
  35111. _getItemFocusLoopSignCorrection: function() {
  35112. return this._itemFocusLooped ? -1 : 1
  35113. },
  35114. _moveFocus: function() {
  35115. this.callBase.apply(this, arguments);
  35116. this._itemFocusLooped = false
  35117. },
  35118. _prevItem: function($items) {
  35119. var $result = this.callBase.apply(this, arguments);
  35120. this._itemFocusLooped = $result.is($items.last());
  35121. return $result
  35122. },
  35123. _nextItem: function($items) {
  35124. var $result = this.callBase.apply(this, arguments);
  35125. this._itemFocusLooped = $result.is($items.first());
  35126. return $result
  35127. },
  35128. _dimensionChanged: function() {
  35129. this._clearItemWidthCache()
  35130. },
  35131. _visibilityChanged: function(visible) {
  35132. if (visible)
  35133. this._dimensionChanged()
  35134. },
  35135. _optionChanged: function(args) {
  35136. var value = args.value;
  35137. switch (args.name) {
  35138. case"loop":
  35139. this.option("loopItemFocus", value);
  35140. break;
  35141. case"animationEnabled":
  35142. break;
  35143. case"swipeEnabled":
  35144. this.element().dxSwipeable("option", "disabled", !value);
  35145. break;
  35146. case"deferRendering":
  35147. this._invalidate();
  35148. break;
  35149. default:
  35150. this.callBase(args)
  35151. }
  35152. }
  35153. }));
  35154. ui.dxMultiView.__internals = {animation: animation}
  35155. })(jQuery, DevExpress);
  35156. /*! Module widgets-base, file ui.validator.js */
  35157. (function($, DX, undefined) {
  35158. var ui = DX.ui,
  35159. validationEngine = DX.validationEngine;
  35160. var VALIDATOR_CLASS = "dx-validator";
  35161. DevExpress.ui.validation.defaultAdapter = DX.Class.inherit({
  35162. ctor: function(editor, validator) {
  35163. var that = this;
  35164. that.editor = editor;
  35165. that.validator = validator;
  35166. that.validationRequestsCallbacks = $.Callbacks();
  35167. var handler = function(params) {
  35168. that.validationRequestsCallbacks.fire()
  35169. };
  35170. editor.validationRequest.add(handler);
  35171. editor.on("disposing", function() {
  35172. editor.validationRequest.remove(handler)
  35173. })
  35174. },
  35175. getValue: function() {
  35176. return this.editor.option("value")
  35177. },
  35178. getCurrentValidationError: function() {
  35179. return this.editor.option("validationError")
  35180. },
  35181. applyValidationResults: function(params) {
  35182. this.editor.option({
  35183. isValid: params.isValid,
  35184. validationError: params.brokenRule
  35185. })
  35186. },
  35187. reset: function() {
  35188. this.editor.reset()
  35189. },
  35190. focus: function() {
  35191. this.editor.focus()
  35192. }
  35193. });
  35194. var dxValidator = DX.DOMComponent.inherit({
  35195. _setDefaultOptions: function() {
  35196. this.callBase();
  35197. this.option({validationRules: []})
  35198. },
  35199. _init: function() {
  35200. this.callBase();
  35201. this._initGroupRegistration();
  35202. this.focused = $.Callbacks();
  35203. this._initAdapter()
  35204. },
  35205. _initGroupRegistration: function _initGroupRegistration() {
  35206. var group = this._findGroup();
  35207. if (!this._groupWasInit)
  35208. this.on("disposing", function(args) {
  35209. validationEngine.removeRegistredValidator(args.component._validationGroup, args.component)
  35210. });
  35211. if (!this._groupWasInit || this._validationGroup !== group) {
  35212. validationEngine.removeRegistredValidator(this._validationGroup, this);
  35213. this._groupWasInit = true;
  35214. this._validationGroup = group;
  35215. validationEngine.registerValidatorInGroup(group, this)
  35216. }
  35217. },
  35218. _setOptionsByReference: function() {
  35219. this.callBase();
  35220. $.extend(this._optionsByReference, {validationGroup: true})
  35221. },
  35222. _initAdapter: function() {
  35223. var that = this,
  35224. dxStandardEditor = that.element().data("dx-validation-target"),
  35225. adapter = that.option("adapter");
  35226. if (!adapter) {
  35227. if (dxStandardEditor) {
  35228. adapter = new DevExpress.ui.validation.defaultAdapter(dxStandardEditor, this);
  35229. adapter.validationRequestsCallbacks.add(function() {
  35230. that.validate()
  35231. });
  35232. this.option("adapter", adapter);
  35233. return
  35234. }
  35235. throw DX.Error("E0120");
  35236. }
  35237. if (adapter.validationRequestsCallbacks)
  35238. adapter.validationRequestsCallbacks.add(function() {
  35239. that.validate()
  35240. })
  35241. },
  35242. _findGroup: DX.ui.validation.findGroup,
  35243. _render: function() {
  35244. this.element().addClass(VALIDATOR_CLASS);
  35245. this.callBase()
  35246. },
  35247. _optionChanged: function(args) {
  35248. switch (args.name) {
  35249. case"validationGroup":
  35250. this._initGroupRegistration();
  35251. return;
  35252. case"validationRules":
  35253. return;
  35254. case"adapter":
  35255. this._initAdapter();
  35256. break;
  35257. default:
  35258. this.callBase(args)
  35259. }
  35260. },
  35261. validate: function() {
  35262. var that = this,
  35263. adapter = that.option("adapter"),
  35264. name = that.option("name"),
  35265. value = adapter.getValue(),
  35266. currentError = adapter.getCurrentValidationError && adapter.getCurrentValidationError(),
  35267. rules = $.map(that.option("validationRules"), function(rule) {
  35268. rule.validator = that;
  35269. return rule
  35270. }),
  35271. result;
  35272. if (currentError && currentError.editorSpecific) {
  35273. currentError.validator = this;
  35274. result = {
  35275. isValid: false,
  35276. brokenRule: currentError
  35277. }
  35278. }
  35279. else
  35280. result = validationEngine.validate(value, rules, name);
  35281. this._applyValidationResult(result, adapter);
  35282. return result
  35283. },
  35284. reset: function() {
  35285. var that = this,
  35286. adapter = that.option("adapter"),
  35287. result = {
  35288. isValid: true,
  35289. brokenRule: null
  35290. };
  35291. adapter.reset();
  35292. this._applyValidationResult(result, adapter)
  35293. },
  35294. _applyValidationResult: function(result, adapter) {
  35295. var validatedAction = this._createActionByOption("onValidated");
  35296. result.validator = this;
  35297. adapter.applyValidationResults && adapter.applyValidationResults(result);
  35298. this.option({isValid: result.isValid});
  35299. validatedAction(result)
  35300. },
  35301. focus: function() {
  35302. var adapter = this.option("adapter");
  35303. adapter.focus()
  35304. }
  35305. });
  35306. DX.registerComponent("dxValidator", ui, dxValidator)
  35307. })(jQuery, DevExpress);
  35308. /*! Module widgets-base, file ui.validationGroup.js */
  35309. (function($, DX, undefined) {
  35310. var ui = DX.ui;
  35311. var VALIDATION_ENGINE_CLASS = "dx-validationgroup";
  35312. DX.registerComponent("dxValidationGroup", ui, DX.DOMComponent.inherit({
  35313. _setDefaultOptions: function() {
  35314. this.callBase();
  35315. this.option({})
  35316. },
  35317. _init: function() {
  35318. this.callBase()
  35319. },
  35320. _render: function() {
  35321. var $element = this.element();
  35322. $element.addClass(VALIDATION_ENGINE_CLASS);
  35323. $element.find(".dx-validator").each(function(_, validatorContainer) {
  35324. $(validatorContainer).dxValidator("instance")._initGroupRegistration()
  35325. });
  35326. $element.find(".dx-validationsummary").each(function(_, summaryContainer) {
  35327. $(summaryContainer).dxValidationSummary("instance")._initGroupRegistration()
  35328. });
  35329. this.callBase()
  35330. },
  35331. validate: function() {
  35332. return DX.validationEngine.validateGroup(this)
  35333. },
  35334. reset: function() {
  35335. return DX.validationEngine.resetGroup(this)
  35336. },
  35337. _optionChanged: function(args) {
  35338. switch (args.name) {
  35339. default:
  35340. this.callBase(args)
  35341. }
  35342. },
  35343. _dispose: function() {
  35344. DX.validationEngine.removeGroup(this);
  35345. this.element().removeClass(VALIDATION_ENGINE_CLASS);
  35346. this.callBase()
  35347. }
  35348. }))
  35349. })(jQuery, DevExpress);
  35350. /*! Module widgets-base, file ui.validationSummary.js */
  35351. (function($, DX, undefined) {
  35352. var ui = DX.ui;
  35353. var VALIDATION_SUMMARY_CLASS = "dx-validationsummary",
  35354. ITEM_CLASS = VALIDATION_SUMMARY_CLASS + "-item",
  35355. ITEM_DATA_KEY = VALIDATION_SUMMARY_CLASS + "-item-data";
  35356. DX.registerComponent("dxValidationSummary", ui, ui.CollectionWidget.inherit({
  35357. _setDefaultOptions: function() {
  35358. this.callBase();
  35359. this.option({
  35360. focusStateEnabled: false,
  35361. noDataText: null
  35362. })
  35363. },
  35364. _setOptionsByReference: function() {
  35365. this.callBase();
  35366. $.extend(this._optionsByReference, {validationGroup: true})
  35367. },
  35368. _findGroup: DX.ui.validation.findGroup,
  35369. _init: function() {
  35370. this.callBase();
  35371. this._initGroupRegistration()
  35372. },
  35373. _initGroupRegistration: function() {
  35374. var group = this._findGroup(),
  35375. groupConfig = DX.validationEngine.addGroup(group);
  35376. this._unsubscribeGroup();
  35377. this._groupWasInit = true;
  35378. this._validationGroup = group;
  35379. this.groupSubscription = $.proxy(this._groupValidationHandler, this);
  35380. groupConfig.on("validated", this.groupSubscription)
  35381. },
  35382. _unsubscribeGroup: function() {
  35383. var groupConfig = DX.validationEngine.getGroupConfig(this._validationGroup);
  35384. groupConfig && groupConfig.off("validated", this.groupSubscription)
  35385. },
  35386. _getOrderedItems: function(validators, items) {
  35387. var orderedItems = [];
  35388. $.each(validators, function(_, validator) {
  35389. var firstItem = $.grep(items, function(item) {
  35390. if (item.validator === validator)
  35391. return true
  35392. })[0];
  35393. if (firstItem)
  35394. orderedItems.push(firstItem)
  35395. });
  35396. return orderedItems
  35397. },
  35398. _groupValidationHandler: function(params) {
  35399. var that = this,
  35400. items = that._getOrderedItems(params.validators, $.map(params.brokenRules, function(rule) {
  35401. return {
  35402. text: rule.message,
  35403. validator: rule.validator
  35404. }
  35405. }));
  35406. that.validators = params.validators;
  35407. $.each(that.validators, function(_, validator) {
  35408. var handler = $.proxy(that._itemValidationHandler, that),
  35409. disposingHandler = function() {
  35410. validator.off("validated", handler);
  35411. handler = null
  35412. };
  35413. validator.on("validated", handler);
  35414. validator.on("disposing", disposingHandler)
  35415. });
  35416. that.option("items", items)
  35417. },
  35418. _itemValidationHandler: function(itemValidationResult) {
  35419. var items = this.option("items"),
  35420. isValid = itemValidationResult.isValid,
  35421. elementIndex,
  35422. replacementFound = false,
  35423. newMessage = itemValidationResult.brokenRule && itemValidationResult.brokenRule.message,
  35424. validator = itemValidationResult.validator;
  35425. if (isValid) {
  35426. $.each(items, function(index, item) {
  35427. if (item.validator === validator) {
  35428. elementIndex = index;
  35429. replacementFound = true;
  35430. return false
  35431. }
  35432. });
  35433. if (replacementFound)
  35434. items.splice(elementIndex, 1)
  35435. }
  35436. else {
  35437. $.each(items, function(index, item) {
  35438. if (item.validator === validator) {
  35439. item.text = newMessage;
  35440. replacementFound = true;
  35441. return false
  35442. }
  35443. });
  35444. if (!replacementFound)
  35445. items.push({
  35446. text: newMessage,
  35447. validator: validator
  35448. })
  35449. }
  35450. items = this._getOrderedItems(this.validators, items);
  35451. this.option("items", items)
  35452. },
  35453. _render: function() {
  35454. this.element().addClass(VALIDATION_SUMMARY_CLASS);
  35455. this.callBase()
  35456. },
  35457. _optionChanged: function(args) {
  35458. switch (args.name) {
  35459. case"validationGroup":
  35460. this._initGroupRegistration();
  35461. break;
  35462. default:
  35463. this.callBase(args)
  35464. }
  35465. },
  35466. _itemClass: function() {
  35467. return ITEM_CLASS
  35468. },
  35469. _itemDataKey: function() {
  35470. return ITEM_DATA_KEY
  35471. },
  35472. _postprocessRenderItem: function(params) {
  35473. params.itemElement.on("click", function() {
  35474. params.itemData.validator.focus()
  35475. })
  35476. },
  35477. _dispose: function() {
  35478. this.callBase();
  35479. this._unsubscribeGroup()
  35480. }
  35481. }))
  35482. })(jQuery, DevExpress);
  35483. /*! Module widgets-base, file ui.fileUploader.js */
  35484. (function($, DX, undefined) {
  35485. var ui = DX.ui,
  35486. utils = DX.utils;
  35487. var FILEUPLOADER_CLASS = "dx-fileuploader",
  35488. FILEUPLOADER_EMPTY_CLASS = "dx-fileuploader-empty",
  35489. FILEUPLOADER_DRAGOVER = "dx-fileuploader-dragover",
  35490. FILEUPLOADER_FILEINPUT_TAG = "<input type='file'>",
  35491. FILEUPLOADER_WRAPPER_CLASS = "dx-fileuploader-wrapper",
  35492. FILEUPLOADER_CONTAINER_CLASS = "dx-fileuploader-container",
  35493. FILEUPLOADER_CONTENT_CLASS = "dx-fileuploader-content",
  35494. FILEUPLOADER_INPUT_WRAPPER_CLASS = "dx-fileuploader-input-wrapper",
  35495. FILEUPLOADER_INPUT_CONTAINER_CLASS = "dx-fileuploader-input-container",
  35496. FILEUPLOADER_INPUT_LABEL_CLASS = "dx-fileuploader-input-label",
  35497. FILEUPLOADER_INPUT_CLASS = "dx-fileuploader-input",
  35498. FILEUPLOADER_FILES_CONTAINER_CLASS = "dx-fileuploader-files-container",
  35499. FILEUPLOADER_FILE_CONTAINER_CLASS = "dx-fileuploader-file-container",
  35500. FILEUPLOADER_FILE_INFO_CLASS = "dx-fileuploader-file-info",
  35501. FILEUPLOADER_FILE_STATUS_CLASS = "dx-fileuploader-file-status",
  35502. FILEUPLOADER_FILE_STATUS_MESSAGE_CLASS = "dx-fileuploader-file-status-message",
  35503. FILEUPLOADER_FILE_CLASS = "dx-fileuploader-file",
  35504. FILEUPLOADER_FILE_NAME_CLASS = "dx-fileuploader-file-name",
  35505. FILEUPLOADER_FILE_SIZE_CLASS = "dx-fileuploader-file-size",
  35506. FILEUPLOADER_BUTTON_CLASS = "dx-fileuploader-button",
  35507. FILEUPLOADER_BUTTON_CONTAINER_CLASS = "dx-fileuploader-button-container",
  35508. FILEUPLOADER_CANCEL_BUTTON_CLASS = "dx-fileuploader-cancel-button",
  35509. FILEUPLOADER_UPLOAD_BUTTON_CLASS = "dx-fileuploader-upload-button",
  35510. FILEUPLOADER_AFTER_LOAD_DELAY = 400;
  35511. var isFormDataSupported = function() {
  35512. return !!window.FormData
  35513. },
  35514. getFormDataPrototype = function() {
  35515. return FormData
  35516. },
  35517. getRequestPrototype = function() {
  35518. return XMLHttpRequest
  35519. };
  35520. DX.registerComponent("dxFileUploader", ui, ui.Editor.inherit({
  35521. _supportedKeys: function() {
  35522. var click = function(e) {
  35523. e.preventDefault();
  35524. if (this._$button)
  35525. this._$button.click()
  35526. };
  35527. return $.extend(this.callBase(), {
  35528. space: click,
  35529. enter: click
  35530. })
  35531. },
  35532. _setDeprecatedOptions: function() {
  35533. this.callBase();
  35534. $.extend(this._deprecatedOptions, {buttonText: {
  35535. since: "15.1",
  35536. alias: "selectButtonText"
  35537. }})
  35538. },
  35539. _setDefaultOptions: function() {
  35540. this.callBase();
  35541. this.option({
  35542. value: null,
  35543. values: [],
  35544. selectButtonText: Globalize.localize("dxFileUploader-selectFile"),
  35545. uploadButtonText: Globalize.localize("dxFileUploader-upload"),
  35546. labelText: Globalize.localize("dxFileUploader-dropFile"),
  35547. name: "files[]",
  35548. multiple: false,
  35549. accept: "",
  35550. uploadUrl: "/",
  35551. allowCanceling: true,
  35552. showFileList: true,
  35553. progress: 0,
  35554. readyToUploadMessage: Globalize.localize("dxFileUploader-readyToUpload"),
  35555. uploadedMessage: Globalize.localize("dxFileUploader-uploaded"),
  35556. uploadFailedMessage: Globalize.localize("dxFileUploader-uploadFailedMessage"),
  35557. uploadMode: "instantly"
  35558. })
  35559. },
  35560. _defaultOptionsRules: function() {
  35561. return this.callBase().concat([{
  35562. device: function(device) {
  35563. return DX.devices.real().generic && !DX.devices.isSimulator()
  35564. },
  35565. options: {focusStateEnabled: true}
  35566. }])
  35567. },
  35568. _init: function() {
  35569. this.option("value", null);
  35570. this.option("values", []);
  35571. this.callBase.apply(this, arguments);
  35572. this._initFileInput();
  35573. this._initLabel();
  35574. this._initDragEvents();
  35575. this._createFiles();
  35576. this.element().addClass(FILEUPLOADER_CLASS)
  35577. },
  35578. _initFileInput: function() {
  35579. if (!this._$fileInput) {
  35580. this._$fileInput = $(FILEUPLOADER_FILEINPUT_TAG);
  35581. this._$fileInput.on("change", $.proxy(this._inputChangeHandler, this));
  35582. this._$fileInput.on("click", $.proxy(function() {
  35583. var isCustomEvent = this._isCustomEvent || false;
  35584. this._isCustomEvent = false;
  35585. return isCustomEvent
  35586. }, this))
  35587. }
  35588. this._$fileInput.prop({
  35589. multiple: this.option("multiple"),
  35590. name: this.option("name"),
  35591. accept: this.option("accept")
  35592. })
  35593. },
  35594. _inputChangeHandler: function(e) {
  35595. if (this._doPreventInputChange)
  35596. return;
  35597. var fileName = this._$fileInput.val().replace(/^.*\\/, ''),
  35598. files = this._$fileInput.prop("files"),
  35599. values = [];
  35600. if (files && !files.length)
  35601. return;
  35602. if (files)
  35603. $.each(files, function(_, value) {
  35604. values.push(value)
  35605. });
  35606. else
  35607. values = [{name: fileName}];
  35608. this._shouldChangeValue = true;
  35609. this.option("values", values);
  35610. delete this._shouldChangeValue;
  35611. if (this.option("uploadMode") === "instantly")
  35612. this._uploadFiles()
  35613. },
  35614. _initLabel: function() {
  35615. if (!this._$inputLabel)
  35616. this._$inputLabel = $("<div>");
  35617. this._$inputLabel.text(this.option("labelText"))
  35618. },
  35619. _initDragEvents: function() {
  35620. if (DX.devices.real().platform !== "generic" || DX.browser.msie)
  35621. return;
  35622. this._dragEventsCount = 0;
  35623. this.element().on("dragenter", $.proxy(this._dragEnterHandler, this)).on("dragleave", $.proxy(this._dragLeaveHandler, this)).on("drop", $.proxy(this._dropHandler, this))
  35624. },
  35625. _dragEnterHandler: function() {
  35626. if (this.option("disabled"))
  35627. return false;
  35628. this._dragEventsCount++;
  35629. this.element().addClass(FILEUPLOADER_DRAGOVER)
  35630. },
  35631. _dragLeaveHandler: function() {
  35632. this._dragEventsCount--;
  35633. if (this._dragEventsCount <= 0)
  35634. this.element().removeClass(FILEUPLOADER_DRAGOVER)
  35635. },
  35636. _dropHandler: function() {
  35637. this._dragEventsCount = 0;
  35638. this.element().removeClass(FILEUPLOADER_DRAGOVER)
  35639. },
  35640. _focusTarget: function() {
  35641. return this.element().find("." + FILEUPLOADER_BUTTON_CLASS)
  35642. },
  35643. _render: function() {
  35644. this._renderWrapper();
  35645. this._renderInputWrapper();
  35646. this._renderSelectButton();
  35647. this._renderInputContainer();
  35648. this._renderFiles();
  35649. this._renderUploadButton();
  35650. this.callBase.apply(this, arguments)
  35651. },
  35652. _createFiles: function() {
  35653. this._files = [];
  35654. $.each(this.option("values"), $.proxy(function(_, value) {
  35655. this._files.push(this._createFile(value))
  35656. }, this))
  35657. },
  35658. _createFile: function(value) {
  35659. return {
  35660. value: value,
  35661. loadedSize: 0,
  35662. onProgress: $.Callbacks(),
  35663. onLoad: $.Callbacks(),
  35664. onError: $.Callbacks(),
  35665. onLoadStart: $.Callbacks()
  35666. }
  35667. },
  35668. _renderFiles: function() {
  35669. if (!this._$filesContainer)
  35670. this._$filesContainer = $("<div>").addClass(FILEUPLOADER_FILES_CONTAINER_CLASS).appendTo(this._$content);
  35671. else
  35672. this._$filesContainer.empty();
  35673. if (this.option("showFileList")) {
  35674. var that = this;
  35675. $.each(this._files, function(_, file) {
  35676. that._renderFile(file)
  35677. })
  35678. }
  35679. this.element().toggleClass(FILEUPLOADER_EMPTY_CLASS, !this._files.length);
  35680. this._updateFileNameMaxWidth()
  35681. },
  35682. _renderFile: function(file) {
  35683. var value = file.value;
  35684. var $fileContainer = $("<div>").addClass(FILEUPLOADER_FILE_CONTAINER_CLASS).appendTo(this._$filesContainer);
  35685. this._renderFileButtons(file, $fileContainer);
  35686. file.$file = $("<div>").addClass(FILEUPLOADER_FILE_CLASS).appendTo($fileContainer);
  35687. var $fileInfo = $("<div>").addClass(FILEUPLOADER_FILE_INFO_CLASS).appendTo(file.$file);
  35688. file.$statusMessage = $("<div>").addClass(FILEUPLOADER_FILE_STATUS_MESSAGE_CLASS).text(this.option("readyToUploadMessage")).appendTo(file.$file);
  35689. $("<div>").addClass(FILEUPLOADER_FILE_NAME_CLASS).text(value.name).appendTo($fileInfo);
  35690. if (utils.isDefined(value.size))
  35691. $("<div>").addClass(FILEUPLOADER_FILE_SIZE_CLASS).text(this._getFileSize(value.size)).appendTo($fileInfo)
  35692. },
  35693. _updateFileNameMaxWidth: function() {
  35694. var cancelButtonsCount = this.option("allowCanceling") ? 1 : 0,
  35695. uploadButtonsCount = this.option("uploadMode") === "useButtons" ? 1 : 0,
  35696. filesContainerWidth = this._$filesContainer.width(),
  35697. $buttonContainer = this._$filesContainer.find("." + FILEUPLOADER_BUTTON_CONTAINER_CLASS).eq(0),
  35698. buttonsWidth = $buttonContainer.width() * (cancelButtonsCount + uploadButtonsCount),
  35699. $fileSize = this._$filesContainer.find("." + FILEUPLOADER_FILE_SIZE_CLASS).eq(0);
  35700. var prevFileSize = $fileSize.text();
  35701. $fileSize.text("1000Mb");
  35702. var fileSizeWidth = $fileSize.width();
  35703. $fileSize.text(prevFileSize);
  35704. this._$filesContainer.find("." + FILEUPLOADER_FILE_NAME_CLASS).css("max-width", filesContainerWidth - buttonsWidth - fileSizeWidth)
  35705. },
  35706. _renderFileButtons: function(file, $container) {
  35707. file.cancelButton = this._createComponent($("<div>").addClass(FILEUPLOADER_BUTTON_CLASS + " " + FILEUPLOADER_CANCEL_BUTTON_CLASS), "dxButton", {
  35708. onClick: $.proxy(function() {
  35709. this._removeFile(file)
  35710. }, this),
  35711. icon: "close",
  35712. visible: this.option("allowCanceling"),
  35713. _templates: {}
  35714. });
  35715. $("<div>").addClass(FILEUPLOADER_BUTTON_CONTAINER_CLASS).append(file.cancelButton.element()).appendTo($container);
  35716. if (this.option("uploadMode") === "useButtons") {
  35717. file.uploadButton = this._createComponent($("<div>").addClass(FILEUPLOADER_BUTTON_CLASS + " " + FILEUPLOADER_UPLOAD_BUTTON_CLASS), "dxButton", {
  35718. onClick: $.proxy(function(e) {
  35719. this._uploadFile(file)
  35720. }, this),
  35721. icon: "upload"
  35722. });
  35723. $("<div>").addClass(FILEUPLOADER_BUTTON_CONTAINER_CLASS).append(file.uploadButton.element()).appendTo($container);
  35724. file.onLoadStart.add($.proxy(function() {
  35725. file.uploadButton.element().remove()
  35726. }, this))
  35727. }
  35728. },
  35729. _removeFile: function(file) {
  35730. file.$file.parent().remove();
  35731. var values = this.option("values");
  35732. values.splice($.inArray(file.value, values), 1);
  35733. this._files.splice($.inArray(file, this._files), 1);
  35734. this.element().toggleClass(FILEUPLOADER_EMPTY_CLASS, !this._files.length);
  35735. this._recalculateProgress();
  35736. this._doPreventInputChange = true;
  35737. this._$fileInput.val("");
  35738. this._doPreventInputChange = false
  35739. },
  35740. _getFileSize: function(size) {
  35741. var i = 0,
  35742. labels = [Globalize.localize("dxFileUploader-bytes"), Globalize.localize("dxFileUploader-kb"), Globalize.localize("dxFileUploader-Mb"), Globalize.localize("dxFileUploader-Gb")],
  35743. count = labels.length - 1;
  35744. while (i < count && size >= 1024) {
  35745. size /= 1024;
  35746. i++
  35747. }
  35748. return Math.round(size) + labels[i]
  35749. },
  35750. _renderSelectButton: function() {
  35751. var $button = $("<div>").addClass(FILEUPLOADER_BUTTON_CLASS).appendTo(this._$inputWrapper);
  35752. $button.off("click").on("click", $.proxy(this._selectButtonClickHandler, this));
  35753. this._selectButton = this._createComponent($button, "dxButton", {
  35754. text: this.option("selectButtonText"),
  35755. focusStateEnabled: false,
  35756. _templates: {}
  35757. })
  35758. },
  35759. _selectButtonClickHandler: function() {
  35760. if (this.option("disabled"))
  35761. return false;
  35762. this._isCustomEvent = true;
  35763. this._$fileInput.click()
  35764. },
  35765. _renderUploadButton: function() {
  35766. if (this.option("uploadMode") !== "useButtons")
  35767. return;
  35768. var $uploadButton = $("<div>").addClass(FILEUPLOADER_BUTTON_CLASS).addClass(FILEUPLOADER_UPLOAD_BUTTON_CLASS).appendTo(this._$content);
  35769. this._uploadButton = this._createComponent($uploadButton, "dxButton", {
  35770. text: this.option("uploadButtonText"),
  35771. onClick: $.proxy(this._uploadButtonClickHandler, this),
  35772. _templates: {}
  35773. })
  35774. },
  35775. _uploadButtonClickHandler: function() {
  35776. this._uploadFiles()
  35777. },
  35778. _renderInputContainer: function() {
  35779. this._$inputContainer = $("<div>").addClass(FILEUPLOADER_INPUT_CONTAINER_CLASS).appendTo(this._$inputWrapper);
  35780. if (DX.browser.msie)
  35781. this._$inputContainer.css("display", "none");
  35782. this._$fileInput.addClass(FILEUPLOADER_INPUT_CLASS).appendTo(this._$inputContainer);
  35783. this._$inputLabel.addClass(FILEUPLOADER_INPUT_LABEL_CLASS).appendTo(this._$inputContainer)
  35784. },
  35785. _renderInputWrapper: function() {
  35786. this._$inputWrapper = $("<div>").addClass(FILEUPLOADER_INPUT_WRAPPER_CLASS).appendTo(this._$content)
  35787. },
  35788. _renderWrapper: function() {
  35789. var $wrapper = $("<div>").addClass(FILEUPLOADER_WRAPPER_CLASS).appendTo(this.element());
  35790. var $container = $("<div>").addClass(FILEUPLOADER_CONTAINER_CLASS).appendTo($wrapper);
  35791. this._$content = $("<div>").addClass(FILEUPLOADER_CONTENT_CLASS).appendTo($container)
  35792. },
  35793. _clean: function() {
  35794. this._$fileInput.detach();
  35795. delete this._$filesContainer;
  35796. this.callBase.apply(this, arguments)
  35797. },
  35798. _uploadFiles: function() {
  35799. if (!isFormDataSupported())
  35800. return;
  35801. $.each(this._files, $.proxy(function(_, file) {
  35802. this._uploadFile(file)
  35803. }, this))
  35804. },
  35805. _uploadFile: function(file) {
  35806. if (file.progressBar)
  35807. return;
  35808. var $file = file.$file,
  35809. value = file.value;
  35810. this._initUploadRequest(file);
  35811. if ($file) {
  35812. file.progressBar = this._createProgressBar(value.size);
  35813. file.progressBar.element().appendTo($file);
  35814. this._initStatusMessage(file);
  35815. this._initCancelButton(file);
  35816. file.onError.add($.proxy(this._onErrorHandler, this, file))
  35817. }
  35818. file.onProgress.add($.proxy(this._onProgressHandler, this, file));
  35819. file.request.send(this._createFormData(this.option("name"), value))
  35820. },
  35821. _onErrorHandler: function(file) {
  35822. var that = this;
  35823. setTimeout(function() {
  35824. file.$statusMessage.text(that.option("uploadFailedMessage"));
  35825. file.$statusMessage.css("display", "");
  35826. file.progressBar.element().remove()
  35827. }, FILEUPLOADER_AFTER_LOAD_DELAY)
  35828. },
  35829. _onLoadedHandler: function(file) {
  35830. var that = this;
  35831. setTimeout(function() {
  35832. file.$statusMessage.text(that.option("uploadedMessage"));
  35833. file.$statusMessage.css("display", "");
  35834. file.progressBar.element().remove()
  35835. }, FILEUPLOADER_AFTER_LOAD_DELAY)
  35836. },
  35837. _onProgressHandler: function(file, e) {
  35838. var totalSize = this._getTotalSize(),
  35839. currentLoadedSize = 0,
  35840. loadedSize = this._getLoadedSize(),
  35841. progress = 0;
  35842. if (file) {
  35843. currentLoadedSize = Math.min(e.loaded, file.value.size);
  35844. loadedSize += currentLoadedSize - file.loadedSize;
  35845. file.progressBar && file.progressBar.option({
  35846. value: currentLoadedSize,
  35847. showStatus: true
  35848. });
  35849. file.loadedSize = currentLoadedSize
  35850. }
  35851. if (totalSize)
  35852. progress = Math.round(loadedSize / totalSize * 100);
  35853. this.option("progress", progress);
  35854. this._setLoadedSize(loadedSize)
  35855. },
  35856. _initStatusMessage: function(file) {
  35857. file.$statusMessage.css("display", "none");
  35858. file.onLoad.add($.proxy(this._onLoadedHandler, this, file))
  35859. },
  35860. _initCancelButton: function(file) {
  35861. var cancelClickHandler = $.proxy(function() {
  35862. file.request.abort();
  35863. this._removeFile(file)
  35864. }, this);
  35865. file.cancelButton.option("onClick", cancelClickHandler);
  35866. var hideCancelButton = function() {
  35867. setTimeout(function() {
  35868. file.cancelButton.option({visible: false})
  35869. }, FILEUPLOADER_AFTER_LOAD_DELAY)
  35870. };
  35871. file.onLoad.add(hideCancelButton);
  35872. file.onError.add(hideCancelButton)
  35873. },
  35874. _initUploadRequest: function(file) {
  35875. file.request = this._createRequest(this.option("uploadUrl"));
  35876. file.loadedSize = 0;
  35877. file.request.onreadystatechange = $.proxy(function(e) {
  35878. if (e.currentTarget.readyState === 4)
  35879. if (e.currentTarget.status === 200)
  35880. this.onLoad.fire(e);
  35881. else
  35882. this.onError.fire(e)
  35883. }, file);
  35884. file.request.upload.onprogress = $.proxy(function(e) {
  35885. this.onProgress.fire(e)
  35886. }, file);
  35887. file.request.upload.onloadstart = $.proxy(function(e) {
  35888. this.onLoadStart.fire(e)
  35889. }, file)
  35890. },
  35891. _createRequest: function(url) {
  35892. var Request = getRequestPrototype(),
  35893. request = new Request;
  35894. request.open("POST", url, true);
  35895. return request
  35896. },
  35897. _createFormData: function(fieldName, fieldValue) {
  35898. var FormData = getFormDataPrototype(),
  35899. formData = new FormData;
  35900. formData.append(fieldName, fieldValue);
  35901. return formData
  35902. },
  35903. _createProgressBar: function(fileSize) {
  35904. return this._createComponent($("<div>"), "dxProgressBar", {
  35905. value: undefined,
  35906. min: 0,
  35907. max: fileSize,
  35908. statusFormat: function(ratio) {
  35909. return Math.round(ratio * 100) + "%"
  35910. },
  35911. showStatus: false,
  35912. statusPosition: "right"
  35913. })
  35914. },
  35915. _getTotalSize: function() {
  35916. if (!this._totalSize) {
  35917. var files = this.option("values"),
  35918. totalSize = 0;
  35919. $.each(files, function(_, file) {
  35920. totalSize += file.size
  35921. });
  35922. this._totalSize = totalSize
  35923. }
  35924. return this._totalSize
  35925. },
  35926. _getLoadedSize: function() {
  35927. if (!this._loadedSize) {
  35928. var loadedSize = 0;
  35929. $.each(this._files, function(_, file) {
  35930. loadedSize += file.loadedSize
  35931. });
  35932. this._loadedSize = loadedSize
  35933. }
  35934. return this._loadedSize
  35935. },
  35936. _setLoadedSize: function(value) {
  35937. this._loadedSize = value
  35938. },
  35939. _recalculateProgress: function() {
  35940. delete this._totalSize;
  35941. delete this._loadedSize;
  35942. this._onProgressHandler()
  35943. },
  35944. _optionChanged: function(args) {
  35945. var value = args.value;
  35946. switch (args.name) {
  35947. case"height":
  35948. case"width":
  35949. this._updateFileNameMaxWidth();
  35950. this.callBase(args);
  35951. break;
  35952. case"value":
  35953. if (!this._shouldChangeValue) {
  35954. this._$fileInput.val("");
  35955. this.option("values", [])
  35956. }
  35957. this.callBase(args);
  35958. break;
  35959. case"values":
  35960. if (value.length && !this._shouldChangeValue)
  35961. this.option("values", []);
  35962. else {
  35963. this._createFiles();
  35964. this._renderFiles();
  35965. this.option("value", value[0] || null);
  35966. this._recalculateProgress()
  35967. }
  35968. break;
  35969. case"name":
  35970. case"accept":
  35971. this._initFileInput();
  35972. break;
  35973. case"multiple":
  35974. this._initFileInput();
  35975. if (!args.value)
  35976. this.option("values", []);
  35977. break;
  35978. case"selectButtonText":
  35979. this._selectButton.option("text", value);
  35980. break;
  35981. case"uploadButtonText":
  35982. this._uploadButton && this._uploadButton.option("text", value);
  35983. break;
  35984. case"readyToUploadMessage":
  35985. case"uploadedMessage":
  35986. case"uploadFailedMessage":
  35987. this._invalidate();
  35988. break;
  35989. case"labelText":
  35990. this._$inputLabel.text(value);
  35991. break;
  35992. case"showFileList":
  35993. this._renderFiles();
  35994. break;
  35995. case"uploadUrl":
  35996. case"progress":
  35997. break;
  35998. case"allowCanceling":
  35999. case"uploadMode":
  36000. this.reset();
  36001. this._invalidate();
  36002. break;
  36003. default:
  36004. this.callBase(args)
  36005. }
  36006. },
  36007. _valueChangeArgs: function() {
  36008. return $.extend(this.callBase.apply(this, arguments), {values: this.option("values")})
  36009. }
  36010. }));
  36011. ui.dxFileUploader.__internals = {
  36012. FILEUPLOADER_CLASS: FILEUPLOADER_CLASS,
  36013. FILEUPLOADER_EMPTY_CLASS: FILEUPLOADER_EMPTY_CLASS,
  36014. FILEUPLOADER_DRAGOVER: FILEUPLOADER_DRAGOVER,
  36015. FILEUPLOADER_WRAPPER_CLASS: FILEUPLOADER_WRAPPER_CLASS,
  36016. FILEUPLOADER_CONTAINER_CLASS: FILEUPLOADER_CONTAINER_CLASS,
  36017. FILEUPLOADER_CONTENT_CLASS: FILEUPLOADER_CONTENT_CLASS,
  36018. FILEUPLOADER_INPUT_WRAPPER_CLASS: FILEUPLOADER_INPUT_WRAPPER_CLASS,
  36019. FILEUPLOADER_INPUT_CONTAINER_CLASS: FILEUPLOADER_INPUT_CONTAINER_CLASS,
  36020. FILEUPLOADER_INPUT_LABEL_CLASS: FILEUPLOADER_INPUT_LABEL_CLASS,
  36021. FILEUPLOADER_INPUT_CLASS: FILEUPLOADER_INPUT_CLASS,
  36022. FILEUPLOADER_FILES_CONTAINER_CLASS: FILEUPLOADER_FILES_CONTAINER_CLASS,
  36023. FILEUPLOADER_FILE_CONTAINER_CLASS: FILEUPLOADER_FILE_CONTAINER_CLASS,
  36024. FILEUPLOADER_FILE_CLASS: FILEUPLOADER_FILE_CLASS,
  36025. FILEUPLOADER_FILE_NAME_CLASS: FILEUPLOADER_FILE_NAME_CLASS,
  36026. FILEUPLOADER_FILE_SIZE_CLASS: FILEUPLOADER_FILE_SIZE_CLASS,
  36027. FILEUPLOADER_BUTTON_CLASS: FILEUPLOADER_BUTTON_CLASS,
  36028. FILEUPLOADER_CANCEL_BUTTON_CLASS: FILEUPLOADER_CANCEL_BUTTON_CLASS,
  36029. FILEUPLOADER_UPLOAD_BUTTON_CLASS: FILEUPLOADER_UPLOAD_BUTTON_CLASS,
  36030. FILEUPLOADER_FILE_INFO_CLASS: FILEUPLOADER_FILE_INFO_CLASS,
  36031. FILEUPLOADER_FILE_STATUS_CLASS: FILEUPLOADER_FILE_STATUS_CLASS,
  36032. FILEUPLOADER_FILE_STATUS_MESSAGE_CLASS: FILEUPLOADER_FILE_STATUS_MESSAGE_CLASS,
  36033. getFormDataPrototype: getFormDataPrototype,
  36034. getRequestPrototype: getRequestPrototype,
  36035. isFormDataSupported: isFormDataSupported,
  36036. changeFileInputTag: function(tag) {
  36037. FILEUPLOADER_FILEINPUT_TAG = tag
  36038. },
  36039. resetFileInputTag: function() {
  36040. FILEUPLOADER_FILEINPUT_TAG = "<input type='file'>"
  36041. },
  36042. changeRequestClass: function(requestClass) {
  36043. getRequestPrototype = function() {
  36044. return requestClass
  36045. }
  36046. },
  36047. resetRequestClass: function() {
  36048. getRequestPrototype = this.getRequestPrototype
  36049. },
  36050. changeFormDataClass: function(customFormData) {
  36051. getFormDataPrototype = function() {
  36052. return customFormData
  36053. }
  36054. },
  36055. resetFormDataClass: function() {
  36056. getFormDataPrototype = this.getFormDataPrototype
  36057. }
  36058. }
  36059. })(jQuery, DevExpress);
  36060. /*! Module widgets-base, file ui.tabPanel.js */
  36061. (function($, DX, undefined) {
  36062. var ui = DX.ui;
  36063. var TABPANEL_CLASS = "dx-tabpanel";
  36064. DX.registerComponent("dxTabPanel", ui, ui.dxMultiView.inherit({
  36065. _setDeprecatedOptions: function() {
  36066. this.callBase();
  36067. $.extend(this._deprecatedOptions, {titleTemplate: {
  36068. since: "14.2",
  36069. alias: "itemTitleTemplate"
  36070. }})
  36071. },
  36072. _setDefaultOptions: function() {
  36073. this.callBase();
  36074. this.option({
  36075. itemTitleTemplate: "title",
  36076. onTitleClick: null,
  36077. onTitleHold: null,
  36078. onTitleRendered: null
  36079. })
  36080. },
  36081. _defaultOptionsRules: function() {
  36082. return this.callBase().concat([{
  36083. device: function(device) {
  36084. return DX.devices.real().generic && !DX.devices.isSimulator()
  36085. },
  36086. options: {focusStateEnabled: true}
  36087. }, {
  36088. device: function(device) {
  36089. return !DX.support.touch
  36090. },
  36091. options: {swipeEnabled: false}
  36092. }, {
  36093. device: {platform: "generic"},
  36094. options: {animationEnabled: false}
  36095. }])
  36096. },
  36097. _init: function() {
  36098. this.callBase();
  36099. this.element().addClass(TABPANEL_CLASS);
  36100. this.setAria("role", "tabpanel");
  36101. this._renderBox()
  36102. },
  36103. _renderBox: function() {
  36104. var $box = $("<div>").appendTo(this.element());
  36105. this._box = this._createComponent($box, "dxBox", {
  36106. direction: "col",
  36107. align: "flex-start",
  36108. crossAlign: "stretch",
  36109. items: [{
  36110. ratio: 0,
  36111. shrink: 0,
  36112. baseSize: "auto",
  36113. template: $.proxy(function() {
  36114. var $tabs = $("<div>");
  36115. this._tabs = this._createComponent($tabs, "dxTabs", this._tabConfig());
  36116. return $tabs
  36117. }, this)
  36118. }, {
  36119. ratio: 1,
  36120. shrink: 1,
  36121. baseSize: "auto",
  36122. template: $.proxy(function(_, __, $content) {
  36123. this._$wrapper.addClass($content.attr("class"));
  36124. $content.replaceWith(this._$wrapper)
  36125. }, this)
  36126. }],
  36127. height: "100%"
  36128. })
  36129. },
  36130. _refreshActiveDescendant: function() {
  36131. var tabs = this._tabs,
  36132. tabItems = tabs.itemElements(),
  36133. $activeTab = $(tabItems[tabs.option("selectedIndex")]),
  36134. id = this.getFocusedItemId();
  36135. this.setAria("controls", undefined, $(tabItems));
  36136. this.setAria("controls", id, $activeTab)
  36137. },
  36138. _tabConfig: function() {
  36139. return {
  36140. selectOnFocus: true,
  36141. focusStateEnabled: this.option("focusStateEnabled"),
  36142. tabIndex: this.option("tabIndex"),
  36143. selectedIndex: this.option("selectedIndex"),
  36144. onItemClick: this.option("onTitleClick"),
  36145. onItemHold: this.option("onTitleHold"),
  36146. itemHoldTimeout: this.option("itemHoldTimeout"),
  36147. onSelectionChanged: $.proxy(function(e) {
  36148. this.option("selectedIndex", e.component.option("selectedIndex"));
  36149. this._refreshActiveDescendant()
  36150. }, this),
  36151. onItemRendered: this.option("onTitleRendered"),
  36152. itemTemplate: this._getTemplateByOption("itemTitleTemplate"),
  36153. items: this.option("items"),
  36154. scrollingEnabled: false,
  36155. itemTemplateProperty: "tabTemplate",
  36156. selectionRequired: true,
  36157. onOptionChanged: $.proxy(function(args) {
  36158. var name = args.name,
  36159. value = args.value;
  36160. if (name === "focusedElement") {
  36161. var id = value ? value.index() : value;
  36162. var newItem = value ? this._itemElements().eq(id) : value;
  36163. this.option("focusedElement", newItem)
  36164. }
  36165. }, this),
  36166. onFocusIn: $.proxy(this._focusInHandler, this),
  36167. onFocusOut: $.proxy(this._focusOutHandler, this)
  36168. }
  36169. },
  36170. _renderFocusTarget: function() {
  36171. this._focusTarget().attr("tabindex", -1);
  36172. this._refreshActiveDescendant()
  36173. },
  36174. _setTabsOption: function(name, value) {
  36175. if (this._tabs)
  36176. this._tabs.option(name, value)
  36177. },
  36178. _updateSelection: function() {
  36179. this.callBase.apply(this, arguments);
  36180. this._box.repaint()
  36181. },
  36182. _optionChanged: function(args) {
  36183. var name = args.name,
  36184. value = args.value;
  36185. switch (name) {
  36186. case"dataSource":
  36187. this.callBase(args);
  36188. break;
  36189. case"items":
  36190. case"selectedIndex":
  36191. case"selectedItem":
  36192. case"itemHoldTimeout":
  36193. case"focusStateEnabled":
  36194. this._setTabsOption(name, value);
  36195. this.callBase(args);
  36196. break;
  36197. case"focusedElement":
  36198. var id = value ? value.index() : value;
  36199. var newItem = value ? this._tabs._itemElements().eq(id) : value;
  36200. this._setTabsOption("focusedElement", newItem);
  36201. this.callBase(args);
  36202. this._tabs.focus();
  36203. break;
  36204. case"itemTitleTemplate":
  36205. this._setTabsOption("itemTemplate", this._getTemplateByOption("itemTitleTemplate"));
  36206. break;
  36207. case"onTitleClick":
  36208. this._setTabsOption("onItemClick", value);
  36209. break;
  36210. case"onTitleHold":
  36211. this._setTabsOption("onItemHold", value);
  36212. break;
  36213. case"onTitleRendered":
  36214. this._setTabsOption("onItemRendered", value);
  36215. break;
  36216. default:
  36217. this.callBase(args)
  36218. }
  36219. }
  36220. }))
  36221. })(jQuery, DevExpress);
  36222. DevExpress.MOD_WIDGETS_BASE = true
  36223. }
  36224. if (!DevExpress.MOD_WIDGETS_MOBILE) {
  36225. if (!DevExpress.MOD_WIDGETS_BASE)
  36226. throw Error('Required module is not referenced: widgets-base');
  36227. /*! Module widgets-mobile, file ui.pivotTabs.js */
  36228. (function($, DX, undefined) {
  36229. var ui = DX.ui,
  36230. fx = DX.fx,
  36231. translator = DX.translator,
  36232. events = ui.events;
  36233. var PIVOT_TABS_CLASS = "dx-pivottabs",
  36234. PIVOT_TAB_CLASS = "dx-pivottabs-tab",
  36235. PIVOT_TAB_SELECTED_CLASS = "dx-pivottabs-tab-selected",
  36236. PIVOT_GHOST_TAB_CLASS = "dx-pivottabs-ghosttab",
  36237. PIVOT_TAB_DATA_KEY = "dxPivotTabData",
  36238. PIVOT_TAB_MOVE_DURATION = 200,
  36239. PIVOT_TAB_MOVE_EASING = "cubic-bezier(.40, .80, .60, 1)";
  36240. var animation = {
  36241. moveTo: function($tab, position, completeAction) {
  36242. return fx.animate($tab, {
  36243. type: "slide",
  36244. to: {left: position},
  36245. duration: PIVOT_TAB_MOVE_DURATION,
  36246. easing: PIVOT_TAB_MOVE_EASING,
  36247. complete: completeAction
  36248. })
  36249. },
  36250. slideAppear: function($tab, position) {
  36251. return fx.animate($tab, {
  36252. type: "slide",
  36253. to: {
  36254. left: position,
  36255. opacity: 1
  36256. },
  36257. duration: PIVOT_TAB_MOVE_DURATION,
  36258. easing: PIVOT_TAB_MOVE_EASING
  36259. })
  36260. },
  36261. slideDisappear: function($tab, position) {
  36262. return fx.animate($tab, {
  36263. type: "slide",
  36264. to: {
  36265. left: position,
  36266. opacity: 0
  36267. },
  36268. duration: PIVOT_TAB_MOVE_DURATION,
  36269. easing: PIVOT_TAB_MOVE_EASING
  36270. })
  36271. },
  36272. complete: function(elements) {
  36273. if (!elements)
  36274. return;
  36275. $.each(elements, function(_, $element) {
  36276. fx.stop($element, true)
  36277. })
  36278. },
  36279. stop: function(elements) {
  36280. if (!elements)
  36281. return;
  36282. $.each(elements, function(_, $element) {
  36283. fx.stop($element)
  36284. })
  36285. }
  36286. };
  36287. DX.registerComponent("dxPivotTabs", ui, ui.CollectionWidget.inherit({
  36288. _setDefaultOptions: function() {
  36289. this.callBase();
  36290. this.option({
  36291. selectedIndex: 0,
  36292. onPrepare: null,
  36293. onUpdatePosition: null,
  36294. onRollback: null,
  36295. focusStateEnabled: false,
  36296. selectionMode: "single",
  36297. selectionRequired: true,
  36298. swipeEnabled: true
  36299. })
  36300. },
  36301. _itemClass: function() {
  36302. return PIVOT_TAB_CLASS
  36303. },
  36304. _itemDataKey: function() {
  36305. return PIVOT_TAB_DATA_KEY
  36306. },
  36307. _itemContainer: function() {
  36308. return this.element()
  36309. },
  36310. _elementWidth: function() {
  36311. if (!this._elementWidthCache)
  36312. this._elementWidthCache = this.element().width();
  36313. return this._elementWidthCache
  36314. },
  36315. _clearElementWidthCache: function() {
  36316. delete this._elementWidthCache
  36317. },
  36318. _itemWidths: function() {
  36319. if (!this._itemWidthsCache) {
  36320. var $tabs = this._itemElements(),
  36321. widths = [];
  36322. $tabs.each(function() {
  36323. widths.push($(this).outerWidth())
  36324. });
  36325. this._itemWidthsCache = widths
  36326. }
  36327. return this._itemWidthsCache
  36328. },
  36329. _init: function() {
  36330. this.callBase();
  36331. this._initGhostTab();
  36332. this._initSwipeHandlers();
  36333. this._initActions()
  36334. },
  36335. _dimensionChanged: function() {
  36336. this._clearElementWidthCache();
  36337. this._cleanPositionCache();
  36338. this._updateTabsPositions()
  36339. },
  36340. _initGhostTab: function() {
  36341. this._$ghostTab = $("<div>").addClass(PIVOT_GHOST_TAB_CLASS)
  36342. },
  36343. _initActions: function() {
  36344. this._updatePositionAction = this._createActionByOption("onUpdatePosition");
  36345. this._rollbackAction = this._createActionByOption("onRollback");
  36346. this._prepareAction = this._createActionByOption("onPrepare")
  36347. },
  36348. _render: function() {
  36349. this.element().addClass(PIVOT_TABS_CLASS);
  36350. this.callBase();
  36351. this._renderGhostTab()
  36352. },
  36353. _renderGhostTab: function() {
  36354. this._itemContainer().append(this._$ghostTab);
  36355. this._toggleGhostTab(false)
  36356. },
  36357. _toggleGhostTab: function(visible) {
  36358. var $ghostTab = this._$ghostTab;
  36359. if (visible) {
  36360. this._updateGhostTabContent();
  36361. $ghostTab.css("opacity", 1)
  36362. }
  36363. else
  36364. $ghostTab.css("opacity", 0)
  36365. },
  36366. _isGhostTabVisible: function() {
  36367. return this._$ghostTab.css("opacity") === "1"
  36368. },
  36369. _updateGhostTabContent: function(prevIndex) {
  36370. prevIndex = prevIndex === undefined ? this._previousIndex() : prevIndex;
  36371. var $ghostTab = this._$ghostTab,
  36372. $items = this._itemElements();
  36373. $ghostTab.html($items.eq(prevIndex).html())
  36374. },
  36375. _updateTabsPositions: function(offset) {
  36376. offset = this._applyOffsetBoundaries(offset);
  36377. var isPrevSwipeHandled = this.option("rtlEnabled") ^ offset > 0 && offset !== 0,
  36378. tabPositions = this._calculateTabPositions(isPrevSwipeHandled ? "replace" : "append");
  36379. this._moveTabs(tabPositions, offset);
  36380. this._toggleGhostTab(isPrevSwipeHandled)
  36381. },
  36382. _moveTabs: function(positions, offset) {
  36383. offset = offset || 0;
  36384. var $tabs = this._allTabElements();
  36385. $tabs.each(function(index) {
  36386. translator.move($(this), {left: positions[index] + offset})
  36387. })
  36388. },
  36389. _applyOffsetBoundaries: function(offset) {
  36390. offset = offset || 0;
  36391. var maxOffset = offset > 0 ? this._maxRightOffset : this._maxLeftOffset;
  36392. return offset * maxOffset
  36393. },
  36394. _animateRollback: function() {
  36395. var that = this,
  36396. $tabs = this._itemElements(),
  36397. positions = this._calculateTabPositions("prepend");
  36398. if (this._isGhostTabVisible()) {
  36399. this._swapGhostWithTab($tabs.eq(this._previousIndex()));
  36400. animation.moveTo(this._$ghostTab, positions[this._indexBoundary()], function() {
  36401. that._toggleGhostTab(false)
  36402. })
  36403. }
  36404. $tabs.each(function(index) {
  36405. animation.moveTo($(this), positions[index])
  36406. })
  36407. },
  36408. _animateComplete: function(newIndex, currentIndex) {
  36409. var $tabs = this._itemElements(),
  36410. isPrevSwipeHandled = this._isGhostTabVisible();
  36411. $tabs.eq(currentIndex).removeClass(PIVOT_TAB_SELECTED_CLASS);
  36412. if (isPrevSwipeHandled)
  36413. this._animateIndexDecreasing(newIndex);
  36414. else
  36415. this._animateIndexIncreasing(newIndex);
  36416. $tabs.eq(newIndex).addClass(PIVOT_TAB_SELECTED_CLASS)
  36417. },
  36418. _animateIndexDecreasing: function(newIndex) {
  36419. var $tabs = this._itemElements(),
  36420. positions = this._calculateTabPositions("append", newIndex),
  36421. animations = [];
  36422. $tabs.each(function(index) {
  36423. animations.push(animation.moveTo($(this), positions[index]))
  36424. });
  36425. animations.push(animation.slideDisappear(this._$ghostTab, positions[this._indexBoundary()]));
  36426. return $.when.apply($, animations)
  36427. },
  36428. _animateIndexIncreasing: function(newIndex) {
  36429. var that = this,
  36430. $tabs = this._itemElements(),
  36431. positions = this._calculateTabPositions("prepend", newIndex),
  36432. previousIndex = this._previousIndex(newIndex),
  36433. $prevTab = $tabs.eq(previousIndex),
  36434. prevTabPosition = translator.locate($prevTab).left,
  36435. rtl = this.option("rtlEnabled"),
  36436. bound = rtl ? this._elementWidth() - this._itemWidths()[previousIndex] : 0,
  36437. isNextSwipeHandled = (prevTabPosition - bound) * this._getRTLSignCorrection() < 0,
  36438. animations = [];
  36439. if (!isNextSwipeHandled)
  36440. this._moveTabs(this._calculateTabPositions("append", previousIndex));
  36441. this._updateGhostTabContent(previousIndex);
  36442. this._swapGhostWithTab($tabs.eq(previousIndex));
  36443. $tabs.each(function(index) {
  36444. var $tab = $(this),
  36445. newPosition = positions[index];
  36446. animations.push(index === previousIndex ? animation.slideAppear($tab, newPosition) : animation.moveTo($tab, newPosition))
  36447. });
  36448. animations.push(animation.moveTo(this._$ghostTab, positions[this._indexBoundary()], function() {
  36449. that._toggleGhostTab(false)
  36450. }));
  36451. return $.when.apply($, animations)
  36452. },
  36453. _swapGhostWithTab: function($tab) {
  36454. var $ghostTab = this._$ghostTab,
  36455. lastTabPosition = translator.locate($tab).left,
  36456. lastTabOpacity = $tab.css("opacity");
  36457. translator.move($tab, {left: translator.locate($ghostTab).left});
  36458. $tab.css("opacity", $ghostTab.css("opacity"));
  36459. translator.move($ghostTab, {left: lastTabPosition});
  36460. $ghostTab.css("opacity", lastTabOpacity)
  36461. },
  36462. _calculateTabPositions: function(ghostPosition, index) {
  36463. index = index === undefined ? this.option("selectedIndex") : index;
  36464. var mark = index + ghostPosition;
  36465. if (this._calculetedPositionsMark !== mark) {
  36466. this._calculetedPositions = this._calculateTabPositionsImpl(index, ghostPosition);
  36467. this._calculetedPositionsMark = mark
  36468. }
  36469. return this._calculetedPositions
  36470. },
  36471. _calculateTabPositionsImpl: function(currentIndex, ghostPosition) {
  36472. var prevIndex = this._normalizeIndex(currentIndex - 1),
  36473. widths = this._itemWidths();
  36474. var rtl = this.option("rtlEnabled"),
  36475. signCorrection = this._getRTLSignCorrection(),
  36476. tabsContainerWidth = this._elementWidth(),
  36477. nextPosition = rtl ? tabsContainerWidth : 0,
  36478. positions = [];
  36479. var calculateTabPosition = function(currentIndex, width) {
  36480. var rtlOffset = rtl * width;
  36481. positions.splice(currentIndex, 0, nextPosition - rtlOffset);
  36482. nextPosition += width * signCorrection
  36483. };
  36484. $.each(widths.slice(currentIndex), calculateTabPosition);
  36485. $.each(widths.slice(0, currentIndex), calculateTabPosition);
  36486. switch (ghostPosition) {
  36487. case"replace":
  36488. var lastTabPosition = positions[prevIndex];
  36489. positions.splice(prevIndex, 1, rtl ? tabsContainerWidth : -widths[prevIndex]);
  36490. positions.push(lastTabPosition);
  36491. break;
  36492. case"prepend":
  36493. positions.push(rtl ? tabsContainerWidth : -widths[prevIndex]);
  36494. break;
  36495. case"append":
  36496. positions.push(nextPosition - widths[currentIndex] * rtl);
  36497. break
  36498. }
  36499. return positions
  36500. },
  36501. _allTabElements: function() {
  36502. return this._itemContainer().find("." + PIVOT_TAB_CLASS + ", ." + PIVOT_GHOST_TAB_CLASS)
  36503. },
  36504. _initSwipeHandlers: function() {
  36505. this.element().on(events.addNamespace("dxswipestart", this.NAME), {itemSizeFunc: $.proxy(this._elementWidth, this)}, $.proxy(this._swipeStartHandler, this)).on(events.addNamespace("dxswipe", this.NAME), $.proxy(this._swipeUpdateHandler, this)).on(events.addNamespace("dxswipeend", this.NAME), $.proxy(this._swipeEndHandler, this))
  36506. },
  36507. _swipeStartHandler: function(e) {
  36508. this._prepareAnimation();
  36509. this._prepareAction();
  36510. e.maxLeftOffset = 1;
  36511. e.maxRightOffset = 1;
  36512. if (DX.designMode || this.option("disabled") || !this.option("swipeEnabled") || this._indexBoundary() <= 1)
  36513. e.cancel = true;
  36514. else
  36515. this._swipeGestureRunning = true
  36516. },
  36517. _prepareAnimation: function() {
  36518. this._stopAnimation()
  36519. },
  36520. _stopAnimation: function() {
  36521. animation.complete(this._allTabElements())
  36522. },
  36523. _swipeUpdateHandler: function(e) {
  36524. var offset = e.offset;
  36525. this._updateTabsPositions(offset);
  36526. this._updatePositionAction({offset: offset})
  36527. },
  36528. _swipeEndHandler: function(e) {
  36529. var targetOffset = e.targetOffset * this._getRTLSignCorrection();
  36530. if (targetOffset === 0) {
  36531. this._animateRollback();
  36532. this._rollbackAction()
  36533. }
  36534. else {
  36535. var newIndex = this._normalizeIndex(this.option("selectedIndex") - targetOffset);
  36536. this.option("selectedIndex", newIndex)
  36537. }
  36538. this._swipeGestureRunning = false
  36539. },
  36540. _previousIndex: function(atIndex) {
  36541. atIndex = atIndex === undefined ? this.option("selectedIndex") : atIndex;
  36542. return this._normalizeIndex(atIndex - 1)
  36543. },
  36544. _normalizeIndex: function(index) {
  36545. var boundary = this._indexBoundary();
  36546. if (index < 0)
  36547. index = boundary + index;
  36548. if (index >= boundary)
  36549. index = index - boundary;
  36550. return index
  36551. },
  36552. _indexBoundary: function() {
  36553. return this.option("items").length
  36554. },
  36555. _renderSelection: function(current) {
  36556. this._calculateMaxOffsets(current);
  36557. this._updateTabsPositions();
  36558. this._itemElements().eq(current).addClass(PIVOT_TAB_SELECTED_CLASS)
  36559. },
  36560. _updateSelection: function(addedItems, removedItems) {
  36561. var newIndex = addedItems[0],
  36562. oldIndex = removedItems[0];
  36563. this._calculateMaxOffsets(newIndex);
  36564. if (!this._swipeGestureRunning)
  36565. this._prepareAnimation();
  36566. if (this._itemElements().length)
  36567. this._animateComplete(newIndex, oldIndex)
  36568. },
  36569. _calculateMaxOffsets: function(index) {
  36570. var currentTabWidth = this._itemWidths()[index],
  36571. prevTabWidth = this._itemWidths()[this._previousIndex(index)],
  36572. rtl = this.option("rtlEnabled");
  36573. this._maxLeftOffset = rtl ? prevTabWidth : currentTabWidth;
  36574. this._maxRightOffset = rtl ? currentTabWidth : prevTabWidth
  36575. },
  36576. _getRTLSignCorrection: function() {
  36577. return this.option("rtlEnabled") ? -1 : 1
  36578. },
  36579. _visibilityChanged: function(visible) {
  36580. if (visible)
  36581. this._dimensionChanged()
  36582. },
  36583. _clean: function() {
  36584. animation.stop(this._allTabElements());
  36585. this._clearElementWidthCache();
  36586. this._cleanPositionCache();
  36587. this.callBase()
  36588. },
  36589. _cleanPositionCache: function() {
  36590. delete this._itemWidthsCache;
  36591. delete this._calculetedPositionsMark
  36592. },
  36593. _optionChanged: function(args) {
  36594. switch (args.name) {
  36595. case"items":
  36596. case"rtlEnabled":
  36597. this._cleanPositionCache();
  36598. this.callBase(args);
  36599. break;
  36600. case"onPrepare":
  36601. case"swipeEnabled":
  36602. break;
  36603. case"onUpdatePosition":
  36604. case"onRollback":
  36605. this._initActions();
  36606. break;
  36607. default:
  36608. this.callBase(args)
  36609. }
  36610. },
  36611. prepare: function() {
  36612. this._prepareAnimation()
  36613. },
  36614. updatePosition: function(offset) {
  36615. this._updateTabsPositions(offset)
  36616. },
  36617. rollback: function() {
  36618. this._animateRollback()
  36619. }
  36620. }));
  36621. ui.dxPivotTabs.__internals = {animation: animation}
  36622. })(jQuery, DevExpress);
  36623. /*! Module widgets-mobile, file ui.pivot.js */
  36624. (function($, DX, undefined) {
  36625. var ui = DX.ui,
  36626. utils = DX.utils,
  36627. events = ui.events,
  36628. fx = DX.fx,
  36629. translator = DX.translator;
  36630. var PIVOT_CLASS = "dx-pivot",
  36631. PIVOT_AUTOHEIGHT_CLASS = "dx-pivot-autoheight",
  36632. PIVOT_WRAPPER_CLASS = "dx-pivot-wrapper",
  36633. PIVOT_TABS_CONTAINER_CLASS = "dx-pivottabs-container",
  36634. PIVOT_ITEM_CONTAINER_CLASS = "dx-pivot-itemcontainer",
  36635. PIVOT_ITEM_WRAPPER_CLASS = "dx-pivot-itemwrapper",
  36636. PIVOT_ITEM_CLASS = "dx-pivot-item",
  36637. PIVOT_ITEM_HIDDEN_CLASS = "dx-pivot-item-hidden",
  36638. PIVOT_ITEM_DATA_KEY = "dxPivotItemData",
  36639. PIVOT_RETURN_BACK_DURATION = 200,
  36640. PIVOT_SLIDE_AWAY_DURATION = 50,
  36641. PIVOT_SLIDE_BACK_DURATION = 250,
  36642. PIVOT_SLIDE_BACK_EASING = "cubic-bezier(.10, 1, 0, 1)";
  36643. var animation = {
  36644. returnBack: function($element) {
  36645. fx.animate($element, {
  36646. type: "slide",
  36647. to: {left: 0},
  36648. duration: PIVOT_RETURN_BACK_DURATION
  36649. })
  36650. },
  36651. slideAway: function($element, position, complete) {
  36652. fx.animate($element, {
  36653. type: "slide",
  36654. to: {left: position},
  36655. duration: PIVOT_SLIDE_AWAY_DURATION,
  36656. complete: complete
  36657. })
  36658. },
  36659. slideBack: function($element) {
  36660. fx.animate($element, {
  36661. type: "slide",
  36662. to: {left: 0},
  36663. easing: PIVOT_SLIDE_BACK_EASING,
  36664. duration: PIVOT_SLIDE_BACK_DURATION
  36665. })
  36666. },
  36667. complete: function($element) {
  36668. fx.stop($element, true)
  36669. }
  36670. };
  36671. DX.registerComponent("dxPivot", ui, ui.CollectionWidget.inherit({
  36672. _setDefaultOptions: function() {
  36673. this.callBase();
  36674. this.option({
  36675. selectedIndex: 0,
  36676. swipeEnabled: true,
  36677. titleTemplate: "title",
  36678. contentTemplate: "content",
  36679. focusStateEnabled: false,
  36680. selectionMode: "single",
  36681. selectionRequired: true,
  36682. selectionByClick: false
  36683. })
  36684. },
  36685. _itemClass: function() {
  36686. return PIVOT_ITEM_CLASS
  36687. },
  36688. _itemDataKey: function() {
  36689. return PIVOT_ITEM_DATA_KEY
  36690. },
  36691. _itemContainer: function() {
  36692. return this._$itemWrapper
  36693. },
  36694. _elementWidth: function() {
  36695. if (!this._elementWidthCache)
  36696. this._elementWidthCache = this.element().width();
  36697. return this._elementWidthCache
  36698. },
  36699. _clearElementWidthCache: function() {
  36700. delete this._elementWidthCache
  36701. },
  36702. _init: function() {
  36703. this.callBase();
  36704. this.element().addClass(PIVOT_CLASS);
  36705. this._initWrapper();
  36706. this._initTabs();
  36707. this._initItemContainer();
  36708. this._clearItemsCache();
  36709. this._initSwipeHandlers()
  36710. },
  36711. _dimensionChanged: function() {
  36712. this._clearElementWidthCache()
  36713. },
  36714. _initWrapper: function() {
  36715. this._$wrapper = $("<div>").addClass(PIVOT_WRAPPER_CLASS).appendTo(this.element())
  36716. },
  36717. _initItemContainer: function() {
  36718. var $itemContainer = $("<div>").addClass(PIVOT_ITEM_CONTAINER_CLASS);
  36719. this._$wrapper.append($itemContainer);
  36720. this._$itemWrapper = $("<div>").addClass(PIVOT_ITEM_WRAPPER_CLASS);
  36721. $itemContainer.append(this._$itemWrapper)
  36722. },
  36723. _clearItemsCache: function() {
  36724. this._itemsCache = []
  36725. },
  36726. _initTabs: function() {
  36727. var that = this,
  36728. $tabsContainer = $("<div>").addClass(PIVOT_TABS_CONTAINER_CLASS);
  36729. this._$wrapper.append($tabsContainer);
  36730. this._tabs = this._createComponent($tabsContainer, "dxPivotTabs", {
  36731. itemTemplateProperty: "titleTemplate",
  36732. itemTemplate: this._getTemplateByOption("titleTemplate"),
  36733. items: this.option("items"),
  36734. selectedIndex: this.option("selectedIndex"),
  36735. onPrepare: function() {
  36736. that._prepareAnimation()
  36737. },
  36738. onUpdatePosition: function(args) {
  36739. that._updateContentPosition(args.offset)
  36740. },
  36741. onRollback: function() {
  36742. that._animateRollback()
  36743. },
  36744. onSelectionChanged: function(args) {
  36745. that.option("selectedItem", args.addedItems[0])
  36746. },
  36747. swipeEnabled: this.option("swipeEnabled")
  36748. })
  36749. },
  36750. _render: function() {
  36751. this._renderContentTemplate();
  36752. this.callBase();
  36753. var selectedIndex = this.option("selectedIndex");
  36754. this._renderCurrentContent(selectedIndex, selectedIndex)
  36755. },
  36756. _renderContentTemplate: function() {
  36757. if (utils.isDefined(this._singleContent))
  36758. return;
  36759. this._getTemplateByOption("contentTemplate").render(this._$itemWrapper);
  36760. this._singleContent = !this._$itemWrapper.is(":empty")
  36761. },
  36762. _renderDimensions: function() {
  36763. this.callBase();
  36764. this.element().toggleClass(PIVOT_AUTOHEIGHT_CLASS, this.option("height") === "auto")
  36765. },
  36766. _renderCurrentContent: function(currentIndex, previousIndex) {
  36767. var itemsCache = this._itemsCache;
  36768. itemsCache[previousIndex] = this._selectedItemElement();
  36769. var $hidingItem = itemsCache[previousIndex],
  36770. $showingItem = itemsCache[currentIndex];
  36771. utils.triggerHidingEvent($hidingItem);
  36772. $hidingItem.addClass(PIVOT_ITEM_HIDDEN_CLASS);
  36773. if ($showingItem) {
  36774. $showingItem.removeClass(PIVOT_ITEM_HIDDEN_CLASS);
  36775. utils.triggerShownEvent($showingItem)
  36776. }
  36777. else
  36778. this._renderContent();
  36779. this._selectionChangePromise && this._selectionChangePromise.resolve();
  36780. this._selectionChangePromise = $.Deferred()
  36781. },
  36782. _updateContentPosition: function(offset) {
  36783. translator.move(this._$itemWrapper, {left: this._calculatePixelOffset(offset)})
  36784. },
  36785. _animateRollback: function() {
  36786. animation.returnBack(this._$itemWrapper)
  36787. },
  36788. _animateComplete: function(newIndex, currentIndex) {
  36789. var $itemWrapper = this._$itemWrapper,
  36790. rtlSignCorrection = this._getRTLSignCorrection(),
  36791. intermediatePosition = this._elementWidth() * (this._isPrevSwipeHandled() ? 1 : -1) * rtlSignCorrection;
  36792. animation.slideAway($itemWrapper, intermediatePosition, $.proxy(function() {
  36793. translator.move($itemWrapper, {left: -intermediatePosition});
  36794. this._renderCurrentContent(newIndex, currentIndex)
  36795. }, this));
  36796. animation.slideBack($itemWrapper)
  36797. },
  36798. _calculatePixelOffset: function(offset) {
  36799. offset = offset || 0;
  36800. return offset * this._elementWidth()
  36801. },
  36802. _isPrevSwipeHandled: function() {
  36803. var wrapperOffset = translator.locate(this._$itemWrapper).left,
  36804. rtl = this.option("rtlEnabled");
  36805. return rtl ^ wrapperOffset > 0 && wrapperOffset !== 0
  36806. },
  36807. _initSwipeHandlers: function() {
  36808. this.element().on(events.addNamespace("dxswipestart", this.NAME), {itemSizeFunc: $.proxy(this._elementWidth, this)}, $.proxy(this._swipeStartHandler, this)).on(events.addNamespace("dxswipe", this.NAME), $.proxy(this._swipeUpdateHandler, this)).on(events.addNamespace("dxswipeend", this.NAME), $.proxy(this._swipeEndHandler, this))
  36809. },
  36810. _swipeStartHandler: function(e) {
  36811. this._prepareAnimation();
  36812. this._tabs.prepare();
  36813. if (DX.designMode || this.option("disabled") || !this.option("swipeEnabled") || this._indexBoundary() <= 1)
  36814. e.cancel = true;
  36815. else
  36816. this._swipeGestureRunning = true;
  36817. e.maxLeftOffset = 1;
  36818. e.maxRightOffset = 1
  36819. },
  36820. _prepareAnimation: function() {
  36821. this._stopAnimation()
  36822. },
  36823. _stopAnimation: function() {
  36824. animation.complete(this._$itemWrapper)
  36825. },
  36826. _swipeUpdateHandler: function(e) {
  36827. var offset = e.offset;
  36828. this._updateContentPosition(offset);
  36829. this._tabs.updatePosition(offset)
  36830. },
  36831. _swipeEndHandler: function(e) {
  36832. var targetOffset = e.targetOffset * this._getRTLSignCorrection();
  36833. if (targetOffset === 0) {
  36834. this._animateRollback();
  36835. this._tabs.rollback()
  36836. }
  36837. else {
  36838. var newIndex = this._normalizeIndex(this.option("selectedIndex") - targetOffset);
  36839. this.option("selectedIndex", newIndex)
  36840. }
  36841. this._swipeGestureRunning = false
  36842. },
  36843. _normalizeIndex: function(index) {
  36844. var boundary = this._indexBoundary();
  36845. if (index < 0)
  36846. index = boundary + index;
  36847. if (index >= boundary)
  36848. index = index - boundary;
  36849. return index
  36850. },
  36851. _indexBoundary: function() {
  36852. return this.option("items").length
  36853. },
  36854. _renderContentImpl: function() {
  36855. if (this._singleContent)
  36856. return;
  36857. var items = this.option("items"),
  36858. selectedIndex = this.option("selectedIndex");
  36859. if (items.length)
  36860. this._renderItems([items[selectedIndex]])
  36861. },
  36862. _selectedItemElement: function() {
  36863. return this._$itemWrapper.children("." + PIVOT_ITEM_CLASS + ":not(." + PIVOT_ITEM_HIDDEN_CLASS + ")")
  36864. },
  36865. _getRTLSignCorrection: function() {
  36866. return this.option("rtlEnabled") ? -1 : 1
  36867. },
  36868. _clean: function() {
  36869. animation.complete(this._$itemWrapper);
  36870. this.callBase()
  36871. },
  36872. _cleanItemContainer: function() {
  36873. if (this._singleContent)
  36874. return;
  36875. this.callBase()
  36876. },
  36877. _refresh: function() {
  36878. this._tabs._refresh();
  36879. this.callBase()
  36880. },
  36881. _updateSelection: function(addedItems, removedItems) {
  36882. var newIndex = addedItems[0],
  36883. oldIndex = removedItems[0];
  36884. if (!this._swipeGestureRunning)
  36885. this._prepareAnimation();
  36886. this._animateComplete(newIndex, oldIndex);
  36887. this._tabs.option("selectedIndex", newIndex)
  36888. },
  36889. _optionChanged: function(args) {
  36890. var value = args.value;
  36891. switch (args.name) {
  36892. case"disabled":
  36893. this._tabs.option("disabled", value);
  36894. this.callBase(args);
  36895. break;
  36896. case"items":
  36897. this._tabs.option("items", value);
  36898. this._clearItemsCache();
  36899. this.callBase(args);
  36900. break;
  36901. case"rtlEnabled":
  36902. this._tabs.option("rtlEnabled", value);
  36903. this._clearItemsCache();
  36904. this.callBase(args);
  36905. break;
  36906. case"titleTemplate":
  36907. this._tabs.option("itemTemplate", this._getTemplate(value));
  36908. break;
  36909. case"swipeEnabled":
  36910. this._tabs.option("swipeEnabled", value);
  36911. break;
  36912. case"contentTemplate":
  36913. this._singleContent = null;
  36914. this._invalidate();
  36915. break;
  36916. default:
  36917. this.callBase(args)
  36918. }
  36919. }
  36920. }));
  36921. ui.dxPivot.__internals = {animation: animation}
  36922. })(jQuery, DevExpress);
  36923. /*! Module widgets-mobile, file ui.actionSheet.js */
  36924. (function($, DX, undefined) {
  36925. var ui = DX.ui;
  36926. var ACTION_SHEET_CLASS = "dx-actionsheet",
  36927. ACTION_SHEET_CONTAINER_CLASS = "dx-actionsheet-container",
  36928. ACTION_SHEET_POPUP_WRAPPER_CLASS = "dx-actionsheet-popup-wrapper",
  36929. ACTION_SHEET_POPOVER_WRAPPER_CLASS = "dx-actionsheet-popover-wrapper",
  36930. ACTION_SHEET_CANCEL_BUTTON_CLASS = "dx-actionsheet-cancel",
  36931. ACTION_SHEET_ITEM_CLASS = "dx-actionsheet-item",
  36932. ACTION_SHEET_ITEM_DATA_KEY = "dxActionSheetItemData",
  36933. ACTION_SHEET_WITHOUT_TITLE_CLASS = "dx-actionsheet-without-title";
  36934. DX.registerComponent("dxActionSheet", ui, ui.CollectionWidget.inherit({
  36935. _setDeprecatedOptions: function() {
  36936. this.callBase();
  36937. $.extend(this._deprecatedOptions, {cancelClickAction: {
  36938. since: "14.2",
  36939. alias: "onCancelClick"
  36940. }})
  36941. },
  36942. _setDefaultOptions: function() {
  36943. this.callBase();
  36944. this.option({
  36945. usePopover: false,
  36946. target: null,
  36947. title: "",
  36948. showTitle: true,
  36949. showCancelButton: true,
  36950. cancelText: Globalize.localize("Cancel"),
  36951. onCancelClick: null,
  36952. visible: false,
  36953. noDataText: "",
  36954. focusStateEnabled: false,
  36955. selectionByClick: false
  36956. })
  36957. },
  36958. _defaultOptionsRules: function() {
  36959. return this.callBase().concat([{
  36960. device: {
  36961. platform: "ios",
  36962. tablet: true
  36963. },
  36964. options: {usePopover: true}
  36965. }])
  36966. },
  36967. _itemContainer: function() {
  36968. return this._$itemContainer
  36969. },
  36970. _itemClass: function() {
  36971. return ACTION_SHEET_ITEM_CLASS
  36972. },
  36973. _itemDataKey: function() {
  36974. return ACTION_SHEET_ITEM_DATA_KEY
  36975. },
  36976. _toggleVisibility: $.noop,
  36977. _renderDimensions: $.noop,
  36978. _render: function() {
  36979. this.element().addClass(ACTION_SHEET_CLASS);
  36980. this._createItemContainer();
  36981. this._renderPopup()
  36982. },
  36983. _createItemContainer: function() {
  36984. this._$itemContainer = $("<div>").addClass(ACTION_SHEET_CONTAINER_CLASS);
  36985. this._renderDisabled()
  36986. },
  36987. _renderDisabled: function() {
  36988. this._$itemContainer.toggleClass("dx-state-disabled", this.option("disabled"))
  36989. },
  36990. _renderPopup: function() {
  36991. this._$popup = $("<div>").appendTo(this.element());
  36992. this._popup = this._isPopoverMode() ? this._createPopover() : this._createPopup();
  36993. this._renderPopupTitle();
  36994. this._mapPopupOption("visible")
  36995. },
  36996. _mapPopupOption: function(optionName) {
  36997. this._popup.option(optionName, this.option(optionName))
  36998. },
  36999. _isPopoverMode: function() {
  37000. return this.option("usePopover") && this.option("target")
  37001. },
  37002. _renderPopupTitle: function() {
  37003. this._mapPopupOption("showTitle");
  37004. this._popup._wrapper().toggleClass(ACTION_SHEET_WITHOUT_TITLE_CLASS, !this.option("showTitle"))
  37005. },
  37006. _clean: function() {
  37007. if (this._$popup)
  37008. this._$popup.remove();
  37009. this.callBase()
  37010. },
  37011. _createPopover: function() {
  37012. var popover = this._createComponent(this._$popup, "dxPopover", {
  37013. showTitle: true,
  37014. title: this.option("title"),
  37015. width: this.option("width") || 200,
  37016. height: this.option("height") || "auto",
  37017. target: this.option("target"),
  37018. onHidden: $.proxy(this.hide, this),
  37019. onContentReady: $.proxy(this._popupContentReadyAction, this)
  37020. });
  37021. popover._wrapper().addClass(ACTION_SHEET_POPOVER_WRAPPER_CLASS);
  37022. return popover
  37023. },
  37024. _createPopup: function() {
  37025. var popup = this._createComponent(this._$popup, "dxPopup", {
  37026. dragEnabled: false,
  37027. title: this.option("title"),
  37028. width: this.option("width") || "100%",
  37029. height: this.option("height") || "auto",
  37030. onContentReady: $.proxy(this._popupContentReadyAction, this),
  37031. showCloseButton: false,
  37032. position: {
  37033. my: "bottom",
  37034. at: "bottom",
  37035. of: window
  37036. },
  37037. animation: {
  37038. show: {
  37039. type: "slide",
  37040. duration: 400,
  37041. from: {position: {
  37042. my: "top",
  37043. at: "bottom",
  37044. of: window
  37045. }},
  37046. to: {position: {
  37047. my: "bottom",
  37048. at: "bottom",
  37049. of: window
  37050. }}
  37051. },
  37052. hide: {
  37053. type: "slide",
  37054. duration: 400,
  37055. from: {position: {
  37056. my: "bottom",
  37057. at: "bottom",
  37058. of: window
  37059. }},
  37060. to: {position: {
  37061. my: "top",
  37062. at: "bottom",
  37063. of: window
  37064. }}
  37065. }
  37066. }
  37067. });
  37068. popup.on("optionChanged", $.proxy(function(args) {
  37069. if (args.name !== "visible")
  37070. return;
  37071. this.option("visible", args.value)
  37072. }, this));
  37073. popup._wrapper().addClass(ACTION_SHEET_POPUP_WRAPPER_CLASS);
  37074. return popup
  37075. },
  37076. _popupContentReadyAction: function() {
  37077. this._popup.content().append(this._$itemContainer);
  37078. this._attachClickEvent();
  37079. this._attachHoldEvent();
  37080. this._renderContent();
  37081. this._renderCancelButton()
  37082. },
  37083. _renderCancelButton: function() {
  37084. if (this._isPopoverMode())
  37085. return;
  37086. if (this._$cancelButton)
  37087. this._$cancelButton.remove();
  37088. if (this.option("showCancelButton")) {
  37089. var cancelClickAction = this._createActionByOption("onCancelClick") || $.noop,
  37090. that = this;
  37091. this._$cancelButton = $("<div>").addClass(ACTION_SHEET_CANCEL_BUTTON_CLASS).appendTo(this._popup.content());
  37092. this._createComponent(this._$cancelButton, "dxButton", {
  37093. text: this.option("cancelText"),
  37094. onClick: function(e) {
  37095. var hidingArgs = {
  37096. jQueryEvent: e,
  37097. cancel: false
  37098. };
  37099. cancelClickAction(hidingArgs);
  37100. if (!hidingArgs.cancel)
  37101. that.hide()
  37102. },
  37103. _templates: {}
  37104. })
  37105. }
  37106. },
  37107. _attachItemClickEvent: $.noop,
  37108. _itemClickHandler: function(e) {
  37109. this.callBase(e);
  37110. if (!$(e.target).is(".dx-state-disabled, .dx-state-disabled *"))
  37111. this.hide()
  37112. },
  37113. _itemHoldHandler: function(e) {
  37114. this.callBase(e);
  37115. if (!$(e.target).is(".dx-state-disabled, .dx-state-disabled *"))
  37116. this.hide()
  37117. },
  37118. _optionChanged: function(args) {
  37119. switch (args.name) {
  37120. case"width":
  37121. case"height":
  37122. case"visible":
  37123. case"title":
  37124. this._mapPopupOption(args.name);
  37125. break;
  37126. case"disabled":
  37127. this._renderDisabled();
  37128. break;
  37129. case"showTitle":
  37130. this._renderPopupTitle();
  37131. break;
  37132. case"showCancelButton":
  37133. case"onCancelClick":
  37134. case"cancelText":
  37135. this._renderCancelButton();
  37136. break;
  37137. case"target":
  37138. case"usePopover":
  37139. case"items":
  37140. this._invalidate();
  37141. break;
  37142. default:
  37143. this.callBase(args)
  37144. }
  37145. },
  37146. toggle: function(showing) {
  37147. var that = this,
  37148. d = $.Deferred();
  37149. that._popup.toggle(showing).done(function() {
  37150. that.option("visible", showing);
  37151. d.resolveWith(that)
  37152. });
  37153. return d.promise()
  37154. },
  37155. show: function() {
  37156. return this.toggle(true)
  37157. },
  37158. hide: function() {
  37159. return this.toggle(false)
  37160. }
  37161. }))
  37162. })(jQuery, DevExpress);
  37163. /*! Module widgets-mobile, file ui.panorama.js */
  37164. (function($, DX, undefined) {
  37165. var ui = DX.ui,
  37166. events = ui.events,
  37167. fx = DX.fx,
  37168. translator = DX.translator;
  37169. var PANORAMA_CLASS = "dx-panorama",
  37170. PANORAMA_WRAPPER_CLASS = "dx-panorama-wrapper",
  37171. PANORAMA_TITLE_CLASS = "dx-panorama-title",
  37172. PANORAMA_GHOST_TITLE_CLASS = "dx-panorama-ghosttitle",
  37173. PANORAMA_ITEMS_CONTAINER_CLASS = "dx-panorama-itemscontainer",
  37174. PANORAMA_ITEM_CLASS = "dx-panorama-item",
  37175. PANORAMA_GHOST_ITEM_CLASS = "dx-panorama-ghostitem",
  37176. PANORAMA_ITEM_DATA_KEY = "dxPanoramaItemData",
  37177. PANORAMA_ITEM_MARGIN_SCALE = 0.02,
  37178. PANORAMA_TITLE_MARGIN_SCALE = 0.02,
  37179. PANORAMA_BACKGROUND_MOVE_DURATION = 300,
  37180. PANORAMA_BACKGROUND_MOVE_EASING = "cubic-bezier(.40, .80, .60, 1)",
  37181. PANORAMA_TITLE_MOVE_DURATION = 300,
  37182. PANORAMA_TITLE_MOVE_EASING = "cubic-bezier(.40, .80, .60, 1)",
  37183. PANORAMA_ITEM_MOVE_DURATION = 300,
  37184. PANORAMA_ITEM_MOVE_EASING = "cubic-bezier(.40, .80, .60, 1)";
  37185. var moveBackground = function($element, position) {
  37186. $element.css("background-position", position + "px 0%")
  37187. };
  37188. var position = function($element) {
  37189. return translator.locate($element).left
  37190. };
  37191. var move = function($element, position) {
  37192. translator.move($element, {left: position})
  37193. };
  37194. var animation = {
  37195. backgroundMove: function($element, position, completeAction) {
  37196. return fx.animate($element, {
  37197. to: {"background-position": position + "px 0%"},
  37198. duration: PANORAMA_BACKGROUND_MOVE_DURATION,
  37199. easing: PANORAMA_BACKGROUND_MOVE_EASING,
  37200. complete: completeAction
  37201. })
  37202. },
  37203. titleMove: function($title, position, completeAction) {
  37204. return fx.animate($title, {
  37205. type: "slide",
  37206. to: {left: position},
  37207. duration: PANORAMA_TITLE_MOVE_DURATION,
  37208. easing: PANORAMA_TITLE_MOVE_EASING,
  37209. complete: completeAction
  37210. })
  37211. },
  37212. itemMove: function($item, position, completeAction) {
  37213. return fx.animate($item, {
  37214. type: "slide",
  37215. to: {left: position},
  37216. duration: PANORAMA_ITEM_MOVE_DURATION,
  37217. easing: PANORAMA_ITEM_MOVE_EASING,
  37218. complete: completeAction
  37219. })
  37220. }
  37221. };
  37222. var endAnimation = function(elements) {
  37223. if (!elements)
  37224. return;
  37225. $.each(elements, function(_, element) {
  37226. fx.stop(element, true)
  37227. })
  37228. };
  37229. var PanoramaItemsRenderStrategy = DX.Class.inherit({
  37230. ctor: function(panorama) {
  37231. this._panorama = panorama
  37232. },
  37233. init: $.noop,
  37234. render: $.noop,
  37235. allItemElements: function() {
  37236. return this._panorama._itemElements()
  37237. },
  37238. updatePositions: DX.abstract,
  37239. animateRollback: DX.abstract,
  37240. detectBoundsTransition: DX.abstract,
  37241. animateComplete: DX.abstract,
  37242. _getRTLSignCorrection: function() {
  37243. return this._panorama._getRTLSignCorrection()
  37244. },
  37245. _isRTLEnabled: function() {
  37246. return this._panorama.option("rtlEnabled")
  37247. },
  37248. _itemMargin: function() {
  37249. return this._containerWidth() * PANORAMA_ITEM_MARGIN_SCALE
  37250. },
  37251. _containerWidth: function() {
  37252. return this._panorama._elementWidth()
  37253. },
  37254. _itemWidth: function() {
  37255. return this._panorama._itemWidth()
  37256. },
  37257. _indexBoundary: function() {
  37258. return this._panorama._indexBoundary()
  37259. },
  37260. _normalizeIndex: function(index) {
  37261. return this._panorama._normalizeIndex(index)
  37262. },
  37263. _startNextPosition: function() {
  37264. if (this._isRTLEnabled())
  37265. return this._containerWidth() - (this._itemMargin() + this._itemWidth());
  37266. else
  37267. return this._itemMargin()
  37268. },
  37269. _startPrevPosition: function() {
  37270. if (this._isRTLEnabled())
  37271. return this._containerWidth();
  37272. else
  37273. return -this._itemWidth()
  37274. }
  37275. });
  37276. var PanoramaOneAndLessItemsRenderStrategy = PanoramaItemsRenderStrategy.inherit({
  37277. updatePositions: function() {
  37278. var $items = this._panorama._itemElements(),
  37279. startPosition = this._startNextPosition();
  37280. $items.each(function() {
  37281. move($(this), startPosition)
  37282. })
  37283. },
  37284. animateRollback: $.noop,
  37285. detectBoundsTransition: $.noop,
  37286. animateComplete: $.noop
  37287. });
  37288. var PanoramaTwoItemsRenderStrategy = PanoramaItemsRenderStrategy.inherit({
  37289. init: function() {
  37290. this._initGhostItem()
  37291. },
  37292. render: function() {
  37293. this._renderGhostItem()
  37294. },
  37295. _initGhostItem: function() {
  37296. this._$ghostItem = $("<div>").addClass(PANORAMA_GHOST_ITEM_CLASS)
  37297. },
  37298. _renderGhostItem: function() {
  37299. this._panorama._itemContainer().append(this._$ghostItem);
  37300. this._toggleGhostItem(false)
  37301. },
  37302. _toggleGhostItem: function(visible) {
  37303. var $ghostItem = this._$ghostItem;
  37304. if (visible)
  37305. $ghostItem.css("opacity", 1);
  37306. else
  37307. $ghostItem.css("opacity", 0)
  37308. },
  37309. _updateGhostItemContent: function(index) {
  37310. if (index !== false && index !== this._prevGhostIndex) {
  37311. this._$ghostItem.html(this._panorama._itemElements().eq(index).html());
  37312. this._prevGhostIndex = index
  37313. }
  37314. },
  37315. _isGhostItemVisible: function() {
  37316. return this._$ghostItem.css("opacity") === "1"
  37317. },
  37318. _swapGhostWithItem: function($item) {
  37319. var $ghostItem = this._$ghostItem,
  37320. lastItemPosition = position($item);
  37321. move($item, position($ghostItem));
  37322. move($ghostItem, lastItemPosition)
  37323. },
  37324. allItemElements: function() {
  37325. return this._panorama._itemContainer().find("." + PANORAMA_ITEM_CLASS + ", ." + PANORAMA_GHOST_ITEM_CLASS)
  37326. },
  37327. updatePositions: function(offset) {
  37328. var $items = this.allItemElements(),
  37329. selectedIndex = this._panorama.option("selectedIndex"),
  37330. adjustedOffset = offset * this._getRTLSignCorrection(),
  37331. isGhostReplaceLast = adjustedOffset > 0 && selectedIndex === 0 || adjustedOffset < 0 && selectedIndex === 1,
  37332. isGhostReplaceFirst = adjustedOffset < 0 && selectedIndex === 0 || adjustedOffset > 0 && selectedIndex === 1,
  37333. ghostPosition = isGhostReplaceLast && "replaceLast" || isGhostReplaceFirst && "replaceFirst",
  37334. ghostContentIndex = isGhostReplaceLast && 1 || isGhostReplaceFirst && 0,
  37335. positions = this._calculateItemPositions(selectedIndex, ghostPosition);
  37336. this._updateGhostItemContent(ghostContentIndex);
  37337. this._toggleGhostItem(isGhostReplaceLast || isGhostReplaceFirst);
  37338. $items.each(function(index) {
  37339. move($(this), positions[index] + offset)
  37340. })
  37341. },
  37342. animateRollback: function(currentIndex) {
  37343. var that = this,
  37344. $items = this._panorama._itemElements(),
  37345. startPosition = this._startNextPosition(),
  37346. signCorrection = this._getRTLSignCorrection(),
  37347. offset = (position($items.eq(currentIndex)) - startPosition) * signCorrection,
  37348. ghostOffset = (position(this._$ghostItem) - startPosition) * signCorrection,
  37349. positions = this._calculateItemPositions(currentIndex, ghostOffset > 0 ? "prepend" : "append"),
  37350. isLastReplasedByGhost = currentIndex === 0 && offset > 0 && ghostOffset > 0 || currentIndex === 1 && ghostOffset < 0;
  37351. if (isLastReplasedByGhost)
  37352. this._swapGhostWithItem($items.eq(1));
  37353. else
  37354. this._swapGhostWithItem($items.eq(0));
  37355. $items.each(function(index) {
  37356. animation.itemMove($(this), positions[index])
  37357. });
  37358. animation.itemMove(this._$ghostItem, positions[2], function() {
  37359. that._toggleGhostItem(false)
  37360. })
  37361. },
  37362. detectBoundsTransition: function(newIndex, currentIndex) {
  37363. var ghostLocation = position(this._$ghostItem),
  37364. startPosition = this._startNextPosition(),
  37365. rtl = this._isRTLEnabled();
  37366. if (newIndex === 0 && rtl ^ ghostLocation < startPosition)
  37367. return "left";
  37368. if (currentIndex === 0 && rtl ^ ghostLocation > startPosition)
  37369. return "right"
  37370. },
  37371. animateComplete: function(boundCross, newIndex, currentIndex) {
  37372. var that = this,
  37373. ghostPosition = !boundCross ^ currentIndex !== 0 ? "prepend" : "append",
  37374. $items = this._panorama._itemElements(),
  37375. positions = this._calculateItemPositions(newIndex, ghostPosition),
  37376. animations = [];
  37377. $items.each(function(index) {
  37378. animations.push(animation.itemMove($(this), positions[index]))
  37379. });
  37380. animations.push(animation.itemMove(this._$ghostItem, positions[2], function() {
  37381. that._toggleGhostItem(false)
  37382. }));
  37383. return $.when.apply($, animations)
  37384. },
  37385. _calculateItemPositions: function(atIndex, ghostPosition) {
  37386. var positions = [],
  37387. itemMargin = this._itemMargin(),
  37388. itemWidth = this._itemWidth(),
  37389. itemPositionOffset = (itemWidth + itemMargin) * this._getRTLSignCorrection(),
  37390. normalFlow = atIndex === 0,
  37391. prevPosition = this._startPrevPosition(),
  37392. nextPosition = this._startNextPosition();
  37393. positions.push(nextPosition);
  37394. nextPosition += itemPositionOffset;
  37395. if (normalFlow)
  37396. positions.push(nextPosition);
  37397. else
  37398. positions.splice(0, 0, nextPosition);
  37399. nextPosition += itemPositionOffset;
  37400. switch (ghostPosition) {
  37401. case"replaceFirst":
  37402. positions.push(positions[0]);
  37403. if (normalFlow)
  37404. positions[0] = nextPosition;
  37405. else
  37406. positions[0] = prevPosition;
  37407. break;
  37408. case"replaceLast":
  37409. if (normalFlow)
  37410. positions.splice(1, 0, prevPosition);
  37411. else
  37412. positions.splice(1, 0, nextPosition);
  37413. break;
  37414. case"prepend":
  37415. positions.push(prevPosition);
  37416. break;
  37417. case"append":
  37418. positions.push(nextPosition);
  37419. break
  37420. }
  37421. return positions
  37422. }
  37423. });
  37424. var PanoramaThreeAndMoreItemsRenderStrategy = PanoramaItemsRenderStrategy.inherit({
  37425. updatePositions: function(offset) {
  37426. var $items = this._panorama._itemElements(),
  37427. movingBack = offset * this._getRTLSignCorrection() < 0,
  37428. positions = this._calculateItemPositions(this._panorama.option("selectedIndex"), movingBack);
  37429. $items.each(function(index) {
  37430. move($(this), positions[index] + offset)
  37431. })
  37432. },
  37433. animateRollback: function(selectedIndex) {
  37434. var $items = this._panorama._itemElements(),
  37435. positions = this._calculateItemPositions(selectedIndex),
  37436. animatingItems = [selectedIndex, this._normalizeIndex(selectedIndex + 1)];
  37437. if (this._isRTLEnabled() ^ position($items.eq(selectedIndex)) > this._startNextPosition())
  37438. animatingItems.push(this._normalizeIndex(selectedIndex - 1));
  37439. $items.each(function(index) {
  37440. var $item = $(this);
  37441. if ($.inArray(index, animatingItems) !== -1)
  37442. animation.itemMove($item, positions[index]);
  37443. else
  37444. move($item, positions[index])
  37445. })
  37446. },
  37447. detectBoundsTransition: function(newIndex, currentIndex) {
  37448. var lastIndex = this._indexBoundary() - 1;
  37449. if (currentIndex === lastIndex && newIndex === 0)
  37450. return "left";
  37451. if (currentIndex === 0 && newIndex === lastIndex)
  37452. return "right"
  37453. },
  37454. animateComplete: function(boundCross, newIndex, currentIndex) {
  37455. var animations = [],
  37456. $items = this._panorama._itemElements(),
  37457. positions = this._calculateItemPositions(newIndex);
  37458. var transitionBack = this._normalizeIndex(currentIndex - 1) === newIndex,
  37459. cyclingItemIndex = $items.length === 3 && transitionBack ? this._normalizeIndex(currentIndex + 1) : null,
  37460. cyclingItemPosition = positions[this._indexBoundary()];
  37461. var animatingItems = [newIndex, currentIndex],
  37462. backAnimatedItemIndex = transitionBack ? currentIndex : newIndex;
  37463. if (!transitionBack)
  37464. animatingItems.push(this._normalizeIndex(backAnimatedItemIndex + 1));
  37465. $items.each(function(index) {
  37466. var $item = $(this);
  37467. if ($.inArray(index, animatingItems) === -1) {
  37468. move($item, positions[index]);
  37469. return
  37470. }
  37471. animations.push(index !== cyclingItemIndex ? animation.itemMove($item, positions[index]) : animation.itemMove($item, cyclingItemPosition, function() {
  37472. move($item, positions[index])
  37473. }))
  37474. });
  37475. return $.when.apply($, animations)
  37476. },
  37477. _calculateItemPositions: function(atIndex, movingBack) {
  37478. var previousIndex = this._normalizeIndex(atIndex - 1),
  37479. itemMargin = this._itemMargin(),
  37480. itemWidth = this._itemWidth(),
  37481. itemPositionOffset = (itemWidth + itemMargin) * this._getRTLSignCorrection(),
  37482. positions = [],
  37483. prevPosition = this._startPrevPosition(),
  37484. nextPosition = this._startNextPosition();
  37485. for (var i = atIndex; i !== previousIndex; i = this._normalizeIndex(i + 1)) {
  37486. positions[i] = nextPosition;
  37487. nextPosition += itemPositionOffset
  37488. }
  37489. if (movingBack) {
  37490. positions[previousIndex] = nextPosition;
  37491. nextPosition += itemPositionOffset
  37492. }
  37493. else
  37494. positions[previousIndex] = prevPosition;
  37495. positions.push(nextPosition);
  37496. return positions
  37497. }
  37498. });
  37499. DX.registerComponent("dxPanorama", ui, ui.CollectionWidget.inherit({
  37500. _setDefaultOptions: function() {
  37501. this.callBase();
  37502. this.option({
  37503. selectedIndex: 0,
  37504. title: "panorama",
  37505. backgroundImage: {
  37506. url: null,
  37507. width: 0,
  37508. height: 0
  37509. },
  37510. focusStateEnabled: false,
  37511. selectionMode: "single",
  37512. selectionRequired: true,
  37513. selectionByClick: false
  37514. })
  37515. },
  37516. _itemClass: function() {
  37517. return PANORAMA_ITEM_CLASS
  37518. },
  37519. _itemDataKey: function() {
  37520. return PANORAMA_ITEM_DATA_KEY
  37521. },
  37522. _itemContainer: function() {
  37523. return this._$itemsContainer
  37524. },
  37525. _itemWidth: function() {
  37526. if (!this._itemWidthCache)
  37527. this._itemWidthCache = this._itemElements().eq(0).outerWidth();
  37528. return this._itemWidthCache
  37529. },
  37530. _clearItemWidthCache: function() {
  37531. delete this._itemWidthCache
  37532. },
  37533. _elementWidth: function() {
  37534. if (!this._elementWidthCache)
  37535. this._elementWidthCache = this.element().width();
  37536. return this._elementWidthCache
  37537. },
  37538. _clearElementWidthCache: function() {
  37539. delete this._elementWidthCache
  37540. },
  37541. _titleWidth: function() {
  37542. if (!this._titleWidthCache)
  37543. this._titleWidthCache = this._$title.outerWidth();
  37544. return this._titleWidthCache
  37545. },
  37546. _clearTitleWidthCache: function() {
  37547. delete this._titleWidthCache
  37548. },
  37549. _init: function() {
  37550. this.callBase();
  37551. this._initItemsRenderStrategy();
  37552. this._initWrapper();
  37553. this._initTitle();
  37554. this._initItemsContainer();
  37555. this._initSwipeHandlers()
  37556. },
  37557. _dimensionChanged: function() {
  37558. this._clearItemWidthCache();
  37559. this._clearElementWidthCache();
  37560. this._clearTitleWidthCache();
  37561. this._updatePositions()
  37562. },
  37563. _initWrapper: function() {
  37564. this._$wrapper = $("<div>").addClass(PANORAMA_WRAPPER_CLASS).appendTo(this.element())
  37565. },
  37566. _initItemsRenderStrategy: function() {
  37567. var itemsRenderStrategy;
  37568. switch (this.option("items").length) {
  37569. case 0:
  37570. case 1:
  37571. itemsRenderStrategy = PanoramaOneAndLessItemsRenderStrategy;
  37572. break;
  37573. case 2:
  37574. itemsRenderStrategy = PanoramaTwoItemsRenderStrategy;
  37575. break;
  37576. default:
  37577. itemsRenderStrategy = PanoramaThreeAndMoreItemsRenderStrategy
  37578. }
  37579. this._itemsRenderStrategy = new itemsRenderStrategy(this);
  37580. this._itemsRenderStrategy.init()
  37581. },
  37582. _initBackgroundImage: function() {
  37583. var bgUrl = this.option("backgroundImage.url");
  37584. if (bgUrl)
  37585. this.element().css("background-image", "url(" + bgUrl + ")")
  37586. },
  37587. _initTitle: function() {
  37588. this._$title = $("<div>").addClass(PANORAMA_TITLE_CLASS);
  37589. this._$ghostTitle = $("<div>").addClass(PANORAMA_GHOST_TITLE_CLASS);
  37590. this._$wrapper.append(this._$title);
  37591. this._$wrapper.append(this._$ghostTitle);
  37592. this._updateTitle()
  37593. },
  37594. _updateTitle: function() {
  37595. var title = this.option("title");
  37596. this._$title.text(title);
  37597. this._$ghostTitle.text(title);
  37598. this._toggleGhostTitle(false)
  37599. },
  37600. _toggleGhostTitle: function(visible) {
  37601. var $ghostTitle = this._$ghostTitle;
  37602. if (visible)
  37603. $ghostTitle.css("opacity", 1);
  37604. else
  37605. $ghostTitle.css("opacity", 0)
  37606. },
  37607. _getRTLSignCorrection: function() {
  37608. return this.option("rtlEnabled") ? -1 : 1
  37609. },
  37610. _initItemsContainer: function() {
  37611. this._$itemsContainer = $("<div>").addClass(PANORAMA_ITEMS_CONTAINER_CLASS);
  37612. this._$wrapper.append(this._$itemsContainer)
  37613. },
  37614. _render: function() {
  37615. this.element().addClass(PANORAMA_CLASS);
  37616. this.callBase();
  37617. this._initBackgroundImage();
  37618. this._itemsRenderStrategy.render()
  37619. },
  37620. _updatePositions: function(offset) {
  37621. offset = offset || 0;
  37622. this._updateBackgroundPosition(offset * this._calculateBackgroundStep());
  37623. this._updateTitlePosition(offset * this._calculateTitleStep());
  37624. this._itemsRenderStrategy.updatePositions(offset * this._elementWidth())
  37625. },
  37626. _updateBackgroundPosition: function(offset) {
  37627. moveBackground(this.element(), this._calculateBackgroundPosition(this.option("selectedIndex")) + offset)
  37628. },
  37629. _updateTitlePosition: function(offset) {
  37630. move(this._$title, this._calculateTitlePosition(this.option("selectedIndex")) + offset)
  37631. },
  37632. _animateRollback: function(currentIndex) {
  37633. this._animateBackgroundMove(currentIndex);
  37634. this._animateTitleMove(currentIndex);
  37635. this._itemsRenderStrategy.animateRollback(currentIndex)
  37636. },
  37637. _animateBackgroundMove: function(toIndex) {
  37638. return animation.backgroundMove(this.element(), this._calculateBackgroundPosition(toIndex))
  37639. },
  37640. _animateTitleMove: function(toIndex) {
  37641. return animation.titleMove(this._$title, this._calculateTitlePosition(toIndex))
  37642. },
  37643. _animateComplete: function(newIndex, currentIndex) {
  37644. var that = this,
  37645. boundCross = this._itemsRenderStrategy.detectBoundsTransition(newIndex, currentIndex);
  37646. var backgroundAnimation = this._performBackgroundAnimation(boundCross, newIndex);
  37647. var titleAnimation = this._performTitleAnimation(boundCross, newIndex);
  37648. var itemsAnimation = this._itemsRenderStrategy.animateComplete(boundCross, newIndex, currentIndex);
  37649. $.when(backgroundAnimation, titleAnimation, itemsAnimation).done(function() {
  37650. that._indexChangeOnAnimation = true;
  37651. that.option("selectedIndex", newIndex);
  37652. that._indexChangeOnAnimation = false
  37653. })
  37654. },
  37655. _performBackgroundAnimation: function(boundCross, newIndex) {
  37656. if (boundCross)
  37657. return this._animateBackgroundBoundsTransition(boundCross, newIndex);
  37658. return this._animateBackgroundMove(newIndex)
  37659. },
  37660. _animateBackgroundBoundsTransition: function(bound, newIndex) {
  37661. var that = this,
  37662. isLeft = bound === "left",
  37663. afterAnimationPosition = this._calculateBackgroundPosition(newIndex),
  37664. animationEndPositionShift = isLeft ^ this.option("rtlEnabled") ? -this._calculateBackgroundScaledWidth() : this._calculateBackgroundScaledWidth(),
  37665. animationEndPosition = afterAnimationPosition + animationEndPositionShift;
  37666. return animation.backgroundMove(this.element(), animationEndPosition, function() {
  37667. moveBackground(that.element(), afterAnimationPosition)
  37668. })
  37669. },
  37670. _performTitleAnimation: function(boundCross, newIndex) {
  37671. if (boundCross)
  37672. return this._animateTitleBoundsTransition(boundCross, newIndex);
  37673. return this._animateTitleMove(newIndex)
  37674. },
  37675. _animateTitleBoundsTransition: function(bound, newIndex) {
  37676. var that = this,
  37677. $ghostTitle = this._$ghostTitle,
  37678. ghostWidth = this._titleWidth(),
  37679. panoramaWidth = this._elementWidth(),
  37680. isLeft = bound === "left",
  37681. rtl = this.option("rtlEnabled"),
  37682. ghostTitleStartPosition = isLeft ^ rtl ? panoramaWidth : -ghostWidth,
  37683. ghostTitleEndPosition = isLeft ^ rtl ? -(panoramaWidth + ghostWidth) : panoramaWidth;
  37684. move($ghostTitle, ghostTitleStartPosition);
  37685. this._toggleGhostTitle(true);
  37686. this._swapGhostWithTitle();
  37687. var ghostAnimation = animation.titleMove($ghostTitle, ghostTitleEndPosition, function() {
  37688. that._toggleGhostTitle(false)
  37689. });
  37690. var titleAnimation = animation.titleMove(this._$title, this._calculateTitlePosition(newIndex));
  37691. return $.when(ghostAnimation, titleAnimation)
  37692. },
  37693. _swapGhostWithTitle: function() {
  37694. var $ghostTitle = this._$ghostTitle,
  37695. $title = this._$title,
  37696. lastTitlePosition = position($title);
  37697. move($title, position($ghostTitle));
  37698. move($ghostTitle, lastTitlePosition)
  37699. },
  37700. _calculateTitlePosition: function(atIndex) {
  37701. var panoramaWidth = this._elementWidth(),
  37702. titleWidth = this._titleWidth(),
  37703. titleMargin = panoramaWidth * PANORAMA_TITLE_MARGIN_SCALE,
  37704. titleStartPosition = this.option("rtlEnabled") ? panoramaWidth - titleMargin - titleWidth : titleMargin,
  37705. titleStep = atIndex * this._calculateTitleStep() * this._getRTLSignCorrection();
  37706. return titleStartPosition - titleStep
  37707. },
  37708. _calculateTitleStep: function() {
  37709. var panoramaWidth = this._elementWidth(),
  37710. titleWidth = this._titleWidth(),
  37711. indexBoundary = this._indexBoundary() || 1;
  37712. return Math.max((titleWidth - panoramaWidth) / indexBoundary, titleWidth / indexBoundary)
  37713. },
  37714. _calculateBackgroundPosition: function(atIndex) {
  37715. var panoramaWidth = this._elementWidth(),
  37716. backgroundScaledWidth = this._calculateBackgroundScaledWidth(),
  37717. backgroundStartPosition = this.option("rtlEnabled") ? panoramaWidth - backgroundScaledWidth : 0,
  37718. backgroundOffset = atIndex * this._calculateBackgroundStep() * this._getRTLSignCorrection();
  37719. return backgroundStartPosition - backgroundOffset
  37720. },
  37721. _calculateBackgroundStep: function() {
  37722. var itemWidth = this._itemWidth(),
  37723. backgroundScaledWidth = this._calculateBackgroundScaledWidth();
  37724. return Math.max((backgroundScaledWidth - itemWidth) / (this._indexBoundary() || 1), 0)
  37725. },
  37726. _calculateBackgroundScaledWidth: function() {
  37727. return this.element().height() * this.option("backgroundImage.width") / (this.option("backgroundImage.height") || 1)
  37728. },
  37729. _initSwipeHandlers: function() {
  37730. this.element().on(events.addNamespace("dxswipestart", this.NAME), {itemSizeFunc: $.proxy(this._elementWidth, this)}, $.proxy(this._swipeStartHandler, this)).on(events.addNamespace("dxswipe", this.NAME), $.proxy(this._swipeUpdateHandler, this)).on(events.addNamespace("dxswipeend", this.NAME), $.proxy(this._swipeEndHandler, this))
  37731. },
  37732. _swipeStartHandler: function(e) {
  37733. this._stopAnimations();
  37734. e.maxLeftOffset = 1;
  37735. e.maxRightOffset = 1;
  37736. if (DX.designMode || this.option("disabled") || this._indexBoundary() <= 1)
  37737. e.cancel = true
  37738. },
  37739. _stopAnimations: function() {
  37740. endAnimation([this.element(), this._$ghostTitle, this._$title]);
  37741. endAnimation(this._itemsRenderStrategy.allItemElements())
  37742. },
  37743. _swipeUpdateHandler: function(e) {
  37744. this._updatePositions(e.offset)
  37745. },
  37746. _swipeEndHandler: function(e) {
  37747. var currentIndex = this.option("selectedIndex"),
  37748. targetOffset = e.targetOffset * this._getRTLSignCorrection();
  37749. if (targetOffset === 0)
  37750. this._animateRollback(currentIndex);
  37751. else
  37752. this._animateComplete(this._normalizeIndex(currentIndex - targetOffset), currentIndex)
  37753. },
  37754. _renderSelection: function(current, previous) {
  37755. if (!this._indexChangeOnAnimation)
  37756. this._updatePositions()
  37757. },
  37758. _normalizeIndex: function(index) {
  37759. var boundary = this._indexBoundary();
  37760. if (index < 0)
  37761. index = boundary + index;
  37762. if (index >= boundary)
  37763. index = index - boundary;
  37764. return index
  37765. },
  37766. _indexBoundary: function() {
  37767. return this.option("items").length
  37768. },
  37769. _visibilityChanged: function(visible) {
  37770. if (visible)
  37771. this._dimensionChanged()
  37772. },
  37773. _optionChanged: function(args) {
  37774. switch (args.name) {
  37775. case"width":
  37776. this.callBase(args);
  37777. this._dimensionChanged();
  37778. break;
  37779. case"backgroundImage":
  37780. this._invalidate();
  37781. break;
  37782. case"title":
  37783. this._updateTitle();
  37784. break;
  37785. case"items":
  37786. this._initItemsRenderStrategy();
  37787. this.callBase(args);
  37788. break;
  37789. default:
  37790. this.callBase(args)
  37791. }
  37792. }
  37793. }));
  37794. ui.dxPanorama.__internals = {animation: animation}
  37795. })(jQuery, DevExpress);
  37796. /*! Module widgets-mobile, file ui.slideOutView.js */
  37797. (function($, DX, undefined) {
  37798. var ui = DX.ui,
  37799. fx = DX.fx,
  37800. translator = DX.translator;
  37801. var SLIDEOUTVIEW_CLASS = "dx-slideoutview",
  37802. SLIDEOUTVIEW_WRAPPER_CLASS = "dx-slideoutview-wrapper",
  37803. SLIDEOUTVIEW_MENU_CONTENT_CLASS = "dx-slideoutview-menu-content",
  37804. SLIDEOUTVIEW_CONTENT_CLASS = "dx-slideoutview-content",
  37805. SLIDEOUTVIEW_SHIELD_CLASS = "dx-slideoutview-shield",
  37806. INVISIBLE_STATE_CLASS = "dx-state-invisible",
  37807. ANONYMOUS_TEMPLATE_NAME = "content",
  37808. ANIMATION_DURATION = 400;
  37809. var animation = {
  37810. moveTo: function($element, position, completeAction) {
  37811. fx.animate($element, {
  37812. type: "slide",
  37813. to: {left: position},
  37814. duration: ANIMATION_DURATION,
  37815. complete: completeAction
  37816. })
  37817. },
  37818. complete: function($element) {
  37819. fx.stop($element, true)
  37820. }
  37821. };
  37822. DX.registerComponent("dxSlideOutView", ui, ui.Widget.inherit({
  37823. _setDefaultOptions: function() {
  37824. this.callBase();
  37825. this.option({
  37826. menuVisible: false,
  37827. swipeEnabled: true,
  37828. menuTemplate: "menu",
  37829. contentTemplate: "content",
  37830. contentOffset: 45
  37831. })
  37832. },
  37833. _defaultOptionsRules: function() {
  37834. return this.callBase().concat([{
  37835. device: {android: true},
  37836. options: {contentOffset: 54}
  37837. }, {
  37838. device: function(device) {
  37839. return device.platform === "generic" && device.deviceType !== "desktop"
  37840. },
  37841. options: {contentOffset: 56}
  37842. }, {
  37843. device: {
  37844. win8: true,
  37845. phone: false
  37846. },
  37847. options: {contentOffset: 76}
  37848. }])
  37849. },
  37850. _getAnonimousTemplateName: function() {
  37851. return ANONYMOUS_TEMPLATE_NAME
  37852. },
  37853. _init: function() {
  37854. this.callBase();
  37855. this.element().addClass(SLIDEOUTVIEW_CLASS);
  37856. this._deferredAnimate = undefined;
  37857. this._initHideTopOverlayHandler()
  37858. },
  37859. _initHideTopOverlayHandler: function() {
  37860. this._hideMenuHandler = $.proxy(this.hideMenu, this)
  37861. },
  37862. _render: function() {
  37863. this.callBase();
  37864. this._renderShield();
  37865. this._initSwipeHandlers();
  37866. this._dimensionChanged()
  37867. },
  37868. _renderContentImpl: function() {
  37869. this._renderMarkup();
  37870. var menuTemplate = this._getTemplate(this.option("menuTemplate")),
  37871. contentTemplate = this._getTemplate(this.option("contentTemplate"));
  37872. menuTemplate && menuTemplate.render(this.menuContent());
  37873. contentTemplate && contentTemplate.render(this.content())
  37874. },
  37875. _renderMarkup: function() {
  37876. var $wrapper = $("<div>").addClass(SLIDEOUTVIEW_WRAPPER_CLASS);
  37877. this._$menu = $("<div>").addClass(SLIDEOUTVIEW_MENU_CONTENT_CLASS);
  37878. this._$container = $("<div>").addClass(SLIDEOUTVIEW_CONTENT_CLASS);
  37879. $wrapper.append(this._$menu);
  37880. $wrapper.append(this._$container);
  37881. this.element().append($wrapper);
  37882. this._$container.on("MSPointerDown", $.noop)
  37883. },
  37884. _renderShield: function() {
  37885. this._$shield = this._$shield || $("<div>").addClass(SLIDEOUTVIEW_SHIELD_CLASS);
  37886. this._$shield.appendTo(this.content());
  37887. this._$shield.off("dxclick").on("dxclick", $.proxy(this.hideMenu, this));
  37888. this._toggleShieldVisibility(this.option("menuVisible"))
  37889. },
  37890. _initSwipeHandlers: function() {
  37891. this._createComponent(this.content(), "dxSwipeable", {
  37892. disabled: !this.option("swipeEnabled"),
  37893. elastic: false,
  37894. itemSizeFunc: $.proxy(this._getMenuWidth, this),
  37895. onStart: $.proxy(this._swipeStartHandler, this),
  37896. onUpdated: $.proxy(this._swipeUpdateHandler, this),
  37897. onEnd: $.proxy(this._swipeEndHandler, this)
  37898. })
  37899. },
  37900. _swipeStartHandler: function(e) {
  37901. var event = e.jQueryEvent,
  37902. menuVisible = this.option("menuVisible"),
  37903. rtl = this.option("rtlEnabled");
  37904. event.maxLeftOffset = +(rtl ? !menuVisible : menuVisible);
  37905. event.maxRightOffset = +(rtl ? menuVisible : !menuVisible);
  37906. this._toggleShieldVisibility(true)
  37907. },
  37908. _swipeUpdateHandler: function(e) {
  37909. var event = e.jQueryEvent,
  37910. offset = this.option("menuVisible") ? event.offset + 1 * this._getRTLSignCorrection() : event.offset;
  37911. offset *= this._getRTLSignCorrection();
  37912. this._renderPosition(offset, false)
  37913. },
  37914. _swipeEndHandler: function(e) {
  37915. var targetOffset = e.jQueryEvent.targetOffset * this._getRTLSignCorrection() + this.option("menuVisible"),
  37916. menuVisible = targetOffset !== 0;
  37917. if (this.option("menuVisible") === menuVisible)
  37918. this._renderPosition(this.option("menuVisible"), true);
  37919. else
  37920. this.option("menuVisible", menuVisible)
  37921. },
  37922. _renderPosition: function(offset, animate) {
  37923. var pos = this._calculatePixelOffset(offset) * this._getRTLSignCorrection();
  37924. this._toggleHideMenuCallback(offset);
  37925. if (animate) {
  37926. this._toggleShieldVisibility(true);
  37927. animation.moveTo(this.content(), pos, $.proxy(this._animationCompleteHandler, this))
  37928. }
  37929. else
  37930. translator.move(this.content(), {left: pos})
  37931. },
  37932. _calculatePixelOffset: function(offset) {
  37933. offset = offset || 0;
  37934. return offset * this._getMenuWidth()
  37935. },
  37936. _getMenuWidth: function() {
  37937. if (!this._menuWidth) {
  37938. var maxMenuWidth = this.element().width() - this.option("contentOffset");
  37939. this.menuContent().css("max-width", maxMenuWidth);
  37940. var currentMenuWidth = this.menuContent().width();
  37941. this._menuWidth = Math.min(currentMenuWidth, maxMenuWidth)
  37942. }
  37943. return this._menuWidth
  37944. },
  37945. _animationCompleteHandler: function() {
  37946. this._toggleShieldVisibility(this.option("menuVisible"));
  37947. if (this._deferredAnimate)
  37948. this._deferredAnimate.resolveWith(this)
  37949. },
  37950. _toggleHideMenuCallback: function(subscribe) {
  37951. if (subscribe)
  37952. DX.hideTopOverlayCallback.add(this._hideMenuHandler);
  37953. else
  37954. DX.hideTopOverlayCallback.remove(this._hideMenuHandler)
  37955. },
  37956. _getRTLSignCorrection: function() {
  37957. return this.option("rtlEnabled") ? -1 : 1
  37958. },
  37959. _dispose: function() {
  37960. fx.stop(this.content());
  37961. this._toggleHideMenuCallback(false);
  37962. this.callBase()
  37963. },
  37964. _visibilityChanged: function(visible) {
  37965. if (visible)
  37966. this._dimensionChanged()
  37967. },
  37968. _dimensionChanged: function() {
  37969. delete this._menuWidth;
  37970. this._renderPosition(this.option("menuVisible"), false)
  37971. },
  37972. _toggleShieldVisibility: function(visible) {
  37973. this._$shield.toggleClass(INVISIBLE_STATE_CLASS, !visible)
  37974. },
  37975. _optionChanged: function(args) {
  37976. switch (args.name) {
  37977. case"width":
  37978. this.callBase(args);
  37979. this._dimensionChanged();
  37980. break;
  37981. case"contentOffset":
  37982. this._dimensionChanged();
  37983. break;
  37984. case"menuVisible":
  37985. this._renderPosition(args.value, true);
  37986. break;
  37987. case"swipeEnabled":
  37988. this._initSwipeHandlers();
  37989. break;
  37990. case"contentTemplate":
  37991. case"menuTemplate":
  37992. this._invalidate();
  37993. break;
  37994. default:
  37995. this.callBase(args)
  37996. }
  37997. },
  37998. menuContent: function() {
  37999. return this._$menu
  38000. },
  38001. content: function() {
  38002. return this._$container
  38003. },
  38004. showMenu: function() {
  38005. return this.toggleMenuVisibility(true)
  38006. },
  38007. hideMenu: function() {
  38008. return this.toggleMenuVisibility(false)
  38009. },
  38010. toggleMenuVisibility: function(showing) {
  38011. showing = showing === undefined ? !this.option("menuVisible") : showing;
  38012. this._deferredAnimate = $.Deferred();
  38013. this.option("menuVisible", showing);
  38014. return this._deferredAnimate.promise()
  38015. }
  38016. }));
  38017. ui.dxSlideOutView.__internals = {animation: animation}
  38018. })(jQuery, DevExpress);
  38019. /*! Module widgets-mobile, file ui.slideOut.js */
  38020. (function($, DX, undefined) {
  38021. var ui = DX.ui,
  38022. utils = DX.utils;
  38023. var SLIDEOUT_CLASS = "dx-slideout",
  38024. SLIDEOUT_ITEM_CONTAINER_CLASS = "dx-slideout-item-container",
  38025. SLIDEOUT_MENU = "dx-slideout-menu",
  38026. SLIDEOUT_ITEM_CLASS = "dx-slideout-item",
  38027. SLIDEOUT_ITEM_DATA_KEY = "dxSlideoutItemData";
  38028. DX.registerComponent("dxSlideOut", ui, ui.CollectionWidget.inherit({
  38029. _setDeprecatedOptions: function() {
  38030. this.callBase();
  38031. $.extend(this._deprecatedOptions, {
  38032. menuItemRender: {
  38033. since: "14.2",
  38034. alias: "menuItemTemplate"
  38035. },
  38036. menuGroupRender: {
  38037. since: "14.2",
  38038. alias: "menuGroupTemplate"
  38039. }
  38040. })
  38041. },
  38042. _setDefaultOptions: function() {
  38043. this.callBase();
  38044. this.option({
  38045. activeStateEnabled: false,
  38046. menuItemTemplate: "menuItem",
  38047. swipeEnabled: true,
  38048. menuVisible: false,
  38049. menuGrouped: false,
  38050. menuGroupTemplate: "menuGroup",
  38051. onMenuItemRendered: null,
  38052. onMenuGroupRendered: null,
  38053. contentTemplate: "content",
  38054. selectionMode: "single",
  38055. selectionRequired: true
  38056. })
  38057. },
  38058. _itemClass: function() {
  38059. return SLIDEOUT_ITEM_CLASS
  38060. },
  38061. _itemDataKey: function() {
  38062. return SLIDEOUT_ITEM_DATA_KEY
  38063. },
  38064. _itemContainer: function() {
  38065. return this._slideOutView.content()
  38066. },
  38067. _init: function() {
  38068. this.callBase();
  38069. this.element().addClass(SLIDEOUT_CLASS);
  38070. this._initSlideOutView()
  38071. },
  38072. _initEditStrategy: function() {
  38073. if (this.option("menuGrouped")) {
  38074. var strategy = ui.CollectionWidget.PlainEditStrategy.inherit({_getPlainItems: function() {
  38075. return $.map(this.callBase(), function(group) {
  38076. return group.items
  38077. })
  38078. }});
  38079. this._editStrategy = new strategy(this)
  38080. }
  38081. else
  38082. this.callBase()
  38083. },
  38084. _initSlideOutView: function() {
  38085. this._slideOutView = this._createComponent(this.element(), "dxSlideOutView", {
  38086. _templates: [],
  38087. menuVisible: this.option("menuVisible"),
  38088. swipeEnabled: this.option("swipeEnabled"),
  38089. onOptionChanged: $.proxy(this._slideOutViewOptionChanged, this)
  38090. });
  38091. this._itemContainer().addClass(SLIDEOUT_ITEM_CONTAINER_CLASS)
  38092. },
  38093. _slideOutViewOptionChanged: function(args) {
  38094. if (args.name === "menuVisible")
  38095. this.option(args.name, args.value)
  38096. },
  38097. _render: function() {
  38098. this._slideOutView._renderShield();
  38099. this._renderList();
  38100. this._renderContentTemplate();
  38101. this.callBase()
  38102. },
  38103. _renderList: function() {
  38104. this._$list = this._$list || $("<div>").addClass(SLIDEOUT_MENU).appendTo(this._slideOutView.menuContent());
  38105. this._renderItemClickAction();
  38106. this._createComponent(this._$list, "dxList", {
  38107. itemTemplateProperty: "menuTemplate",
  38108. indicateLoading: false,
  38109. onItemClick: $.proxy(this._listItemClickHandler, this),
  38110. items: this.option("items"),
  38111. dataSource: this.option("dataSource"),
  38112. itemTemplate: this._getTemplateByOption("menuItemTemplate"),
  38113. grouped: this.option("menuGrouped"),
  38114. groupTemplate: this.option("menuGroupTemplate"),
  38115. onItemRendered: this.option("onMenuItemRendered"),
  38116. onGroupRendered: this.option("onMenuGroupRendered"),
  38117. onContentReady: $.proxy(this._updateSlideOutView, this)
  38118. })
  38119. },
  38120. _updateSlideOutView: function() {
  38121. this._slideOutView._dimensionChanged()
  38122. },
  38123. _renderItemClickAction: function() {
  38124. this._itemClickAction = this._createActionByOption("onItemClick")
  38125. },
  38126. _listItemClickHandler: function(e) {
  38127. var selectedIndex = this._$list.find(".dx-list-item").index(e.itemElement);
  38128. this.option("selectedIndex", selectedIndex);
  38129. this._itemClickAction(e)
  38130. },
  38131. _renderContentTemplate: function() {
  38132. if (utils.isDefined(this._singleContent))
  38133. return;
  38134. var $result = this._getTemplateByOption("contentTemplate").render(this._itemContainer());
  38135. this._singleContent = !!$result.length || $result.is(":empty")
  38136. },
  38137. _itemClickHandler: $.noop,
  38138. _renderContentImpl: function(template) {
  38139. if (this._singleContent)
  38140. return;
  38141. var items = this.option("items"),
  38142. selectedIndex = this.option("selectedIndex");
  38143. if (items.length && selectedIndex > -1) {
  38144. var selectedItem = this._$list.dxList("instance").getItemByIndex(selectedIndex);
  38145. this._renderItems([selectedItem])
  38146. }
  38147. },
  38148. _renderItem: function(index, item, container) {
  38149. this._itemContainer().find("." + SLIDEOUT_ITEM_CLASS).remove();
  38150. this.callBase(index, item)
  38151. },
  38152. _selectedItemElement: function(index) {
  38153. return this._itemElements().eq(0)
  38154. },
  38155. _renderSelection: function() {
  38156. this._renderContent()
  38157. },
  38158. _getListWidth: function() {
  38159. return this._slideOutView._getMenuWidth()
  38160. },
  38161. _changeMenuOption: function(name, value) {
  38162. this._$list.dxList("instance").option(name, value);
  38163. this._updateSlideOutView()
  38164. },
  38165. _cleanItemContainer: function() {
  38166. if (this._singleContent)
  38167. return;
  38168. this.callBase()
  38169. },
  38170. _optionChanged: function(args) {
  38171. var name = args.name;
  38172. var value = args.value;
  38173. switch (name) {
  38174. case"menuVisible":
  38175. case"swipeEnabled":
  38176. case"rtlEnabled":
  38177. this._slideOutView.option(name, value);
  38178. break;
  38179. case"width":
  38180. this.callBase(args);
  38181. this._updateSlideOutView();
  38182. break;
  38183. case"menuItemTemplate":
  38184. this._changeMenuOption("itemTemplate", this._getTemplate(value));
  38185. break;
  38186. case"items":
  38187. this._changeMenuOption(name, value);
  38188. break;
  38189. case"dataSource":
  38190. this._changeMenuOption(name, value);
  38191. this.callBase(args);
  38192. break;
  38193. case"menuGrouped":
  38194. this._initEditStrategy();
  38195. this._changeMenuOption("grouped", value);
  38196. break;
  38197. case"menuGroupTemplate":
  38198. this._changeMenuOption("groupTemplate", this._getTemplate(value));
  38199. break;
  38200. case"onMenuItemRendered":
  38201. this._changeMenuOption("onItemRendered", value);
  38202. break;
  38203. case"onMenuGroupRendered":
  38204. this._changeMenuOption("onGroupRendered", value);
  38205. break;
  38206. case"onItemClick":
  38207. this._renderItemClickAction();
  38208. break;
  38209. case"contentTemplate":
  38210. this._singleContent = null;
  38211. this._invalidate();
  38212. break;
  38213. default:
  38214. this.callBase(args)
  38215. }
  38216. },
  38217. showMenu: function() {
  38218. return this._slideOutView.toggleMenuVisibility(true)
  38219. },
  38220. hideMenu: function() {
  38221. return this._slideOutView.toggleMenuVisibility(false)
  38222. },
  38223. toggleMenuVisibility: function(showing) {
  38224. return this._slideOutView.toggleMenuVisibility(showing)
  38225. }
  38226. }))
  38227. })(jQuery, DevExpress);
  38228. DevExpress.MOD_WIDGETS_MOBILE = true
  38229. }
  38230. if (!DevExpress.MOD_WIDGETS_WEB) {
  38231. if (!DevExpress.MOD_WIDGETS_BASE)
  38232. throw Error('Required module is not referenced: widgets-base');
  38233. /*! Module widgets-web, file ui.accordion.js */
  38234. (function($, DX, undefined) {
  38235. var ui = DX.ui,
  38236. events = ui.events,
  38237. fx = DX.fx;
  38238. var ACCORDION_CLASS = "dx-accordion",
  38239. ACCORDION_WRAPPER_CLASS = "dx-accordion-wrapper",
  38240. ACCORDION_ITEM_CLASS = "dx-accordion-item",
  38241. ACCORDION_ITEM_OPENED_CLASS = "dx-accordion-item-opened",
  38242. ACCORDION_ITEM_CLOSED_CLASS = "dx-accordion-item-closed",
  38243. ACCORDION_ITEM_TITLE_CLASS = "dx-accordion-item-title",
  38244. ACCORDION_ITEM_BODY_CLASS = "dx-accordion-item-body",
  38245. ACCORDION_ITEM_DATA_KEY = "dxAccordionItemData",
  38246. ACCORDION_ITEM_TITLE_DATA_KEY = "dxAccordionItemTitleData",
  38247. ACCORDION_ITEM_CONTENT_DATA_KEY = "dxAccordionItemContentData";
  38248. DX.registerComponent("dxAccordion", ui, ui.CollectionWidget.inherit({
  38249. _activeStateUnit: "." + ACCORDION_ITEM_CLASS,
  38250. _setDefaultOptions: function() {
  38251. this.callBase();
  38252. this.option({
  38253. height: undefined,
  38254. itemTitleTemplate: "title",
  38255. onItemTitleClick: null,
  38256. onItemTitleHold: null,
  38257. selectedIndex: 0,
  38258. collapsible: false,
  38259. multiple: false,
  38260. animationDuration: 300,
  38261. deferRendering: true,
  38262. selectionByClick: true,
  38263. activeStateEnabled: true,
  38264. _itemAttributes: {role: "tab"}
  38265. })
  38266. },
  38267. _defaultOptionsRules: function() {
  38268. return this.callBase().concat([{
  38269. device: function(device) {
  38270. return DX.devices.real().generic && !DX.devices.isSimulator()
  38271. },
  38272. options: {
  38273. hoverStateEnabled: true,
  38274. focusStateEnabled: true
  38275. }
  38276. }])
  38277. },
  38278. _init: function() {
  38279. this.callBase();
  38280. this.option("selectionRequired", !this.option("collapsible"));
  38281. this.option("selectionMode", this.option("multiple") ? "multi" : "single");
  38282. var $element = this.element();
  38283. $element.addClass(ACCORDION_CLASS);
  38284. this._$container = $("<div>").addClass(ACCORDION_WRAPPER_CLASS);
  38285. $element.append(this._$container)
  38286. },
  38287. _render: function() {
  38288. this._deferredItems = [];
  38289. this.callBase();
  38290. this.setAria({
  38291. role: "tablist",
  38292. multiselectable: this.option("multiple")
  38293. });
  38294. this._attachItemTitleClickAction()
  38295. },
  38296. _itemDataKey: function() {
  38297. return ACCORDION_ITEM_DATA_KEY
  38298. },
  38299. _itemClass: function() {
  38300. return ACCORDION_ITEM_CLASS
  38301. },
  38302. _itemContainer: function() {
  38303. return this._$container
  38304. },
  38305. _itemTitles: function() {
  38306. return this._itemElements().find("." + ACCORDION_ITEM_TITLE_CLASS)
  38307. },
  38308. _itemContents: function() {
  38309. return this._itemElements().find("." + ACCORDION_ITEM_BODY_CLASS)
  38310. },
  38311. _getItemData: function(target) {
  38312. return $(target).parent().data(this._itemDataKey()) || this.callBase.apply(this, arguments)
  38313. },
  38314. _executeItemRenderAction: function(itemData, itemElement) {
  38315. if (itemData.type)
  38316. return;
  38317. this.callBase.apply(this, arguments)
  38318. },
  38319. _itemSelectHandler: function(e) {
  38320. if ($(e.target).closest("." + ACCORDION_ITEM_BODY_CLASS).length)
  38321. return;
  38322. this.callBase.apply(this, arguments)
  38323. },
  38324. _renderItemContent: function(index, itemData, $container) {
  38325. $container = $container || this._itemContainer();
  38326. var $itemTitle = this.callBase.apply(this, [index, $.extend({
  38327. type: "title",
  38328. titleTemplate: this._getTemplateByOption("itemTitleTemplate")
  38329. }, itemData), $container]);
  38330. var $item = $itemTitle.parent();
  38331. this._deferredItems.push($.Deferred());
  38332. this._deferredItems[index].done($.proxy(this._renderItemBody, this, this.callBase, index, itemData, $item));
  38333. if (!this.option("deferRendering"))
  38334. this._deferredItems[index].resolve()
  38335. },
  38336. _renderItemBody: function(baseRenderer, index, itemData, $item) {
  38337. var $itemBody = $("<div>").appendTo($item);
  38338. baseRenderer.apply(this, [index, $.extend({
  38339. type: "content",
  38340. template: this._getTemplateByOption("itemTemplate")
  38341. }, itemData), $itemBody])
  38342. },
  38343. _getItemTemplateName: function(itemData) {
  38344. var templateProperty = this.option("itemTemplateProperty");
  38345. if (itemData.type === "title")
  38346. templateProperty = "titleTemplate";
  38347. return itemData && itemData[templateProperty] || this.option("itemTemplate")
  38348. },
  38349. _addItemContentClasses: function($container, itemData) {
  38350. switch (itemData.type) {
  38351. case"title":
  38352. $container.addClass(ACCORDION_ITEM_TITLE_CLASS).data(ACCORDION_ITEM_TITLE_DATA_KEY, itemData);
  38353. break;
  38354. case"content":
  38355. $container.addClass(ACCORDION_ITEM_BODY_CLASS).data(ACCORDION_ITEM_CONTENT_DATA_KEY, itemData);
  38356. break;
  38357. default:
  38358. this.callBase.apply(this, arguments)
  38359. }
  38360. },
  38361. _attachItemTitleClickAction: function() {
  38362. var itemSelector = "." + ACCORDION_ITEM_TITLE_CLASS,
  38363. eventName = events.addNamespace("dxclick", this.NAME);
  38364. this._itemContainer().off(eventName, itemSelector).on(eventName, itemSelector, $.proxy(this._itemTitleClickHandler, this))
  38365. },
  38366. _itemTitleClickHandler: function(e) {
  38367. this._itemJQueryEventHandler(e, "onItemTitleClick")
  38368. },
  38369. _renderSelection: function(addedSelection, removedSelection) {
  38370. this._itemElements().addClass(ACCORDION_ITEM_CLOSED_CLASS);
  38371. this._updateItems(addedSelection, removedSelection, true)
  38372. },
  38373. _updateSelection: function(addedSelection, removedSelection) {
  38374. this._updateItems(addedSelection, removedSelection, false)
  38375. },
  38376. _updateItems: function(addedSelection, removedSelection, skipAnimation) {
  38377. var $items = this._itemElements(),
  38378. that = this;
  38379. $.each(addedSelection, function(_, index) {
  38380. var $item = $items.eq(index);
  38381. if ($item.find("." + ACCORDION_ITEM_BODY_CLASS).length === 0)
  38382. that._deferredItems[index].resolve();
  38383. $item.addClass(ACCORDION_ITEM_OPENED_CLASS);
  38384. $item.removeClass(ACCORDION_ITEM_CLOSED_CLASS)
  38385. });
  38386. $.each(removedSelection, function(_, index) {
  38387. $items.eq(index).removeClass(ACCORDION_ITEM_OPENED_CLASS)
  38388. });
  38389. this._updateItemHeights(skipAnimation)
  38390. },
  38391. _updateItemHeights: function(skipAnimation) {
  38392. var $items = this._itemElements();
  38393. var itemHeight = this._splitFreeSpace(this._calculateFreeSpace());
  38394. $.each($items, $.proxy(function(_, item) {
  38395. var $item = $(item),
  38396. $title = $item.children("." + ACCORDION_ITEM_TITLE_CLASS);
  38397. var startItemHeight = $item.outerHeight();
  38398. var finalItemHeight = $item.hasClass(ACCORDION_ITEM_OPENED_CLASS) ? itemHeight + $title.outerHeight() || $item.height("auto").outerHeight() : $title.outerHeight();
  38399. if (fx.isAnimating($item))
  38400. fx.stop($item);
  38401. if (!skipAnimation)
  38402. this._animateItem($item, startItemHeight, finalItemHeight);
  38403. else
  38404. $item.css("height", finalItemHeight)
  38405. }, this))
  38406. },
  38407. _animateItem: function(element, startHeight, endHeight) {
  38408. fx.animate(element, {
  38409. type: "slide",
  38410. from: {height: startHeight},
  38411. to: {height: endHeight},
  38412. duration: this.option("animationDuration"),
  38413. complete: $.proxy(function() {
  38414. if (this._deferredAnimate)
  38415. this._deferredAnimate.resolveWith(this);
  38416. this._itemElements().not("." + ACCORDION_ITEM_OPENED_CLASS).addClass(ACCORDION_ITEM_CLOSED_CLASS)
  38417. }, this)
  38418. })
  38419. },
  38420. _splitFreeSpace: function(freeSpace) {
  38421. if (!freeSpace)
  38422. return freeSpace;
  38423. return freeSpace / this.option("selectedItems").length
  38424. },
  38425. _calculateFreeSpace: function() {
  38426. var height = this.option("height");
  38427. if (height === undefined || height === "auto")
  38428. return;
  38429. var $titles = this._itemTitles(),
  38430. itemsHeight = 0;
  38431. $.each($titles, function(_, title) {
  38432. itemsHeight += $(title).outerHeight()
  38433. });
  38434. return this.element().height() - itemsHeight
  38435. },
  38436. _visibilityChanged: function(visible) {
  38437. if (visible)
  38438. this._dimensionChanged()
  38439. },
  38440. _dimensionChanged: function() {
  38441. this._updateItemHeights(true)
  38442. },
  38443. _optionChanged: function(args) {
  38444. switch (args.name) {
  38445. case"animationDuration":
  38446. case"onItemTitleClick":
  38447. break;
  38448. case"collapsible":
  38449. this.option("selectionRequired", !this.option("collapsible"));
  38450. break;
  38451. case"itemTitleTemplate":
  38452. case"itemContentTemplate":
  38453. case"onItemTitleHold":
  38454. case"height":
  38455. case"deferRendering":
  38456. this._invalidate();
  38457. break;
  38458. case"multiple":
  38459. this.option("selectionMode", args.value ? "multi" : "single");
  38460. break;
  38461. default:
  38462. this.callBase(args)
  38463. }
  38464. },
  38465. expandItem: function(index) {
  38466. this._deferredAnimate = $.Deferred();
  38467. this.selectItem(index);
  38468. return this._deferredAnimate.promise()
  38469. },
  38470. collapseItem: function(index) {
  38471. this._deferredAnimate = $.Deferred();
  38472. this.unselectItem(index);
  38473. return this._deferredAnimate.promise()
  38474. }
  38475. }))
  38476. })(jQuery, DevExpress);
  38477. /*! Module widgets-web, file ui.pager.js */
  38478. (function($, DX, undefined) {
  38479. var ui = DX.ui,
  38480. utils = DX.utils,
  38481. events = ui.events,
  38482. Class = DX.Class;
  38483. var PAGES_LIMITER = 4,
  38484. PAGER_CLASS = 'dx-pager',
  38485. PAGER_PAGE_CLASS = 'dx-page',
  38486. PAGER_PAGES_CLASS = 'dx-pages',
  38487. PAGER_SELECTION_CLASS = 'dx-selection',
  38488. PAGER_PAGE_SEPARATOR_CLASS = 'dx-separator',
  38489. PAGER_PAGE_SIZES_CLASS = 'dx-page-sizes',
  38490. PAGER_PAGE_SIZE_CLASS = 'dx-page-size',
  38491. PAGER_NAVIGATE_BUTTON = 'dx-navigate-button',
  38492. PAGER_PREV_BUTTON_CLASS = "dx-prev-button",
  38493. PAGER_NEXT_BUTTON_CLASS = "dx-next-button",
  38494. PAGER_INFO_CLASS = "dx-info",
  38495. PAGER_BUTTON_DISABLE_CLASS = "dx-button-disable";
  38496. var Page = Class.inherit({
  38497. ctor: function(value, index) {
  38498. var that = this;
  38499. that.index = index;
  38500. that._$page = $('<div />').text(value).addClass(PAGER_PAGE_CLASS)
  38501. },
  38502. value: function(value) {
  38503. var that = this;
  38504. if (utils.isDefined(value))
  38505. that._$page.text(value);
  38506. else {
  38507. var text = that._$page.text();
  38508. if (utils.isNumber(text))
  38509. return parseInt(text);
  38510. else
  38511. return text
  38512. }
  38513. },
  38514. element: function() {
  38515. return this._$page
  38516. },
  38517. select: function(value) {
  38518. this._$page.toggleClass(PAGER_SELECTION_CLASS, value)
  38519. },
  38520. render: function(rootElement, rtlEnabled) {
  38521. rtlEnabled ? this._$page.prependTo(rootElement) : this._$page.appendTo(rootElement)
  38522. }
  38523. });
  38524. DX.registerComponent("dxPager", ui, ui.Widget.inherit({
  38525. _setDefaultOptions: function() {
  38526. this.callBase();
  38527. this.option({
  38528. visible: true,
  38529. pageIndex: 1,
  38530. maxPagesCount: 10,
  38531. pageCount: 10,
  38532. pageSize: 5,
  38533. showPageSizes: true,
  38534. pageSizes: [5, 10],
  38535. hasKnownLastPage: true,
  38536. showNavigationButtons: false,
  38537. showInfo: false,
  38538. infoText: Globalize.localize("dxPager-infoText"),
  38539. rtlEnabled: false,
  38540. pageIndexChanged: $.noop,
  38541. pageSizeChanged: $.noop
  38542. })
  38543. },
  38544. _toggleVisibility: function(value) {
  38545. var $element = this.element();
  38546. if ($element)
  38547. $element.css("display", value ? "" : "none")
  38548. },
  38549. _getPages: function(currentPage, count) {
  38550. var pages = [],
  38551. showMoreButton = !this.option("hasKnownLastPage"),
  38552. firstValue,
  38553. i;
  38554. this._testPagesCount = count;
  38555. this._testShowMoreButton = showMoreButton;
  38556. if (count > 0 || showMoreButton)
  38557. if (count <= this.option("maxPagesCount")) {
  38558. for (i = 1; i <= count; i++)
  38559. pages.push(new Page(i, i - 1));
  38560. if (showMoreButton)
  38561. pages.push(new Page('>', i - 1))
  38562. }
  38563. else {
  38564. pages.push(new Page(1, 0));
  38565. firstValue = currentPage ? currentPage.value() - currentPage.index : 1;
  38566. for (i = 1; i <= PAGES_LIMITER; i++)
  38567. pages.push(new Page(firstValue + i, i));
  38568. pages.push(new Page(count, PAGES_LIMITER + 1));
  38569. if (showMoreButton)
  38570. pages.push(new Page('>', PAGES_LIMITER + 1))
  38571. }
  38572. return pages
  38573. },
  38574. _getPageByValue: function(value) {
  38575. var that = this,
  38576. page,
  38577. i;
  38578. for (i = 0; i < that._pages.length; i++) {
  38579. page = that._pages[i];
  38580. if (page.value() === value)
  38581. return page
  38582. }
  38583. },
  38584. _processSelectedPage: function(maxPagesCount, pageIndex, pageCount) {
  38585. var that = this,
  38586. isPageIndexValid = false,
  38587. selectedPageIndex;
  38588. if (that._pages) {
  38589. $.each(that._pages, function(key, page) {
  38590. if (pageIndex === page.value())
  38591. isPageIndexValid = true
  38592. });
  38593. if (!isPageIndexValid)
  38594. that.selectedPage = null
  38595. }
  38596. if (utils.isDefined(that.selectedPage)) {
  38597. if (pageIndex === pageCount && pageCount > maxPagesCount && that.selectedPage.index !== PAGES_LIMITER + 1)
  38598. that.selectedPage.index = PAGES_LIMITER + 1
  38599. }
  38600. else if (pageIndex > PAGES_LIMITER && pageIndex < pageCount) {
  38601. selectedPageIndex = pageCount - PAGES_LIMITER < pageIndex ? PAGES_LIMITER - (pageCount - pageIndex) + 1 : 2;
  38602. that.selectedPage = new Page(pageIndex, selectedPageIndex)
  38603. }
  38604. },
  38605. _selectPageByValue: function(value) {
  38606. var that = this,
  38607. i,
  38608. page = that._getPageByValue(value),
  38609. pages = that._pages,
  38610. pagesLength = pages.length,
  38611. prevPage,
  38612. nextPage,
  38613. morePage;
  38614. if (!utils.isDefined(page))
  38615. return;
  38616. prevPage = that._pages[page.index - 1];
  38617. nextPage = that._pages[page.index + 1];
  38618. if (nextPage && nextPage.value() === '>') {
  38619. morePage = nextPage;
  38620. nextPage = undefined;
  38621. pagesLength--;
  38622. pages.pop()
  38623. }
  38624. if (that.selectedPage)
  38625. that.selectedPage.select(false);
  38626. page.select(true);
  38627. that.selectedPage = page;
  38628. if (nextPage && nextPage.value() - value > 1)
  38629. if (page.index !== 0) {
  38630. prevPage.value(value + 1);
  38631. that._pages.splice(page.index, 1);
  38632. that._pages.splice(page.index - 1, 0, page);
  38633. that._pages[page.index].index = page.index;
  38634. page.index = page.index - 1;
  38635. for (i = page.index - 1; i > 0; i--)
  38636. that._pages[i].value(that._pages[i + 1].value() - 1)
  38637. }
  38638. else
  38639. for (i = 0; i < pagesLength - 1; i++)
  38640. that._pages[i].value(i + 1);
  38641. if (prevPage && value - prevPage.value() > 1)
  38642. if (page.index !== pagesLength - 1) {
  38643. nextPage.value(value - 1);
  38644. that._pages.splice(page.index, 1);
  38645. that._pages.splice(page.index + 1, 0, page);
  38646. that._pages[page.index].index = page.index;
  38647. page.index = page.index + 1;
  38648. for (i = page.index + 1; i < pagesLength - 1; i++)
  38649. that._pages[i].value(that._pages[i - 1].value() + 1)
  38650. }
  38651. else
  38652. for (i = 1; i <= pagesLength - 2; i++)
  38653. that._pages[pagesLength - 1 - i].value(that._pages[pagesLength - 1].value() - i);
  38654. if (morePage)
  38655. pages.push(morePage)
  38656. },
  38657. _nextPage: function(direction) {
  38658. var pageIndex = this.selectedPage && this.selectedPage.value(),
  38659. pageCount = this.option("pageCount");
  38660. if (utils.isDefined(pageIndex)) {
  38661. pageIndex = direction === "next" ? ++pageIndex : --pageIndex;
  38662. if (pageIndex > 0 && pageIndex <= pageCount)
  38663. this.option("pageIndex", pageIndex)
  38664. }
  38665. },
  38666. _renderPages: function(pages) {
  38667. var that = this,
  38668. $separator,
  38669. pageslength = pages.length,
  38670. clickPagesIndexAction = that._createAction(function(args) {
  38671. var e = args.jQueryEvent,
  38672. pageNumber = $(e.target).text(),
  38673. pageIndex = pageNumber === '>' ? that.option("pageCount") + 1 : Number(pageNumber);
  38674. that._testPageIndex = pageIndex;
  38675. that.option("pageIndex", pageIndex)
  38676. }),
  38677. page;
  38678. if (pageslength > 1) {
  38679. that._pageClickHandler = function(e) {
  38680. clickPagesIndexAction({jQueryEvent: e})
  38681. };
  38682. that.$pagesChooser.on(events.addNamespace("dxclick", that.Name + "Pages"), '.' + PAGER_PAGE_CLASS, that._pageClickHandler)
  38683. }
  38684. for (var i = 0; i < pageslength; i++) {
  38685. page = pages[i];
  38686. page.render(that.$pagesChooser, that.option('rtlEnabled'));
  38687. that.setAria({
  38688. role: "button",
  38689. label: "Page " + page.value()
  38690. }, page.element());
  38691. if (pages[i + 1] && pages[i + 1].value() - page.value() > 1) {
  38692. $separator = $("<div>. . .</div>").addClass(PAGER_PAGE_SEPARATOR_CLASS);
  38693. that.option('rtlEnabled') ? $separator.prependTo(that.$pagesChooser) : $separator.appendTo(that.$pagesChooser)
  38694. }
  38695. }
  38696. },
  38697. _renderPagesChooser: function() {
  38698. var that = this,
  38699. $element = that.element();
  38700. if (!$element)
  38701. return;
  38702. if (that._pages.length === 0) {
  38703. that.selectedPage = null;
  38704. return
  38705. }
  38706. if (utils.isDefined(that.$pagesChooser))
  38707. that.$pagesChooser.empty();
  38708. else
  38709. that.$pagesChooser = $('<div />').addClass(PAGER_PAGES_CLASS);
  38710. that._renderInfo();
  38711. that._renderNavigateButton("prev");
  38712. that._renderPages(that._pages);
  38713. that._renderNavigateButton("next");
  38714. if (!utils.isDefined(that.$pagesChooser[0].parentElement))
  38715. that.$pagesChooser.appendTo($element)
  38716. },
  38717. _renderPagesSizeChooser: function() {
  38718. var that = this,
  38719. i,
  38720. $pageSize,
  38721. currentPageSize = that.option("pageSize"),
  38722. pageSizes = that.option("pageSizes"),
  38723. showPageSizes = that.option("showPageSizes"),
  38724. pageSizeValue,
  38725. pagesSizesLength = pageSizes && pageSizes.length,
  38726. $element = that.element();
  38727. if (!$element)
  38728. return;
  38729. that._clickPagesSizeAction = that._createAction(function(args) {
  38730. var e = args.jQueryEvent;
  38731. pageSizeValue = parseInt($(e.target).text());
  38732. that._testPageSizeIndex = pageSizeValue;
  38733. that.option("pageSize", pageSizeValue)
  38734. });
  38735. if (utils.isDefined(that.pagesSizeChooserElement))
  38736. that.pagesSizeChooserElement.empty();
  38737. else
  38738. that.pagesSizeChooserElement = $('<div />').addClass(PAGER_PAGE_SIZES_CLASS).on(events.addNamespace("dxclick", that.Name + "PageSize"), '.' + PAGER_PAGE_SIZE_CLASS, function(e) {
  38739. that._clickPagesSizeAction({jQueryEvent: e})
  38740. });
  38741. if (!showPageSizes || !pagesSizesLength)
  38742. return;
  38743. that._testCurrentPageSize = currentPageSize;
  38744. for (i = 0; i < pagesSizesLength; i++) {
  38745. $pageSize = $('<div />').text(pageSizes[i]).addClass(PAGER_PAGE_SIZE_CLASS);
  38746. that.setAria({
  38747. role: "button",
  38748. label: "Display " + pageSizes[i] + " items on page"
  38749. }, $pageSize);
  38750. if (currentPageSize === pageSizes[i])
  38751. $pageSize.addClass(PAGER_SELECTION_CLASS);
  38752. that.option('rtlEnabled') ? that.pagesSizeChooserElement.prepend($pageSize) : that.pagesSizeChooserElement.append($pageSize)
  38753. }
  38754. if (!utils.isDefined(that.pagesSizeChooserElement[0].parentElement))
  38755. that.pagesSizeChooserElement.appendTo($element)
  38756. },
  38757. _renderInfo: function() {
  38758. var infoText = this.option("infoText");
  38759. if (this.option("showInfo") && utils.isDefined(infoText))
  38760. $("<div>").addClass(PAGER_INFO_CLASS).text(utils.stringFormat(infoText, this.selectedPage && this.selectedPage.value(), this.option("pageCount"))).appendTo(this.$pagesChooser)
  38761. },
  38762. _renderNavigateButton: function(direction) {
  38763. var that = this,
  38764. currentPageIndex,
  38765. clickAction = that._createAction(function(e) {
  38766. that._nextPage(direction)
  38767. }),
  38768. $button,
  38769. enabled;
  38770. if (that.option("showNavigationButtons")) {
  38771. currentPageIndex = that.option("pageIndex");
  38772. enabled = currentPageIndex > 1 && direction === "prev" || currentPageIndex < that.option("pageCount") && direction === "next";
  38773. $button = $("<div>").addClass(PAGER_NAVIGATE_BUTTON).addClass(!enabled ? PAGER_BUTTON_DISABLE_CLASS : "").on(events.addNamespace("dxclick", that.Name + "Pages"), function(e) {
  38774. clickAction({jQueryEvent: e})
  38775. });
  38776. that.setAria({
  38777. role: "button",
  38778. label: direction === "prev" ? "Previous page" : " Next page"
  38779. }, $button);
  38780. if (that.option("rtlEnabled")) {
  38781. $button.addClass(direction === "prev" ? PAGER_NEXT_BUTTON_CLASS : PAGER_PREV_BUTTON_CLASS);
  38782. $button.prependTo(this.$pagesChooser)
  38783. }
  38784. else {
  38785. $button.addClass(direction === "prev" ? PAGER_PREV_BUTTON_CLASS : PAGER_NEXT_BUTTON_CLASS);
  38786. $button.appendTo(this.$pagesChooser)
  38787. }
  38788. }
  38789. },
  38790. _render: function() {
  38791. this.callBase();
  38792. this._update();
  38793. this.element().addClass(PAGER_CLASS);
  38794. this._toggleVisibility(this.option("visible"));
  38795. this._renderPagesSizeChooser();
  38796. this._renderPagesChooser()
  38797. },
  38798. _update: function() {
  38799. var pageCount = this.option("pageCount"),
  38800. pageIndex = this.option("pageIndex");
  38801. this._processSelectedPage(this.option("maxPagesCount"), pageIndex, pageCount);
  38802. this._pages = this._getPages(this.selectedPage, pageCount);
  38803. this._selectPageByValue(pageIndex)
  38804. },
  38805. _optionChanged: function(args) {
  38806. switch (args.name) {
  38807. case"visible":
  38808. this._toggleVisibility(args.value);
  38809. break;
  38810. case"pageIndex":
  38811. var pageIndexChanged = this.option("pageIndexChanged");
  38812. if (pageIndexChanged)
  38813. pageIndexChanged(args.value);
  38814. this._update();
  38815. this._renderPagesChooser();
  38816. break;
  38817. case"maxPagesCount":
  38818. case"pageCount":
  38819. case"hasKnownLastPage":
  38820. case"showNavigationButtons":
  38821. this._update();
  38822. this._renderPagesChooser();
  38823. break;
  38824. case"pageSize":
  38825. var pageSizeChanged = this.option("pageSizeChanged");
  38826. if (pageSizeChanged)
  38827. pageSizeChanged(args.value);
  38828. this._renderPagesSizeChooser();
  38829. break;
  38830. case"pageSizes":
  38831. this._renderPagesSizeChooser();
  38832. break;
  38833. default:
  38834. this._invalidate()
  38835. }
  38836. },
  38837. _clean: function() {
  38838. this.$pagesChooser && this.$pagesChooser.off(events.addNamespace("dxclick", this.Name + "Pages"), '.' + PAGER_PAGE_CLASS, this._pageClickHandler)
  38839. },
  38840. getHeight: function() {
  38841. return this.option("visible") ? this.element().outerHeight() : 0
  38842. }
  38843. }));
  38844. ui.dxPager.__internals = {
  38845. PAGER_CLASS: PAGER_CLASS,
  38846. PAGER_PAGE_CLASS: PAGER_PAGE_CLASS,
  38847. PAGER_PAGES_CLASS: PAGER_PAGES_CLASS,
  38848. PAGER_SELECTION_CLASS: PAGER_SELECTION_CLASS,
  38849. PAGER_PAGE_SEPARATOR_CLASS: PAGER_PAGE_SEPARATOR_CLASS,
  38850. PAGER_PAGE_SIZES_CLASS: PAGER_PAGE_SIZES_CLASS,
  38851. PAGER_PAGE_SIZE_CLASS: PAGER_PAGE_SIZE_CLASS,
  38852. PAGER_NAVIGATE_BUTTON: PAGER_NAVIGATE_BUTTON,
  38853. PAGER_PREV_BUTTON_CLASS: PAGER_PREV_BUTTON_CLASS,
  38854. PAGER_NEXT_BUTTON_CLASS: PAGER_NEXT_BUTTON_CLASS,
  38855. PAGER_INFO_CLASS: PAGER_INFO_CLASS,
  38856. PAGER_BUTTON_DISABLE_CLASS: PAGER_BUTTON_DISABLE_CLASS
  38857. }
  38858. })(jQuery, DevExpress);
  38859. /*! Module widgets-web, file ui.colorView.js */
  38860. (function($, DX, undefined) {
  38861. var ui = DX.ui,
  38862. translator = DX.translator;
  38863. var COLOR_VIEW_CLASS = "dx-colorview",
  38864. COLOR_VIEW_CONTAINER_CLASS = "dx-colorview-container",
  38865. COLOR_VIEW_ROW_CLASS = "dx-colorview-container-row",
  38866. COLOR_VIEW_CELL_CLASS = "dx-colorview-container-cell",
  38867. COLOR_VIEW_PALETTE_CLASS = "dx-colorview-palette",
  38868. COLOR_VIEW_PALETTE_CELL_CLASS = "dx-colorview-palette-cell",
  38869. COLOR_VIEW_PALETTE_HANDLE_CLASS = "dx-colorview-palette-handle",
  38870. COLOR_VIEW_PALETTE_GRADIENT_CLASS = "dx-colorview-palette-gradient",
  38871. COLOR_VIEW_PALETTE_GRADIENT_WHITE_CLASS = "dx-colorview-palette-gradient-white",
  38872. COLOR_VIEW_PALETTE_GRADIENT_BLACK_CLASS = "dx-colorview-palette-gradient-black",
  38873. COLOR_VIEW_HUE_SCALE_CLASS = "dx-colorview-hue-scale",
  38874. COLOR_VIEW_HUE_SCALE_CELL_CLASS = "dx-colorview-hue-scale-cell",
  38875. COLOR_VIEW_HUE_SCALE_HANDLE_CLASS = "dx-colorview-hue-scale-handle",
  38876. COLOR_VIEW_HUE_SCALE_WRAPPER_CLASS = "dx-colorview-hue-scale-wrapper",
  38877. COLOR_VIEW_CONTROLS_CONTAINER_CLASS = "dx-colorview-controls-container",
  38878. COLOR_VIEW_RED_LABEL_CLASS = "dx-colorview-label-red",
  38879. COLOR_VIEW_GREEN_LABEL_CLASS = "dx-colorview-label-green",
  38880. COLOR_VIEW_BLUE_LABEL_CLASS = "dx-colorview-label-blue",
  38881. COLOR_VIEW_HEX_LABEL_CLASS = "dx-colorview-label-hex",
  38882. COLOR_VIEW_ALPHA_CHANNEL_SCALE_CLASS = "dx-colorview-alpha-channel-scale",
  38883. COLOR_VIEW_APLHA_CHANNEL_ROW_CLASS = "dx-colorview-alpha-channel-row",
  38884. COLOR_VIEW_ALPHA_CHANNEL_SCALE_WRAPPER_CLASS = "dx-colorview-alpha-channel-wrapper",
  38885. COLOR_VIEW_ALPHA_CHANNEL_LABEL_CLASS = "dx-colorview-alpha-channel-label",
  38886. COLOR_VIEW_ALPHA_CHANNEL_HANDLE_CLASS = "dx-colorview-alpha-channel-handle",
  38887. COLOR_VIEW_ALPHA_CHANNEL_CELL_CLASS = "dx-colorview-alpha-channel-cell",
  38888. COLOR_VIEW_ALPHA_CHANNEL_BORDER_CLASS = "dx-colorview-alpha-channel-border",
  38889. COLOR_VIEW_COLOR_PREVIEW = "dx-colorview-color-preview",
  38890. COLOR_VIEW_COLOR_PREVIEW_CONTAINER_CLASS = "dx-colorview-color-preview-container",
  38891. COLOR_VIEW_COLOR_PREVIEW_CONTAINER_INNER_CLASS = "dx-colorview-color-preview-container-inner",
  38892. COLOR_VIEW_COLOR_PREVIEW_COLOR_CURRENT = "dx-colorview-color-preview-color-current",
  38893. COLOR_VIEW_COLOR_PREVIEW_COLOR_NEW = "dx-colorview-color-preview-color-new";
  38894. DX.registerComponent("dxColorView", ui, ui.Editor.inherit({
  38895. _supportedKeys: function() {
  38896. var isRTL = this.option("rtlEnabled");
  38897. var that = this,
  38898. getHorizontalPaletteStep = function(e) {
  38899. var step = 100 / that._paletteWidth;
  38900. if (e.shiftKey)
  38901. step = step * that.option("keyStep");
  38902. step = step > 1 ? step : 1;
  38903. return Math.round(step)
  38904. },
  38905. updateHorizontalPaletteValue = function(step) {
  38906. var value = that._currentColor.hsv.s + step;
  38907. if (value > 100)
  38908. value = 100;
  38909. else if (value < 0)
  38910. value = 0;
  38911. that._currentColor.hsv.s = value;
  38912. updatePaletteValue()
  38913. },
  38914. getVerticalPaletteStep = function(e) {
  38915. var step = 100 / that._paletteHeight;
  38916. if (e.shiftKey)
  38917. step = step * that.option("keyStep");
  38918. step = step > 1 ? step : 1;
  38919. return Math.round(step)
  38920. },
  38921. updateVerticalPaletteValue = function(step) {
  38922. var value = that._currentColor.hsv.v + step;
  38923. if (value > 100)
  38924. value = 100;
  38925. else if (value < 0)
  38926. value = 0;
  38927. that._currentColor.hsv.v = value;
  38928. updatePaletteValue()
  38929. },
  38930. updatePaletteValue = function() {
  38931. that._placePaletteHandle();
  38932. that._updateColorFromHsv(that._currentColor.hsv.h, that._currentColor.hsv.s, that._currentColor.hsv.v)
  38933. },
  38934. getHueScaleStep = function(e) {
  38935. var step = 360 / (that._hueScaleWrapperHeight - that._hueScaleHandleHeight);
  38936. if (e.shiftKey)
  38937. step = step * that.option("keyStep");
  38938. step = step > 1 ? step : 1;
  38939. return step
  38940. },
  38941. updateHueScaleValue = function(step) {
  38942. that._currentColor.hsv.h += step;
  38943. that._placeHueScaleHandle();
  38944. var handleLocation = translator.locate(that._$hueScaleHandle);
  38945. that._updateColorHue(handleLocation.top + that._hueScaleHandleHeight / 2)
  38946. },
  38947. getAlphaScaleStep = function(e) {
  38948. var step = 1 / that._alphaChannelScaleWorkWidth;
  38949. if (e.shiftKey)
  38950. step = step * that.option("keyStep");
  38951. step = step > 0.01 ? step : 0.01;
  38952. step = isRTL ? -step : step;
  38953. return step
  38954. },
  38955. updateAlphaScaleValue = function(step) {
  38956. that._currentColor.a += step;
  38957. that._placeAlphaChannelHandle();
  38958. var handleLocation = translator.locate(that._$alphaChannelHandle);
  38959. that._calculateColorTransparenceByScaleWidth(handleLocation.left + that._alphaChannelHandleWidth / 2)
  38960. };
  38961. return $.extend(this.callBase(), {
  38962. upArrow: function(e) {
  38963. e.preventDefault();
  38964. e.stopPropagation();
  38965. if (e.ctrlKey) {
  38966. if (this._currentColor.hsv.h <= 360 && !this._isTopColorHue)
  38967. updateHueScaleValue(getHueScaleStep(e))
  38968. }
  38969. else if (this._currentColor.hsv.v < 100)
  38970. updateVerticalPaletteValue(getVerticalPaletteStep(e))
  38971. },
  38972. downArrow: function(e) {
  38973. e.preventDefault();
  38974. e.stopPropagation();
  38975. if (e.ctrlKey) {
  38976. if (this._currentColor.hsv.h >= 0) {
  38977. if (this._isTopColorHue)
  38978. this._currentColor.hsv.h = 360;
  38979. updateHueScaleValue(-getHueScaleStep(e))
  38980. }
  38981. }
  38982. else if (this._currentColor.hsv.v > 0)
  38983. updateVerticalPaletteValue(-getVerticalPaletteStep(e))
  38984. },
  38985. rightArrow: function(e) {
  38986. e.preventDefault();
  38987. e.stopPropagation();
  38988. if (e.ctrlKey) {
  38989. if (isRTL ? this._currentColor.a < 1 : this._currentColor.a > 0 && this.option("editAlphaChannel"))
  38990. updateAlphaScaleValue(-getAlphaScaleStep(e))
  38991. }
  38992. else if (this._currentColor.hsv.s < 100)
  38993. updateHorizontalPaletteValue(getHorizontalPaletteStep(e))
  38994. },
  38995. leftArrow: function(e) {
  38996. e.preventDefault();
  38997. e.stopPropagation();
  38998. if (e.ctrlKey) {
  38999. if (isRTL ? this._currentColor.a > 0 : this._currentColor.a < 1 && this.option("editAlphaChannel"))
  39000. updateAlphaScaleValue(getAlphaScaleStep(e))
  39001. }
  39002. else if (this._currentColor.hsv.s > 0)
  39003. updateHorizontalPaletteValue(-getHorizontalPaletteStep(e))
  39004. },
  39005. enter: function(e) {
  39006. if (this.option("applyValueMode") === "useButtons")
  39007. this.applyColor()
  39008. }
  39009. })
  39010. },
  39011. _setDefaultOptions: function() {
  39012. this.callBase();
  39013. this.option({
  39014. value: null,
  39015. editAlphaChannel: false,
  39016. applyValueMode: "useButtons",
  39017. keyStep: 1
  39018. })
  39019. },
  39020. _defaultOptionsRules: function() {
  39021. return this.callBase().concat([{
  39022. device: function(device) {
  39023. return DX.devices.real().generic && !DX.devices.isSimulator()
  39024. },
  39025. options: {focusStateEnabled: true}
  39026. }])
  39027. },
  39028. _init: function() {
  39029. this.callBase();
  39030. this._initColorAndOpacity()
  39031. },
  39032. _initColorAndOpacity: function() {
  39033. this._setCurrentColor(this.option("value"))
  39034. },
  39035. _setCurrentColor: function(value) {
  39036. value = value || "#000000";
  39037. var newColor = new DX.Color(value);
  39038. if (!newColor.colorIsInvalid) {
  39039. if (!this._currentColor || this._makeRgba(this._currentColor) !== this._makeRgba(newColor)) {
  39040. this._currentColor = newColor;
  39041. if (this._$currentColor)
  39042. this._makeTransparentBackground(this._$currentColor, newColor)
  39043. }
  39044. }
  39045. else
  39046. this.option("value", this._currentColor.baseColor)
  39047. },
  39048. _render: function() {
  39049. this.callBase();
  39050. this.element().addClass(COLOR_VIEW_CLASS);
  39051. this._renderColorPickerContainer()
  39052. },
  39053. _enterKeyHandler: function() {
  39054. if (this.option("applyValueMode") === "useButtons")
  39055. this.applyColor()
  39056. },
  39057. _makeTransparentBackground: function($el, color) {
  39058. if (!(color instanceof DX.Color))
  39059. color = new DX.Color(color);
  39060. if (DX.browser.msie && DX.browser.version === "8.0")
  39061. $el.css({
  39062. background: color.toHex(),
  39063. filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=" + color.a * 100 + ")"
  39064. });
  39065. else
  39066. $el.css("backgroundColor", this._makeRgba(color))
  39067. },
  39068. _makeRgba: function(color) {
  39069. if (!(color instanceof DX.Color))
  39070. color = new DX.Color(color);
  39071. return "rgba(" + [color.r, color.g, color.b, color.a].join(", ") + ")"
  39072. },
  39073. _renderValue: function() {
  39074. this.callBase(this.option("editAlphaChannel") ? this._makeRgba(this._currentColor) : this.option("value"))
  39075. },
  39076. _renderColorPickerContainer: function() {
  39077. var $parent = this.element();
  39078. this._$colorPickerContainer = $("<div>", {
  39079. "class": COLOR_VIEW_CONTAINER_CLASS,
  39080. appendTo: $parent
  39081. });
  39082. this._renderHtmlRows();
  39083. this._renderPalette();
  39084. this._renderHueScale();
  39085. this._renderControlsContainer();
  39086. this._renderControls();
  39087. this._renderAlphaChannelElements()
  39088. },
  39089. _renderHtmlRows: function(updatedOption) {
  39090. var $renderedRows = this._$colorPickerContainer.find("." + COLOR_VIEW_ROW_CLASS),
  39091. renderedRowsCount = $renderedRows.length,
  39092. rowCount = this._calculateRowsCount(),
  39093. delta = renderedRowsCount - rowCount;
  39094. if (delta > 0) {
  39095. var index = this._calculateRemovedHtmlRowIndex(renderedRowsCount, updatedOption);
  39096. $renderedRows.eq(index).remove()
  39097. }
  39098. if (delta < 0) {
  39099. delta = Math.abs(delta);
  39100. var rows = [];
  39101. for (var i = 0; i < delta; i++)
  39102. rows.push($("<div>", {"class": COLOR_VIEW_ROW_CLASS}));
  39103. if (renderedRowsCount) {
  39104. var previousRowIndex = this._calculateHtmlRowIndex(renderedRowsCount, updatedOption);
  39105. $renderedRows.eq(previousRowIndex).after(rows)
  39106. }
  39107. else
  39108. this._$colorPickerContainer.append(rows)
  39109. }
  39110. },
  39111. _renderHtmlCellInsideRow: function(rowSelector, $rowParent, additionalClass) {
  39112. return $("<div>", {
  39113. "class": COLOR_VIEW_CELL_CLASS,
  39114. addClass: additionalClass,
  39115. appendTo: $rowParent.find("." + COLOR_VIEW_ROW_CLASS + rowSelector)
  39116. })
  39117. },
  39118. _calculateRowsCount: function() {
  39119. if (this.option("editAlphaChannel"))
  39120. return this.option("applyValueMode") === "instantly" ? 2 : 3;
  39121. return this.option("applyValueMode") === "instantly" ? 1 : 2
  39122. },
  39123. _calculateRemovedHtmlRowIndex: function(renderedRowsCount, updatedOption) {
  39124. var index = -1;
  39125. if (renderedRowsCount === 3) {
  39126. if (updatedOption === "editAlphaChannel")
  39127. index = -2;
  39128. if (updatedOption === "applyValueMode")
  39129. index = -1
  39130. }
  39131. return index
  39132. },
  39133. _calculateHtmlRowIndex: function(renderedRowsCount, updatedOption) {
  39134. var index = 0;
  39135. if (renderedRowsCount === 2)
  39136. if (updatedOption === "applyValueMode")
  39137. index = 1;
  39138. return index
  39139. },
  39140. _renderPalette: function() {
  39141. var $paletteCell = this._renderHtmlCellInsideRow(":first", this._$colorPickerContainer, COLOR_VIEW_PALETTE_CELL_CLASS),
  39142. $paletteGradientWhite = $("<div>", {"class": [COLOR_VIEW_PALETTE_GRADIENT_CLASS, COLOR_VIEW_PALETTE_GRADIENT_WHITE_CLASS].join(" ")}),
  39143. $paletteGradientBlack = $("<div>", {"class": [COLOR_VIEW_PALETTE_GRADIENT_CLASS, COLOR_VIEW_PALETTE_GRADIENT_BLACK_CLASS].join(" ")});
  39144. this._$palette = $("<div>", {
  39145. "class": COLOR_VIEW_PALETTE_CLASS,
  39146. css: {backgroundColor: this._currentColor.getPureColor().toHex()},
  39147. appendTo: $paletteCell
  39148. });
  39149. this._paletteHeight = this._$palette.height();
  39150. this._paletteWidth = this._$palette.width();
  39151. this._renderPaletteHandle();
  39152. this._$palette.append([$paletteGradientWhite, $paletteGradientBlack])
  39153. },
  39154. _renderPaletteHandle: function() {
  39155. this._createComponent(this._$paletteHandle = $("<div>", {
  39156. "class": COLOR_VIEW_PALETTE_HANDLE_CLASS,
  39157. appendTo: this._$palette
  39158. }), "dxDraggable", {
  39159. area: this._$palette,
  39160. allowMoveByClick: true,
  39161. boundOffset: $.proxy(function() {
  39162. return -this._paletteHandleHeight / 2
  39163. }, this),
  39164. onDrag: $.proxy(function(e) {
  39165. var paletteHandlePosition = translator.locate(this._$paletteHandle);
  39166. this._updateByDrag = true;
  39167. this._updateColorFromHsv(this._currentColor.hsv.h, this._calculateColorSaturation(paletteHandlePosition), this._calculateColorValue(paletteHandlePosition))
  39168. }, this)
  39169. });
  39170. this._paletteHandleWidth = this._$paletteHandle.width();
  39171. this._paletteHandleHeight = this._$paletteHandle.height();
  39172. this._placePaletteHandle()
  39173. },
  39174. _placePaletteHandle: function() {
  39175. translator.move(this._$paletteHandle, {
  39176. left: Math.round(this._paletteWidth * this._currentColor.hsv.s / 100 - this._paletteHandleWidth / 2),
  39177. top: Math.round(this._paletteHeight - this._paletteHeight * this._currentColor.hsv.v / 100 - this._paletteHandleHeight / 2)
  39178. })
  39179. },
  39180. _calculateColorValue: function(paletteHandlePosition) {
  39181. var value = Math.floor(paletteHandlePosition.top + this._paletteHandleHeight / 2);
  39182. return 100 - Math.round(value * 100 / this._paletteHeight)
  39183. },
  39184. _calculateColorSaturation: function(paletteHandlePosition) {
  39185. var saturation = Math.floor(paletteHandlePosition.left + this._paletteHandleWidth / 2);
  39186. return Math.round(saturation * 100 / this._paletteWidth)
  39187. },
  39188. _updateColorFromHsv: function(hue, saturation, value) {
  39189. var a = this._currentColor.a;
  39190. this._currentColor = new DX.Color("hsv(" + [hue, saturation, value].join(",") + ")");
  39191. this._currentColor.a = a;
  39192. this._updateColorParamsAndColorPreview();
  39193. if (this.option("applyValueMode") === "instantly")
  39194. this.applyColor()
  39195. },
  39196. _renderHueScale: function() {
  39197. var $hueScaleCell = this._renderHtmlCellInsideRow(":first", this._$colorPickerContainer, COLOR_VIEW_HUE_SCALE_CELL_CLASS);
  39198. this._$hueScaleWrapper = $("<div>", {
  39199. "class": COLOR_VIEW_HUE_SCALE_WRAPPER_CLASS,
  39200. appendTo: $hueScaleCell
  39201. });
  39202. this._$hueScale = $("<div>", {
  39203. "class": COLOR_VIEW_HUE_SCALE_CLASS,
  39204. appendTo: this._$hueScaleWrapper
  39205. });
  39206. this._hueScaleHeight = this._$hueScale.height();
  39207. this._hueScaleWrapperHeight = this._$hueScaleWrapper.outerHeight();
  39208. this._renderHueScaleHandle()
  39209. },
  39210. _renderHueScaleHandle: function() {
  39211. this._createComponent(this._$hueScaleHandle = $("<div>", {
  39212. "class": COLOR_VIEW_HUE_SCALE_HANDLE_CLASS,
  39213. appendTo: this._$hueScaleWrapper
  39214. }), "dxDraggable", {
  39215. area: this._$hueScaleWrapper,
  39216. allowMoveByClick: true,
  39217. direction: "vertical",
  39218. onDrag: $.proxy(function(e) {
  39219. this._updateByDrag = true;
  39220. this._updateColorHue(translator.locate(this._$hueScaleHandle).top + this._hueScaleHandleHeight / 2)
  39221. }, this)
  39222. });
  39223. this._hueScaleHandleHeight = this._$hueScaleHandle.height();
  39224. this._placeHueScaleHandle()
  39225. },
  39226. _placeHueScaleHandle: function() {
  39227. var hueScaleHeight = this._hueScaleWrapperHeight,
  39228. handleHeight = this._hueScaleHandleHeight,
  39229. top = (hueScaleHeight - handleHeight) * (360 - this._currentColor.hsv.h) / 360;
  39230. if (hueScaleHeight < top + handleHeight)
  39231. top = hueScaleHeight - handleHeight;
  39232. if (top < 0)
  39233. top = 0;
  39234. translator.move(this._$hueScaleHandle, {top: Math.round(top)})
  39235. },
  39236. _updateColorHue: function(handlePosition) {
  39237. var hue = 360 - Math.round((handlePosition - this._hueScaleHandleHeight / 2) * 360 / (this._hueScaleWrapperHeight - this._hueScaleHandleHeight)),
  39238. saturation = this._currentColor.hsv.s,
  39239. value = this._currentColor.hsv.v;
  39240. this._isTopColorHue = false;
  39241. hue = hue < 0 ? 0 : hue;
  39242. if (hue >= 360) {
  39243. this._isTopColorHue = true;
  39244. hue = 0
  39245. }
  39246. this._updateColorFromHsv(hue, saturation, value);
  39247. this._$palette.css("backgroundColor", this._currentColor.getPureColor().toHex())
  39248. },
  39249. _renderControlsContainer: function() {
  39250. var $controlsContainerCell = this._renderHtmlCellInsideRow(":first", this._$colorPickerContainer);
  39251. this._$controlsContainer = $("<div>", {
  39252. "class": COLOR_VIEW_CONTROLS_CONTAINER_CLASS,
  39253. appendTo: $controlsContainerCell
  39254. })
  39255. },
  39256. _renderControls: function() {
  39257. this._renderColorsPreview();
  39258. this._renderRgbInputs();
  39259. this._renderHexInput()
  39260. },
  39261. _renderColorsPreview: function() {
  39262. var $colorsPreviewContainer = $("<div>", {
  39263. "class": COLOR_VIEW_COLOR_PREVIEW_CONTAINER_CLASS,
  39264. appendTo: this._$controlsContainer
  39265. }),
  39266. $colorsPreviewContainerInner = $("<div>", {
  39267. "class": COLOR_VIEW_COLOR_PREVIEW_CONTAINER_INNER_CLASS,
  39268. appendTo: $colorsPreviewContainer
  39269. });
  39270. this._$currentColor = $("<div>", {"class": [COLOR_VIEW_COLOR_PREVIEW, COLOR_VIEW_COLOR_PREVIEW_COLOR_CURRENT].join(" ")});
  39271. this._$newColor = $("<div>", {"class": [COLOR_VIEW_COLOR_PREVIEW, COLOR_VIEW_COLOR_PREVIEW_COLOR_NEW].join(" ")});
  39272. this._makeTransparentBackground(this._$currentColor, this._currentColor);
  39273. this._makeTransparentBackground(this._$newColor, this._currentColor);
  39274. $colorsPreviewContainerInner.append([this._$currentColor, this._$newColor])
  39275. },
  39276. _renderAlphaChannelElements: function() {
  39277. if (this.option("editAlphaChannel")) {
  39278. this._$colorPickerContainer.find("." + COLOR_VIEW_ROW_CLASS).eq(1).addClass(COLOR_VIEW_APLHA_CHANNEL_ROW_CLASS);
  39279. this._renderAlphaChannelScale();
  39280. this._renderAlphaChannelInput()
  39281. }
  39282. },
  39283. _renderRgbInputs: function() {
  39284. this._rgbInputsWithLabels = [this._renderEditorWithLabel({
  39285. editorType: "dxNumberBox",
  39286. value: this._currentColor.r,
  39287. onValueChanged: $.proxy(this._updateColor, this, false),
  39288. labelText: "R",
  39289. labelAriaText: Globalize.localize("dxColorView-ariaRed"),
  39290. labelClass: COLOR_VIEW_RED_LABEL_CLASS
  39291. }), this._renderEditorWithLabel({
  39292. editorType: "dxNumberBox",
  39293. value: this._currentColor.g,
  39294. onValueChanged: $.proxy(this._updateColor, this, false),
  39295. labelText: "G",
  39296. labelAriaText: Globalize.localize("dxColorView-ariaGreen"),
  39297. labelClass: COLOR_VIEW_GREEN_LABEL_CLASS
  39298. }), this._renderEditorWithLabel({
  39299. editorType: "dxNumberBox",
  39300. value: this._currentColor.b,
  39301. onValueChanged: $.proxy(this._updateColor, this, false),
  39302. labelText: "B",
  39303. labelAriaText: Globalize.localize("dxColorView-ariaBlue"),
  39304. labelClass: COLOR_VIEW_BLUE_LABEL_CLASS
  39305. })];
  39306. this._$controlsContainer.append(this._rgbInputsWithLabels);
  39307. this._rgbInputs = [this._rgbInputsWithLabels[0].find(".dx-numberbox").dxNumberBox("instance"), this._rgbInputsWithLabels[1].find(".dx-numberbox").dxNumberBox("instance"), this._rgbInputsWithLabels[2].find(".dx-numberbox").dxNumberBox("instance")];
  39308. $.each(this._rgbInputs, $.proxy(function(_, instance) {
  39309. this._attachEnterKeyHandler(instance)
  39310. }, this))
  39311. },
  39312. _renderEditorWithLabel: function(options) {
  39313. var $editor = $("<div>"),
  39314. $label = $("<label>", {
  39315. "class": options.labelClass,
  39316. text: options.labelText + ":",
  39317. append: $editor
  39318. }).off("dxclick").on("dxclick", function(e) {
  39319. e.preventDefault()
  39320. }),
  39321. editorType = options.editorType,
  39322. editorOptions = {
  39323. value: options.value,
  39324. onValueChanged: options.onValueChanged
  39325. };
  39326. if (editorType === "dxNumberBox") {
  39327. editorOptions.min = options.min || 0;
  39328. editorOptions.max = options.max || 255;
  39329. editorOptions.step = options.step || 1
  39330. }
  39331. $editor[editorType](editorOptions);
  39332. this.setAria("label", options.labelAriaText, $editor);
  39333. return $label
  39334. },
  39335. _renderHexInput: function() {
  39336. this._hexInput = this._renderEditorWithLabel({
  39337. editorType: "dxTextBox",
  39338. value: this._currentColor.toHex().replace("#", ""),
  39339. onValueChanged: $.proxy(this._updateColor, this, true),
  39340. labelClass: COLOR_VIEW_HEX_LABEL_CLASS,
  39341. labelText: "#",
  39342. labelAriaText: Globalize.localize("dxColorView-ariaHex")
  39343. }).appendTo(this._$controlsContainer).find(".dx-textbox").dxTextBox("instance");
  39344. this._attachEnterKeyHandler(this._hexInput)
  39345. },
  39346. _attachEnterKeyHandler: function(instance) {
  39347. instance.registerKeyHandler("enter", $.proxy(function(e) {
  39348. this._enterKeyHandler(e)
  39349. }, this))
  39350. },
  39351. _renderAlphaChannelScale: function() {
  39352. var $alphaChannelScaleCell = this._renderHtmlCellInsideRow(":eq(1)", this._$colorPickerContainer, COLOR_VIEW_ALPHA_CHANNEL_CELL_CLASS),
  39353. $alphaChannelBorder = $("<div>", {
  39354. "class": COLOR_VIEW_ALPHA_CHANNEL_BORDER_CLASS,
  39355. appendTo: $alphaChannelScaleCell
  39356. }),
  39357. $alphaChannelScaleWrapper = $("<div>", {
  39358. "class": COLOR_VIEW_ALPHA_CHANNEL_SCALE_WRAPPER_CLASS,
  39359. appendTo: $alphaChannelBorder
  39360. });
  39361. this._$alphaChannelScale = $("<div>", {
  39362. "class": COLOR_VIEW_ALPHA_CHANNEL_SCALE_CLASS,
  39363. appendTo: $alphaChannelScaleWrapper
  39364. });
  39365. this._makeCSSLinearGradient(this._$alphaChannelScale);
  39366. this._renderAlphaChannelHandle($alphaChannelScaleCell)
  39367. },
  39368. _makeCSSLinearGradient: function($el) {
  39369. var color = this._currentColor,
  39370. colorAsRgb = [color.r, color.g, color.b].join(","),
  39371. colorAsHex = color.toHex().replace("#", "");
  39372. var combineGradientString = function(colorAsRgb, colorAsHex) {
  39373. var rtlEnabled = this.option("rtlEnabled"),
  39374. startColor = "rgba(" + colorAsRgb + ", " + (rtlEnabled ? "1" : "0") + ")",
  39375. finishColor = "rgba(" + colorAsRgb + ", " + (rtlEnabled ? "0" : "1") + ")",
  39376. startColorIE = "'#" + (rtlEnabled ? "00" : "") + colorAsHex + "'",
  39377. finishColorIE = "'#" + (rtlEnabled ? "" : "00") + colorAsHex + "'";
  39378. return ["background-image: -webkit-linear-gradient(180deg, " + startColor + ", " + finishColor + ")", "background-image: -moz-linear-gradient(-90deg, " + startColor + ", " + finishColor + ")", "background-image: -ms-linear-gradient(-90deg, " + startColor + ", " + finishColor + ")", "background-image: -o-linear-gradient(-90deg, " + startColor + ", " + finishColor + ")", "background-image: linear-gradient(-90deg, " + startColor + ", " + finishColor + ")", "filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr=" + startColorIE + ", endColorstr=" + finishColorIE + ")", "-ms-filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr=" + startColorIE + ", endColorstr=" + finishColorIE + ")"].join(";")
  39379. };
  39380. $el.attr("style", combineGradientString.call(this, colorAsRgb, colorAsHex))
  39381. },
  39382. _renderAlphaChannelInput: function() {
  39383. var that = this,
  39384. $alphaChannelInputCell = this._renderHtmlCellInsideRow(":eq(1)", this._$colorPickerContainer);
  39385. that._alphaChannelInput = this._renderEditorWithLabel({
  39386. editorType: "dxNumberBox",
  39387. value: this._currentColor.a,
  39388. max: 1,
  39389. step: 0.1,
  39390. onValueChanged: function(e) {
  39391. var value = e.value;
  39392. value = that._currentColor.isValidAlpha(value) ? value : that._currentColor.a;
  39393. that._updateColorTransparence(value);
  39394. that._placeAlphaChannelHandle()
  39395. },
  39396. labelClass: COLOR_VIEW_ALPHA_CHANNEL_LABEL_CLASS,
  39397. labelText: "Alpha",
  39398. labelAriaText: Globalize.localize("dxColorView-ariaAlpha")
  39399. }).appendTo($alphaChannelInputCell).find(".dx-numberbox").dxNumberBox("instance");
  39400. this._attachEnterKeyHandler(that._alphaChannelInput)
  39401. },
  39402. _updateColorTransparence: function(transparence) {
  39403. this._currentColor.a = transparence;
  39404. this._makeTransparentBackground(this._$newColor, this._currentColor);
  39405. if (this.option("applyValueMode") === "instantly")
  39406. this.applyColor()
  39407. },
  39408. _renderAlphaChannelHandle: function($parent) {
  39409. this._createComponent(this._$alphaChannelHandle = $("<div>", {
  39410. "class": COLOR_VIEW_ALPHA_CHANNEL_HANDLE_CLASS,
  39411. appendTo: $parent
  39412. }), "dxDraggable", {
  39413. area: $parent,
  39414. allowMoveByClick: true,
  39415. direction: "horizontal",
  39416. onDrag: $.proxy(function(e) {
  39417. this._updateByDrag = true;
  39418. var $alphaChannelHandle = this._$alphaChannelHandle,
  39419. alphaChannelHandlePosition = translator.locate($alphaChannelHandle).left + this._alphaChannelHandleWidth / 2;
  39420. this._calculateColorTransparenceByScaleWidth(alphaChannelHandlePosition)
  39421. }, this)
  39422. });
  39423. this._alphaChannelHandleWidth = this._$alphaChannelHandle.width();
  39424. this._alphaChannelScaleWorkWidth = $parent.width() - this._alphaChannelHandleWidth;
  39425. this._placeAlphaChannelHandle()
  39426. },
  39427. _calculateColorTransparenceByScaleWidth: function(handlePosition) {
  39428. var transparence = (handlePosition - this._alphaChannelHandleWidth / 2) / this._alphaChannelScaleWorkWidth,
  39429. rtlEnabled = this.option("rtlEnabled");
  39430. transparence = rtlEnabled ? transparence : 1 - transparence;
  39431. if (handlePosition >= this._alphaChannelScaleWorkWidth + this._alphaChannelHandleWidth / 2)
  39432. transparence = rtlEnabled ? 1 : 0;
  39433. else if (transparence < 1)
  39434. transparence = transparence.toFixed(2);
  39435. this._alphaChannelInput.option("value", transparence)
  39436. },
  39437. _placeAlphaChannelHandle: function() {
  39438. var left = this._alphaChannelScaleWorkWidth * (1 - this._currentColor.a);
  39439. if (left < 0)
  39440. left = 0;
  39441. if (this._alphaChannelScaleWorkWidth < left)
  39442. left = this._alphaChannelScaleWorkWidth;
  39443. translator.move(this._$alphaChannelHandle, {left: this.option("rtlEnabled") ? this._alphaChannelScaleWorkWidth - left : left})
  39444. },
  39445. applyColor: function() {
  39446. var colorValue = this.option("editAlphaChannel") ? this._makeRgba(this._currentColor) : this._currentColor.toHex();
  39447. this._makeTransparentBackground(this._$currentColor, this._currentColor);
  39448. this.option("value", colorValue)
  39449. },
  39450. cancelColor: function() {
  39451. this._initColorAndOpacity();
  39452. this._refreshMarkup()
  39453. },
  39454. _updateColor: function(isHex) {
  39455. var rgba,
  39456. newColor;
  39457. if (isHex)
  39458. newColor = this._validateHex("#" + this._hexInput.option("value"));
  39459. else {
  39460. rgba = this._validateRgb();
  39461. if (this._alphaChannelInput) {
  39462. rgba.push(this._alphaChannelInput.option("value"));
  39463. newColor = "rgba(" + rgba.join(", ") + ")"
  39464. }
  39465. else
  39466. newColor = "rgb(" + rgba.join(", ") + ")"
  39467. }
  39468. if (!this._suppressEditorsValueUpdating) {
  39469. this._currentColor = new DX.Color(newColor);
  39470. this._refreshMarkup();
  39471. if (this.option("applyValueMode") === "instantly")
  39472. this.applyColor()
  39473. }
  39474. },
  39475. _validateHex: function(hex) {
  39476. return this._currentColor.isValidHex(hex) ? hex : this._currentColor.toHex()
  39477. },
  39478. _validateRgb: function() {
  39479. var r = this._rgbInputs[0].option("value"),
  39480. g = this._rgbInputs[1].option("value"),
  39481. b = this._rgbInputs[2].option("value");
  39482. if (!this._currentColor.isValidRGB(r, g, b)) {
  39483. r = this._currentColor.r;
  39484. g = this._currentColor.g;
  39485. b = this._currentColor.b
  39486. }
  39487. return [r, g, b]
  39488. },
  39489. _refreshMarkup: function() {
  39490. this._placeHueScaleHandle();
  39491. this._placePaletteHandle();
  39492. this._updateColorParamsAndColorPreview();
  39493. this._$palette.css("backgroundColor", this._currentColor.getPureColor().toHex());
  39494. if (this._$alphaChannelHandle) {
  39495. this._updateColorTransparence(this._currentColor.a);
  39496. this._placeAlphaChannelHandle()
  39497. }
  39498. },
  39499. _updateColorParamsAndColorPreview: function() {
  39500. this._suppressEditorsValueUpdating = true;
  39501. this._hexInput.option("value", this._currentColor.toHex().replace("#", ""));
  39502. this._rgbInputs[0].option("value", this._currentColor.r);
  39503. this._rgbInputs[1].option("value", this._currentColor.g);
  39504. this._rgbInputs[2].option("value", this._currentColor.b);
  39505. this._suppressEditorsValueUpdating = false;
  39506. this._makeTransparentBackground(this._$newColor, this._currentColor);
  39507. if (this.option("editAlphaChannel")) {
  39508. this._makeCSSLinearGradient.call(this, this._$alphaChannelScale);
  39509. this._alphaChannelInput.option("value", this._currentColor.a)
  39510. }
  39511. },
  39512. _optionChanged: function(args) {
  39513. var value = args.value;
  39514. switch (args.name) {
  39515. case"value":
  39516. this._setCurrentColor(value);
  39517. if (!this._updateByDrag)
  39518. this._refreshMarkup();
  39519. this._updateByDrag = false;
  39520. this.callBase(args);
  39521. break;
  39522. case"editAlphaChannel":
  39523. if (this._$colorPickerContainer) {
  39524. this._renderHtmlRows("editAlphaChannel");
  39525. this._renderAlphaChannelElements()
  39526. }
  39527. break;
  39528. case"applyValueMode":
  39529. if (this._$colorPickerContainer)
  39530. this._renderHtmlRows("applyValueMode");
  39531. break;
  39532. case"keyStep":
  39533. break;
  39534. default:
  39535. this.callBase(args)
  39536. }
  39537. }
  39538. }))
  39539. })(jQuery, DevExpress);
  39540. /*! Module widgets-web, file ui.colorBox.js */
  39541. (function($, DX, undefined) {
  39542. var ui = DX.ui;
  39543. var COLOR_BOX_CLASS = "dx-colorbox",
  39544. COLOR_BOX_INPUT_CLASS = COLOR_BOX_CLASS + "-input",
  39545. COLOR_BOX_INPUT_CONTAINER_CLASS = COLOR_BOX_INPUT_CLASS + "-container",
  39546. COLOR_BOX_COLOR_RESULT_PREVIEW_CLASS = COLOR_BOX_CLASS + "-color-result-preview",
  39547. COLOR_BOX_COLOR_IS_NOT_DEFINED = COLOR_BOX_CLASS + "-color-is-not-defined",
  39548. COLOR_BOX_OVERLAY_CLASS = COLOR_BOX_CLASS + "-overlay",
  39549. COLOR_BOX_CONTAINER_CELL_CLASS = "dx-colorview-container-cell",
  39550. COLOR_BOX_BUTTON_CELL_CLASS = "dx-colorview-button-cell",
  39551. COLOR_BOX_BUTTONS_CONTAINER_CLASS = "dx-colorview-buttons-container",
  39552. COLOR_BOX_APPLY_BUTTON_CLASS = "dx-colorview-apply-button",
  39553. COLOR_BOX_CANCEL_BUTTON_CLASS = "dx-colorview-cancel-button";
  39554. var colorEditorPrototype = ui.dxColorView.prototype,
  39555. colorUtils = {
  39556. makeTransparentBackground: $.proxy(colorEditorPrototype._makeTransparentBackground, colorEditorPrototype),
  39557. makeRgba: $.proxy(colorEditorPrototype._makeRgba, colorEditorPrototype)
  39558. };
  39559. DX.registerComponent("dxColorBox", ui, ui.dxDropDownEditor.inherit({
  39560. _supportedKeys: function() {
  39561. var arrowHandler = function(e) {
  39562. e.stopPropagation();
  39563. if (this.option("opened")) {
  39564. e.preventDefault();
  39565. return true
  39566. }
  39567. };
  39568. var upArrowHandler = function(e) {
  39569. if (!this.option("opened")) {
  39570. e.preventDefault();
  39571. return false
  39572. }
  39573. if (e.altKey) {
  39574. this.close();
  39575. return false
  39576. }
  39577. return true
  39578. };
  39579. var downArrowHandler = function(e) {
  39580. if (!this.option("opened") && !e.altKey) {
  39581. e.preventDefault();
  39582. return false
  39583. }
  39584. if (!this.option("opened") && e.altKey) {
  39585. this._validatedOpening();
  39586. return false
  39587. }
  39588. return true
  39589. };
  39590. return $.extend(this.callBase(), {
  39591. tab: function(e) {
  39592. if (this.option("opened")) {
  39593. e.preventDefault();
  39594. this._colorView._rgbInputs[0].focus()
  39595. }
  39596. },
  39597. enter: this._enterKeyHandler,
  39598. leftArrow: arrowHandler,
  39599. rightArrow: arrowHandler,
  39600. upArrow: upArrowHandler,
  39601. downArrow: downArrowHandler
  39602. })
  39603. },
  39604. _setDefaultOptions: function() {
  39605. this.callBase();
  39606. this.option({
  39607. editAlphaChannel: false,
  39608. applyButtonText: Globalize.localize("OK"),
  39609. cancelButtonText: Globalize.localize("Cancel"),
  39610. applyValueMode: "useButtons",
  39611. keyStep: 1,
  39612. onApplyButtonClick: null,
  39613. onCancelButtonClick: null,
  39614. buttonsLocation: "bottom after"
  39615. })
  39616. },
  39617. _popupConfig: function() {
  39618. return $.extend(this.callBase(), {
  39619. height: "auto",
  39620. width: ""
  39621. })
  39622. },
  39623. _contentReadyHandler: function() {
  39624. this._createColorView();
  39625. this._addPopupBottomClasses()
  39626. },
  39627. _addPopupBottomClasses: function() {
  39628. var $popupBottom = this._popup.bottomToolbar();
  39629. if ($popupBottom) {
  39630. $popupBottom.addClass(COLOR_BOX_CONTAINER_CELL_CLASS).addClass(COLOR_BOX_BUTTON_CELL_CLASS).find(".dx-toolbar-items-container").addClass(COLOR_BOX_BUTTONS_CONTAINER_CLASS);
  39631. $popupBottom.find(".dx-popup-done").addClass(COLOR_BOX_APPLY_BUTTON_CLASS);
  39632. $popupBottom.find(".dx-popup-cancel").addClass(COLOR_BOX_CANCEL_BUTTON_CLASS)
  39633. }
  39634. },
  39635. _createColorView: function() {
  39636. this._popup.overlayContent().addClass(COLOR_BOX_OVERLAY_CLASS);
  39637. var $colorView = $("<div>").appendTo(this._popup.content());
  39638. this._colorView = this._createComponent($colorView, "dxColorView", this._colorViewConfig());
  39639. this._colorView._enterKeyHandler = $.proxy(this._enterKeyHandler, this);
  39640. $colorView.on("focus", $.proxy(function() {
  39641. this.focus()
  39642. }, this))
  39643. },
  39644. _colorViewConfig: function() {
  39645. var that = this,
  39646. isAttachKeyboardEvent = that.option("focusStateEnabled") && !that.option("disabled");
  39647. return {
  39648. value: that.option("value"),
  39649. editAlphaChannel: that.option("editAlphaChannel"),
  39650. applyValueMode: that.option("applyValueMode"),
  39651. focusStateEnabled: that.option("focusStateEnabled"),
  39652. onValueChanged: function(args) {
  39653. var value = args.value;
  39654. that.option("value", value);
  39655. if (value)
  39656. colorUtils.makeTransparentBackground(that._$colorResultPreview, value)
  39657. },
  39658. _keyboardProcessor: isAttachKeyboardEvent ? that._keyboardProcessor.attachChildProcessor() : null
  39659. }
  39660. },
  39661. _enterKeyHandler: function(e) {
  39662. var newValue = this._input().val(),
  39663. oldValue = this.option("editAlphaChannel") ? colorUtils.makeRgba(this.option("value")) : this.option("value");
  39664. if (newValue && newValue !== oldValue) {
  39665. this._applyColorFromInput(newValue);
  39666. this.option("value", this.option("editAlphaChannel") ? colorUtils.makeRgba(newValue) : newValue);
  39667. return false
  39668. }
  39669. if (this.option("applyValueMode") === "useButtons")
  39670. this._colorView.applyColor();
  39671. if (this.option("opened")) {
  39672. e.preventDefault();
  39673. this.close()
  39674. }
  39675. return false
  39676. },
  39677. _applyButtonHandler: function() {
  39678. this._colorView.applyColor();
  39679. if ($.isFunction(this.option("onApplyButtonClick")))
  39680. this.option("onApplyButtonClick")();
  39681. this.callBase()
  39682. },
  39683. _cancelButtonHandler: function() {
  39684. this._colorView.cancelColor();
  39685. if ($.isFunction(this.option("onCancelButtonClick")))
  39686. this.option("onCancelButtonClick")();
  39687. this.callBase()
  39688. },
  39689. _attachChildKeyboardEvents: function() {
  39690. var child = this._keyboardProcessor.attachChildProcessor();
  39691. if (this._colorView) {
  39692. this._colorView.option("_keyboardProcessor", child);
  39693. return
  39694. }
  39695. },
  39696. _init: function() {
  39697. this.callBase()
  39698. },
  39699. _render: function() {
  39700. this.callBase();
  39701. this.element().addClass(COLOR_BOX_CLASS)
  39702. },
  39703. _renderInput: function() {
  39704. this.callBase();
  39705. this.element().wrapInner($("<div/>").addClass(COLOR_BOX_INPUT_CONTAINER_CLASS));
  39706. this._$colorBoxInputContainer = this.element().children().eq(0);
  39707. this._$colorResultPreview = $("<div>", {
  39708. "class": COLOR_BOX_COLOR_RESULT_PREVIEW_CLASS,
  39709. appendTo: this._$colorBoxInputContainer
  39710. });
  39711. if (!this.option("value"))
  39712. this._$colorBoxInputContainer.addClass(COLOR_BOX_COLOR_IS_NOT_DEFINED);
  39713. else
  39714. colorUtils.makeTransparentBackground(this._$colorResultPreview, this.option("value"));
  39715. this._input().addClass(COLOR_BOX_INPUT_CLASS)
  39716. },
  39717. _renderValue: function() {
  39718. var value = this.option("value");
  39719. this.option("text", this.option("editAlphaChannel") ? colorUtils.makeRgba(value) : value);
  39720. this.callBase()
  39721. },
  39722. _valueChangeEventHandler: function(e) {
  39723. var value = this._input().val();
  39724. if (value) {
  39725. value = this._applyColorFromInput(value);
  39726. if (this._colorView) {
  39727. this._colorView._setCurrentColor(value);
  39728. this._colorView._refreshMarkup()
  39729. }
  39730. }
  39731. this.callBase(e, value)
  39732. },
  39733. _applyColorFromInput: function(value) {
  39734. var newColor = new DX.Color(value);
  39735. if (newColor.colorIsInvalid) {
  39736. value = this.option("value");
  39737. this._input().val(value)
  39738. }
  39739. return value
  39740. },
  39741. _optionChanged: function(args) {
  39742. var value = args.value,
  39743. name = args.name;
  39744. switch (name) {
  39745. case"value":
  39746. this._$colorBoxInputContainer.toggleClass(COLOR_BOX_COLOR_IS_NOT_DEFINED, !value);
  39747. if (value)
  39748. colorUtils.makeTransparentBackground(this._$colorResultPreview, value);
  39749. else
  39750. this._$colorResultPreview.removeAttr("style");
  39751. if (this._colorView)
  39752. this._colorView.option("value", value);
  39753. this.callBase(args);
  39754. break;
  39755. case"applyButtonText":
  39756. case"cancelButtonText":
  39757. this.callBase(args);
  39758. this._popup && this._addPopupBottomClasses();
  39759. break;
  39760. case"editAlphaChannel":
  39761. case"onCancelButtonClick":
  39762. case"onApplyButtonClick":
  39763. case"keyStep":
  39764. if (this._colorView)
  39765. this._colorView.option(name, value);
  39766. break;
  39767. case"applyValueMode":
  39768. if (this._colorView)
  39769. this._colorView.option(name, value);
  39770. this.callBase(args);
  39771. break;
  39772. case"rtlEnabled":
  39773. if (this._colorView)
  39774. this._colorView.option(name, value);
  39775. this.callBase(args);
  39776. break;
  39777. default:
  39778. this.callBase(args)
  39779. }
  39780. }
  39781. }));
  39782. DX.registerComponent("dxColorPicker", ui, ui.dxColorBox.inherit({ctor: function() {
  39783. DX.log("W0000", this.NAME, "14.2", "Use 'dxColorBox' instead");
  39784. this.callBase.apply(this, arguments)
  39785. }}));
  39786. ui.dxColorBox.__internals = {
  39787. COLOR_BOX_CLASS: COLOR_BOX_CLASS,
  39788. COLOR_BOX_INPUT_CLASS: COLOR_BOX_INPUT_CLASS,
  39789. COLOR_BOX_INPUT_CONTAINER_CLASS: COLOR_BOX_INPUT_CONTAINER_CLASS,
  39790. COLOR_BOX_COLOR_RESULT_PREVIEW_CLASS: COLOR_BOX_COLOR_RESULT_PREVIEW_CLASS,
  39791. COLOR_BOX_COLOR_IS_NOT_DEFINED: COLOR_BOX_COLOR_IS_NOT_DEFINED,
  39792. COLOR_BOX_OVERLAY_CLASS: COLOR_BOX_OVERLAY_CLASS
  39793. }
  39794. })(jQuery, DevExpress);
  39795. /*! Module widgets-web, file ui.menuBase.js */
  39796. (function($, DX, undefined) {
  39797. var ui = DX.ui,
  39798. utils = DX.utils;
  39799. var DX_MENU_CLASS = "dx-menu",
  39800. DX_MENU_BASE_CLASS = "dx-menu-base",
  39801. DX_MENU_ITEM_CLASS = DX_MENU_CLASS + "-item",
  39802. DX_MENU_SELECTED_ITEM_CLASS = DX_MENU_ITEM_CLASS + "-selected",
  39803. DX_MENU_ITEM_WRAPPER_CLASS = DX_MENU_ITEM_CLASS + "-wrapper",
  39804. DX_MENU_ITEMS_CONTAINER_CLASS = DX_MENU_CLASS + "-items-container",
  39805. DX_MENU_ITEM_EXPANDED_CLASS = DX_MENU_ITEM_CLASS + "-expanded",
  39806. DX_MENU_SEPARATOR_CLASS = DX_MENU_CLASS + "-separator",
  39807. DX_MENU_ITEM_LAST_GROUP_ITEM = DX_MENU_CLASS + "-last-group-item",
  39808. DX_ITEM_HAS_TEXT = DX_MENU_ITEM_CLASS + "-has-text",
  39809. DX_ITEM_HAS_ICON = DX_MENU_ITEM_CLASS + "-has-icon",
  39810. DX_ITEM_HAS_SUBMENU = DX_MENU_ITEM_CLASS + "-has-submenu",
  39811. DX_STATE_FOCUSED_CLASS = "dx-state-focused",
  39812. DX_MENU_ITEM_CLASS_SELECTOR = "." + DX_MENU_ITEM_CLASS,
  39813. DX_ITEM_SELECTED_SELECTOR = "." + DX_MENU_SELECTED_ITEM_CLASS,
  39814. SINGLE_SELECTION_MODE = "single",
  39815. NONE_SELECTION_MODE = "none",
  39816. FIRST_SUBMENU_LEVEL = 1,
  39817. DEFAULT_SHOW_DELAY = 50,
  39818. DEFAULT_HIDE_DELAY = 300;
  39819. var dxMenuBase = ui.CollectionWidget.inherit({
  39820. NAME: "dxMenuBase",
  39821. _setDefaultOptions: function() {
  39822. this.callBase();
  39823. this.option({
  39824. items: [],
  39825. cssClass: "",
  39826. activeStateEnabled: true,
  39827. showSubmenuMode: {
  39828. name: "onHover",
  39829. delay: {
  39830. show: 50,
  39831. hide: 300
  39832. }
  39833. },
  39834. animation: {
  39835. show: {
  39836. type: "fade",
  39837. from: 0,
  39838. to: 1,
  39839. duration: 100
  39840. },
  39841. hide: {
  39842. type: "fade",
  39843. from: 1,
  39844. to: 0,
  39845. duration: 100
  39846. }
  39847. },
  39848. selectionByClick: false,
  39849. selectionMode: "none",
  39850. focusOnSelectedItem: false,
  39851. _remoteSelectionSync: false,
  39852. hoverStateEnabled: true,
  39853. _itemAttributes: {role: "menuitem"}
  39854. })
  39855. },
  39856. _defaultOptionsRules: function() {
  39857. return this.callBase().concat([{
  39858. device: function(device) {
  39859. return DX.devices.real().generic && !DX.devices.isSimulator()
  39860. },
  39861. options: {focusStateEnabled: true}
  39862. }])
  39863. },
  39864. _activeStateUnit: DX_MENU_ITEM_CLASS_SELECTOR,
  39865. _itemDataKey: function() {
  39866. return "dxMenuItemDataKey"
  39867. },
  39868. _itemClass: function() {
  39869. return DX_MENU_ITEM_CLASS
  39870. },
  39871. _setAriaSelected: $.noop,
  39872. _selectedItemClass: function() {
  39873. return DX_MENU_SELECTED_ITEM_CLASS
  39874. },
  39875. _focusTarget: function() {
  39876. return this._itemContainer()
  39877. },
  39878. _eventBindingTarget: function() {
  39879. return this._itemContainer()
  39880. },
  39881. _supportedKeys: function() {
  39882. var selectItem = function(e) {
  39883. var $item = this.option("focusedElement");
  39884. if (!$item || !this._isSelectionEnabled())
  39885. return;
  39886. this.selectItem($item)
  39887. };
  39888. return $.extend(this.callBase(), {
  39889. space: selectItem,
  39890. pageUp: $.noop,
  39891. pageDown: $.noop
  39892. })
  39893. },
  39894. _isSelectionEnabled: function() {
  39895. return this._getSelectionMode() === SINGLE_SELECTION_MODE
  39896. },
  39897. _getSelectionMode: function() {
  39898. return this.option("selectionMode") === SINGLE_SELECTION_MODE ? SINGLE_SELECTION_MODE : NONE_SELECTION_MODE
  39899. },
  39900. _init: function() {
  39901. this.callBase();
  39902. this._initActions()
  39903. },
  39904. _initActions: $.noop,
  39905. _render: function() {
  39906. var $element = this.element();
  39907. this.callBase(arguments);
  39908. this._addCustomCssClass($element);
  39909. this._itemContainer().addClass(DX_MENU_BASE_CLASS)
  39910. },
  39911. _getShowSubmenuMode: function() {
  39912. var modeName;
  39913. if (utils.isObject(this.option("showSubmenuMode")))
  39914. modeName = this._isDesktopDevice() ? this.option("showSubmenuMode").name : "onClick";
  39915. else
  39916. modeName = this._isDesktopDevice() ? this.option("showSubmenuMode") : "onClick";
  39917. return modeName
  39918. },
  39919. _isDesktopDevice: function() {
  39920. return DX.devices.real().deviceType === "desktop"
  39921. },
  39922. _initEditStrategy: function() {
  39923. var strategy = ui.CollectionWidget.MenuBaseEditStrategy;
  39924. this._editStrategy = new strategy(this)
  39925. },
  39926. _addCustomCssClass: function($element) {
  39927. $element.addClass(this.option("cssClass"))
  39928. },
  39929. _itemWrapperSelector: function() {
  39930. return "." + DX_MENU_ITEM_WRAPPER_CLASS
  39931. },
  39932. _hoverStartHandler: function(e) {
  39933. var that = this,
  39934. $itemElement = that._getItemElementByEventArgs(e);
  39935. if ($itemElement) {
  39936. if (that._isItemDisabled($itemElement))
  39937. return;
  39938. e.stopPropagation();
  39939. that.option("focusedElement", $itemElement);
  39940. if (that._getShowSubmenuMode() === "onHover")
  39941. setTimeout($.proxy(that._showSubmenu, that, $itemElement), that._getSubmenuShowDelay())
  39942. }
  39943. },
  39944. _isItemDisabled: function($item) {
  39945. return $item.data(this._itemDataKey()).disabled
  39946. },
  39947. _showSubmenu: function($itemElement) {
  39948. if ($itemElement.hasClass(DX_STATE_FOCUSED_CLASS))
  39949. this._addExpandedClass($itemElement)
  39950. },
  39951. _addExpandedClass: function($itemElement) {
  39952. $itemElement.addClass(DX_MENU_ITEM_EXPANDED_CLASS)
  39953. },
  39954. _getSubmenuHideDelay: function() {
  39955. var delay = this.option("showSubmenuMode").delay;
  39956. if (delay)
  39957. return utils.isObject(delay) ? delay.hide : delay;
  39958. else
  39959. return DEFAULT_HIDE_DELAY
  39960. },
  39961. _getSubmenuShowDelay: function() {
  39962. var delay = this.option("showSubmenuMode").delay,
  39963. resultDelay;
  39964. if (delay)
  39965. resultDelay = utils.isObject(delay) ? delay.show : delay;
  39966. else
  39967. resultDelay = DEFAULT_SHOW_DELAY;
  39968. return resultDelay
  39969. },
  39970. _getItemElementByEventArgs: function(eventArgs) {
  39971. var $target = $(eventArgs.target);
  39972. if ($target.hasClass(this._itemClass()) || $target.get(0) === eventArgs.currentTarget)
  39973. return $target;
  39974. while (!$target.hasClass(this._itemClass())) {
  39975. $target = $target.parent();
  39976. if ($target.hasClass("dx-submenu"))
  39977. return null
  39978. }
  39979. return $target
  39980. },
  39981. _hoverEndHandler: $.noop,
  39982. _hasSubmenu: function(item) {
  39983. return item.items && item.items.length > 0
  39984. },
  39985. _renderItems: function(items, submenuLevel, submenuContainer) {
  39986. submenuLevel = submenuLevel || FIRST_SUBMENU_LEVEL;
  39987. var that = this,
  39988. $itemsContainer;
  39989. if (items.length) {
  39990. $itemsContainer = this._renderContainer(submenuLevel, submenuContainer);
  39991. $.each(items, function(index, item) {
  39992. that._renderItem(index, item, $itemsContainer, submenuLevel)
  39993. })
  39994. }
  39995. this._setSelectionFromItems()
  39996. },
  39997. _renderContainer: function(submenuLevel) {
  39998. return this._createItemsContainer().addClass(DX_MENU_ITEMS_CONTAINER_CLASS)
  39999. },
  40000. _createItemsContainer: function() {
  40001. var $rootGroup = $("<div>").appendTo(this.element());
  40002. return $("<ul>").appendTo($rootGroup)
  40003. },
  40004. _renderItem: function(index, item, $itemsContainer, submenuLevel) {
  40005. var items = this.option("items"),
  40006. $itemWrapper = $("<li>"),
  40007. $item;
  40008. this._renderSeparator(item, index, $itemsContainer);
  40009. $itemWrapper.appendTo($itemsContainer).addClass(DX_MENU_ITEM_WRAPPER_CLASS);
  40010. if (items[index + 1] && items[index + 1].beginGroup)
  40011. $itemWrapper.addClass(DX_MENU_ITEM_LAST_GROUP_ITEM);
  40012. if (!utils.isObject(item))
  40013. item = {text: item};
  40014. if (!utils.isDefined(item.selected))
  40015. item.selected = false;
  40016. $item = this.callBase(index, item, $itemWrapper);
  40017. this._addContentClasses(item, $item);
  40018. if (this._hasSubmenu(item))
  40019. this._renderSubmenuItems(item, $item, submenuLevel)
  40020. },
  40021. _addContentClasses: function(item, $item) {
  40022. if (item.text)
  40023. $item.addClass(DX_ITEM_HAS_TEXT);
  40024. if (item.icon || item.iconSrc)
  40025. $item.addClass(DX_ITEM_HAS_ICON);
  40026. if (item.items && item.items.length > 0)
  40027. $item.addClass(DX_ITEM_HAS_SUBMENU)
  40028. },
  40029. _setSelectionFromItems: function() {
  40030. var selectedIndex = this.option("selectedIndex"),
  40031. searchSelectedFromItems = !selectedIndex || selectedIndex === -1;
  40032. if (this.option("_remoteSelectionSync") || !searchSelectedFromItems)
  40033. return;
  40034. $.each(this._editStrategy._getPlainItems(), function(index, item) {
  40035. if (item.selected && item.selectable !== false)
  40036. selectedIndex = index
  40037. });
  40038. if (selectedIndex >= 0)
  40039. this.option("selectedIndex", selectedIndex)
  40040. },
  40041. _renderSeparator: function(item, index, $itemsContainer) {
  40042. if (item.beginGroup && index > 0)
  40043. $("<li>").appendTo($itemsContainer).addClass(DX_MENU_SEPARATOR_CLASS)
  40044. },
  40045. _renderSubmenuItems: function(item, $item) {
  40046. this.setAria("haspopup", "true", $item)
  40047. },
  40048. _itemClickHandler: function(e) {
  40049. var itemClickActionHandler = this._createAction($.proxy(this._updateSubmenuVisibilityOnClick, this));
  40050. this._itemJQueryEventHandler(e, "onItemClick", {}, {afterExecute: $.proxy(itemClickActionHandler, this)})
  40051. },
  40052. _updateSubmenuVisibilityOnClick: function(actionArgs) {
  40053. this._updateSelectedItemOnClick(actionArgs);
  40054. if (this._getShowSubmenuMode() === "onClick")
  40055. this._addExpandedClass(actionArgs.args[0].itemElement)
  40056. },
  40057. _updateSelectedItemOnClick: function(actionArgs) {
  40058. var args = actionArgs.args ? actionArgs.args[0] : actionArgs,
  40059. isSelectionByClickEnabled = this._isSelectionEnabled() && this.option("selectionByClick"),
  40060. $selectedItem,
  40061. selectedItemData;
  40062. if (isSelectionByClickEnabled && args.itemData.selectable !== false && !this._hasSubmenu(args.itemData)) {
  40063. $selectedItem = this._itemContainer().find(DX_ITEM_SELECTED_SELECTOR);
  40064. if ($selectedItem.length) {
  40065. selectedItemData = this._getItemData($selectedItem);
  40066. $selectedItem.removeClass(this._selectedItemClass());
  40067. if (selectedItemData) {
  40068. selectedItemData.selected = false;
  40069. this._clearSelectedItems()
  40070. }
  40071. if (!$selectedItem.is(args.itemElement))
  40072. this._setSelectedItems(args)
  40073. }
  40074. else
  40075. this._setSelectedItems(args)
  40076. }
  40077. },
  40078. _setSelectedItems: function(args) {
  40079. args.itemData.selected = true;
  40080. this.option("selectedItems", [args.itemData])
  40081. },
  40082. _syncSelectionOptions: function(byOption) {
  40083. var items = this._editStrategy._getPlainItems() || [],
  40084. selectedItems = this.option("selectedItems") || [],
  40085. selectedItem = this.option("selectedItem"),
  40086. selectedIndex = this.option("selectedIndex");
  40087. byOption = byOption || this._chooseSelectOption();
  40088. switch (byOption) {
  40089. case"selectedItems":
  40090. this._setOptionSilent("selectedItem", selectedItems[0]);
  40091. this._setOptionSilent("selectedIndex", $.inArray(selectedItems[0], items));
  40092. break;
  40093. case"selectedItem":
  40094. if (utils.isDefined(selectedItem)) {
  40095. this._setOptionSilent("selectedItems", [selectedItem]);
  40096. this._setOptionSilent("selectedIndex", $.inArray(selectedItem, items))
  40097. }
  40098. else {
  40099. this._setOptionSilent("selectedItems", []);
  40100. this._setOptionSilent("selectedIndex", -1)
  40101. }
  40102. break;
  40103. case"selectedIndex":
  40104. if (utils.isDefined(items[selectedIndex])) {
  40105. this._setOptionSilent("selectedItems", [items[selectedIndex]]);
  40106. this._setOptionSilent("selectedItem", items[selectedIndex])
  40107. }
  40108. else {
  40109. this._setOptionSilent("selectedItems", []);
  40110. this._setOptionSilent("selectedItem", null)
  40111. }
  40112. break
  40113. }
  40114. },
  40115. _getStringifiedArray: function(array) {
  40116. return $.map(array, function(item) {
  40117. return JSON.stringify(item)
  40118. })
  40119. },
  40120. _isOwnItem: function(item) {
  40121. var plainItems = this._editStrategy._getPlainItems();
  40122. return $.inArray(JSON.stringify(item), this._getStringifiedArray(plainItems)) >= 0
  40123. },
  40124. _optionChanged: function(args) {
  40125. switch (args.name) {
  40126. case"showSubmenuMode":
  40127. break;
  40128. case"_remoteSelectionSync":
  40129. case"cssClass":
  40130. case"position":
  40131. case"selectionByClick":
  40132. case"animation":
  40133. this._invalidate();
  40134. break;
  40135. default:
  40136. this.callBase(args)
  40137. }
  40138. },
  40139. selectItem: function(itemElement) {
  40140. var itemIndex = this._editStrategy.getNormalizedIndex(itemElement),
  40141. itemData = this._getItemData(itemElement);
  40142. if (itemIndex === -1)
  40143. return;
  40144. var itemSelectionIndex = $.inArray(itemIndex, this._selectedItemIndices);
  40145. if (itemSelectionIndex !== -1)
  40146. return;
  40147. if (this.option("selectionMode") === "single" && itemData.selectable !== false) {
  40148. var items = this._editStrategy.fetchSelectedItems([itemIndex]);
  40149. items[0].selected = true;
  40150. this.option("selectedItems", items)
  40151. }
  40152. },
  40153. unselectItem: function(itemElement) {
  40154. var itemIndex = this._editStrategy.getNormalizedIndex(itemElement);
  40155. if (itemIndex === -1)
  40156. return;
  40157. var itemSelectionIndex = $.inArray(itemIndex, this._selectedItemIndices);
  40158. if (itemSelectionIndex === -1)
  40159. return;
  40160. var items = this._editStrategy.fetchSelectedItems([itemSelectionIndex]);
  40161. items[0].selected = false;
  40162. this.option("selectedItems", [])
  40163. }
  40164. });
  40165. ui.dxMenuBase = dxMenuBase
  40166. })(jQuery, DevExpress);
  40167. /*! Module widgets-web, file ui.menuBase.edit.strategy.js */
  40168. (function($, DX, undefined) {
  40169. var ui = DX.ui;
  40170. ui.CollectionWidget.MenuBaseEditStrategy = ui.CollectionWidget.PlainEditStrategy.inherit({
  40171. _getPlainItems: function() {
  40172. return $.map(this._collectionWidget.option("items"), function getMenuItems(item) {
  40173. return item.items ? [item].concat($.map(item.items, getMenuItems)) : item
  40174. })
  40175. },
  40176. _getStringifiedArray: function(array) {
  40177. var that = this;
  40178. return $.map(array, function(item) {
  40179. return that._stringifyItem(item)
  40180. })
  40181. },
  40182. _stringifyItem: function(item) {
  40183. var that = this;
  40184. return JSON.stringify(item, function(key, value) {
  40185. if (key === "template")
  40186. return that._getTemplateString(value);
  40187. return value
  40188. })
  40189. },
  40190. _getTemplateString: function(template) {
  40191. var result;
  40192. if (typeof template === "object")
  40193. result = $(template).text();
  40194. else
  40195. result = template.toString();
  40196. return result
  40197. },
  40198. selectedItemIndices: function() {
  40199. var selectedIndices = [],
  40200. items = this._getStringifiedArray(this._getPlainItems()),
  40201. selectedItems = this._collectionWidget.option("selectedItems");
  40202. $.each(selectedItems, function(_, selectedItem) {
  40203. var index = $.inArray(JSON.stringify(selectedItem), items);
  40204. if (index !== -1)
  40205. selectedIndices.push(index);
  40206. else
  40207. DX.log("W1002", selectedItem)
  40208. });
  40209. return selectedIndices
  40210. },
  40211. fetchSelectedItems: function(indices) {
  40212. indices = indices || this._collectionWidget._selectedItemIndices;
  40213. var items = this._getPlainItems(),
  40214. selectedItems = [];
  40215. $.each(indices, function(_, index) {
  40216. selectedItems.push(items[index])
  40217. });
  40218. return selectedItems
  40219. }
  40220. })
  40221. })(jQuery, DevExpress);
  40222. /*! Module widgets-web, file ui.contextMenu.js */
  40223. (function($, DX, undefined) {
  40224. var ui = DX.ui,
  40225. utils = DX.utils,
  40226. events = ui.events,
  40227. fx = DX.fx;
  40228. var DX_MENU_CLASS = "dx-menu",
  40229. DX_MENU_ITEM_CLASS = DX_MENU_CLASS + "-item",
  40230. DX_MENU_ITEM_EXPANDED_CLASS = DX_MENU_ITEM_CLASS + "-expanded",
  40231. DX_MENU_PHONE_CLASS = "dx-menu-phone-overlay",
  40232. DX_MENU_ITEMS_CONTAINER_CLASS = DX_MENU_CLASS + "-items-container",
  40233. DX_MENU_ITEM_WRAPPER_CLASS = DX_MENU_ITEM_CLASS + "-wrapper",
  40234. DX_SUBMENU_CLASS = "dx-submenu",
  40235. DX_CONTEXT_MENU_CLASS = "dx-context-menu",
  40236. DX_HAS_CONTEXT_MENU_CLASS = "dx-has-context-menu",
  40237. DX_STATE_DISABLED_CLASS = "dx-state-disabled",
  40238. DX_SUBMENU_LEVEL_ID = "dxSubmenuLevel",
  40239. FOCUS_UP = "up",
  40240. FOCUS_DOWN = "down",
  40241. FOCUS_LEFT = "left",
  40242. FOCUS_RIGHT = "right",
  40243. FOCUS_FIRST = "first",
  40244. FOCUS_LAST = "last",
  40245. ACTIONS = ["onShowing", "onShown", "onHiding", "onHidden", "onPositioning", "onLeftFirstItem", "onLeftLastItem", "onCloseRootSubmenu", "onExpandLastSubmenu"],
  40246. LOCAL_SUBMENU_DIRECTIONS = [FOCUS_UP, FOCUS_DOWN, FOCUS_FIRST, FOCUS_LAST];
  40247. DX.registerComponent("dxContextMenu", ui, ui.dxMenuBase.inherit({
  40248. _setDefaultOptions: function() {
  40249. this.callBase();
  40250. this.option({
  40251. alternativeInvocationMode: {
  40252. enabled: false,
  40253. invokingElement: null
  40254. },
  40255. position: {
  40256. at: "top left",
  40257. my: "top left"
  40258. },
  40259. onShowing: null,
  40260. onShown: null,
  40261. onHiding: null,
  40262. onHidden: null,
  40263. onPositioning: null,
  40264. submenuDirection: "auto",
  40265. visible: false,
  40266. target: window,
  40267. onLeftFirstItem: null,
  40268. onLeftLastItem: null,
  40269. onCloseRootSubmenu: null,
  40270. onExpandLastSubmenu: null
  40271. })
  40272. },
  40273. _initActions: function() {
  40274. this._actions = {};
  40275. $.each(ACTIONS, $.proxy(function(index, action) {
  40276. this._actions[action] = this._createActionByOption(action) || $.noop
  40277. }, this))
  40278. },
  40279. _setOptionsByReference: function() {
  40280. this.callBase();
  40281. $.extend(this._optionsByReference, {
  40282. animation: true,
  40283. position: true,
  40284. selectedItem: true
  40285. })
  40286. },
  40287. _itemContainer: function() {
  40288. return this._overlay.content()
  40289. },
  40290. _supportedKeys: function() {
  40291. return $.extend(this.callBase(), {esc: this.hide})
  40292. },
  40293. _moveFocus: function(location) {
  40294. var $items = this._getItemsByLocation(location),
  40295. $oldTarget = this._getActiveItem(true),
  40296. $newTarget,
  40297. $focusedItem = this.option("focusedElement");
  40298. switch (location) {
  40299. case FOCUS_UP:
  40300. $newTarget = $focusedItem ? this._prevItem($items) : $items.last();
  40301. if ($oldTarget.is($items.first()))
  40302. this._actions.onLeftFirstItem($oldTarget);
  40303. break;
  40304. case FOCUS_DOWN:
  40305. $newTarget = $focusedItem ? this._nextItem($items) : $items.first();
  40306. if ($oldTarget.is($items.last()))
  40307. this._actions.onLeftLastItem($oldTarget);
  40308. break;
  40309. case FOCUS_RIGHT:
  40310. $newTarget = this.option("rtlEnabled") ? this._hideSubmenuHandler($items) : this._expandSubmenuHandler($items);
  40311. break;
  40312. case FOCUS_LEFT:
  40313. $newTarget = this.option("rtlEnabled") ? this._expandSubmenuHandler($items) : this._hideSubmenuHandler($items);
  40314. break;
  40315. case FOCUS_FIRST:
  40316. $newTarget = $items.first();
  40317. break;
  40318. case FOCUS_LAST:
  40319. $newTarget = $items.last();
  40320. break;
  40321. default:
  40322. return this.callBase(location)
  40323. }
  40324. if ($newTarget.length !== 0)
  40325. this.option("focusedElement", $newTarget)
  40326. },
  40327. _getItemsByLocation: function(location) {
  40328. var $items,
  40329. $activeItem = this._getActiveItem(true),
  40330. expandedLocation = this.option("rtlEnabled") ? FOCUS_LEFT : FOCUS_RIGHT;
  40331. if ($.inArray(location, LOCAL_SUBMENU_DIRECTIONS) >= 0)
  40332. $items = $activeItem.closest("." + DX_MENU_ITEMS_CONTAINER_CLASS).children().children();
  40333. else {
  40334. $items = this._itemElements();
  40335. if (location !== expandedLocation)
  40336. $items = $items.filter(":visible")
  40337. }
  40338. return $items
  40339. },
  40340. _refreshActiveDescendant: function() {
  40341. var $target = this._overlay.content(),
  40342. id = this.getFocusedItemId();
  40343. if (!$target)
  40344. return this.callBase();
  40345. this.setAria("activedescendant", "", $target);
  40346. this.setAria("activedescendant", id, $target)
  40347. },
  40348. _hideSubmenuHandler: function($items) {
  40349. var $curItem = this._getActiveItem(true),
  40350. $parentItem = $curItem.parents("." + DX_MENU_ITEM_EXPANDED_CLASS).first();
  40351. if ($parentItem.length) {
  40352. this._hideSubmenusOnSameLevel($parentItem);
  40353. return $parentItem
  40354. }
  40355. this._actions.onCloseRootSubmenu($curItem);
  40356. return $curItem
  40357. },
  40358. _expandSubmenuHandler: function($items) {
  40359. var $curItem = this._getActiveItem(true),
  40360. $submenu = $curItem.children("." + DX_SUBMENU_CLASS);
  40361. if ($submenu.length && !$curItem.hasClass(DX_STATE_DISABLED_CLASS)) {
  40362. if ($submenu.css("visibility") === "hidden")
  40363. this._showSubmenu($curItem);
  40364. return this._nextItem($items)
  40365. }
  40366. this._actions.onExpandLastSubmenu($curItem);
  40367. return $curItem
  40368. },
  40369. _render: function() {
  40370. this.element().addClass(DX_HAS_CONTEXT_MENU_CLASS);
  40371. this.callBase();
  40372. this.setAria("role", "menu")
  40373. },
  40374. _renderContentImpl: function() {
  40375. this._renderContextMenuOverlay();
  40376. this._detachShowContextMenuEvents();
  40377. this._attachShowContextMenuEvents();
  40378. this._attachInvokeContextMenuEvents();
  40379. this.callBase()
  40380. },
  40381. _renderContextMenuOverlay: function() {
  40382. var overlayOptions = this._getOverlayOptions(),
  40383. $overlayElement = $("<div>"),
  40384. $overlayContent;
  40385. this._overlay = this._createComponent($overlayElement.appendTo(this._$element), "dxOverlay", overlayOptions);
  40386. $overlayContent = this._overlay.content();
  40387. $overlayContent.addClass(DX_CONTEXT_MENU_CLASS);
  40388. this._addCustomCssClass($overlayContent);
  40389. this._addPlatformDependentClass($overlayContent);
  40390. if (this.option("visible"))
  40391. this._show()
  40392. },
  40393. _addPlatformDependentClass: function($element) {
  40394. if (DX.devices.current().phone)
  40395. $element.addClass(DX_MENU_PHONE_CLASS)
  40396. },
  40397. _detachShowContextMenuEvents: function() {
  40398. var eventName = events.addNamespace("dxcontextmenu", this.NAME);
  40399. $(this.option("target")).off(eventName);
  40400. this._overlay && this._overlay.content().off(eventName)
  40401. },
  40402. _attachShowContextMenuEvents: function() {
  40403. var that = this,
  40404. eventName = events.addNamespace("dxcontextmenu", this.NAME),
  40405. contextMenuAction = this._createAction($.proxy(function(e) {
  40406. if (!that.option("alternativeInvocationMode").enabled)
  40407. that._show(e.jQueryEvent)
  40408. }, this));
  40409. this._overlay && this._overlay.content().on(eventName, $.noop);
  40410. $(this.option("target")).on(eventName, $.proxy(function(e) {
  40411. contextMenuAction({jQueryEvent: e})
  40412. }, this))
  40413. },
  40414. _attachInvokeContextMenuEvents: function() {
  40415. var that = this,
  40416. eventName = events.addNamespace("dxclick", this.NAME),
  40417. contextMenuAction = this._createAction($.proxy(function() {
  40418. that.toggle()
  40419. }, this));
  40420. if (this.option("alternativeInvocationMode").enabled && this._getInvokeTarget())
  40421. $(this._getInvokeTarget()).off(eventName).on(eventName, $.proxy(function(e) {
  40422. contextMenuAction({jQueryEvent: e})
  40423. }, this))
  40424. },
  40425. _getInvokeTarget: function() {
  40426. return this.option("alternativeInvocationMode").invokingElement
  40427. },
  40428. _hoverEndHandler: function(e) {
  40429. e.stopPropagation()
  40430. },
  40431. _renderDimensions: $.noop,
  40432. _renderContainer: function(submenuLevel, submenuContainer) {
  40433. var $submenu = $("<div>"),
  40434. $itemsContainer = $("<ul>"),
  40435. $holder = submenuLevel === 1 ? this._itemContainer() : submenuContainer;
  40436. $submenu.appendTo($holder).addClass(DX_SUBMENU_CLASS).data(DX_SUBMENU_LEVEL_ID, submenuLevel).css("visibility", submenuLevel === 1 ? "visible" : "hidden");
  40437. $itemsContainer.appendTo($submenu).addClass(DX_MENU_ITEMS_CONTAINER_CLASS);
  40438. if (submenuLevel === 1) {
  40439. if (this.option("width"))
  40440. $itemsContainer.css("min-width", this.option("width"));
  40441. if (this.option("height"))
  40442. $itemsContainer.css("min-height", this.option("height"))
  40443. }
  40444. return $itemsContainer
  40445. },
  40446. _renderSubmenuItems: function(item, $item, submenuLevel) {
  40447. this._renderItems(item.items, ++submenuLevel, $item);
  40448. this.callBase(item, $item)
  40449. },
  40450. _getOverlayOptions: function() {
  40451. var position = this.option("position"),
  40452. overlayAnimation = this.option("animation"),
  40453. overlayOptions = {
  40454. focusStateEnabled: this.option("focusStateEnabled"),
  40455. animation: overlayAnimation,
  40456. closeOnOutsideClick: $.proxy(this._closeOnOutsideClickHandler, this),
  40457. closeOnTargetScroll: true,
  40458. deferRendering: false,
  40459. disabled: this.option("disabled"),
  40460. position: {
  40461. at: position.at,
  40462. my: position.my,
  40463. of: this.option("target")
  40464. },
  40465. shading: false,
  40466. showTitle: false,
  40467. height: "auto",
  40468. width: "auto",
  40469. onShowing: $.proxy(this._overlayShowingActionHandler, this),
  40470. onShown: $.proxy(this._overlayShownActionHandler, this),
  40471. onHiding: $.proxy(this._overlayHidingActionHandler, this),
  40472. onHidden: $.proxy(this._overlayHiddenActionHandler, this),
  40473. onPositioned: $.proxy(this._overlayPositionedActionHandler, this),
  40474. onPositioning: $.proxy(this._overlayPositioningActionHandler, this)
  40475. };
  40476. return overlayOptions
  40477. },
  40478. _overlayShowingActionHandler: function(arg) {
  40479. this._actions.onShowing(arg);
  40480. this._clearFocusedItem()
  40481. },
  40482. _overlayShownActionHandler: function(arg) {
  40483. this._actions.onShown(arg);
  40484. this._clearFocusedItem()
  40485. },
  40486. _clearFocusedItem: function() {
  40487. this._removeFocusedItem();
  40488. this.option("focusedElement", null)
  40489. },
  40490. _overlayHidingActionHandler: function(arg) {
  40491. this._actions.onHiding(arg);
  40492. if (!arg.cancel)
  40493. this._hideAllShownSubmenus()
  40494. },
  40495. _overlayHiddenActionHandler: function(arg) {
  40496. this._actions.onHidden(arg);
  40497. this._setOptionSilent("visible", false)
  40498. },
  40499. _overlayPositionedActionHandler: $.noop,
  40500. _overlayPositioningActionHandler: function(arg) {
  40501. var targetPosition = arg.position,
  40502. newPosition = targetPosition;
  40503. if ((targetPosition.h.oversize !== 0 || targetPosition.v.oversize !== 0) && !this.option("_notChangePosition")) {
  40504. newPosition.h.location = Math.round(targetPosition.h.location - targetPosition.h.oversize);
  40505. newPosition.v.location = Math.round(targetPosition.v.location - targetPosition.v.oversize);
  40506. DX.position(this.element(), newPosition)
  40507. }
  40508. },
  40509. _closeOnOutsideClickHandler: function(e) {
  40510. var $clickedItem,
  40511. $activeItemContainer,
  40512. $itemContainers,
  40513. $rootItem,
  40514. isRootItemClicked,
  40515. isInnerOverlayClicked,
  40516. isInvokeTarget = $(e.target).closest(this._getInvokeTarget());
  40517. if (e.target === document)
  40518. return true;
  40519. if (isInvokeTarget && isInvokeTarget.length)
  40520. return false;
  40521. $activeItemContainer = this._getActiveItemsContainer(e.target);
  40522. $itemContainers = this._getItemsContainers();
  40523. $clickedItem = this._searchActiveItem(e.target);
  40524. $rootItem = this.element().parents("." + DX_MENU_ITEM_CLASS);
  40525. isRootItemClicked = $clickedItem[0] === $rootItem[0] && $clickedItem.length && $rootItem.length;
  40526. isInnerOverlayClicked = this._isIncludeOverlay($activeItemContainer, $itemContainers) && $clickedItem.length;
  40527. if (isInnerOverlayClicked || isRootItemClicked) {
  40528. if (this._getShowSubmenuMode() === "onClick")
  40529. this._hideAllShownChildSubmenus($clickedItem);
  40530. return false
  40531. }
  40532. return true
  40533. },
  40534. _getActiveItemsContainer: function(target) {
  40535. return $(target).closest("." + DX_MENU_ITEMS_CONTAINER_CLASS)
  40536. },
  40537. _getItemsContainers: function() {
  40538. return this._overlay._$content.find("." + DX_MENU_ITEMS_CONTAINER_CLASS)
  40539. },
  40540. _searchActiveItem: function(target) {
  40541. return $(target).closest("." + DX_MENU_ITEM_CLASS).eq(0)
  40542. },
  40543. _isIncludeOverlay: function($activeOverlay, $allOverlays) {
  40544. var isSame = false;
  40545. $.each($allOverlays, function(index, $overlay) {
  40546. if ($activeOverlay.is($overlay) && !isSame)
  40547. isSame = true
  40548. });
  40549. return isSame
  40550. },
  40551. _hideAllShownChildSubmenus: function($clickedItem) {
  40552. var that = this,
  40553. $submenuElements = $clickedItem.find("." + DX_SUBMENU_CLASS),
  40554. shownSubmenus = $.extend([], this._shownSubmenus),
  40555. $context;
  40556. if ($submenuElements.length > 0)
  40557. $.each(shownSubmenus, function(index, $submenu) {
  40558. $context = that._searchActiveItem($submenu.context).parent();
  40559. if ($context.parent().is($clickedItem.parent().parent()) && !$context.is($clickedItem.parent()))
  40560. that._hideSubmenu($submenu)
  40561. })
  40562. },
  40563. _showSubmenu: function($item) {
  40564. var isItemHasSubmenu = $item.children("." + DX_SUBMENU_CLASS).length,
  40565. isSubmenuVisible;
  40566. this._hideSubmenusOnSameLevel($item);
  40567. if (isItemHasSubmenu) {
  40568. this.callBase($item);
  40569. $item.closest("." + DX_MENU_ITEMS_CONTAINER_CLASS).find("." + DX_MENU_ITEM_EXPANDED_CLASS).removeClass(DX_MENU_ITEM_EXPANDED_CLASS);
  40570. isSubmenuVisible = this._isSubmenuVisible($item.children("." + DX_SUBMENU_CLASS));
  40571. if (!isSubmenuVisible) {
  40572. $item.addClass(DX_MENU_ITEM_EXPANDED_CLASS);
  40573. this._drawSubmenu($item)
  40574. }
  40575. }
  40576. },
  40577. _hideSubmenusOnSameLevel: function($item) {
  40578. var $expandedItems = $item.closest("." + DX_MENU_ITEMS_CONTAINER_CLASS).find("." + DX_MENU_ITEM_EXPANDED_CLASS);
  40579. if ($expandedItems.length) {
  40580. $expandedItems.removeClass(DX_MENU_ITEM_EXPANDED_CLASS);
  40581. this._hideSubmenu($expandedItems.find("." + DX_SUBMENU_CLASS))
  40582. }
  40583. },
  40584. _hideSubmenuGroup: function($submenu) {
  40585. if (this._isSubmenuVisible($submenu))
  40586. this._hideSubmenuCore($submenu)
  40587. },
  40588. _isSubmenuVisible: function($submenu) {
  40589. return $submenu.css("visibility") === "visible"
  40590. },
  40591. _drawSubmenu: function($itemElement) {
  40592. var animation = this.option("animation") ? this.option("animation").show : {},
  40593. $submenu = $itemElement.children("." + DX_SUBMENU_CLASS);
  40594. if (this._overlay && this._overlay.option("visible")) {
  40595. if (!utils.isDefined(this._shownSubmenus))
  40596. this._shownSubmenus = [];
  40597. if ($.inArray($submenu, this._shownSubmenus))
  40598. this._shownSubmenus.push($submenu);
  40599. DX.position($submenu, this._getSubmenuPosition($itemElement));
  40600. animation && this._animate($submenu, animation);
  40601. $submenu.css("visibility", "visible");
  40602. this._stopAnimate($submenu)
  40603. }
  40604. },
  40605. _animate: function($container, options) {
  40606. fx.animate($container, options)
  40607. },
  40608. _getSubmenuPosition: function($rootItem) {
  40609. var submenuDirection = this.option("submenuDirection").toLowerCase(),
  40610. $rootItemWrapper = $rootItem.parent("." + DX_MENU_ITEM_WRAPPER_CLASS),
  40611. position = {
  40612. collision: "flip",
  40613. of: $rootItemWrapper,
  40614. offset: {
  40615. h: 0,
  40616. v: -1
  40617. }
  40618. };
  40619. switch (submenuDirection) {
  40620. case"left":
  40621. position.at = "left top";
  40622. position.my = "right top";
  40623. break;
  40624. case"right":
  40625. position.at = "right top";
  40626. position.my = "left top";
  40627. break;
  40628. default:
  40629. if (this.option("rtlEnabled")) {
  40630. position.at = "left top";
  40631. position.my = "right top"
  40632. }
  40633. else {
  40634. position.at = "right top";
  40635. position.my = "left top"
  40636. }
  40637. break
  40638. }
  40639. return position
  40640. },
  40641. _updateSubmenuVisibilityOnClick: function(actionArgs) {
  40642. var $itemElement,
  40643. itemData,
  40644. $submenuElement,
  40645. notCloseMenuOnItemClick;
  40646. if (actionArgs.args.length && actionArgs.args[0]) {
  40647. actionArgs.args[0].jQueryEvent.stopPropagation();
  40648. $itemElement = actionArgs.args[0].itemElement;
  40649. itemData = this._getItemData($itemElement);
  40650. notCloseMenuOnItemClick = itemData && itemData.closeMenuOnClick === false;
  40651. $submenuElement = $itemElement.children("." + DX_SUBMENU_CLASS);
  40652. if ($itemElement.context === $submenuElement.context && $submenuElement.css("visibility") === "visible")
  40653. return;
  40654. if (!itemData || itemData.disabled || notCloseMenuOnItemClick)
  40655. return;
  40656. this._updateSelectedItemOnClick(actionArgs);
  40657. if ($submenuElement.length === 0) {
  40658. var $prevSubmenu = $($itemElement.parents("." + DX_SUBMENU_CLASS)[0]);
  40659. this._hideSubmenu($prevSubmenu);
  40660. if (!actionArgs.canceled && this._overlay && this._overlay.option("visible"))
  40661. this.option("visible", false)
  40662. }
  40663. else {
  40664. if (this._shownSubmenus && this._shownSubmenus.length > 0)
  40665. if (this._shownSubmenus[0].is($submenuElement) || this._shownSubmenus[0].has($submenuElement).length === 1)
  40666. this._hideSubmenu($submenuElement);
  40667. else
  40668. this._hideAllShownSubmenus();
  40669. this._showSubmenu($itemElement)
  40670. }
  40671. }
  40672. },
  40673. _hideSubmenu: function($curSubmenu) {
  40674. var that = this,
  40675. shownSubmenus = $.extend([], that._shownSubmenus);
  40676. $.each(shownSubmenus, function(index, $submenu) {
  40677. if ($curSubmenu.is($submenu) || $curSubmenu.has($submenu).length) {
  40678. $submenu.parent().removeClass(DX_MENU_ITEM_EXPANDED_CLASS);
  40679. that._hideSubmenuCore($submenu)
  40680. }
  40681. })
  40682. },
  40683. _hideSubmenuCore: function($submenu) {
  40684. var index = $.inArray($submenu, this._shownSubmenus),
  40685. animation = this.option("animation") ? this.option("animation").hide : null;
  40686. if (index >= 0)
  40687. this._shownSubmenus.splice(index, 1);
  40688. this._stopAnimate($submenu);
  40689. animation && this._animate($submenu, animation);
  40690. $submenu.css("visibility", "hidden")
  40691. },
  40692. _stopAnimate: function($container) {
  40693. fx.stop($container, true)
  40694. },
  40695. _hideAllShownSubmenus: function() {
  40696. var that = this,
  40697. shownSubmenus = $.extend([], that._shownSubmenus),
  40698. $expandedItems = this._overlay.content().find("." + DX_MENU_ITEM_EXPANDED_CLASS);
  40699. $expandedItems.removeClass(DX_MENU_ITEM_EXPANDED_CLASS);
  40700. $.each(shownSubmenus, function(_, $submenu) {
  40701. that._hideSubmenuCore($submenu)
  40702. })
  40703. },
  40704. _optionChanged: function(args) {
  40705. if (this._cancelOptionChange)
  40706. return;
  40707. if ($.inArray(args.name, ACTIONS) > -1) {
  40708. this._initActions();
  40709. return
  40710. }
  40711. switch (args.name) {
  40712. case"visible":
  40713. this._toggleVisibility(args.value);
  40714. break;
  40715. case"alternativeInvocationMode":
  40716. this._invalidate();
  40717. break;
  40718. case"items":
  40719. if (this._overlay.option("visible"))
  40720. this._overlay.hide();
  40721. this.callBase(args);
  40722. break;
  40723. case"position":
  40724. case"submenuDirection":
  40725. this._invalidate();
  40726. break;
  40727. case"target":
  40728. args.previousValue && this._detachShowContextMenuEvents($(args.previousValue));
  40729. this._invalidate();
  40730. break;
  40731. case"focusedElement":
  40732. this.callBase(args);
  40733. break;
  40734. default:
  40735. if (this._overlay)
  40736. if (this._overlay.option("visible"))
  40737. this._overlay.hide();
  40738. this.callBase(args)
  40739. }
  40740. },
  40741. _toggleVisibility: function(showing) {
  40742. showing ? this._show() : this._hide()
  40743. },
  40744. _show: function(jQEvent) {
  40745. var canShowMenu = !(this._overlay && this._positionContextMenu(jQEvent)),
  40746. id = new DevExpress.data.Guid,
  40747. promise;
  40748. if (canShowMenu && this._overlay) {
  40749. this.option("focusedElement", this._itemElements().first());
  40750. promise = this._overlay.show();
  40751. this._overlay.content().attr({
  40752. id: id,
  40753. role: "menu"
  40754. });
  40755. this.setAria("owns", id);
  40756. this._setOptionSilent("visible", true)
  40757. }
  40758. return promise || $.Deferred().reject().promise()
  40759. },
  40760. _positionContextMenu: function(jQEvent) {
  40761. var position = this.option("position"),
  40762. positioningAction = this._createActionByOption("onPositioning", actionArgs),
  40763. actionArgs;
  40764. if (jQEvent && jQEvent.preventDefault)
  40765. position = {
  40766. at: "top left",
  40767. my: "top left",
  40768. of: jQEvent
  40769. };
  40770. if (!position.of)
  40771. position.of = this.option("target");
  40772. actionArgs = {
  40773. position: position,
  40774. jQueryEvent: jQEvent
  40775. };
  40776. positioningAction(actionArgs);
  40777. if (!actionArgs.canceled && this._overlay)
  40778. position && this._overlay.option("position", position);
  40779. else
  40780. actionArgs.jQueryEvent.cancel = true;
  40781. return actionArgs.canceled
  40782. },
  40783. _hide: function() {
  40784. var promise;
  40785. if (this._overlay) {
  40786. this._overlay.content().removeAttr("id");
  40787. promise = this._overlay.hide();
  40788. this._setOptionSilent("visible", false)
  40789. }
  40790. this.setAria("owns", undefined);
  40791. return promise || $.Deferred().reject().promise()
  40792. },
  40793. _clean: function() {
  40794. if (this._overlay) {
  40795. this._overlay.element().remove();
  40796. this._overlay = null
  40797. }
  40798. this._detachShowContextMenuEvents($(this.option("target")))
  40799. },
  40800. toggle: function(showing) {
  40801. var visible = this.option("visible");
  40802. showing = showing === undefined ? !visible : showing;
  40803. return showing ? this._show() : this._hide()
  40804. },
  40805. show: function() {
  40806. return this.toggle(true)
  40807. },
  40808. hide: function() {
  40809. return this.toggle(false)
  40810. }
  40811. }))
  40812. })(jQuery, DevExpress);
  40813. /*! Module widgets-web, file ui.menu.js */
  40814. (function($, DX, undefined) {
  40815. var ui = DX.ui,
  40816. utils = DX.utils,
  40817. events = ui.events;
  40818. var DX_MENU_CLASS = "dx-menu",
  40819. DX_MENU_VERTICAL_CLASS = DX_MENU_CLASS + "-vertical",
  40820. DX_MENU_HORIZONTAL_CLASS = DX_MENU_CLASS + "-horizontal",
  40821. DX_MENU_ITEM_CLASS = DX_MENU_CLASS + "-item",
  40822. DX_MENU_ITEMS_CONTAINER_CLASS = DX_MENU_CLASS + "-items-container",
  40823. DX_MENU_ITEM_EXPANDED_CLASS = DX_MENU_ITEM_CLASS + "-expanded",
  40824. DX_CONTEXT_MENU_CLASS = "dx-context-menu",
  40825. DX_CONTEXT_MENU_CONTAINER_BORDER_CLASS = DX_CONTEXT_MENU_CLASS + "-container-border",
  40826. DX_CONTEXT_MENU_CONTENT_DELIMITER_CLASS = "dx-context-menu-content-delimiter",
  40827. DX_SUBMENU_CLASS = "dx-submenu",
  40828. DX_STATE_DISABLED_CLASS = "dx-state-disabled",
  40829. DX_STATE_FOCUSED_CLASS = "dx-state-focused",
  40830. DX_STATE_HOVER_CLASS = "dx-state-hover",
  40831. FOCUS_UP = "up",
  40832. FOCUS_DOWN = "down",
  40833. FOCUS_LEFT = "left",
  40834. FOCUS_RIGHT = "right",
  40835. SHOW_SUBMENU_OPERATION = "showSubmenu",
  40836. NEXTITEM_OPERATION = "nextItem",
  40837. PREVITEM_OPERATION = "prevItem",
  40838. DEFAULT_SHOW_DELAY = 50,
  40839. DEFAULT_HIDE_DELAY = 300,
  40840. ACTIONS = ["onSubmenuShowing", "onSubmenuShown", "onSubmenuHiding", "onSubmenuHidden"],
  40841. dxSubmenu = ui.dxContextMenu.inherit({
  40842. _setDefaultOptions: function() {
  40843. this.callBase();
  40844. this.option({orientation: "horizontal"})
  40845. },
  40846. _renderContentImpl: function() {
  40847. this.callBase();
  40848. this._renderDelimiter()
  40849. },
  40850. _renderDelimiter: function() {
  40851. this.$contentDelimiter = $("<div>").appendTo(this._itemContainer()).addClass(DX_CONTEXT_MENU_CONTENT_DELIMITER_CLASS)
  40852. },
  40853. _overlayPositionedActionHandler: function(arg) {
  40854. this._showDelimiter(arg)
  40855. },
  40856. _hoverEndHandler: function(e) {
  40857. var $itemElement = $(e.currentTarget);
  40858. $itemElement.removeClass(DX_STATE_FOCUSED_CLASS)
  40859. },
  40860. _hoverStartHandler: function(e) {
  40861. this.callBase(e);
  40862. var $itemElement = $(e.currentTarget);
  40863. $itemElement.addClass(DX_STATE_FOCUSED_CLASS)
  40864. },
  40865. _showDelimiter: function(arg) {
  40866. var $submenu = this._itemContainer().children("." + DX_SUBMENU_CLASS).eq(0),
  40867. $rootItem = this.option("position").of,
  40868. position = {of: $submenu},
  40869. containerOffset,
  40870. rootOffset;
  40871. if (this.$contentDelimiter) {
  40872. containerOffset = arg.position;
  40873. rootOffset = $rootItem.offset();
  40874. this.$contentDelimiter.css("display", "block");
  40875. if (this.option("orientation") === "horizontal") {
  40876. this.$contentDelimiter.width($rootItem.width() < $submenu.width() ? $rootItem.width() - 2 : $submenu.width() - 2);
  40877. this.$contentDelimiter.height(2);
  40878. if (containerOffset.v.location > rootOffset.top)
  40879. if (Math.round(containerOffset.h.location) === Math.round(rootOffset.left)) {
  40880. position.offset = "1 -1";
  40881. position.at = "left top";
  40882. position.my = "left top"
  40883. }
  40884. else {
  40885. position.offset = "-1 -1";
  40886. position.at = "right top";
  40887. position.my = "right top"
  40888. }
  40889. else {
  40890. this.$contentDelimiter.height(4);
  40891. if (Math.round(containerOffset.h.location) === Math.round(rootOffset.left)) {
  40892. position.offset = "1 2";
  40893. position.at = "left bottom";
  40894. position.my = "left bottom"
  40895. }
  40896. else {
  40897. position.offset = "-1 2";
  40898. position.at = "right bottom";
  40899. position.my = "right bottom"
  40900. }
  40901. }
  40902. }
  40903. else if (this.option("orientation") === "vertical") {
  40904. this.$contentDelimiter.width(2);
  40905. this.$contentDelimiter.height($rootItem.height() < $submenu.height() ? $rootItem.height() - 2 : $submenu.height() - 2);
  40906. if (containerOffset.h.location > rootOffset.left)
  40907. if (Math.round(containerOffset.v.location) === Math.round(rootOffset.top)) {
  40908. position.offset = "-1 1";
  40909. position.at = "left top";
  40910. position.my = "left top"
  40911. }
  40912. else {
  40913. position.offset = "-1 -1";
  40914. position.at = "left bottom";
  40915. position.my = "left bottom"
  40916. }
  40917. else if (Math.round(containerOffset.v.location) === Math.round(rootOffset.top)) {
  40918. position.offset = "1 1";
  40919. position.at = "right top";
  40920. position.my = "right top"
  40921. }
  40922. else {
  40923. position.offset = "1 -1";
  40924. position.at = "right bottom";
  40925. position.my = "right bottom"
  40926. }
  40927. }
  40928. DX.position(this.$contentDelimiter, position)
  40929. }
  40930. }
  40931. });
  40932. DX.registerComponent("dxMenu", ui, ui.dxMenuBase.inherit({
  40933. _setDeprecatedOptions: function() {
  40934. this.callBase();
  40935. $.extend(this._deprecatedOptions, {
  40936. allowSelection: {
  40937. since: "14.2",
  40938. message: 'Use the "selectionMode" option instead'
  40939. },
  40940. submenuHiddenAction: {
  40941. since: "14.2",
  40942. alias: "onSubmenuHidden"
  40943. },
  40944. submenuHidingAction: {
  40945. since: "14.2",
  40946. alias: "onSubmenuHiding"
  40947. },
  40948. submenuShowingAction: {
  40949. since: "14.2",
  40950. alias: "onSubmenuShowing"
  40951. },
  40952. submenuShownAction: {
  40953. since: "14.2",
  40954. alias: "onSubmenuShown"
  40955. }
  40956. })
  40957. },
  40958. _setDefaultOptions: function() {
  40959. this.callBase();
  40960. this.option({
  40961. orientation: "horizontal",
  40962. submenuDirection: "auto",
  40963. showFirstSubmenuMode: {
  40964. name: "onClick",
  40965. delay: {
  40966. show: 50,
  40967. hide: 300
  40968. }
  40969. },
  40970. hideSubmenuOnMouseLeave: false,
  40971. onSubmenuShowing: null,
  40972. onSubmenuShown: null,
  40973. onSubmenuHiding: null,
  40974. onSubmenuHidden: null
  40975. })
  40976. },
  40977. _setOptionsByReference: function() {
  40978. this.callBase();
  40979. $.extend(this._optionsByReference, {
  40980. animation: true,
  40981. selectedItem: true
  40982. })
  40983. },
  40984. _focusTarget: function() {
  40985. return this.element()
  40986. },
  40987. _eventBindingTarget: function() {
  40988. return this.element()
  40989. },
  40990. _getOrientation: function() {
  40991. return this.option("orientation") === "vertical" ? "vertical" : "horizontal"
  40992. },
  40993. _isMenuHorizontal: function() {
  40994. return this._getOrientation() === "horizontal"
  40995. },
  40996. _moveFocus: function(location) {
  40997. var $items = this._itemElements().filter(":visible"),
  40998. isMenuHorizontal = this._isMenuHorizontal(),
  40999. argument,
  41000. $activeItem = this._getActiveItem(true),
  41001. operation,
  41002. navigationAction,
  41003. $newTarget;
  41004. switch (location) {
  41005. case FOCUS_UP:
  41006. operation = isMenuHorizontal ? SHOW_SUBMENU_OPERATION : this._getItemsNavigationOperation(PREVITEM_OPERATION);
  41007. argument = isMenuHorizontal ? $activeItem : $items;
  41008. navigationAction = this._getKeyboardNavigationAction(operation, argument);
  41009. $newTarget = navigationAction();
  41010. break;
  41011. case FOCUS_DOWN:
  41012. operation = isMenuHorizontal ? SHOW_SUBMENU_OPERATION : this._getItemsNavigationOperation(NEXTITEM_OPERATION);
  41013. argument = isMenuHorizontal ? $activeItem : $items;
  41014. navigationAction = this._getKeyboardNavigationAction(operation, argument);
  41015. $newTarget = navigationAction();
  41016. break;
  41017. case FOCUS_RIGHT:
  41018. operation = isMenuHorizontal ? this._getItemsNavigationOperation(NEXTITEM_OPERATION) : SHOW_SUBMENU_OPERATION;
  41019. argument = isMenuHorizontal ? $items : $activeItem;
  41020. navigationAction = this._getKeyboardNavigationAction(operation, argument);
  41021. $newTarget = navigationAction();
  41022. break;
  41023. case FOCUS_LEFT:
  41024. operation = isMenuHorizontal ? this._getItemsNavigationOperation(PREVITEM_OPERATION) : SHOW_SUBMENU_OPERATION;
  41025. argument = isMenuHorizontal ? $items : $activeItem;
  41026. navigationAction = this._getKeyboardNavigationAction(operation, argument);
  41027. $newTarget = navigationAction();
  41028. break;
  41029. default:
  41030. return this.callBase(location)
  41031. }
  41032. if ($newTarget && $newTarget.length !== 0)
  41033. this.option("focusedElement", $newTarget)
  41034. },
  41035. _getItemsNavigationOperation: function(operation) {
  41036. var navOperation = operation;
  41037. if (this.option("rtlEnabled"))
  41038. navOperation = operation === PREVITEM_OPERATION ? NEXTITEM_OPERATION : PREVITEM_OPERATION;
  41039. return navOperation
  41040. },
  41041. _getKeyboardNavigationAction: function(operation, argument) {
  41042. var action = $.noop;
  41043. switch (operation) {
  41044. case SHOW_SUBMENU_OPERATION:
  41045. if (!argument.hasClass(DX_STATE_DISABLED_CLASS))
  41046. action = $.proxy(this._showSubmenu, this, argument);
  41047. break;
  41048. case NEXTITEM_OPERATION:
  41049. action = $.proxy(this._nextItem, this, argument);
  41050. break;
  41051. case PREVITEM_OPERATION:
  41052. action = $.proxy(this._prevItem, this, argument);
  41053. break
  41054. }
  41055. return action
  41056. },
  41057. _init: function() {
  41058. this.callBase();
  41059. this._submenus = []
  41060. },
  41061. _initActions: function() {
  41062. this._actions = {};
  41063. $.each(ACTIONS, $.proxy(function(index, action) {
  41064. this._actions[action] = this._createActionByOption(action) || $.noop
  41065. }, this))
  41066. },
  41067. _render: function() {
  41068. this._visibleSubmenu = [];
  41069. this.callBase();
  41070. this.element().addClass(DX_MENU_CLASS);
  41071. this.setAria("role", "menubar")
  41072. },
  41073. _getHideDelay: function() {
  41074. var delay = this.option("showFirstSubmenuMode").delay;
  41075. if (delay)
  41076. return utils.isObject(delay) ? delay.hide : delay;
  41077. else
  41078. return DEFAULT_HIDE_DELAY
  41079. },
  41080. _getShowDelay: function() {
  41081. var delay = this.option("showFirstSubmenuMode").delay,
  41082. resultDelay;
  41083. if (delay)
  41084. resultDelay = utils.isObject(delay) ? delay.show : delay;
  41085. else
  41086. resultDelay = DEFAULT_SHOW_DELAY;
  41087. return resultDelay
  41088. },
  41089. _renderContainer: function() {
  41090. var isVerticalMenu = this.option("orientation") === "vertical",
  41091. $rootGroup = $("<div>"),
  41092. $itemsContainer = $("<ul>");
  41093. $rootGroup.appendTo(this.element()).addClass(isVerticalMenu ? DX_MENU_VERTICAL_CLASS : DX_MENU_HORIZONTAL_CLASS);
  41094. $itemsContainer.appendTo($rootGroup).addClass(DX_MENU_ITEMS_CONTAINER_CLASS).css("min-height", this._getValueHeight($rootGroup));
  41095. return $itemsContainer
  41096. },
  41097. _getValueHeight: function($root) {
  41098. var $div = $("<div>").html("Jj").css({
  41099. width: "auto",
  41100. position: "fixed",
  41101. top: "-3000px",
  41102. left: "-3000px"
  41103. }).appendTo($root),
  41104. height = $div.height();
  41105. $div.remove();
  41106. return height
  41107. },
  41108. _renderSubmenuItems: function(item, $item) {
  41109. var submenu = this._createSubmenu(item.items, $item);
  41110. this._submenus.push(submenu);
  41111. this._renderBorderElement($item);
  41112. this.callBase(item, $item)
  41113. },
  41114. _createSubmenu: function(items, $rootItem) {
  41115. var $submenuContainer = $("<div>").addClass(DX_CONTEXT_MENU_CLASS).appendTo($rootItem);
  41116. var result = this._createComponent($submenuContainer, "dxSubmenu", $.extend(this._getSubmenuOptions(), {
  41117. items: items,
  41118. position: this.getSubmenuPosition($rootItem)
  41119. }));
  41120. this._attachSubmenuHandlers($rootItem, result);
  41121. return result
  41122. },
  41123. _getSubmenuOptions: function() {
  41124. var $submenuTarget = $("<div>"),
  41125. isMenuHorizontal = this._isMenuHorizontal();
  41126. return {
  41127. itemTemplate: this.option("itemTemplate"),
  41128. templateProvider: this.option("templateProvider"),
  41129. target: $submenuTarget,
  41130. orientation: this.option("orientation"),
  41131. selectionMode: this.option("selectionMode"),
  41132. selectionByClick: this.option("selectionByClick"),
  41133. cssClass: this.option("cssClass"),
  41134. hoverStateEnabled: this.option("hoverStateEnabled"),
  41135. activeStateEnabled: this.option("activeStateEnabled"),
  41136. focusStateEnabled: this.option("focusStateEnabled"),
  41137. animation: this.option("animation"),
  41138. disabled: this.option("disabled"),
  41139. showSubmenuMode: this._getShowSubmenuMode(),
  41140. onSelectionChanged: $.proxy(this._nestedItemOnSelectionChangedHandler, this),
  41141. onItemClick: $.proxy(this._nestedItemOnItemClickHandler, this),
  41142. onLeftFirstItem: isMenuHorizontal ? null : $.proxy(this._moveMainMenuFocus, this, PREVITEM_OPERATION),
  41143. onLeftLastItem: isMenuHorizontal ? null : $.proxy(this._moveMainMenuFocus, this, NEXTITEM_OPERATION),
  41144. onCloseRootSubmenu: isMenuHorizontal ? $.proxy(this._moveMainMenuFocus, this, PREVITEM_OPERATION) : null,
  41145. onExpandLastSubmenu: isMenuHorizontal ? $.proxy(this._moveMainMenuFocus, this, NEXTITEM_OPERATION) : null,
  41146. _remoteSelectionSync: true,
  41147. _notChangePosition: true
  41148. }
  41149. },
  41150. _getShowFirstSubmenuMode: function() {
  41151. var modeName;
  41152. if (utils.isObject(this.option("showFirstSubmenuMode")))
  41153. modeName = this._isDesktopDevice() ? this.option("showFirstSubmenuMode").name : "onClick";
  41154. else
  41155. modeName = this._isDesktopDevice() ? this.option("showFirstSubmenuMode") : "onClick";
  41156. return modeName
  41157. },
  41158. _moveMainMenuFocus: function(direction) {
  41159. var $expandedItem = this.element().find("." + DX_MENU_ITEM_EXPANDED_CLASS).first(),
  41160. $newItem;
  41161. switch (direction) {
  41162. case PREVITEM_OPERATION:
  41163. $newItem = $expandedItem.parent().prev();
  41164. if (!$newItem.length)
  41165. $newItem = $expandedItem.parent().siblings().last();
  41166. $newItem = $newItem.children();
  41167. break;
  41168. case NEXTITEM_OPERATION:
  41169. $newItem = $expandedItem.parent().next();
  41170. if (!$newItem.length)
  41171. $newItem = $expandedItem.parent().siblings().first();
  41172. $newItem = $newItem.children();
  41173. break
  41174. }
  41175. this._visibleSubmenu.length && this._hideSubmenu(this._visibleSubmenu);
  41176. this.focus();
  41177. this.option("focusedElement", $newItem)
  41178. },
  41179. _nestedItemOnSelectionChangedHandler: function(args) {
  41180. var selectedItems = args.addedItems,
  41181. submenu = args.element.dxSubmenu("instance");
  41182. this._clearSelectionInSubmenus(selectedItems[0], submenu);
  41183. this._clearRootSelection();
  41184. this.option("selectedItems", selectedItems)
  41185. },
  41186. _clearSelectionInSubmenus: function(item, targetSubmenu) {
  41187. var that = this,
  41188. cleanAllSubmenus = !arguments.length;
  41189. $.each(this._submenus, function(index, submenu) {
  41190. var $submenu = submenu._itemContainer(),
  41191. isOtherItem = !$submenu.is(targetSubmenu && targetSubmenu._itemContainer()),
  41192. $selectedItem = $submenu.find("." + that._selectedItemClass());
  41193. if (isOtherItem && $selectedItem.length || cleanAllSubmenus) {
  41194. var selectedItemData;
  41195. $selectedItem.removeClass(that._selectedItemClass());
  41196. selectedItemData = that._getItemData($selectedItem);
  41197. if (selectedItemData)
  41198. selectedItemData.selected = false;
  41199. submenu._clearSelectedItems()
  41200. }
  41201. })
  41202. },
  41203. _clearRootSelection: function() {
  41204. var $prevSelectedItem = this.element().find("." + DX_MENU_ITEMS_CONTAINER_CLASS).first().children().children().filter("." + this._selectedItemClass());
  41205. if ($prevSelectedItem.length) {
  41206. var prevSelectedItemData;
  41207. prevSelectedItemData = this._getItemData($prevSelectedItem);
  41208. prevSelectedItemData.selected = false;
  41209. $prevSelectedItem.removeClass(this._selectedItemClass())
  41210. }
  41211. this._clearSelectedItems()
  41212. },
  41213. _nestedItemOnItemClickHandler: function(arg) {
  41214. var onItemClick = this._createActionByOption("onItemClick", {});
  41215. onItemClick(arg)
  41216. },
  41217. _updateSelectedItemOnClick: function(actionArgs) {
  41218. var selectedIndex = this.option("selectedIndex");
  41219. this.callBase(actionArgs);
  41220. if (selectedIndex !== this.option("selectedIndex"))
  41221. this._clearSelectionInSubmenus()
  41222. },
  41223. _attachSubmenuHandlers: function($rootItem, submenu) {
  41224. var that = this,
  41225. $submenuOverlayContent = submenu._overlay.content(),
  41226. submenus = $submenuOverlayContent.find("." + DX_SUBMENU_CLASS),
  41227. submenuMouseLeaveName = events.addNamespace("dxhoverend", this.NAME + "_submenu");
  41228. submenu.option({
  41229. onShowing: $.proxy(this._submenuOnShowingHandler, this, $rootItem, submenu),
  41230. onShown: $.proxy(this._submenuOnShownHandler, this, $rootItem, submenu),
  41231. onHiding: $.proxy(this._submenuOnHidingHandler, this, $rootItem, submenu),
  41232. onHidden: $.proxy(this._submenuOnHiddenHandler, this, $rootItem, submenu)
  41233. });
  41234. $.each(submenus, function(index, submenu) {
  41235. $(submenu).off(submenuMouseLeaveName).on(submenuMouseLeaveName, null, $.proxy(that._submenuMouseLeaveHandler, that, $rootItem))
  41236. })
  41237. },
  41238. _submenuOnShowingHandler: function($rootItem, submenu) {
  41239. var $border = $rootItem.children("." + DX_CONTEXT_MENU_CONTAINER_BORDER_CLASS);
  41240. this._actions.onSubmenuShowing({
  41241. rootItem: $rootItem,
  41242. submenu: submenu
  41243. });
  41244. if (this._options.width !== undefined)
  41245. if (this._options.rtlEnabled)
  41246. $border.css("width", this._$element.width() - $rootItem.position().right);
  41247. else
  41248. $border.css("width", this._$element.width() - $rootItem.position().left);
  41249. $border.show();
  41250. $rootItem.addClass(DX_MENU_ITEM_EXPANDED_CLASS)
  41251. },
  41252. _submenuOnShownHandler: function($rootItem, submenu) {
  41253. this._actions.onSubmenuShown({
  41254. rootItem: $rootItem,
  41255. submenu: submenu
  41256. })
  41257. },
  41258. _submenuOnHidingHandler: function($rootItem, submenu, eventArgs) {
  41259. var $border = $rootItem.children("." + DX_CONTEXT_MENU_CONTAINER_BORDER_CLASS),
  41260. args = eventArgs;
  41261. args.rootItem = $rootItem;
  41262. args.submenu = submenu;
  41263. this._actions.onSubmenuHiding(args);
  41264. eventArgs = args;
  41265. if (!eventArgs.cancel) {
  41266. $border.hide();
  41267. $rootItem.removeClass(DX_MENU_ITEM_EXPANDED_CLASS)
  41268. }
  41269. },
  41270. _submenuOnHiddenHandler: function($rootItem, submenu) {
  41271. this._actions.onSubmenuHidden({
  41272. rootItem: $rootItem,
  41273. submenu: submenu
  41274. })
  41275. },
  41276. _submenuMouseLeaveHandler: function($rootItem, eventArgs) {
  41277. var that = this,
  41278. target = $(eventArgs.relatedTarget).parents("." + DX_CONTEXT_MENU_CLASS)[0],
  41279. contextmenu = this._getSubmenuElementByRootElement($rootItem).dxSubmenu("instance")._overlay.content()[0];
  41280. if (this.option("hideSubmenuOnMouseLeave") && target !== contextmenu) {
  41281. clearTimeout(this._showSubmenuTimer);
  41282. clearTimeout(this._hideSubmenuTimer);
  41283. setTimeout($.proxy(this._hideSubmenuAfterTimeout, this), that._getHideDelay(), $rootItem)
  41284. }
  41285. },
  41286. _hideSubmenuAfterTimeout: function($rootItem) {
  41287. var $submenu = this._getSubmenuElementByRootElement($rootItem),
  41288. hasVisibleSubmenu = this._visibleSubmenu.length,
  41289. isRootItemHovered = $(this._visibleSubmenu.context).hasClass(DX_STATE_HOVER_CLASS);
  41290. if (hasVisibleSubmenu && !this._getFocusedSubmenuItem(this._getSubmenuInstance(this._visibleSubmenu)).length && !isRootItemHovered)
  41291. $submenu.length && this._getSubmenuInstance($submenu).hide()
  41292. },
  41293. _getFocusedSubmenuItem: function($submenu) {
  41294. return $submenu._overlay.content().find("." + DX_STATE_FOCUSED_CLASS)
  41295. },
  41296. _getSubmenuInstance: function($submenu) {
  41297. return $submenu.dxSubmenu("instance")
  41298. },
  41299. _getSubmenuElementByRootElement: function($rootItem) {
  41300. return $rootItem && $rootItem.children("." + DX_CONTEXT_MENU_CLASS)
  41301. },
  41302. _getSubmenuInstanceByRootElement: function($rootItem) {
  41303. var $submenu = this._getSubmenuElementByRootElement($rootItem);
  41304. return $submenu.length && this._getSubmenuInstance($submenu)
  41305. },
  41306. getSubmenuPosition: function($rootItem) {
  41307. var isVerticalMenu = this.option("orientation").toLowerCase() === "vertical",
  41308. submenuDirection = this.option("submenuDirection").toLowerCase(),
  41309. rtlEnabled = this.option("rtlEnabled"),
  41310. submenuPosition = {
  41311. collision: "flip",
  41312. of: $rootItem
  41313. };
  41314. switch (submenuDirection) {
  41315. case"leftortop":
  41316. submenuPosition.at = isVerticalMenu ? "left top" : "left top";
  41317. submenuPosition.my = isVerticalMenu ? "right top" : "left bottom";
  41318. break;
  41319. case"rightorbottom":
  41320. submenuPosition.at = isVerticalMenu ? "right top" : "left bottom";
  41321. submenuPosition.my = isVerticalMenu ? "left top" : "left top";
  41322. break;
  41323. default:
  41324. if (isVerticalMenu) {
  41325. submenuPosition.at = rtlEnabled ? "left top" : "right top";
  41326. submenuPosition.my = rtlEnabled ? "right top" : "left top"
  41327. }
  41328. else {
  41329. submenuPosition.at = rtlEnabled ? "right bottom" : "left bottom";
  41330. submenuPosition.my = rtlEnabled ? "right top" : "left top"
  41331. }
  41332. break
  41333. }
  41334. return submenuPosition
  41335. },
  41336. _renderBorderElement: function($item) {
  41337. $("<div>").appendTo($item).addClass(DX_CONTEXT_MENU_CONTAINER_BORDER_CLASS).hide()
  41338. },
  41339. _hoverStartHandler: function(e) {
  41340. var mouseMoveEventName = events.addNamespace("dxpointermove", this.NAME),
  41341. $item = this._getItemElementByEventArgs(e),
  41342. submenu = this._getSubmenuInstanceByRootElement($item),
  41343. isSelectionActive = utils.isDefined(e.buttons) && e.buttons === 1 || !utils.isDefined(e.buttons) && e.which === 1;
  41344. if (this._isItemDisabled($item))
  41345. return;
  41346. $item.off(mouseMoveEventName);
  41347. if (this._getShowFirstSubmenuMode() === "onHover" && submenu && !isSelectionActive) {
  41348. clearTimeout(this._hideSubmenuTimer);
  41349. clearTimeout(this._showSubmenuTimer);
  41350. if (!submenu._overlay.option("visible")) {
  41351. $item.on(mouseMoveEventName, $.proxy(this._itemMouseMoveHandler, this));
  41352. this._showSubmenuTimer = this._getHideDelay()
  41353. }
  41354. if (!submenu.element().is(this._visibleSubmenu))
  41355. this._hideSubmenu(this._visibleSubmenu)
  41356. }
  41357. },
  41358. _hoverEndHandler: function(eventArg) {
  41359. var that = this,
  41360. $item = this._getItemElementByEventArgs(eventArg);
  41361. if (this._isItemDisabled($item))
  41362. return;
  41363. if ($(eventArg.relatedTarget).hasClass(DX_CONTEXT_MENU_CONTENT_DELIMITER_CLASS))
  41364. return;
  41365. if (this.option("hideSubmenuOnMouseLeave") && !$(eventArg.relatedTarget).hasClass(DX_MENU_ITEMS_CONTAINER_CLASS)) {
  41366. clearTimeout(this._showSubmenuTimer);
  41367. clearTimeout(this._hideSubmenuTimer);
  41368. this._hideSubmenuTimer = setTimeout(function() {
  41369. that._hideSubmenuAfterTimeout($item)
  41370. }, that._getHideDelay())
  41371. }
  41372. },
  41373. _showSubmenu: function($itemElement) {
  41374. var $submenu = this._getSubmenuElementByRootElement($itemElement);
  41375. if (this._visibleSubmenu.length && !this._visibleSubmenu.is($submenu))
  41376. this._hideSubmenu(this._visibleSubmenu);
  41377. $submenu.length && this._getSubmenuInstance($submenu).show();
  41378. this._visibleSubmenu = $submenu;
  41379. this._hoveredRootItem = $itemElement
  41380. },
  41381. _hideSubmenu: function($submenu) {
  41382. $submenu.length && this._getSubmenuInstance($submenu).hide();
  41383. if (this._visibleSubmenu.length && this._visibleSubmenu.is($submenu))
  41384. this._visibleSubmenu = [];
  41385. this._hoveredRootItem = null
  41386. },
  41387. _itemMouseMoveHandler: function(e) {
  41388. var that = this,
  41389. $item = $(e.currentTarget);
  41390. if (this._showSubmenuTimer) {
  41391. clearTimeout(this._hideSubmenuTimer);
  41392. clearTimeout(this._showSubmenuTimer);
  41393. this._showSubmenuTimer = setTimeout(function() {
  41394. if (!that._getSubmenuInstanceByRootElement($item)._overlay.option("visible"))
  41395. that._showSubmenu($item)
  41396. }, that._getShowDelay())
  41397. }
  41398. },
  41399. _updateSubmenuVisibilityOnClick: function(actionArgs) {
  41400. var $item,
  41401. item,
  41402. submenu,
  41403. args = actionArgs.args.length && actionArgs.args[0];
  41404. if (args) {
  41405. args.jQueryEvent.stopPropagation();
  41406. item = args.itemData;
  41407. $item = args.itemElement;
  41408. if (item.disabled)
  41409. return;
  41410. submenu = this._getSubmenuInstanceByRootElement($item);
  41411. this._updateSelectedItemOnClick(actionArgs);
  41412. if (submenu)
  41413. if (submenu._overlay.option("visible")) {
  41414. if (this._getShowFirstSubmenuMode() === "onClick")
  41415. this._hideSubmenu(submenu.element())
  41416. }
  41417. else
  41418. this._showSubmenu($item);
  41419. else if (this._visibleSubmenu.length)
  41420. this._hideSubmenu(this._visibleSubmenu)
  41421. }
  41422. },
  41423. _optionChanged: function(args) {
  41424. if (this._cancelOptionChange)
  41425. return;
  41426. this._hideShownSubmenuOnOptionChange(args.name);
  41427. switch (args.name) {
  41428. case"selectedItems":
  41429. var item = args.value[0];
  41430. if (this._isItemInSubmenu(item)) {
  41431. this._syncSelectionOptions(args.name);
  41432. this._normalizeSelectedItems()
  41433. }
  41434. else
  41435. this.callBase(args);
  41436. break;
  41437. case"orientation":
  41438. case"submenuDirection":
  41439. case"hideSubmenuOnMouseLeave":
  41440. case"showFirstSubmenuMode":
  41441. this._invalidate();
  41442. break;
  41443. case"showSubmenuMode":
  41444. this._changeSubmenusOption(args.name, args.value);
  41445. break;
  41446. case"onSubmenuShowing":
  41447. case"onSubmenuShown":
  41448. case"onSubmenuHiding":
  41449. case"onSubmenuHidden":
  41450. this._initActions();
  41451. break;
  41452. default:
  41453. this.callBase(args)
  41454. }
  41455. },
  41456. _hideShownSubmenuOnOptionChange: function(optionName) {
  41457. if (optionName !== "focusedElement" && this._visibleSubmenu.length)
  41458. this._hideSubmenu(this._visibleSubmenu)
  41459. },
  41460. _changeSubmenusOption: function(name, value) {
  41461. $.each(this._submenus, function(index, submenu) {
  41462. submenu.option(name, value)
  41463. })
  41464. },
  41465. _isItemInSubmenu: function(item) {
  41466. return $.inArray(JSON.stringify(item), this._getStringifiedArray(this.option("items"))) < 0
  41467. },
  41468. selectItem: function(itemElement) {
  41469. var itemData = this._getItemData(itemElement);
  41470. if (this._isItemInSubmenu(itemData))
  41471. $.each(this._submenus, function(index, submenu) {
  41472. if (submenu._isOwnItem(itemData))
  41473. submenu.selectItem(itemElement)
  41474. });
  41475. else
  41476. this.callBase(itemElement)
  41477. }
  41478. }));
  41479. DX.registerComponent("dxSubmenu", ui.dxMenu, dxSubmenu);
  41480. ui.dxMenu.__internals = {}
  41481. })(jQuery, DevExpress);
  41482. /*! Module widgets-web, file ui.treeView.js */
  41483. (function($, DX, undefined) {
  41484. var ui = DX.ui,
  41485. events = ui.events,
  41486. dataUtils = DX.data.utils,
  41487. utils = DX.utils;
  41488. var WIDGET_CLASS = "dx-treeview",
  41489. NODE_CONTAINER_CLASS = "dx-treeview-node-container",
  41490. OPENED_NODE_CONTAINER_CLASS = "dx-treeview-node-container-opened",
  41491. NODE_CLASS = "dx-treeview-node",
  41492. ITEM_CLASS = "dx-treeview-item",
  41493. ITEM_WITH_CHECKBOX_CLASS = "dx-treeview-item-with-checkbox",
  41494. ITEM_DATA_KEY = "dx-treeview-item-data",
  41495. IS_LEAF = "dx-treeview-node-is-leaf",
  41496. TOGGLE_ITEM_VISIBILITY_CLASS = "dx-treeview-toggle-item-visibility",
  41497. TOGGLE_ITEM_VISIBILITY_OPENED_CLASS = "dx-treeview-toggle-item-visibility-opened",
  41498. SELECT_ALL_ITEM_CLASS = "dx-treeview-select-all-item",
  41499. FOCUSED_STATE_CLASS = "dx-state-focused",
  41500. DISABLED_STATE_CLASS = "dx-state-disabled",
  41501. DATA_ITEM_ID = "data-item-id",
  41502. DBLCLICK_EVENT_NAME = "dxdblclick";
  41503. var scrollableContainerUpdatedOnInit = $.noop;
  41504. DX.registerComponent("dxTreeView", ui, ui.CollectionWidget.inherit({
  41505. _supportedKeys: function(e) {
  41506. var click = function(e) {
  41507. var $itemElement = this.option("focusedElement");
  41508. if (!$itemElement)
  41509. return;
  41510. e.target = $itemElement;
  41511. e.currentTarget = $itemElement;
  41512. this._itemClickHandler(e, $itemElement.find(">." + ITEM_CLASS))
  41513. };
  41514. var select = function(e) {
  41515. e.preventDefault();
  41516. this._changeCheckBoxState(this.option("focusedElement"))
  41517. };
  41518. var toggleExpandedNestedItems = function(state, e) {
  41519. if (!this.option("expandAllEnabled"))
  41520. return;
  41521. e.preventDefault();
  41522. var $rootElement = this.option("focusedElement");
  41523. if (!$rootElement)
  41524. return;
  41525. var rootItem = this._getItemData($rootElement.find("." + ITEM_CLASS));
  41526. this._toggleExpandedNestedItems([rootItem], state)
  41527. };
  41528. return $.extend(this.callBase(), {
  41529. enter: this.option("showCheckBoxes") ? select : click,
  41530. space: this.option("showCheckBoxes") ? select : click,
  41531. asterisk: $.proxy(toggleExpandedNestedItems, this, true),
  41532. minus: $.proxy(toggleExpandedNestedItems, this, false)
  41533. })
  41534. },
  41535. _changeCheckBoxState: function($element) {
  41536. var $checkbox = $element.find("> .dx-checkbox");
  41537. var checkboxInstance = $checkbox.dxCheckBox("instance"),
  41538. currentState = checkboxInstance.option("value");
  41539. if (!checkboxInstance.option("disabled"))
  41540. this._updateItemSelection(!currentState, $element.find("." + ITEM_CLASS).get(0), true, $element)
  41541. },
  41542. _toggleExpandedNestedItems: function(items, state) {
  41543. if (!items)
  41544. return;
  41545. for (var i = 0, len = items.length; i < len; i++) {
  41546. var item = items[i];
  41547. this._toggleExpandedState(item, state);
  41548. this._toggleExpandedNestedItems(item.items, state)
  41549. }
  41550. },
  41551. _getNodeElementById: function(id) {
  41552. return this.element().find("[" + DATA_ITEM_ID + "='" + id + "']")
  41553. },
  41554. _activeStateUnit: "." + ITEM_CLASS,
  41555. _setDefaultOptions: function() {
  41556. this.callBase();
  41557. this.option({
  41558. animationEnabled: true,
  41559. dataStructure: "tree",
  41560. expandedItems: [],
  41561. expandAllEnabled: false,
  41562. keyExpr: "id",
  41563. displayExpr: "text",
  41564. selectedExpr: "selected",
  41565. expandedExpr: "expanded",
  41566. disabledExpr: "disabled",
  41567. itemsExpr: "items",
  41568. parentIdExpr: "parentId",
  41569. hasItemsExpr: "hasItems",
  41570. showCheckBoxes: false,
  41571. selectNodesRecursive: true,
  41572. selectAllEnabled: false,
  41573. selectAllText: "(" + Globalize.localize("dxList-selectAll") + ")",
  41574. onItemSelected: null,
  41575. onItemExpanded: null,
  41576. onItemCollapsed: null,
  41577. scrollDirection: "vertical",
  41578. virtualModeEnabled: false,
  41579. rootValue: 0,
  41580. focusStateEnabled: false,
  41581. selectionMode: "multi"
  41582. })
  41583. },
  41584. _setDeprecatedOptions: function() {
  41585. this.callBase();
  41586. $.extend(this._deprecatedOptions, {
  41587. selectedItems: {
  41588. since: "14.2",
  41589. message: "Use item.selected instead"
  41590. },
  41591. expandedItems: {
  41592. since: "14.2",
  41593. message: "Use item.expanded instead"
  41594. }
  41595. })
  41596. },
  41597. _initSelectedItems: $.noop,
  41598. _syncSelectionOptions: $.noop,
  41599. _fireSelectionChanged: function() {
  41600. var selectionChangePromise = this._selectionChangePromise;
  41601. $.when(selectionChangePromise).done($.proxy(function() {
  41602. this._createActionByOption("onSelectionChanged", {excludeValidators: ["disabled", "readOnly"]})()
  41603. }, this))
  41604. },
  41605. _initExpressions: function() {
  41606. this._compileKeyAccessors();
  41607. this._compileDisplayAccessors();
  41608. this._compileSelectedAccessors();
  41609. this._compileExpandedAccessors();
  41610. this._compileItemsAccessors();
  41611. this._compileParentIdAccessors();
  41612. this._compileDisabledAccessors();
  41613. this._compileHasItemsAccessors()
  41614. },
  41615. _initDynamicTemplates: function() {
  41616. var displayExpr = this.option("displayExpr");
  41617. if (displayExpr !== "text" && displayExpr !== "html")
  41618. this._dynamicTemplates["item"] = new ui.DefaultTemplate($.proxy(function(itemData) {
  41619. var $itemContent = $("<div>"),
  41620. icon = itemData.icon || itemData.iconSrc;
  41621. if (icon)
  41622. utils.getImageContainer(icon).appendTo($itemContent);
  41623. $("<span>").text(this._displayGetter(itemData)).appendTo($itemContent);
  41624. return $itemContent
  41625. }, this));
  41626. else
  41627. delete this._dynamicTemplates["item"]
  41628. },
  41629. _compileKeyAccessors: function() {
  41630. this._keyGetter = dataUtils.compileGetter(this.option("keyExpr"));
  41631. this._keySetter = dataUtils.compileSetter(this.option("keyExpr"))
  41632. },
  41633. _compileDisplayAccessors: function() {
  41634. this._displayGetter = dataUtils.compileGetter(this.option("displayExpr"));
  41635. this._displaySetter = dataUtils.compileSetter(this.option("displayExpr"))
  41636. },
  41637. _compileSelectedAccessors: function() {
  41638. this._selectedGetter = dataUtils.compileGetter(this.option("selectedExpr"));
  41639. this._selectedSetter = dataUtils.compileSetter(this.option("selectedExpr"))
  41640. },
  41641. _compileExpandedAccessors: function() {
  41642. this._expandedGetter = dataUtils.compileGetter(this.option("expandedExpr"));
  41643. this._expandedSetter = dataUtils.compileSetter(this.option("expandedExpr"))
  41644. },
  41645. _compileItemsAccessors: function() {
  41646. this._itemsGetter = dataUtils.compileGetter(this.option("itemsExpr"));
  41647. this._itemsSetter = dataUtils.compileSetter(this.option("itemsExpr"))
  41648. },
  41649. _compileParentIdAccessors: function() {
  41650. this._parentIdGetter = dataUtils.compileGetter(this.option("parentIdExpr"));
  41651. this._parentIdSetter = dataUtils.compileSetter(this.option("parentIdExpr"))
  41652. },
  41653. _compileDisabledAccessors: function() {
  41654. this._disabledGetter = dataUtils.compileGetter(this.option("disabledExpr"));
  41655. this._disabledSetter = dataUtils.compileSetter(this.option("disabledExpr"))
  41656. },
  41657. _compileHasItemsAccessors: function() {
  41658. this._hasItemsGetter = dataUtils.compileGetter(this.option("hasItemsExpr"));
  41659. this._hasItemsSetter = dataUtils.compileSetter(this.option("hasItemsExpr"))
  41660. },
  41661. _defaultOptionsRules: function() {
  41662. return this.callBase().concat([{
  41663. device: function(device) {
  41664. return DX.devices.real().generic && !DX.devices.isSimulator()
  41665. },
  41666. options: {
  41667. hoverStateEnabled: true,
  41668. focusStateEnabled: true
  41669. }
  41670. }])
  41671. },
  41672. _optionChanged: function(args) {
  41673. var name = args.name,
  41674. value = args.value;
  41675. switch (name) {
  41676. case"selectAllEnabled":
  41677. if (value) {
  41678. if (!this._$selectAllItem || !this._$selectAllItem.length)
  41679. this._renderSelectAllItem()
  41680. }
  41681. else if (this._$selectAllItem) {
  41682. this._$selectAllItem.remove();
  41683. delete this._$selectAllItem
  41684. }
  41685. break;
  41686. case"selectAllText":
  41687. if (this._$selectAllItem)
  41688. this._$selectAllItem.dxCheckBox("instance").option("text", value);
  41689. break;
  41690. case"scrollDirection":
  41691. this._scrollableContainer.option("direction", value);
  41692. break;
  41693. case"selectedItems":
  41694. if (this._$selectAllItem) {
  41695. var selectAllItem = this._$selectAllItem.dxCheckBox("instance"),
  41696. selectAllItemValue = selectAllItem.option("value");
  41697. if (selectAllItemValue && this._itemsCount === value.length)
  41698. return;
  41699. this._suppressUpdateSelectAllItemValue = true;
  41700. selectAllItem.option("value", this._calculateSelectAllItemValue());
  41701. this._suppressUpdateSelectAllItemValue = false
  41702. }
  41703. break;
  41704. case"items":
  41705. this._suppressDeprecatedWarnings();
  41706. delete this._$selectAllItem;
  41707. if (this.option("selectedItems").length)
  41708. this.option("selectedItems", []);
  41709. if (this.option("expandedItems").length)
  41710. this.option("expandedItems", []);
  41711. this.callBase(args);
  41712. this._resumeDeprecatedWarnings();
  41713. break;
  41714. case"keyExpr":
  41715. case"displayExpr":
  41716. if (!this._dynamicTemplates["item"])
  41717. this._initDynamicTemplates();
  41718. this._initExpressions();
  41719. this.repaint();
  41720. break;
  41721. case"itemsExpr":
  41722. case"selectedExpr":
  41723. case"expandedExpr":
  41724. case"parentIdExpr":
  41725. case"disabledExpr":
  41726. case"hasItemsExpr":
  41727. this._initExpressions();
  41728. this.repaint();
  41729. break;
  41730. case"dataStructure":
  41731. case"showCheckBoxes":
  41732. case"rootValue":
  41733. this.repaint();
  41734. break;
  41735. case"expandedItems":
  41736. var isFocused = this.element().hasClass(FOCUSED_STATE_CLASS);
  41737. this.repaint();
  41738. if (isFocused) {
  41739. this.element().focus();
  41740. var key = this.option("focusedElement").attr(DATA_ITEM_ID);
  41741. var $node = this._getNodeElementById(key);
  41742. this.option("focusedElement", $node)
  41743. }
  41744. break;
  41745. case"selectNodesRecursive":
  41746. case"onItemSelected":
  41747. case"onItemExpanded":
  41748. case"onItemCollapsed":
  41749. case"expandAllEnabled":
  41750. case"animationEnabled":
  41751. case"virtualModeEnabled":
  41752. break;
  41753. case"virtualModeEnabled":
  41754. case"rootValue":
  41755. this.callBase(args);
  41756. break;
  41757. default:
  41758. this.callBase(args)
  41759. }
  41760. },
  41761. _nodes: [],
  41762. _initDataSource: function() {
  41763. this.callBase();
  41764. if (this._isVirtualMode())
  41765. this._dataSource.filter(this.option("parentIdExpr"), this.option("rootValue"))
  41766. },
  41767. _dataSourceLoadErrorHandler: function() {
  41768. this._renderEmptyMessage()
  41769. },
  41770. _init: function() {
  41771. this._initExpressions();
  41772. this.callBase();
  41773. this._initDynamicTemplates()
  41774. },
  41775. _render: function() {
  41776. var that = this;
  41777. this.element().addClass(WIDGET_CLASS);
  41778. this._itemsCount = 0;
  41779. this.element().off("dxpointerdown").on("dxpointerdown", function(e) {
  41780. var $target = $(e.target).closest(that._activeStateUnit);
  41781. if (!$target.length)
  41782. e.preventDefault()
  41783. });
  41784. this._makeNodes();
  41785. this._setKeyForItems(this._nodes, 1);
  41786. this.callBase();
  41787. this.setAria("role", "tree");
  41788. if (this._isVirtualMode() && this._dataSource && !this._dataSource.items().length)
  41789. this._initialized = false
  41790. },
  41791. _makeNodes: function() {
  41792. this._nodes = this._getSmartItemsCopy(this.option("items"));
  41793. if (this.option("dataStructure") === "plain")
  41794. this._nodes = this._createHierarchicalStructure(this._nodes)
  41795. },
  41796. _getSmartItemsCopy: function(items) {
  41797. var that = this,
  41798. result = [];
  41799. $.each(items, function(_, item) {
  41800. var itemCopy = $.extend(true, {}, item);
  41801. if (that._itemHasChildren(itemCopy)) {
  41802. var children = that._itemsGetter(itemCopy);
  41803. var childrenCopy = that._getSmartItemsCopy(children);
  41804. that._itemsSetter(itemCopy, childrenCopy)
  41805. }
  41806. result.push(itemCopy)
  41807. });
  41808. return result
  41809. },
  41810. _setKeyForItems: function(items, startKey) {
  41811. var that = this;
  41812. $.each(items, function(index, item) {
  41813. if (that._isPrimitiveValue(item))
  41814. item = that._makeObjectFromPrimitive(item);
  41815. if (utils.isDefined(that._keyGetter(item)))
  41816. return false;
  41817. that._keySetter(item, startKey);
  41818. startKey++;
  41819. if (that._itemHasChildren(item))
  41820. startKey = that._setKeyForItems(that._itemsGetter(item), startKey)
  41821. });
  41822. return startKey
  41823. },
  41824. _makePlainItems: function() {
  41825. return this._makePlainList(this.option("items"), null, true)
  41826. },
  41827. _makePlainNodes: function() {
  41828. return this._makePlainList(this._nodes, null, true)
  41829. },
  41830. _updateSelectionItemsOption: function() {
  41831. var that = this,
  41832. selectedItems = [];
  41833. $.each(that._plainItems, function(_, item) {
  41834. if (that._selectedGetter(item))
  41835. selectedItems.push(item)
  41836. });
  41837. return selectedItems
  41838. },
  41839. _renderContentImpl: function() {
  41840. var items = this._nodes;
  41841. if (items.length) {
  41842. this._makePlainStructures();
  41843. this._applyExpandedItemsFromOption();
  41844. this._applySelectedItemsFromOption(items);
  41845. var plainList = this._makePlainList(items, null);
  41846. if (this.option("selectNodesRecursive")) {
  41847. items = this._calculateChildrenSelectedState(items);
  41848. this._calculateParentSelectedState(plainList)
  41849. }
  41850. this._calculateParentExpandedState(plainList);
  41851. this._createParentFieldForEachItem(items);
  41852. this._suppressDeprecatedWarnings();
  41853. var selectedItems = this._updateSelectionItemsOption();
  41854. if (selectedItems.length)
  41855. this.option("selectedItems", selectedItems);
  41856. this._resumeDeprecatedWarnings();
  41857. this._renderScrollableContainer();
  41858. var $nodeContainer = this._renderNodeContainer();
  41859. this._scrollableContainer.content().append($nodeContainer);
  41860. this._renderItems($nodeContainer, items, true);
  41861. if (this.option("selectAllEnabled"))
  41862. this._renderSelectAllItem($nodeContainer)
  41863. }
  41864. this._renderEmptyMessage()
  41865. },
  41866. _makePlainStructures: function() {
  41867. this._startIndex = 1;
  41868. this._plainItems = this._makePlainItems();
  41869. this._startIndex = 1;
  41870. this._plainNodes = this._makePlainNodes()
  41871. },
  41872. _isVirtualMode: function() {
  41873. return this.option("virtualModeEnabled") && this.option("dataSource")
  41874. },
  41875. _fireContentReadyAction: function() {
  41876. this.callBase();
  41877. if (this._scrollableContainer && this._scrollableContainer.content().height() > this.element().height()) {
  41878. this._scrollableContainer.update();
  41879. scrollableContainerUpdatedOnInit()
  41880. }
  41881. },
  41882. _createHierarchicalStructure: function(items) {
  41883. var result = [],
  41884. lookup = {},
  41885. itemCount = items.length,
  41886. i;
  41887. for (i = 0; i < itemCount; i++) {
  41888. lookup[this._keyGetter(items[i])] = items[i];
  41889. this._itemsSetter(items[i], [])
  41890. }
  41891. for (i = 0; i < itemCount; i++) {
  41892. var parentId = this._parentIdGetter(items[i]),
  41893. node = this._createNode(items[i]);
  41894. if (parentId) {
  41895. var children = this._itemsGetter(lookup[parentId]);
  41896. children.push(node)
  41897. }
  41898. else
  41899. result.push(node)
  41900. }
  41901. return result
  41902. },
  41903. _createNode: function(itemData) {
  41904. var node = {};
  41905. this._keySetter(node, this._keyGetter(itemData));
  41906. this._displaySetter(node, this._displayGetter(itemData));
  41907. this._itemsSetter(node, this._itemsGetter(itemData));
  41908. this._expandedSetter(node, this._expandedGetter(itemData));
  41909. this._disabledSetter(node, this._disabledGetter(itemData));
  41910. if (itemData.hasOwnProperty(this.option("selectedExpr")) && typeof this._selectedGetter(itemData) !== "undefined")
  41911. this._selectedSetter(node, this._selectedGetter(itemData));
  41912. else
  41913. this._selectedSetter(node, false);
  41914. return node
  41915. },
  41916. _createParentFieldForEachItem: function(items, parent) {
  41917. var that = this;
  41918. parent = parent ? $.extend(true, {}, parent) : null;
  41919. $.each(items, function(_, item) {
  41920. that._itemsCount++;
  41921. if (utils.isDefined(parent) && that._itemsGetter(parent))
  41922. that._itemsSetter(parent, null);
  41923. if (that._isPrimitiveValue(item))
  41924. item = that._makeObjectFromPrimitive(item);
  41925. item.parent = parent;
  41926. that._plainNodes[that._keyGetter(item)].parent = parent;
  41927. if (that._itemHasChildren(item))
  41928. that._createParentFieldForEachItem(that._itemsGetter(item), item)
  41929. })
  41930. },
  41931. _makeObjectFromPrimitive: function(item) {
  41932. var key = item;
  41933. item = {};
  41934. this._keySetter(item, key);
  41935. return item
  41936. },
  41937. _isPrimitiveValue: function(value) {
  41938. return $.inArray($.type(value), ["object", "array", "function"]) === -1
  41939. },
  41940. _itemHasChildren: function(item) {
  41941. var items = this._itemsGetter(item);
  41942. return items && items.length
  41943. },
  41944. _renderScrollableContainer: function() {
  41945. this._scrollableContainer = this._createComponent($("<div />").appendTo(this.element()), "dxScrollable", {
  41946. direction: this.option("scrollDirection"),
  41947. useKeyboard: false
  41948. })
  41949. },
  41950. _renderNodeContainer: function($parent) {
  41951. var $container = $("<ul />").addClass(NODE_CONTAINER_CLASS);
  41952. this.setAria("role", "group", $container);
  41953. if ($parent) {
  41954. var itemData = this._getItemData($parent.find("> ." + ITEM_CLASS));
  41955. if (this._expandedGetter(itemData))
  41956. $container.addClass(OPENED_NODE_CONTAINER_CLASS);
  41957. $container.appendTo($parent)
  41958. }
  41959. return $container
  41960. },
  41961. _renderItems: function($nodeContainer, items) {
  41962. var that = this,
  41963. showCheckBoxes = that.option("showCheckBoxes");
  41964. $.each(items, function(i, item) {
  41965. if (that._isPrimitiveValue(item))
  41966. item = that._makeObjectFromPrimitive(item);
  41967. var key = that._keyGetter(item);
  41968. var $node = $("<li />").addClass(NODE_CLASS).appendTo($nodeContainer).attr(DATA_ITEM_ID, key);
  41969. var sourceItem = that._getSourceItemByKey(key);
  41970. that.setAria({
  41971. role: "treeitem",
  41972. label: that._displayGetter(sourceItem) || "",
  41973. expanded: sourceItem.items && (that._expandedGetter(sourceItem) || "false")
  41974. }, $node);
  41975. if (showCheckBoxes)
  41976. that._renderCheckBox($node, item);
  41977. var $item = that._renderItem.call(that, i, sourceItem, $node);
  41978. that._attachDblclickToItem($item);
  41979. if (that._hasItemsGetter(sourceItem) !== false) {
  41980. if (that._isVirtualMode()) {
  41981. that._renderToggleItemVisibilityIcon($node, item);
  41982. that._renderNodeContainer($node);
  41983. return
  41984. }
  41985. var nestedItems = that._itemsGetter(item);
  41986. if (nestedItems && $.isArray(nestedItems) && nestedItems.length) {
  41987. that._renderToggleItemVisibilityIcon($node, item);
  41988. var $nestedNodeContainer = that._renderNodeContainer($node);
  41989. if (that._expandedGetter(item)) {
  41990. that._renderItems($nestedNodeContainer, nestedItems, false);
  41991. $nestedNodeContainer.addClass(OPENED_NODE_CONTAINER_CLASS)
  41992. }
  41993. }
  41994. else
  41995. that._addLeafClass($node)
  41996. }
  41997. else
  41998. that._addLeafClass($node)
  41999. });
  42000. this._renderFocusTarget()
  42001. },
  42002. _addLeafClass: function($node) {
  42003. $node.addClass(IS_LEAF)
  42004. },
  42005. _attachDblclickToItem: function($item) {
  42006. var that = this,
  42007. eventName = events.addNamespace(DBLCLICK_EVENT_NAME, that.NAME);
  42008. $item.off(eventName).on(eventName, function() {
  42009. var itemData = that._getItemData($item);
  42010. that._toggleExpandedState(itemData)
  42011. })
  42012. },
  42013. _toggleExpandedState: function(itemData, state, e) {
  42014. if (this._isVirtualMode()) {
  42015. var $node = this._getNodeElementById(this._getItemKey(itemData));
  42016. this._createLoadIndicator($node)
  42017. }
  42018. var currentState = this._expandedGetter(itemData);
  42019. if (this._disabledGetter(itemData))
  42020. return;
  42021. if (utils.isDefined(currentState) && currentState === state)
  42022. return;
  42023. if (!utils.isDefined(state))
  42024. state = !currentState;
  42025. this._updateExpandedState(itemData, state);
  42026. this._updateExpandedItemsUI(itemData, state);
  42027. this._fireExpandedStateUpdatedEvt(state, itemData, e)
  42028. },
  42029. _createLoadIndicator: function($node) {
  42030. var $icon = $node.find(">." + TOGGLE_ITEM_VISIBILITY_CLASS),
  42031. $nodeContainer = $node.find(" > ." + NODE_CONTAINER_CLASS);
  42032. if (!$icon.hasClass(TOGGLE_ITEM_VISIBILITY_OPENED_CLASS) && $nodeContainer.is(":empty")) {
  42033. this._createComponent("<div>", "dxLoadIndicator", {
  42034. width: 15,
  42035. height: 15
  42036. }).element().appendTo($node);
  42037. $icon.css("display", "none")
  42038. }
  42039. },
  42040. _getSourceItemByKey: function(key) {
  42041. return this._plainItems[key]
  42042. },
  42043. _getItemKey: function(itemData) {
  42044. var result = this._keyGetter(itemData);
  42045. if (!utils.isDefined(result))
  42046. result = this._getKeyForSourceItem(itemData);
  42047. return result
  42048. },
  42049. _getKeyForSourceItem: function(itemData) {
  42050. var result = null;
  42051. $.each(this._plainItems, function(key, item) {
  42052. if (itemData === item) {
  42053. result = key;
  42054. return false
  42055. }
  42056. });
  42057. return result
  42058. },
  42059. _getNodeByKey: function(key) {
  42060. return this._plainNodes[key]
  42061. },
  42062. _renderSelectAllItem: function($container) {
  42063. $container = $container || this.element().find("." + NODE_CONTAINER_CLASS).first();
  42064. this._$selectAllItem = $("<div />").addClass(SELECT_ALL_ITEM_CLASS);
  42065. this._createComponent(this._$selectAllItem, "dxCheckBox", {
  42066. value: this._calculateSelectAllItemValue(),
  42067. text: this.option("selectAllText"),
  42068. onValueChanged: $.proxy(this._toggleSelectAll, this)
  42069. });
  42070. $container.before(this._$selectAllItem)
  42071. },
  42072. _calculateSelectAllItemValue: function() {
  42073. this._suppressDeprecatedWarnings();
  42074. var result = false,
  42075. selectedItemsCount = this.option("selectedItems").length;
  42076. if (selectedItemsCount)
  42077. result = this._itemsCount === selectedItemsCount ? true : undefined;
  42078. this._resumeDeprecatedWarnings();
  42079. return result
  42080. },
  42081. _toggleSelectAll: function(args) {
  42082. if (!this._suppressUpdateSelectAllItemValue) {
  42083. this._suppressDeprecatedWarnings();
  42084. this._updateAllItems(this._nodes, args.value);
  42085. if (!args.value)
  42086. this.option("selectedItems", []);
  42087. else {
  42088. var selectedItems = this._updateSelectionItemsOption();
  42089. this.option("selectedItems", selectedItems)
  42090. }
  42091. this._resumeDeprecatedWarnings();
  42092. this._fireSelectionChanged()
  42093. }
  42094. },
  42095. _updateAllItems: function(nodes, value) {
  42096. var that = this;
  42097. $.each(nodes, function(_, node) {
  42098. var $node = that._getNodeElementById(that._keyGetter(node));
  42099. var itemData = that._getSourceItemByKey(that._keyGetter(node)),
  42100. currentState = that._selectedGetter(node);
  42101. if (currentState === value)
  42102. return true;
  42103. if ($node.length)
  42104. $node.find("> .dx-checkbox").dxCheckBox("instance").option("value", value);
  42105. that._commonSelectedSetter(itemData, node, value);
  42106. $node = null;
  42107. if (that._itemHasChildren(node))
  42108. that._updateAllItems(that._itemsGetter(node), value)
  42109. })
  42110. },
  42111. _applySelectedItemsFromOption: function(items) {
  42112. var that = this;
  42113. this._suppressDeprecatedWarnings();
  42114. $.each(this.option("selectedItems"), function(_, item) {
  42115. var currentItem = that._getItemFromArray(item, items);
  42116. if (currentItem) {
  42117. var currentNode = that._getNodeByKey(that._keyGetter(currentItem));
  42118. that._commonSelectedSetter(currentItem, currentNode, true)
  42119. }
  42120. var node = that._getNodeByKey(that._getItemKey(item));
  42121. that._commonSelectedSetter(item, node, true)
  42122. });
  42123. this._resumeDeprecatedWarnings()
  42124. },
  42125. _applyExpandedItemsFromOption: function() {
  42126. var that = this;
  42127. this._suppressDeprecatedWarnings();
  42128. $.each(this.option("expandedItems"), function(_, item) {
  42129. var node = that._getNodeByKey(that._getItemKey(item));
  42130. that._commonExpandedSetter(item, node, true)
  42131. });
  42132. this._resumeDeprecatedWarnings()
  42133. },
  42134. _commonExpandedSetter: function(item, node, value) {
  42135. this._expandedSetter(item, value);
  42136. this._expandedSetter(node, value)
  42137. },
  42138. _commonSelectedSetter: function(item, node, value) {
  42139. this._selectedSetter(item, value);
  42140. this._selectedSetter(node, value)
  42141. },
  42142. _calculateChildrenSelectedState: function(items) {
  42143. var that = this;
  42144. $.each(items, function(_, item) {
  42145. if (that._selectedGetter(item))
  42146. if (that._itemHasChildren(item))
  42147. $.each(that._itemsGetter(item), function(_, child) {
  42148. var sourceItem = that._getSourceItemByKey(that._keyGetter(child));
  42149. that._commonSelectedSetter(sourceItem, child, true)
  42150. });
  42151. if (that._itemHasChildren(item))
  42152. that._itemsSetter(item, that._calculateChildrenSelectedState(that._itemsGetter(item)))
  42153. });
  42154. return items
  42155. },
  42156. _makePlainList: function(items, plainList, makeHash) {
  42157. var that = this,
  42158. dataStructure = makeHash ? {} : [];
  42159. plainList = plainList || dataStructure;
  42160. $.each(items, function(_, item) {
  42161. if (makeHash) {
  42162. if (that._isPrimitiveValue(item))
  42163. item = that._makeObjectFromPrimitive(item);
  42164. var index = that._keyGetter(item);
  42165. if (!utils.isDefined(index))
  42166. index = that._startIndex;
  42167. plainList[index] = item;
  42168. that._startIndex++
  42169. }
  42170. else
  42171. plainList.push(item);
  42172. if (that._itemHasChildren(item))
  42173. that._makePlainList(that._itemsGetter(item), plainList, makeHash)
  42174. });
  42175. return plainList
  42176. },
  42177. _calculateParentSelectedState: function(list) {
  42178. var listSize = list.length - 1,
  42179. that = this;
  42180. function isSelected(child) {
  42181. return that._selectedGetter(child) === true
  42182. }
  42183. function isIntermediate(child) {
  42184. return child.hasOwnProperty(that.option("selectedExpr")) && typeof that._selectedGetter(child) === "undefined"
  42185. }
  42186. for (var i = listSize; i >= 0; i--) {
  42187. if (this._selectedGetter(list[i]))
  42188. continue;
  42189. var children = this._itemsGetter(list[i]);
  42190. if (children && children.length) {
  42191. var selectedChildren = $.grep(children, isSelected),
  42192. indeterminateChildren = $.grep(children, isIntermediate),
  42193. sourceItem = this._getSourceItemByKey(this._keyGetter(list[i])),
  42194. selected = false;
  42195. if (selectedChildren.length)
  42196. selected = selectedChildren.length === children.length ? true : undefined;
  42197. else if (indeterminateChildren.length)
  42198. selected = undefined;
  42199. that._commonSelectedSetter(list[i], sourceItem, selected)
  42200. }
  42201. }
  42202. return list
  42203. },
  42204. _calculateParentExpandedState: function(list) {
  42205. var listSize = list.length - 1,
  42206. that = this;
  42207. function isExpanded(child) {
  42208. return that._expandedGetter(child) === true
  42209. }
  42210. for (var i = listSize; i >= 0; i--) {
  42211. if (this._expandedGetter(list[i]))
  42212. continue;
  42213. var children = this._itemsGetter(list[i]);
  42214. if (children && children.length) {
  42215. var expandedChildren = $.grep(children, isExpanded);
  42216. if (expandedChildren.length) {
  42217. var sourceItem = this._getSourceItemByKey(this._keyGetter(list[i]));
  42218. this._commonExpandedSetter(list[i], sourceItem, true)
  42219. }
  42220. }
  42221. }
  42222. },
  42223. _renderCheckBox: function($node, node) {
  42224. var checkBoxValue = this._calculateCheckBoxValue(node);
  42225. $node.addClass(ITEM_WITH_CHECKBOX_CLASS);
  42226. this.setAria("selected", checkBoxValue, $node);
  42227. var $checkbox = $("<div />").appendTo($node);
  42228. this._createComponent($checkbox, "dxCheckBox", {
  42229. value: checkBoxValue,
  42230. onValueChanged: $.proxy(this._changeCheckboxValue, this),
  42231. focusStateEnabled: false,
  42232. disabled: this._disabledGetter(node)
  42233. });
  42234. this._attachCheckboxClick($checkbox, node)
  42235. },
  42236. _attachCheckboxClick: function($checkbox, node) {
  42237. var eventName = events.addNamespace("dxclick", this.NAME),
  42238. key = this._keyGetter(node);
  42239. var handleItemSelected = function(e) {
  42240. this._itemJQueryEventHandler(e, "onItemSelected", {node: this._getNodeByKey(key)})
  42241. };
  42242. $checkbox.off(eventName).on(eventName, $.proxy(handleItemSelected, this))
  42243. },
  42244. _renderToggleItemVisibilityIcon: function($node, itemData) {
  42245. var $icon = $("<div />").addClass(TOGGLE_ITEM_VISIBILITY_CLASS).appendTo($node);
  42246. if (this._expandedGetter(itemData) && !this._isVirtualMode()) {
  42247. $icon.addClass(TOGGLE_ITEM_VISIBILITY_OPENED_CLASS);
  42248. $node.parent().addClass(OPENED_NODE_CONTAINER_CLASS)
  42249. }
  42250. if (this._disabledGetter(itemData))
  42251. $icon.addClass(DISABLED_STATE_CLASS);
  42252. this._renderToggleItemVisibilityIconClick($icon, itemData)
  42253. },
  42254. _renderToggleItemVisibilityIconClick: function($icon, itemData) {
  42255. var eventName = events.addNamespace("dxclick", this.NAME),
  42256. that = this;
  42257. $icon.off(eventName).on(eventName, function(e) {
  42258. var $item = $icon.parent().find(">." + ITEM_CLASS),
  42259. itemData = that._getItemData($item);
  42260. that._toggleExpandedState(itemData, undefined, e)
  42261. })
  42262. },
  42263. _updateExpandedState: function(itemData, isExpanded) {
  42264. this._suppressDeprecatedWarnings();
  42265. var expandedItems = this.option("expandedItems"),
  42266. key = this._getItemKey(itemData),
  42267. node = this._getNodeByKey(key),
  42268. that = this;
  42269. that._commonExpandedSetter(itemData, node, isExpanded);
  42270. if (isExpanded) {
  42271. if (!that._getItemFromArray(itemData, expandedItems))
  42272. expandedItems.push(itemData)
  42273. }
  42274. else
  42275. $.each(expandedItems, function(i, item) {
  42276. if (that._keyGetter(item) === key) {
  42277. expandedItems.splice(i, 1);
  42278. return false
  42279. }
  42280. });
  42281. this._resumeDeprecatedWarnings()
  42282. },
  42283. _updateExpandedItemsUI: function(itemData, state) {
  42284. var $node = this._getNodeElementById(this._getItemKey(itemData)),
  42285. $icon = $node.find(">." + TOGGLE_ITEM_VISIBILITY_CLASS),
  42286. $nodeContainer = $node.find(" > ." + NODE_CONTAINER_CLASS);
  42287. $icon.toggleClass(TOGGLE_ITEM_VISIBILITY_OPENED_CLASS, state);
  42288. this.setAria("expanded", state, $node);
  42289. this._renderNestedItems($nodeContainer);
  42290. this._animateNodeContainer($nodeContainer, state)
  42291. },
  42292. _animateNodeContainer: function($nodeContainer, state) {
  42293. var nodeHeight = $nodeContainer.height();
  42294. DX.fx.stop($nodeContainer, true);
  42295. DX.fx.animate($nodeContainer, {
  42296. type: "custom",
  42297. duration: this.option("animationEnabled") ? 400 : 0,
  42298. from: {"max-height": state ? 0 : nodeHeight},
  42299. to: {"max-height": state ? nodeHeight : 0},
  42300. start: function() {
  42301. $nodeContainer.addClass(OPENED_NODE_CONTAINER_CLASS)
  42302. },
  42303. complete: $.proxy(function() {
  42304. $nodeContainer.css("max-height", "none");
  42305. $nodeContainer.toggleClass(OPENED_NODE_CONTAINER_CLASS, state);
  42306. this._scrollableContainer.update()
  42307. }, this)
  42308. })
  42309. },
  42310. _fireExpandedStateUpdatedEvt: function(isExpanded, itemData, e) {
  42311. var optionName = isExpanded ? "onItemExpanded" : "onItemCollapsed",
  42312. itemKey = this._getItemKey(itemData),
  42313. node = this._getNodeByKey(itemKey);
  42314. var handler = this.option(optionName);
  42315. if (handler)
  42316. handler.call(this, {
  42317. itemData: itemData,
  42318. node: node,
  42319. itemElement: this._getNodeElementById(this._keyGetter(itemData)).find(">." + ITEM_CLASS),
  42320. jQueryEvent: e
  42321. })
  42322. },
  42323. _getParentById: function(nodes, id) {
  42324. var parent;
  42325. $.each(nodes, function(_, node) {
  42326. if (node.id === id)
  42327. parent = node;
  42328. return
  42329. });
  42330. return parent
  42331. },
  42332. _renderNestedItems: function($container) {
  42333. if (!$container.is(":empty"))
  42334. return;
  42335. var itemElement = $container.parent().find(">." + ITEM_CLASS),
  42336. itemData = this._getItemData(itemElement),
  42337. itemKey = this._getItemKey(itemData),
  42338. node = this._getNodeByKey(itemKey);
  42339. if (this._isVirtualMode())
  42340. this._renderVirtualNodes($container);
  42341. else
  42342. this._renderItems($container, this._itemsGetter(node), false)
  42343. },
  42344. _renderVirtualNodes: function($container) {
  42345. var itemElement = $container.parent().find(">." + ITEM_CLASS),
  42346. itemData = this._getItemData(itemElement),
  42347. itemKey = this._getItemKey(itemData),
  42348. that = this;
  42349. this._dataSource.filter([this.option("parentIdExpr"), itemKey]);
  42350. this._dataSource.load().done(function(data) {
  42351. var virtualItems = [];
  42352. $.each(data, function(_, item) {
  42353. virtualItems.push(that._createNode(item))
  42354. });
  42355. that._renderItems($container, virtualItems, false);
  42356. if (virtualItems.length && !that._selectedGetter(itemData)) {
  42357. var firstItemKey = that._keyGetter(virtualItems[0]),
  42358. $firstChild = that._getNodeElementById(firstItemKey);
  42359. that._updateParentsState(that._getNodeByKey(firstItemKey), $firstChild)
  42360. }
  42361. that._normalizeIconState(itemElement, virtualItems.length)
  42362. })
  42363. },
  42364. _normalizeIconState: function(itemElement, hasNewItems) {
  42365. var $loadIndicator = itemElement.siblings(".dx-loadindicator"),
  42366. $icon = itemElement.siblings("." + TOGGLE_ITEM_VISIBILITY_CLASS);
  42367. $loadIndicator.dxLoadIndicator("instance").option("visible", false);
  42368. if (!hasNewItems) {
  42369. itemElement.siblings("." + TOGGLE_ITEM_VISIBILITY_CLASS).removeClass(TOGGLE_ITEM_VISIBILITY_CLASS);
  42370. itemElement.parent().addClass(IS_LEAF)
  42371. }
  42372. else
  42373. $icon.css("display", "block")
  42374. },
  42375. _dataSourceChangedHandler: function(newItems) {
  42376. if (this._initialized && this._isVirtualMode()) {
  42377. this.option().items = this.option("items").concat(newItems);
  42378. this._updateNodesFields(newItems)
  42379. }
  42380. else
  42381. this.option("items", newItems)
  42382. },
  42383. _updateNodes: function() {
  42384. this._makeNodes();
  42385. this._makePlainStructures()
  42386. },
  42387. _calculateCheckBoxValue: function(itemData) {
  42388. var result;
  42389. if (this._isVirtualMode())
  42390. result = !!itemData.selected;
  42391. else
  42392. result = itemData.hasOwnProperty(this.option("selectedExpr")) ? this._selectedGetter(itemData) : false;
  42393. return result
  42394. },
  42395. _changeCheckboxValue: function(e) {
  42396. if (this._isVirtualMode())
  42397. this._updateNodesFields();
  42398. var $node = e.element.parent("." + NODE_CLASS),
  42399. itemData = this._getItemData($node.find("> ." + ITEM_CLASS)),
  42400. value = e.value,
  42401. key = this._getItemKey(itemData),
  42402. node = this._getNodeByKey(key);
  42403. this._commonSelectedSetter(itemData, node, value);
  42404. this.setAria("selected", value, $node);
  42405. if (e.jQueryEvent && !this.option("selectNodesRecursive"))
  42406. this._fireSelectionChanged();
  42407. if (!e.jQueryEvent || !this.option("selectNodesRecursive"))
  42408. return;
  42409. this._updateParentsAndChildren(node, value, false, $node)
  42410. },
  42411. _updateNodesFields: function(newItems) {
  42412. if (this._isVirtualMode()) {
  42413. var parentId = this._dataSource.filter() && this._dataSource.filter()[1];
  42414. if (parentId && parentId !== this.option("rootValue")) {
  42415. var parentNode = this._getNodeByKey(parentId),
  42416. selectNodesRecursive = this.option("selectNodesRecursive");
  42417. if (newItems && newItems.length)
  42418. this._itemsSetter(parentNode, newItems);
  42419. this._updateNodes();
  42420. if (newItems && this._selectedGetter(parentNode)) {
  42421. if (selectNodesRecursive)
  42422. $.each(newItems, $.proxy(function(_, item) {
  42423. this._selectedSetter(item, true)
  42424. }, this))
  42425. }
  42426. else {
  42427. if (selectNodesRecursive)
  42428. this._calculateParentSelectedState(this._makePlainList(this._nodes, null));
  42429. this._createParentFieldForEachItem(this._nodes)
  42430. }
  42431. }
  42432. }
  42433. },
  42434. _updateParentsAndChildren: function(node, childValue, suppressOnSelectionChanged, $node) {
  42435. if (node.parent && node.parent !== null)
  42436. this._updateParentsState(node, $node);
  42437. if (node.items && node.items.length)
  42438. this._updateChildrenState(this._itemsGetter(node), childValue, $node);
  42439. this._suppressDeprecatedWarnings();
  42440. var selectedItems = this._updateSelectionItemsOption();
  42441. this.option("selectedItems", selectedItems);
  42442. this._resumeDeprecatedWarnings();
  42443. if (!suppressOnSelectionChanged)
  42444. this._fireSelectionChanged()
  42445. },
  42446. _getItemFromArray: function(itemData, data) {
  42447. var result = null,
  42448. that = this,
  42449. key = that._keyGetter(itemData);
  42450. $.each(data, function(_, item) {
  42451. if (key === that._keyGetter(item)) {
  42452. result = item;
  42453. return false
  42454. }
  42455. });
  42456. return result
  42457. },
  42458. _calculateSelectedItemsOption: function(value, itemData) {
  42459. var key = this._getItemKey(itemData),
  42460. node = this._getNodeByKey(key);
  42461. this._commonSelectedSetter(itemData, node, value)
  42462. },
  42463. _reduceSelectedItemsOption: function(selectedItems, itemData) {
  42464. var that = this,
  42465. itemDataKey = that._keyGetter(itemData);
  42466. $.each(selectedItems, function(index, item) {
  42467. if (itemDataKey === that._keyGetter(item))
  42468. return false
  42469. })
  42470. },
  42471. _updateParentsState: function(node, $node) {
  42472. var parentNode = this._getNodeByKey(this._keyGetter(node.parent)),
  42473. $parentNode,
  42474. that = this;
  42475. $.each(this._itemsGetter(parentNode), function(_, item) {
  42476. if (that._keyGetter(node) === that._keyGetter(item))
  42477. that._selectedSetter(item, that._selectedGetter(node))
  42478. });
  42479. var nodesCount = this._itemsGetter(parentNode).length,
  42480. selectedNodesCount = this._getSelectedChildrenFromNode(parentNode),
  42481. intermediateNodesCount = this._getIntermediateChildrenFromNode(parentNode),
  42482. parentValue;
  42483. if (selectedNodesCount === nodesCount)
  42484. parentValue = true;
  42485. else if (!selectedNodesCount && !intermediateNodesCount)
  42486. parentValue = false;
  42487. if ($node && this.option("showCheckBoxes")) {
  42488. $parentNode = $($node.parents("." + NODE_CLASS)[0]);
  42489. $parentNode.find("> .dx-checkbox").dxCheckBox("instance").option("value", parentValue)
  42490. }
  42491. this._updateParentField(node, parentValue);
  42492. this._selectedSetter(parentNode, parentValue);
  42493. if (parentNode.parent)
  42494. this._updateParentsState(parentNode, $parentNode);
  42495. this._calculateSelectedItemsOption(parentValue, this._getSourceItemByKey(this._keyGetter(node.parent)))
  42496. },
  42497. _getSelectedChildrenFromNode: function(node) {
  42498. var items = this._itemsGetter(node),
  42499. that = this;
  42500. if (items && items.length)
  42501. return $.grep(items, function(item) {
  42502. return that._selectedGetter(item) === true
  42503. }).length;
  42504. return 0
  42505. },
  42506. _getIntermediateChildrenFromNode: function(node) {
  42507. var items = this._itemsGetter(node),
  42508. that = this;
  42509. if (items && items.length)
  42510. return $.grep(items, function(item) {
  42511. return item.hasOwnProperty(that.option("selectedExpr")) && that._selectedGetter(item) === undefined
  42512. }).length;
  42513. return 0
  42514. },
  42515. _updateChildrenState: function(childNodes, value, $node) {
  42516. var that = this;
  42517. $.each(childNodes, function(_, childNode) {
  42518. var itemData = that._getSourceItemByKey(that._keyGetter(childNode));
  42519. that._updateParentField(childNode, value);
  42520. that._calculateSelectedItemsOption(value, itemData);
  42521. if (that._itemHasChildren(childNode))
  42522. that._updateChildrenState(that._itemsGetter(childNode), value)
  42523. });
  42524. if ($node) {
  42525. var $childrenContainer = $node.find("> ." + NODE_CONTAINER_CLASS);
  42526. $childrenContainer.find(".dx-checkbox").each(function(_, checkbox) {
  42527. $(checkbox).dxCheckBox("instance").option("value", value)
  42528. })
  42529. }
  42530. },
  42531. _updateParentField: function(node, value) {
  42532. if (node.parent)
  42533. this._selectedSetter(node.parent, value)
  42534. },
  42535. _itemEventHandlerImpl: function(initiator, action, actionArgs) {
  42536. var $itemElement = $(initiator).closest("." + NODE_CLASS).find("> ." + ITEM_CLASS);
  42537. actionArgs = $.extend({
  42538. itemElement: $itemElement,
  42539. itemData: this._getItemData($itemElement)
  42540. }, actionArgs);
  42541. return action(actionArgs)
  42542. },
  42543. _itemClass: function() {
  42544. return ITEM_CLASS
  42545. },
  42546. _itemDataKey: function() {
  42547. return ITEM_DATA_KEY
  42548. },
  42549. _selectionEnabled: function() {
  42550. return true
  42551. },
  42552. _attachClickEvent: function() {
  42553. var that = this,
  42554. itemSelector = that._itemSelector(),
  42555. eventName = events.addNamespace("dxclick", that.NAME),
  42556. pointerDownEvent = events.addNamespace("dxpointerdown", this.NAME);
  42557. that._itemContainer().off(eventName, itemSelector).on(eventName, itemSelector, function(e) {
  42558. that._itemClickHandler(e, $(this))
  42559. }).off(pointerDownEvent, itemSelector).on(pointerDownEvent, itemSelector, $.proxy(this._itemPointerDownHandler, this))
  42560. },
  42561. _itemClickHandler: function(e, $item) {
  42562. var itemData = this._getItemData($item),
  42563. node = this._getNodeByKey(this._getItemKey(itemData));
  42564. this._itemJQueryEventHandler(e, "onItemClick", {node: node})
  42565. },
  42566. _updateItemSelection: function(value, itemElement, suppressOnSelectionChanged, $node) {
  42567. var itemData = itemElement.nodeType ? this._getItemData(itemElement) : itemElement,
  42568. key = this._getItemKey(itemData),
  42569. node = this._getNodeByKey(key);
  42570. if (this._disabledGetter(itemData))
  42571. return;
  42572. var currentState = this._selectedGetter(node);
  42573. if (currentState === value)
  42574. return;
  42575. if (!$node) {
  42576. var $tmpNode = this._getNodeElementById(key);
  42577. if ($tmpNode.length)
  42578. $node = $tmpNode
  42579. }
  42580. if ($node)
  42581. $node.find("> .dx-checkbox").dxCheckBox("instance").option("value", value);
  42582. this._commonSelectedSetter(itemData, node, value);
  42583. this._calculateSelectedItemsOption(value, node);
  42584. if (this.option("selectNodesRecursive"))
  42585. this._updateParentsAndChildren(node, value, suppressOnSelectionChanged, $node);
  42586. else {
  42587. this._suppressDeprecatedWarnings();
  42588. var selectedItems = this._updateSelectionItemsOption();
  42589. this.option("selectedItems", selectedItems);
  42590. this._resumeDeprecatedWarnings()
  42591. }
  42592. var handler = this.option("onItemSelected");
  42593. if (handler)
  42594. handler.call(this, {
  42595. itemData: itemData,
  42596. node: node
  42597. })
  42598. },
  42599. _updateSelectionToFirstItem: function($items, startIndex) {
  42600. var itemIndex = startIndex;
  42601. while (itemIndex >= 0) {
  42602. var $item = $($items[itemIndex]);
  42603. this._updateItemSelection(true, $item.find("." + ITEM_CLASS).get(0), true, $item);
  42604. itemIndex--
  42605. }
  42606. },
  42607. _updateSelectionToLastItem: function($items, startIndex) {
  42608. var itemIndex = startIndex,
  42609. length = $items.length;
  42610. while (itemIndex < length) {
  42611. var $item = $($items[itemIndex]);
  42612. this._updateItemSelection(true, $item.find("." + ITEM_CLASS).get(0), true, $item);
  42613. itemIndex++
  42614. }
  42615. },
  42616. _enlargeExpandedItemsOption: function(itemData, expandedItems) {
  42617. if (!this._getItemFromArray(itemData, expandedItems)) {
  42618. expandedItems.push(itemData);
  42619. this._expandedSetter(itemData, true)
  42620. }
  42621. if (itemData.parent)
  42622. this._enlargeExpandedItemsOption(itemData.parent, expandedItems);
  42623. return expandedItems
  42624. },
  42625. _reduceExpandedItemsOption: function(node, expandedItems) {
  42626. var that = this,
  42627. nodeKey = that._keyGetter(node);
  42628. var sourceItem = that._getSourceItemByKey(nodeKey);
  42629. that._commonExpandedSetter(sourceItem, node, false);
  42630. $.each(expandedItems, function(i, item) {
  42631. if (that._keyGetter(item) === nodeKey) {
  42632. expandedItems.splice(i, 1);
  42633. if (that._itemHasChildren(node))
  42634. $.each(that._itemsGetter(node), function(_, child) {
  42635. var sourceItemChild = that._getSourceItemByKey(that._keyGetter(child));
  42636. that._commonExpandedSetter(sourceItemChild, child, false);
  42637. that._reduceExpandedItemsOption(child, expandedItems)
  42638. })
  42639. }
  42640. });
  42641. return expandedItems
  42642. },
  42643. _focusInHandler: function(e) {
  42644. var currentTarget = e.currentTarget,
  42645. focusTargets = this._focusTarget();
  42646. if ($.inArray(currentTarget, focusTargets) !== -1)
  42647. $(currentTarget).addClass(FOCUSED_STATE_CLASS);
  42648. if (!this.option("focusedElement")) {
  42649. var $activeItem = this._getActiveItem();
  42650. this.option("focusedElement", $activeItem.closest("." + NODE_CLASS))
  42651. }
  42652. else
  42653. this._setFocusedItem(this.option("focusedElement"))
  42654. },
  42655. _setFocusedItem: function($target) {
  42656. if (!$target || !$target.length)
  42657. return;
  42658. if (!$target.children().hasClass(DISABLED_STATE_CLASS))
  42659. this.callBase($target)
  42660. },
  42661. _itemPointerDownHandler: function(e) {
  42662. if (!this.option("focusStateEnabled"))
  42663. return;
  42664. var $target = $(e.target).closest("." + NODE_CLASS);
  42665. if ($target.hasClass(NODE_CLASS))
  42666. if ($target.hasClass(DISABLED_STATE_CLASS))
  42667. this.option("focusedElement", null);
  42668. else
  42669. this.option("focusedElement", $target)
  42670. },
  42671. _moveFocus: function(location, e) {
  42672. var FOCUS_UP = "up",
  42673. FOCUS_DOWN = "down",
  42674. FOCUS_FIRST = "first",
  42675. FOCUS_LAST = "last",
  42676. FOCUS_LEFT = this.option("rtlEnabled") ? "right" : "left",
  42677. FOCUS_RIGHT = this.option("rtlEnabled") ? "left" : "right";
  42678. this.element().find("." + NODE_CONTAINER_CLASS).each(function() {
  42679. DX.fx.stop(this, true)
  42680. });
  42681. var $items = this._nodeElements().not(function() {
  42682. return $(this).find(">." + ITEM_CLASS).hasClass(DISABLED_STATE_CLASS)
  42683. });
  42684. switch (location) {
  42685. case FOCUS_UP:
  42686. var $prevItem = this._prevItem($items);
  42687. this.option("focusedElement", $prevItem);
  42688. if (e.shiftKey && this.option("showCheckBoxes"))
  42689. this._updateItemSelection(true, $prevItem.find("." + ITEM_CLASS).get(0), true, $prevItem);
  42690. break;
  42691. case FOCUS_DOWN:
  42692. var $nextItem = this._nextItem($items);
  42693. this.option("focusedElement", $nextItem);
  42694. if (e.shiftKey && this.option("showCheckBoxes"))
  42695. this._updateItemSelection(true, $nextItem.find("." + ITEM_CLASS).get(0), true, $nextItem);
  42696. break;
  42697. case FOCUS_FIRST:
  42698. var $firstItem = $items.first();
  42699. if (e.shiftKey && this.option("showCheckBoxes"))
  42700. this._updateSelectionToFirstItem($items, $items.index(this._prevItem($items)));
  42701. this.option("focusedElement", $firstItem);
  42702. break;
  42703. case FOCUS_LAST:
  42704. var $lastItem = $items.last();
  42705. if (e.shiftKey && this.option("showCheckBoxes"))
  42706. this._updateSelectionToLastItem($items, $items.index(this._nextItem($items)));
  42707. this.option("focusedElement", $lastItem);
  42708. break;
  42709. case FOCUS_RIGHT:
  42710. this._expandFocusedContainer();
  42711. break;
  42712. case FOCUS_LEFT:
  42713. this._collapseFocusedContainer();
  42714. break;
  42715. default:
  42716. this.callBase.apply(this, arguments);
  42717. return
  42718. }
  42719. },
  42720. _nodeElements: function() {
  42721. return this.element().find("." + NODE_CLASS).not(":hidden")
  42722. },
  42723. _expandFocusedContainer: function() {
  42724. var $focusedItem = this.option("focusedElement");
  42725. if (!$focusedItem || $focusedItem.hasClass(IS_LEAF))
  42726. return;
  42727. var $node = $focusedItem.find("." + NODE_CONTAINER_CLASS).eq(0);
  42728. if ($node.hasClass(OPENED_NODE_CONTAINER_CLASS)) {
  42729. this.option("focusedElement", this._nextItem(this._nodeElements()));
  42730. return
  42731. }
  42732. var itemData = this._getItemData($focusedItem.find(">." + ITEM_CLASS));
  42733. this._toggleExpandedState(itemData, true)
  42734. },
  42735. _collapseFocusedContainer: function() {
  42736. var $focusedItem = this.option("focusedElement");
  42737. if (!$focusedItem)
  42738. return;
  42739. var nodeElement = $focusedItem.find("." + NODE_CONTAINER_CLASS).eq(0);
  42740. if (!$focusedItem.hasClass(IS_LEAF) && nodeElement.hasClass(OPENED_NODE_CONTAINER_CLASS)) {
  42741. var itemData = this._getItemData($focusedItem.find(">." + ITEM_CLASS));
  42742. this._toggleExpandedState(itemData, false)
  42743. }
  42744. else {
  42745. var parentElement = $focusedItem.parent("." + NODE_CONTAINER_CLASS);
  42746. var collapsedNode = parentElement.parent("." + NODE_CLASS).eq(0);
  42747. if (collapsedNode.length)
  42748. this.option("focusedElement", collapsedNode)
  42749. }
  42750. },
  42751. updateDimensions: function() {
  42752. var that = this,
  42753. deferred = $.Deferred();
  42754. if (that._scrollableContainer)
  42755. that._scrollableContainer.update().done(function() {
  42756. deferred.resolveWith(that)
  42757. });
  42758. else
  42759. deferred.resolveWith(that);
  42760. return deferred.promise()
  42761. },
  42762. selectItem: function(itemElement) {
  42763. this._updateItemSelection(true, itemElement)
  42764. },
  42765. unselectItem: function(itemElement) {
  42766. this._updateItemSelection(false, itemElement)
  42767. },
  42768. expandItem: function(itemElement) {
  42769. var itemData = this._getItemData($(itemElement));
  42770. this._toggleExpandedState(itemData, true)
  42771. },
  42772. collapseItem: function(itemElement) {
  42773. var itemData = this._getItemData($(itemElement));
  42774. this._toggleExpandedState(itemData, false)
  42775. },
  42776. getNodes: function() {
  42777. return this._nodes
  42778. },
  42779. selectAll: function() {
  42780. this._toggleSelectAll({value: true})
  42781. },
  42782. unselectAll: function() {
  42783. this._toggleSelectAll({value: false})
  42784. }
  42785. }));
  42786. ui.dxTreeView.__internals = {
  42787. WIDGET_CLASS: WIDGET_CLASS,
  42788. NODE_CONTAINER_CLASS: NODE_CONTAINER_CLASS,
  42789. OPENED_NODE_CONTAINER_CLASS: OPENED_NODE_CONTAINER_CLASS,
  42790. ITEM_CLASS: ITEM_CLASS,
  42791. NODE_CLASS: NODE_CLASS,
  42792. ITEM_WITH_CHECKBOX_CLASS: ITEM_WITH_CHECKBOX_CLASS,
  42793. ITEM_DATA_KEY: ITEM_DATA_KEY,
  42794. IS_LEAF: IS_LEAF,
  42795. TOGGLE_ITEM_VISIBILITY_CLASS: TOGGLE_ITEM_VISIBILITY_CLASS,
  42796. TOGGLE_ITEM_VISIBILITY_OPENED_CLASS: TOGGLE_ITEM_VISIBILITY_OPENED_CLASS,
  42797. SELECT_ALL_ITEM_CLASS: SELECT_ALL_ITEM_CLASS,
  42798. scrollableContainerUpdatedOnInitAccessor: function(value) {
  42799. if (value)
  42800. scrollableContainerUpdatedOnInit = value;
  42801. return scrollableContainerUpdatedOnInit
  42802. }
  42803. }
  42804. })(jQuery, DevExpress);
  42805. /*! Module widgets-web, file ui.sortable.js */
  42806. (function($, DX) {
  42807. var ui = DX.ui,
  42808. addNamespace = ui.events.addNamespace;
  42809. var SORTABLE_NAMESPACE = "dxSortable",
  42810. SORTABLE_CLASS = "dx-sortable";
  42811. var elementHasPoint = function(element, x, y) {
  42812. var $item = $(element),
  42813. offset = $item.offset();
  42814. if (x >= offset.left && x <= offset.left + $item.outerWidth(true))
  42815. if (y >= offset.top && y <= offset.top + $item.outerHeight(true))
  42816. return true
  42817. };
  42818. DX.registerComponent("dxSortable", ui, DX.DOMComponent.inherit({
  42819. _setDefaultOptions: function() {
  42820. this.callBase();
  42821. this.option({
  42822. onChanged: null,
  42823. onDragging: null,
  42824. itemRender: null,
  42825. groupSelector: null,
  42826. itemSelector: ".dx-sort-item",
  42827. itemContainerSelector: ".dx-sortable",
  42828. sourceClass: "dx-drag-source",
  42829. dragClass: "dx-drag",
  42830. targetClass: "dx-drag-target"
  42831. })
  42832. },
  42833. _renderItem: function($sourceItem, target) {
  42834. var itemRender = this.option("itemRender"),
  42835. $item;
  42836. if (itemRender)
  42837. $item = itemRender($sourceItem, target);
  42838. else {
  42839. $item = $sourceItem.clone();
  42840. $item.css({
  42841. width: $sourceItem.width(),
  42842. height: $sourceItem.height()
  42843. })
  42844. }
  42845. return $item
  42846. },
  42847. _attachEventHandlers: function() {
  42848. var that = this,
  42849. itemSelector = that.option("itemSelector"),
  42850. itemContainerSelector = that.option("itemContainerSelector"),
  42851. groupSelector = that.option("groupSelector"),
  42852. sourceClass = that.option("sourceClass"),
  42853. dragClass = that.option("dragClass"),
  42854. targetClass = that.option("targetClass"),
  42855. $sourceItem,
  42856. sourceIndex,
  42857. $targetItem,
  42858. $targetGroup,
  42859. startPosition,
  42860. $draggable,
  42861. element = that.element();
  42862. element.off(addNamespace("dxdragstart dxdrag dxdragend dxdragenter dxdragleave dxdrop", SORTABLE_NAMESPACE));
  42863. element.on(addNamespace("dxdragstart", SORTABLE_NAMESPACE), itemSelector, function(e) {
  42864. $sourceItem = $(e.currentTarget);
  42865. startPosition = $sourceItem.offset();
  42866. startPosition.top -= element.offset().top;
  42867. startPosition.left -= element.offset().left;
  42868. $draggable = that._renderItem($sourceItem, 'drag').appendTo(element);
  42869. $targetItem = that._renderItem($sourceItem, 'target');
  42870. $draggable.addClass(dragClass);
  42871. $sourceItem.addClass(sourceClass);
  42872. sourceIndex = $sourceItem.index();
  42873. $targetItem.addClass(targetClass)
  42874. });
  42875. element.on(addNamespace("dxdrag", SORTABLE_NAMESPACE), function(e) {
  42876. if (!$sourceItem)
  42877. return;
  42878. var onDragging = that.option("onDragging"),
  42879. draggingArgs,
  42880. $item,
  42881. $itemContainer,
  42882. $items,
  42883. $groups = groupSelector ? element.find(groupSelector) : element;
  42884. $targetGroup && $targetGroup.removeClass(targetClass);
  42885. $targetGroup = undefined;
  42886. $.each($groups, function() {
  42887. if (elementHasPoint(this, e.pageX, e.pageY)) {
  42888. $targetGroup = $(this);
  42889. return false
  42890. }
  42891. });
  42892. if ($targetGroup) {
  42893. $itemContainer = $targetGroup.find(itemContainerSelector);
  42894. $items = $itemContainer.find(itemSelector);
  42895. $.each($items, function() {
  42896. if (elementHasPoint(this, e.pageX, e.pageY)) {
  42897. $item = $(this);
  42898. return false
  42899. }
  42900. })
  42901. }
  42902. if ($targetGroup && $sourceItem) {
  42903. draggingArgs = {
  42904. sourceGroup: $sourceItem.closest(groupSelector).attr("group"),
  42905. sourceIndex: sourceIndex,
  42906. sourceElement: $sourceItem,
  42907. targetGroup: $targetGroup.attr("group"),
  42908. targetIndex: $targetItem.index()
  42909. };
  42910. onDragging && onDragging(draggingArgs)
  42911. }
  42912. if (draggingArgs && draggingArgs.cancel) {
  42913. $targetGroup = undefined;
  42914. $item = undefined
  42915. }
  42916. $targetGroup && $targetGroup.addClass(targetClass);
  42917. if ($item) {
  42918. if (!$item.hasClass(targetClass)) {
  42919. $targetItem.detach();
  42920. if (!$item.hasClass(sourceClass) && !$item.prev().hasClass(sourceClass))
  42921. $targetItem.insertBefore($item)
  42922. }
  42923. }
  42924. else {
  42925. $targetItem.detach();
  42926. if ($targetGroup && !$items.last().hasClass(sourceClass))
  42927. $targetItem.appendTo($itemContainer)
  42928. }
  42929. $draggable.css({
  42930. top: startPosition.top + e.offset.y,
  42931. left: startPosition.left + e.offset.x
  42932. })
  42933. });
  42934. element.on(addNamespace("dxdragend", SORTABLE_NAMESPACE), function() {
  42935. var onChanged = that.option("onChanged"),
  42936. changedArgs,
  42937. sourceGroup;
  42938. if ($sourceItem) {
  42939. if ($targetGroup) {
  42940. $targetGroup.removeClass(targetClass);
  42941. sourceGroup = $sourceItem.closest(groupSelector).attr("group");
  42942. changedArgs = {
  42943. sourceGroup: sourceGroup,
  42944. sourceIndex: sourceIndex,
  42945. sourceElement: $sourceItem,
  42946. targetGroup: $targetGroup.attr("group"),
  42947. targetIndex: $targetItem.index(),
  42948. removeSourceElement: true
  42949. };
  42950. if (sourceGroup !== changedArgs.targetGroup || $targetItem.parent().length) {
  42951. onChanged && onChanged(changedArgs);
  42952. if (changedArgs.removeSourceElement)
  42953. $sourceItem.remove()
  42954. }
  42955. }
  42956. $sourceItem.removeClass(sourceClass);
  42957. $draggable.remove();
  42958. $sourceItem = null;
  42959. $targetItem.removeClass(targetClass);
  42960. $targetItem = null
  42961. }
  42962. })
  42963. },
  42964. _init: function() {
  42965. this.callBase();
  42966. this._attachEventHandlers()
  42967. },
  42968. _render: function() {
  42969. this.callBase();
  42970. this.element().addClass(SORTABLE_CLASS)
  42971. },
  42972. _optionChanged: function(args) {
  42973. var that = this;
  42974. switch (args.name) {
  42975. case"onDragging":
  42976. case"onChanged":
  42977. case"itemRender":
  42978. case"groupSelector":
  42979. case"itemSelector":
  42980. case"itemContainerSelector":
  42981. case"sourceClass":
  42982. case"targetClass":
  42983. case"dragClass":
  42984. that._attachEventHandlers();
  42985. break;
  42986. default:
  42987. that.callBase(args)
  42988. }
  42989. }
  42990. }))
  42991. })(jQuery, DevExpress);
  42992. /*! Module widgets-web, file ui.dataGrid.js */
  42993. (function($, DX) {
  42994. var ui = DX.ui,
  42995. utils = DX.utils;
  42996. var DATAGRID_ROW_SELECTOR = ".dx-row",
  42997. DATAGRID_DEPRECATED_TEMPLATE_WARNING = "Specifying grid templates with the name of a jQuery selector is now deprecated. Instead, use the jQuery object that references this selector.";
  42998. var ModuleItem = DX.Class.inherit({
  42999. ctor: function(component) {
  43000. var that = this;
  43001. that.component = component;
  43002. that._actions = {};
  43003. that._actionConfigs = {};
  43004. $.each(this.callbackNames() || [], function(index, name) {
  43005. var flags = that.callbackFlags(name);
  43006. that[this] = $.Callbacks(flags)
  43007. })
  43008. },
  43009. callbackNames: function(){},
  43010. callbackFlags: function(name){},
  43011. publicMethods: function(){},
  43012. init: function(){},
  43013. option: function() {
  43014. return this.component.option.apply(this.component, arguments)
  43015. },
  43016. on: function() {
  43017. return this.component.on.apply(this.component, arguments)
  43018. },
  43019. off: function() {
  43020. return this.component.off.apply(this.component, arguments)
  43021. },
  43022. optionChanged: function(args) {
  43023. if (args.name in this._actions) {
  43024. this.createAction(args.name, this._actionConfigs[args.name]);
  43025. args.handled = true
  43026. }
  43027. },
  43028. getAction: function(actionName) {
  43029. return this._actions[actionName]
  43030. },
  43031. setAria: function() {
  43032. return this.component.setAria.apply(this.component, arguments)
  43033. },
  43034. _createComponent: function() {
  43035. return this.component._createComponent.apply(this.component, arguments)
  43036. },
  43037. getController: function(name) {
  43038. return this.component._controllers[name]
  43039. },
  43040. createAction: function(actionName, config) {
  43041. var action;
  43042. if (utils.isFunction(actionName)) {
  43043. action = this.component._createAction($.proxy(actionName, this), config);
  43044. return function(e) {
  43045. action({jQueryEvent: e})
  43046. }
  43047. }
  43048. else {
  43049. this._actions[actionName] = this.component._createActionByOption(actionName, config);
  43050. this._actionConfigs[actionName] = config
  43051. }
  43052. },
  43053. executeAction: function(actionName, options) {
  43054. var action = this._actions[actionName];
  43055. return action && action(options)
  43056. },
  43057. dispose: function() {
  43058. var that = this;
  43059. $.each(that.callbackNames() || [], function() {
  43060. that[this].empty()
  43061. })
  43062. }
  43063. });
  43064. var Controller = ModuleItem;
  43065. var ViewController = Controller.inherit({
  43066. getView: function(name) {
  43067. return this.component._views[name]
  43068. },
  43069. getViews: function() {
  43070. return this.component._views
  43071. }
  43072. });
  43073. var View = ModuleItem.inherit({
  43074. element: function() {
  43075. return this._$element
  43076. },
  43077. _renderCore: function(options){},
  43078. _resizeCore: function(){},
  43079. _afterRender: function($root){},
  43080. _parentElement: function() {
  43081. return this._$parent
  43082. },
  43083. ctor: function(component) {
  43084. this.callBase(component);
  43085. this.renderCompleted = $.Callbacks();
  43086. this.resizeCompleted = $.Callbacks()
  43087. },
  43088. isVisible: function() {
  43089. return true
  43090. },
  43091. getTemplate: function(name) {
  43092. return this.component._getTemplate(name)
  43093. },
  43094. render: function($parent, options) {
  43095. var $element = this._$element,
  43096. isVisible = this.isVisible();
  43097. if (!$element) {
  43098. $element = this._$element = $('<div />').appendTo($parent);
  43099. this._$parent = $parent
  43100. }
  43101. $element.toggle(isVisible);
  43102. if (isVisible) {
  43103. this._renderCore(options);
  43104. this._afterRender($parent);
  43105. this.renderCompleted.fire()
  43106. }
  43107. },
  43108. resize: function() {
  43109. this.isResizing = true;
  43110. this._resizeCore();
  43111. this.resizeCompleted.fire();
  43112. this.isResizing = false
  43113. },
  43114. focus: function() {
  43115. this.element().focus()
  43116. }
  43117. });
  43118. var processModules = function(that, modules) {
  43119. var controllerTypes = {},
  43120. viewTypes = {};
  43121. $.each(modules, function() {
  43122. var controllers = this.controllers,
  43123. moduleName = this.name,
  43124. views = this.views;
  43125. controllers && $.each(controllers, function(name, type) {
  43126. if (controllerTypes[name])
  43127. throw DX.Error("E1001", moduleName, name);
  43128. else if (!(type && type.subclassOf && type.subclassOf(Controller))) {
  43129. type.subclassOf(Controller);
  43130. throw DX.Error("E1002", moduleName, name);
  43131. }
  43132. controllerTypes[name] = type
  43133. });
  43134. views && $.each(views, function(name, type) {
  43135. if (viewTypes[name])
  43136. throw DX.Error("E1003", moduleName, name);
  43137. else if (!(type && type.subclassOf && type.subclassOf(View)))
  43138. throw DX.Error("E1004", moduleName, name);
  43139. viewTypes[name] = type
  43140. })
  43141. });
  43142. $.each(modules, function() {
  43143. var extenders = this.extenders;
  43144. if (extenders) {
  43145. extenders.controllers && $.each(extenders.controllers, function(name, extender) {
  43146. if (controllerTypes[name])
  43147. controllerTypes[name] = controllerTypes[name].inherit(extender)
  43148. });
  43149. extenders.views && $.each(extenders.views, function(name, extender) {
  43150. if (viewTypes[name])
  43151. viewTypes[name] = viewTypes[name].inherit(extender)
  43152. })
  43153. }
  43154. });
  43155. var registerPublicMethods = function(that, name, moduleItem) {
  43156. var publicMethods = moduleItem.publicMethods();
  43157. if (publicMethods)
  43158. $.each(publicMethods, function(index, methodName) {
  43159. if (moduleItem[methodName])
  43160. if (!that[methodName])
  43161. that[methodName] = function() {
  43162. return moduleItem[methodName].apply(moduleItem, arguments)
  43163. };
  43164. else
  43165. throw DX.Error("E1005", methodName);
  43166. else
  43167. throw DX.Error("E1006", name, methodName);
  43168. })
  43169. };
  43170. var createModuleItems = function(moduleTypes) {
  43171. var moduleItems = {};
  43172. $.each(moduleTypes, function(name, moduleType) {
  43173. var moduleItem = new moduleType(that);
  43174. moduleItem.name = name;
  43175. registerPublicMethods(that, name, moduleItem);
  43176. moduleItems[name] = moduleItem
  43177. });
  43178. return moduleItems
  43179. };
  43180. that._controllers = createModuleItems(controllerTypes);
  43181. that._views = createModuleItems(viewTypes)
  43182. };
  43183. var callModuleItemsMethod = function(that, methodName, args) {
  43184. args = args || [];
  43185. if (that._controllers)
  43186. $.each(that._controllers, function() {
  43187. this[methodName] && this[methodName].apply(this, args)
  43188. });
  43189. if (that._views)
  43190. $.each(that._views, function() {
  43191. this[methodName] && this[methodName].apply(this, args)
  43192. })
  43193. };
  43194. DX.registerComponent("dxDataGrid", ui, ui.Widget.inherit({
  43195. _activeStateUnit: DATAGRID_ROW_SELECTOR,
  43196. _setDeprecatedOptions: function() {
  43197. this.callBase();
  43198. $.extend(this._deprecatedOptions, {
  43199. rowClick: {
  43200. since: "14.2",
  43201. alias: "onRowClick"
  43202. },
  43203. cellClick: {
  43204. since: "14.2",
  43205. alias: "onCellClick"
  43206. },
  43207. cellHoverChanged: {
  43208. since: "14.2",
  43209. alias: "onCellHoverChanged"
  43210. },
  43211. cellPrepared: {
  43212. since: "14.2",
  43213. message: "The cellPrepared option is deprecated. Use the onCellPrepared option instead. For further information, see http://js.devexpress.com/Documentation/ApiReference/UI_Widgets/dxDataGrid/Configuration/?version=14_2#onCellPrepared"
  43214. },
  43215. rowPrepared: {
  43216. since: "14.2",
  43217. message: "The rowPrepared option is deprecated. Use the onRowPrepared option instead. For further information, see http://js.devexpress.com/Documentation/ApiReference/UI_Widgets/dxDataGrid/Configuration/?version=14_2#onRowPrepared"
  43218. },
  43219. selectionChanged: {
  43220. since: "14.2",
  43221. alias: "onSelectionChanged"
  43222. },
  43223. dataErrorOccurred: {
  43224. since: "14.2",
  43225. alias: "onDataErrorOccurred"
  43226. },
  43227. initNewRow: {
  43228. since: "14.2",
  43229. alias: "onInitNewRow"
  43230. },
  43231. rowInserting: {
  43232. since: "14.2",
  43233. alias: "onRowInserting"
  43234. },
  43235. rowInserted: {
  43236. since: "14.2",
  43237. alias: "onRowInserted"
  43238. },
  43239. editingStart: {
  43240. since: "14.2",
  43241. alias: "onEditingStart"
  43242. },
  43243. rowUpdating: {
  43244. since: "14.2",
  43245. alias: "onRowUpdating"
  43246. },
  43247. rowUpdated: {
  43248. since: "14.2",
  43249. alias: "onRowUpdated"
  43250. },
  43251. rowRemoving: {
  43252. since: "14.2",
  43253. alias: "onRowRemoving"
  43254. },
  43255. rowRemoved: {
  43256. since: "14.2",
  43257. alias: "onRowRemoved"
  43258. },
  43259. editorPreparing: {
  43260. since: "14.2",
  43261. message: "The editorPreparing option is deprecated. Use the onEditorPreparing option instead. For further information, see http://js.devexpress.com/Documentation/ApiReference/UI_Widgets/dxDataGrid/Configuration/?version=14_2#onEditorPreparing"
  43262. },
  43263. editorPrepared: {
  43264. since: "14.2",
  43265. message: "The editorPrepared option is deprecated. Use the onEditorPrepared option instead. For further information, see http://js.devexpress.com/Documentation/ApiReference/UI_Widgets/dxDataGrid/Configuration/?version=14_2#onEditorPrepared"
  43266. },
  43267. contentReadyAction: {
  43268. since: "14.2",
  43269. alias: "onContentReady"
  43270. }
  43271. })
  43272. },
  43273. _setDefaultOptions: function() {
  43274. var that = this;
  43275. that.callBase();
  43276. $.each(ui.dxDataGrid.modules, function() {
  43277. if ($.isFunction(this.defaultOptions))
  43278. that.option(this.defaultOptions())
  43279. })
  43280. },
  43281. _defaultOptionsRules: function() {
  43282. return this.callBase().concat([{
  43283. device: {platform: "ios"},
  43284. options: {showRowLines: true}
  43285. }, {
  43286. device: function() {
  43287. return DevExpress.browser.webkit
  43288. },
  43289. options: {loadPanel: {animation: {show: {
  43290. easing: 'cubic-bezier(1, 0, 1, 0)',
  43291. duration: 500,
  43292. from: {opacity: 0},
  43293. to: {opacity: 1}
  43294. }}}}
  43295. }])
  43296. },
  43297. _init: function() {
  43298. var that = this;
  43299. that.callBase();
  43300. processModules(that, ui.dxDataGrid.modules);
  43301. callModuleItemsMethod(that, 'init')
  43302. },
  43303. _clean: $.noop,
  43304. _optionChanged: function(args) {
  43305. var that = this;
  43306. callModuleItemsMethod(that, 'optionChanged', [args]);
  43307. if (!args.handled)
  43308. that.callBase(args)
  43309. },
  43310. _dimensionChanged: function() {
  43311. this.updateDimensions()
  43312. },
  43313. _visibilityChanged: function(visible) {
  43314. if (visible)
  43315. this.updateDimensions()
  43316. },
  43317. _renderContentImpl: function() {
  43318. var that = this;
  43319. that.getView('gridView').render(that.element())
  43320. },
  43321. _renderContent: function() {
  43322. this._renderContentImpl()
  43323. },
  43324. _getTemplate: function(templateName) {
  43325. var template = templateName;
  43326. if (DX.utils.isString(template) && template[0] === '#') {
  43327. template = $(templateName);
  43328. DX.utils.logger.warn(DATAGRID_DEPRECATED_TEMPLATE_WARNING)
  43329. }
  43330. return this.callBase(template)
  43331. },
  43332. _dispose: function() {
  43333. var that = this;
  43334. that.callBase();
  43335. callModuleItemsMethod(that, 'dispose')
  43336. },
  43337. isReady: function() {
  43338. return this.getController("data").isReady()
  43339. },
  43340. beginUpdate: function() {
  43341. var that = this;
  43342. that.callBase();
  43343. callModuleItemsMethod(that, 'beginUpdate')
  43344. },
  43345. endUpdate: function() {
  43346. var that = this;
  43347. callModuleItemsMethod(that, 'endUpdate');
  43348. that.callBase()
  43349. },
  43350. getController: function(name) {
  43351. return this._controllers[name]
  43352. },
  43353. getView: function(name) {
  43354. return this._views[name]
  43355. },
  43356. focus: function(element) {
  43357. this.callBase();
  43358. if (utils.isDefined(element))
  43359. this.getController("keyboardNavigation").focus(element)
  43360. }
  43361. }));
  43362. var MAX_EQUAL_KEYS_LEVEL = 3;
  43363. $.extend(ui.dxDataGrid, {
  43364. __internals: {},
  43365. modules: [],
  43366. View: View,
  43367. ViewController: ViewController,
  43368. Controller: Controller,
  43369. registerModule: function(name, module) {
  43370. var modules = this.modules,
  43371. i;
  43372. for (i = 0; i < modules.length; i++)
  43373. if (modules[i].name === name)
  43374. return;
  43375. module.name = name;
  43376. modules.push(module)
  43377. },
  43378. unregisterModule: function(name) {
  43379. this.modules = $.grep(this.modules, function(module) {
  43380. return module.name !== name
  43381. })
  43382. },
  43383. processModules: processModules,
  43384. formatValue: function(value, options) {
  43385. var valueText = DX.formatHelper.format(value, options.format, options.precision) || value && value.toString() || '',
  43386. formatObject = {
  43387. value: value,
  43388. valueText: options.getDisplayFormat ? options.getDisplayFormat(valueText) : valueText
  43389. };
  43390. return options.customizeText ? options.customizeText.call(options, formatObject) : formatObject.valueText
  43391. },
  43392. getDisplayValue: function(column, value) {
  43393. return column.lookup ? column.lookup.calculateCellValue(value) : value
  43394. },
  43395. getGroupRowSummaryText: function(summaryItems, summaryTexts) {
  43396. var result = "(",
  43397. i,
  43398. summaryItem;
  43399. for (i = 0; i < summaryItems.length; i++) {
  43400. summaryItem = summaryItems[i];
  43401. result += (i > 0 ? ", " : "") + ui.dxDataGrid.getSummaryText(summaryItem, summaryTexts)
  43402. }
  43403. return result += ")"
  43404. },
  43405. getSummaryText: function(summaryItem, summaryTexts) {
  43406. var displayFormat = summaryItem.displayFormat || summaryItem.columnCaption && summaryTexts[summaryItem.summaryType + "OtherColumn"] || summaryTexts[summaryItem.summaryType];
  43407. return this.formatValue(summaryItem.value, {
  43408. format: summaryItem.valueFormat,
  43409. precision: summaryItem.precision,
  43410. getDisplayFormat: function(valueText) {
  43411. return displayFormat ? utils.stringFormat(displayFormat, valueText, summaryItem.columnCaption) : valueText
  43412. },
  43413. customizeText: summaryItem.customizeText
  43414. })
  43415. },
  43416. equalKeys: function(key1, key2, level) {
  43417. var propertyName,
  43418. i;
  43419. level = level || 0;
  43420. if (level < MAX_EQUAL_KEYS_LEVEL)
  43421. if (utils.isObject(key1) && utils.isObject(key2)) {
  43422. for (propertyName in key1)
  43423. if (key1.hasOwnProperty(propertyName) && !ui.dxDataGrid.equalKeys(key1[propertyName], key2[propertyName], level + 1))
  43424. return false;
  43425. for (propertyName in key2)
  43426. if (!(propertyName in key1))
  43427. return false;
  43428. return true
  43429. }
  43430. else if (utils.isArray(key1) && utils.isArray(key2)) {
  43431. if (key1.length !== key2.length)
  43432. return false;
  43433. for (i = 0; i < key1.length; i++)
  43434. if (!ui.dxDataGrid.equalKeys(key1[i], key2[i], level + 1))
  43435. return false;
  43436. return true
  43437. }
  43438. else if (utils.isDate(key1) && utils.isDate(key2))
  43439. return key1.getTime() === key2.getTime();
  43440. else
  43441. return key1 === key2;
  43442. return true
  43443. },
  43444. getIndexByKey: function(key, items) {
  43445. var index = -1;
  43446. $.each(items, function(i, item) {
  43447. if (ui.dxDataGrid.equalKeys(key, item.key)) {
  43448. index = i;
  43449. return false
  43450. }
  43451. });
  43452. return index
  43453. },
  43454. normalizeSortingInfo: function(sort) {
  43455. sort = sort || [];
  43456. var result,
  43457. i;
  43458. result = DX.data.utils.normalizeSortingInfo(sort);
  43459. for (i = 0; i < sort.length; i++)
  43460. if (sort && sort[i] && sort[i].isExpanded !== undefined)
  43461. result[i].isExpanded = sort[i].isExpanded;
  43462. return result
  43463. }
  43464. })
  43465. })(jQuery, DevExpress);
  43466. /*! Module widgets-web, file ui.dataGrid.stateStoring.js */
  43467. (function($, DX) {
  43468. var ui = DX.ui,
  43469. utils = DX.utils,
  43470. dataGrid = ui.dxDataGrid;
  43471. dataGrid.StateStoringController = dataGrid.ViewController.inherit(function() {
  43472. var getStorage = function(options) {
  43473. var storage = options.type === 'sessionStorage' ? sessionStorage : localStorage;
  43474. if (!storage)
  43475. throw new Error("E1007");
  43476. return storage
  43477. };
  43478. var getUniqueStorageKey = function(options) {
  43479. return 'dx_datagrid_' + (utils.isDefined(options.storageKey) ? options.storageKey : 'storage')
  43480. };
  43481. var dateReviver = function(key, value) {
  43482. var date;
  43483. if (typeof value === 'string') {
  43484. date = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
  43485. if (date)
  43486. return new Date(Date.UTC(+date[1], +date[2] - 1, +date[3], +date[4], +date[5], +date[6]))
  43487. }
  43488. return value
  43489. };
  43490. var processLoadState = function(that) {
  43491. var columnsController = that.getController('columns'),
  43492. selectionController = that.getController('selection'),
  43493. exportController = that.getController("export"),
  43494. dataController = that.getController('data'),
  43495. pagerView = that.getView('pagerView');
  43496. if (columnsController)
  43497. columnsController.columnsChanged.add(function() {
  43498. $.extend(that._state, {columns: columnsController.getUserState()});
  43499. that.isEnabled() && that.save()
  43500. });
  43501. if (selectionController)
  43502. selectionController.selectionChanged.add(function(keys) {
  43503. $.extend(that._state, {selectedRowKeys: keys});
  43504. that.isEnabled() && that.save()
  43505. });
  43506. if (dataController) {
  43507. that._initialPageSize = that.option("paging.pageSize");
  43508. dataController.changed.add(function() {
  43509. $.extend(that._state, {
  43510. searchText: that.option("searchPanel.text"),
  43511. pageIndex: dataController.pageIndex(),
  43512. pageSize: dataController.pageSize(),
  43513. allowedPageSizes: pagerView ? pagerView.getPageSizes() : undefined
  43514. });
  43515. that.isEnabled() && that.save()
  43516. })
  43517. }
  43518. if (exportController)
  43519. exportController.selectionOnlyChanged.add(function() {
  43520. $.extend(that._state, {exportSelectionOnly: exportController.selectionOnly()});
  43521. that.isEnabled() && that.save()
  43522. })
  43523. };
  43524. var applyState = function(that, state) {
  43525. var allowedPageSizes = state.allowedPageSizes,
  43526. searchText = state.searchText,
  43527. selectedRowKeys = state.selectedRowKeys,
  43528. exportController = that.getController("export"),
  43529. columnsController = that.getController('columns'),
  43530. scrollingMode = that.option('scrolling.mode');
  43531. that.component.beginUpdate();
  43532. if (columnsController)
  43533. columnsController.setUserState(state.columns);
  43534. if (exportController)
  43535. exportController.selectionOnly(state.exportSelectionOnly);
  43536. that.option('selectedRowKeys', selectedRowKeys || []);
  43537. if (allowedPageSizes && that.option('pager.allowedPageSizes') === 'auto')
  43538. that.option('pager').allowedPageSizes = allowedPageSizes;
  43539. that.option('searchPanel.text', searchText || '');
  43540. that.option('paging.pageSize', scrollingMode !== "virtual" && scrollingMode !== "infinite" && state.pageSize ? state.pageSize : that._initialPageSize);
  43541. that.option('paging.pageIndex', state.pageIndex || 0);
  43542. that.component.endUpdate()
  43543. };
  43544. return {
  43545. _loadState: function() {
  43546. var options = this.option('stateStoring');
  43547. if (options.type === 'custom')
  43548. return options.customLoad && options.customLoad();
  43549. try {
  43550. return JSON.parse(getStorage(options).getItem(getUniqueStorageKey(options)), dateReviver)
  43551. }
  43552. catch(e) {
  43553. DX.utils.logger.error(e.message)
  43554. }
  43555. },
  43556. _saveState: function(state) {
  43557. var options = this.option('stateStoring');
  43558. if (options.type === 'custom') {
  43559. options.customSave && options.customSave(state);
  43560. return
  43561. }
  43562. try {
  43563. getStorage(options).setItem(getUniqueStorageKey(options), JSON.stringify(state))
  43564. }
  43565. catch(e) {}
  43566. },
  43567. publicMethods: function() {
  43568. return ['state']
  43569. },
  43570. isEnabled: function() {
  43571. return this.option('stateStoring.enabled')
  43572. },
  43573. init: function() {
  43574. var that = this;
  43575. that._state = {};
  43576. that._isLoaded = false;
  43577. that._isLoading = false;
  43578. that._windowUnloadHandler = function() {
  43579. if (that._savingTimeoutID !== undefined)
  43580. that._saveState(that.state())
  43581. },
  43582. $(window).on('unload', that._windowUnloadHandler);
  43583. processLoadState(that)
  43584. },
  43585. isLoaded: function() {
  43586. return this._isLoaded
  43587. },
  43588. isLoading: function() {
  43589. return this._isLoading
  43590. },
  43591. load: function() {
  43592. var that = this,
  43593. loadResult;
  43594. that._isLoading = true;
  43595. loadResult = that._loadState();
  43596. if (!loadResult || !$.isFunction(loadResult.done))
  43597. loadResult = $.Deferred().resolve(loadResult);
  43598. loadResult.done(function(state) {
  43599. that._isLoaded = true;
  43600. that._isLoading = false;
  43601. that.state(state)
  43602. });
  43603. return loadResult
  43604. },
  43605. state: function(state) {
  43606. var that = this;
  43607. if (!arguments.length)
  43608. return $.extend(true, {}, that._state);
  43609. else {
  43610. that._state = $.extend({}, state);
  43611. applyState(that, $.extend({}, state))
  43612. }
  43613. },
  43614. save: function() {
  43615. var that = this;
  43616. clearTimeout(that._savingTimeoutID);
  43617. that._savingTimeoutID = setTimeout(function() {
  43618. that._saveState(that.state());
  43619. that._savingTimeoutID = undefined
  43620. }, that.option('stateStoring.savingTimeout'))
  43621. },
  43622. optionChanged: function(args) {
  43623. var that = this;
  43624. switch (args.name) {
  43625. case'stateStoring':
  43626. if (that.isEnabled())
  43627. that.load();
  43628. args.handled = true;
  43629. break;
  43630. default:
  43631. that.callBase(args)
  43632. }
  43633. },
  43634. dispose: function() {
  43635. clearTimeout(this._savingTimeoutID);
  43636. $(window).off('unload', this._windowUnloadHandler)
  43637. }
  43638. }
  43639. }());
  43640. dataGrid.registerModule('stateStoring', {
  43641. defaultOptions: function() {
  43642. return {stateStoring: {
  43643. enabled: false,
  43644. storageKey: null,
  43645. type: 'localStorage',
  43646. customLoad: null,
  43647. customSave: null,
  43648. savingTimeout: 2000
  43649. }}
  43650. },
  43651. controllers: {stateStoring: ui.dxDataGrid.StateStoringController},
  43652. extenders: {controllers: {
  43653. columns: {getVisibleColumns: function() {
  43654. var visibleColumns = this.callBase(),
  43655. stateStoringController = this.getController('stateStoring');
  43656. return stateStoringController.isEnabled() && !stateStoringController.isLoaded() ? [] : visibleColumns
  43657. }},
  43658. data: {
  43659. _refreshDataSource: function() {
  43660. var that = this,
  43661. callBase = that.callBase,
  43662. stateStoringController = that.getController('stateStoring');
  43663. if (stateStoringController.isEnabled() && !stateStoringController.isLoaded()) {
  43664. clearTimeout(that._restoreStateTimeoutID);
  43665. that._restoreStateTimeoutID = setTimeout(function() {
  43666. stateStoringController.load().always(function() {
  43667. that._restoreStateTimeoutID = null;
  43668. callBase.call(that)
  43669. })
  43670. })
  43671. }
  43672. else if (!that._restoreStateTimeoutID)
  43673. callBase.call(that)
  43674. },
  43675. isLoading: function() {
  43676. var that = this,
  43677. stateStoringController = that.getController('stateStoring');
  43678. return this.callBase() || stateStoringController.isLoading()
  43679. },
  43680. dispose: function() {
  43681. clearTimeout(this._restoreStateTimeoutID);
  43682. this.callBase()
  43683. }
  43684. }
  43685. }}
  43686. })
  43687. })(jQuery, DevExpress);
  43688. /*! Module widgets-web, file ui.dataGrid.columnsController.js */
  43689. (function($, DX, undefined) {
  43690. var ui = DX.ui,
  43691. dataGrid = ui.dxDataGrid,
  43692. normalizeSortingInfo = dataGrid.normalizeSortingInfo,
  43693. utils = DX.utils,
  43694. normalizeIndexes = utils.normalizeIndexes,
  43695. dataUtils = DX.data.utils,
  43696. isDefined = utils.isDefined;
  43697. var USER_STATE_FIELD_NAMES_15_1 = ['filterValues', 'filterType', 'fixed', 'fixedPosition'],
  43698. USER_STATE_FIELD_NAMES = ['visibleIndex', 'dataField', 'name', 'dataType', 'width', 'visibleWidth', 'visible', 'sortOrder', 'sortIndex', 'groupIndex', 'filterValue', 'selectedFilterOperation'].concat(USER_STATE_FIELD_NAMES_15_1),
  43699. DATAGRID_COMMAND_EXPAND_CLASS = 'dx-command-expand';
  43700. dataGrid.checkChanges = function(changes, changeNames) {
  43701. var changesWithChangeNamesCount = 0,
  43702. i;
  43703. for (i = 0; i < changeNames.length; i++)
  43704. if (changes[changeNames[i]])
  43705. changesWithChangeNamesCount++;
  43706. return changes.length && changes.length === changesWithChangeNamesCount
  43707. };
  43708. var ColumnsController = dataGrid.Controller.inherit(function() {
  43709. var DEFAULT_COLUMN_OPTIONS = {
  43710. visible: true,
  43711. showInColumnChooser: true
  43712. },
  43713. DATATYPE_OPERATIONS = {
  43714. number: ['=', '<>', '<', '>', '<=', '>='],
  43715. string: ['contains', 'notcontains', 'startswith', 'endswith', '=', '<>'],
  43716. date: ['=', '<>', '<', '>', '<=', '>=']
  43717. },
  43718. GROUP_LOCATION = 'group',
  43719. COLUMN_CHOOSER_LOCATION = 'columnChooser';
  43720. var convertNameToCaption = function(name) {
  43721. var captionList = [],
  43722. i,
  43723. char,
  43724. isPrevCharNewWord = false,
  43725. isNewWord = false;
  43726. for (i = 0; i < name.length; i++) {
  43727. char = name.charAt(i);
  43728. isNewWord = char === char.toUpperCase() || char in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
  43729. if (char === '_' || char === '.') {
  43730. char = ' ';
  43731. isNewWord = true
  43732. }
  43733. else if (i === 0) {
  43734. char = char.toUpperCase();
  43735. isNewWord = true
  43736. }
  43737. else if (!isPrevCharNewWord && isNewWord)
  43738. if (captionList.length > 0)
  43739. captionList.push(' ');
  43740. captionList.push(char);
  43741. isPrevCharNewWord = isNewWord
  43742. }
  43743. return captionList.join('')
  43744. };
  43745. var createColumn = function(that, columnOptions, userStateColumnOptions) {
  43746. var commonColumnOptions,
  43747. calculatedColumnOptions;
  43748. if (columnOptions) {
  43749. if (utils.isString(columnOptions))
  43750. columnOptions = {dataField: columnOptions};
  43751. if (columnOptions.command)
  43752. return $.extend(true, {}, columnOptions);
  43753. else {
  43754. commonColumnOptions = that.getCommonSettings();
  43755. if (userStateColumnOptions && userStateColumnOptions.name && userStateColumnOptions.dataField)
  43756. columnOptions = $.extend({}, columnOptions, {dataField: userStateColumnOptions.dataField});
  43757. calculatedColumnOptions = that._createCalculatedColumnOptions(columnOptions);
  43758. return $.extend(true, {}, DEFAULT_COLUMN_OPTIONS, commonColumnOptions, calculatedColumnOptions, columnOptions)
  43759. }
  43760. }
  43761. };
  43762. var createColumnsFromOptions = function(that, columnsOptions) {
  43763. var result = [];
  43764. if (columnsOptions)
  43765. $.each(columnsOptions, function(index, columnOptions) {
  43766. var userStateColumnOptions = that._columnsUserState && checkUserStateColumn(columnOptions, that._columnsUserState[index]) && that._columnsUserState[index],
  43767. column = createColumn(that, columnOptions, userStateColumnOptions);
  43768. if (column)
  43769. result.push(column)
  43770. });
  43771. return result
  43772. };
  43773. var getValueDataType = function(value) {
  43774. var dataType = $.type(value);
  43775. if (dataType !== 'string' && dataType !== 'boolean' && dataType !== 'number' && dataType !== 'date')
  43776. dataType = undefined;
  43777. return dataType
  43778. };
  43779. var getSerializationFormat = function(dataType, value) {
  43780. switch (dataType) {
  43781. case'date':
  43782. if (utils.isNumber(value))
  43783. return 'number';
  43784. else if (utils.isString(value))
  43785. return 'yyyy/MM/dd';
  43786. break;
  43787. case'number':
  43788. if (utils.isString(value))
  43789. return 'string'
  43790. }
  43791. };
  43792. var updateSerializers = function(options, dataType) {
  43793. if (!options.deserializeValue) {
  43794. if (dataType === 'date') {
  43795. options.deserializeValue = function(value) {
  43796. var serializationFormat = this.serializationFormat,
  43797. parsedValue;
  43798. if (!serializationFormat || serializationFormat === 'number' || serializationFormat === 'yyyy/MM/dd') {
  43799. parsedValue = serializationFormat === 'number' ? value : !utils.isDate(value) && Date.parse(value);
  43800. return parsedValue ? new Date(parsedValue) : value
  43801. }
  43802. else if (value !== undefined)
  43803. return Globalize.parseDate(value, serializationFormat)
  43804. };
  43805. options.serializeValue = function(value) {
  43806. var serializationFormat = this.serializationFormat;
  43807. if (serializationFormat === 'number')
  43808. return value && value.valueOf && value.valueOf();
  43809. else if (serializationFormat)
  43810. return Globalize.format(value, serializationFormat);
  43811. else
  43812. return value
  43813. }
  43814. }
  43815. if (dataType === 'number') {
  43816. options.deserializeValue = function(value) {
  43817. return value ? Number(value) : value
  43818. };
  43819. options.serializeValue = function(value) {
  43820. return value ? value.toString() : value
  43821. }
  43822. }
  43823. }
  43824. };
  43825. var getAlignmentByDataType = function(dataType, isRTL) {
  43826. switch (dataType) {
  43827. case'number':
  43828. return 'right';
  43829. case'boolean':
  43830. return 'center';
  43831. case'date':
  43832. return 'left';
  43833. default:
  43834. return isRTL ? 'right' : 'left'
  43835. }
  43836. };
  43837. var getFormatByDataType = function(dataType) {
  43838. switch (dataType) {
  43839. case"date":
  43840. return "shortDate"
  43841. }
  43842. };
  43843. var getCustomizeTextByDataType = function(dataType) {
  43844. if (dataType === 'boolean')
  43845. return function(e) {
  43846. if (e.value === true)
  43847. return this.trueText || 'true';
  43848. else if (e.value === false)
  43849. return this.falseText || 'false';
  43850. else
  43851. return e.valueText || ''
  43852. }
  43853. };
  43854. var createColumnsFromDataSource = function(that, dataSource) {
  43855. var firstItems = getFirstItems(dataSource),
  43856. fieldName,
  43857. processedFields = {},
  43858. i,
  43859. result = [];
  43860. for (i = 0; i < firstItems.length; i++)
  43861. if (firstItems[i])
  43862. for (fieldName in firstItems[i])
  43863. processedFields[fieldName] = true;
  43864. for (fieldName in processedFields)
  43865. if (fieldName.indexOf('__') !== 0) {
  43866. var column = createColumn(that, fieldName);
  43867. result.push(column)
  43868. }
  43869. return result
  43870. };
  43871. var equalSortParameters = function(sortParameters1, sortParameters2) {
  43872. var i;
  43873. if ($.isArray(sortParameters1) && $.isArray(sortParameters2)) {
  43874. if (sortParameters1.length !== sortParameters2.length)
  43875. return false;
  43876. else
  43877. for (i = 0; i < sortParameters1.length; i++)
  43878. if (sortParameters1[i].selector !== sortParameters2[i].selector || sortParameters1[i].desc !== sortParameters2[i].desc || Boolean(sortParameters1[i].isExpanded) !== Boolean(sortParameters2[i].isExpanded))
  43879. return false;
  43880. return true
  43881. }
  43882. else
  43883. return (!sortParameters1 || !sortParameters1.length) === (!sortParameters2 || !sortParameters2.length)
  43884. };
  43885. var getFirstItems = function(dataSource) {
  43886. var groupsCount,
  43887. items = [];
  43888. var getFirstItemsCore = function(items, groupsCount) {
  43889. var i,
  43890. childItems;
  43891. if (!items || !groupsCount)
  43892. return items;
  43893. for (i = 0; i < items.length; i++) {
  43894. childItems = getFirstItemsCore(items[i].items || items[i].collapsedItems, groupsCount - 1);
  43895. if (childItems && childItems.length)
  43896. return childItems
  43897. }
  43898. };
  43899. if (dataSource && dataSource.items().length > 0) {
  43900. groupsCount = normalizeSortingInfo(dataSource.group()).length;
  43901. items = getFirstItemsCore(dataSource.items(), groupsCount) || []
  43902. }
  43903. return items
  43904. };
  43905. var updateColumnIndexes = function(that) {
  43906. $.each(that._columns, function(index, column) {
  43907. column.index = index
  43908. });
  43909. $.each(that._commandColumns, function(index, column) {
  43910. column.index = -(index + 1)
  43911. })
  43912. };
  43913. var updateColumnGroupIndexes = function(that, currentColumn) {
  43914. normalizeIndexes(that._columns, 'groupIndex', currentColumn, function(column) {
  43915. var grouped = column.grouped;
  43916. delete column.grouped;
  43917. return grouped
  43918. })
  43919. };
  43920. var updateColumnSortIndexes = function(that, currentColumn) {
  43921. $.each(that._columns, function(index, column) {
  43922. if (isDefined(column.sortIndex) && !isSortOrderValid(column.sortOrder))
  43923. delete column.sortIndex
  43924. });
  43925. normalizeIndexes(that._columns, 'sortIndex', currentColumn, function(column) {
  43926. return !isDefined(column.groupIndex) && isSortOrderValid(column.sortOrder)
  43927. })
  43928. };
  43929. var updateColumnVisibleIndexes = function(that, currentColumn) {
  43930. normalizeIndexes(that._columns, 'visibleIndex', currentColumn)
  43931. };
  43932. var getColumnIndexByVisibleIndex = function(that, visibleIndex, location) {
  43933. var columns = location === GROUP_LOCATION ? that.getGroupColumns() : location === COLUMN_CHOOSER_LOCATION ? that.getChooserColumns() : that.getVisibleColumns(),
  43934. column = columns[visibleIndex];
  43935. return column && isDefined(column.index) ? column.index : -1
  43936. };
  43937. var moveColumnToGroup = function(that, column, groupIndex) {
  43938. var groupColumns = that.getGroupColumns(),
  43939. i;
  43940. if (groupIndex >= 0) {
  43941. for (i = 0; i < groupColumns.length; i++)
  43942. if (groupColumns[i].groupIndex >= groupIndex)
  43943. groupColumns[i].groupIndex++
  43944. }
  43945. else {
  43946. groupIndex = 0;
  43947. for (i = 0; i < groupColumns.length; i++)
  43948. groupIndex = Math.max(groupIndex, groupColumns[i].groupIndex + 1)
  43949. }
  43950. column.groupIndex = groupIndex
  43951. };
  43952. var checkUserStateColumn = function(column, userStateColumn) {
  43953. return column && userStateColumn && userStateColumn.name === column.name && (userStateColumn.dataField === column.dataField || column.name)
  43954. };
  43955. var applyUserState = function(that) {
  43956. var columnsUserState = that._columnsUserState,
  43957. columns = that._columns,
  43958. resultColumns = [],
  43959. column,
  43960. i;
  43961. function handleStateField(index, fieldName) {
  43962. if (fieldName === 'dataType')
  43963. column[fieldName] = column[fieldName] || columnsUserState[i][fieldName];
  43964. else if ($.inArray(fieldName, USER_STATE_FIELD_NAMES_15_1) >= 0) {
  43965. if (fieldName in columnsUserState[i])
  43966. column[fieldName] = columnsUserState[i][fieldName]
  43967. }
  43968. else
  43969. column[fieldName] = columnsUserState[i][fieldName]
  43970. }
  43971. if (columnsUserState) {
  43972. if (columns.length !== columnsUserState.length)
  43973. return;
  43974. for (i = 0; i < columnsUserState.length; i++) {
  43975. column = isDefined(columnsUserState[i].initialIndex) ? columns[columnsUserState[i].initialIndex] : columns[i];
  43976. if (column && checkUserStateColumn(column, columnsUserState[i])) {
  43977. column = $.extend({}, column);
  43978. $.each(USER_STATE_FIELD_NAMES, handleStateField);
  43979. resultColumns.push(column)
  43980. }
  43981. else
  43982. return
  43983. }
  43984. assignColumns(that, resultColumns)
  43985. }
  43986. };
  43987. var updateIndexes = function(that, column) {
  43988. updateColumnIndexes(that);
  43989. updateColumnGroupIndexes(that, column);
  43990. updateColumnSortIndexes(that, column);
  43991. updateColumnVisibleIndexes(that, column)
  43992. };
  43993. var isLocalDataSource = function(dataSource) {
  43994. return dataSource && dataSource.store && dataSource.store() instanceof DX.data.ArrayStore
  43995. };
  43996. var assignColumns = function(that, columns) {
  43997. that._columns = columns;
  43998. that._visibleColumns = undefined;
  43999. that.updateColumnDataTypes()
  44000. };
  44001. var updateColumnChanges = function(that, changeType, optionName, columnIndex) {
  44002. var columnChanges = that._columnChanges || {
  44003. optionNames: {length: 0},
  44004. changeTypes: {length: 0},
  44005. columnIndex: columnIndex
  44006. };
  44007. optionName = optionName || 'all';
  44008. var changeTypes = columnChanges.changeTypes;
  44009. if (changeType && !changeTypes[changeType]) {
  44010. changeTypes[changeType] = true;
  44011. changeTypes.length++
  44012. }
  44013. var optionNames = columnChanges.optionNames;
  44014. if (optionName && !optionNames[optionName]) {
  44015. optionNames[optionName] = true;
  44016. optionNames.length++
  44017. }
  44018. if (columnIndex === undefined || columnIndex !== columnChanges.columnIndex)
  44019. delete columnChanges.columnIndex;
  44020. that._columnChanges = columnChanges;
  44021. that._visibleColumns = undefined
  44022. };
  44023. var fireColumnsChanged = function(that) {
  44024. var onColumnsChanging = that.option("onColumnsChanging"),
  44025. columnChanges = that._columnChanges;
  44026. if (that.isInitialized() && !that._updateLockCount && columnChanges) {
  44027. if (onColumnsChanging) {
  44028. that._updateLockCount++;
  44029. onColumnsChanging($.extend({component: that.component}, columnChanges));
  44030. that._updateLockCount--
  44031. }
  44032. that._columnChanges = undefined;
  44033. if (columnChanges.optionNames && columnChanges.optionNames.dataField)
  44034. that.reinit();
  44035. that.columnsChanged.fire(columnChanges)
  44036. }
  44037. };
  44038. var columnOptionCore = function(that, column, optionName, value, notFireEvent) {
  44039. var optionGetter = dataUtils.compileGetter(optionName),
  44040. changeType;
  44041. if (arguments.length === 3)
  44042. return optionGetter(column, {functionsAsIs: true});
  44043. if (optionGetter(column, {functionsAsIs: true}) !== value) {
  44044. if (optionName === 'groupIndex')
  44045. changeType = 'grouping';
  44046. else if (optionName === 'sortIndex' || optionName === 'sortOrder')
  44047. changeType = 'sorting';
  44048. else
  44049. changeType = 'columns';
  44050. dataUtils.compileSetter(optionName)(column, value, {functionsAsIs: true});
  44051. if (!notFireEvent)
  44052. updateColumnChanges(that, changeType, optionName, column.index)
  44053. }
  44054. };
  44055. var isSortOrderValid = function(sortOrder) {
  44056. return sortOrder === 'asc' || sortOrder === 'desc'
  44057. };
  44058. var addExpandColumn = function(that) {
  44059. that.addCommandColumn({
  44060. command: 'expand',
  44061. width: 'auto',
  44062. cssClass: DATAGRID_COMMAND_EXPAND_CLASS,
  44063. allowEditing: false,
  44064. allowGrouping: false,
  44065. allowSorting: false,
  44066. allowResizing: false,
  44067. allowReordering: false,
  44068. allowHiding: false
  44069. })
  44070. };
  44071. return {
  44072. init: function() {
  44073. var that = this,
  44074. columns = that.option('columns');
  44075. that._updateLockCount = that._updateLockCount || 0;
  44076. that._commandColumns = that._commandColumns || [];
  44077. that._columns = that._columns || [];
  44078. addExpandColumn(that);
  44079. that._isColumnsFromOptions = !!columns;
  44080. if (that._isColumnsFromOptions) {
  44081. assignColumns(that, columns ? createColumnsFromOptions(that, columns) : []);
  44082. applyUserState(that)
  44083. }
  44084. else
  44085. assignColumns(that, that._columnsUserState ? createColumnsFromOptions(that, that._columnsUserState) : that._columns);
  44086. if (that._dataSourceApplied)
  44087. that.applyDataSource(that._dataSource, true);
  44088. else
  44089. updateIndexes(that)
  44090. },
  44091. callbackNames: function() {
  44092. return ['columnsChanged']
  44093. },
  44094. optionChanged: function(args) {
  44095. switch (args.name) {
  44096. case'columns':
  44097. args.handled = true;
  44098. this._columnsUserState = null;
  44099. this.init();
  44100. break;
  44101. case'commonColumnSettings':
  44102. case'columnAutoWidth':
  44103. case'allowColumnResizing':
  44104. case'allowColumnReordering':
  44105. case'columnFixing':
  44106. case'grouping':
  44107. case'groupPanel':
  44108. case'regenerateColumnsByVisibleItems':
  44109. case'customizeColumns':
  44110. case'editing':
  44111. args.handled = true;
  44112. this.reinit();
  44113. break;
  44114. case'rtlEnabled':
  44115. this.reinit();
  44116. break;
  44117. default:
  44118. this.callBase(args)
  44119. }
  44120. },
  44121. publicMethods: function() {
  44122. return ['addColumn', 'columnOption', 'columnCount', 'clearSorting', 'clearGrouping']
  44123. },
  44124. applyDataSource: function(dataSource, forceApplying) {
  44125. var that = this,
  44126. isDataSourceLoaded = dataSource && dataSource.isLoaded();
  44127. that._dataSource = dataSource;
  44128. if (!that._dataSourceApplied || that._dataSourceColumnsCount === 0 || forceApplying || that.option('regenerateColumnsByVisibleItems'))
  44129. if (isDataSourceLoaded) {
  44130. if (!that._isColumnsFromOptions) {
  44131. assignColumns(that, createColumnsFromDataSource(that, dataSource));
  44132. that._dataSourceColumnsCount = that._columns.length;
  44133. applyUserState(that)
  44134. }
  44135. return that.updateColumns(dataSource, forceApplying)
  44136. }
  44137. },
  44138. reset: function() {
  44139. this._dataSourceApplied = false;
  44140. this._dataSourceColumnsCount = undefined;
  44141. this.reinit()
  44142. },
  44143. reinit: function() {
  44144. this._columnsUserState = this.getUserState();
  44145. this.init()
  44146. },
  44147. isInitialized: function() {
  44148. return !!this._columns.length
  44149. },
  44150. isDataSourceApplied: function() {
  44151. return this._dataSourceApplied
  44152. },
  44153. beginUpdate: function() {
  44154. this._updateLockCount++
  44155. },
  44156. endUpdate: function() {
  44157. var that = this;
  44158. that._updateLockCount--;
  44159. if (!that._updateLockCount)
  44160. fireColumnsChanged(that)
  44161. },
  44162. getCommonSettings: function() {
  44163. var commonColumnSettings = this.option('commonColumnSettings') || {},
  44164. groupingOptions = this.option('grouping') || {},
  44165. groupPanelOptions = this.option('groupPanel') || {};
  44166. return $.extend({
  44167. allowFixing: this.option('columnFixing.enabled'),
  44168. allowResizing: this.option('allowColumnResizing'),
  44169. allowReordering: this.option('allowColumnReordering'),
  44170. autoExpandGroup: groupingOptions.autoExpandAll,
  44171. allowCollapsing: groupingOptions.allowCollapsing,
  44172. allowGrouping: groupPanelOptions.allowColumnDragging && groupPanelOptions.visible
  44173. }, commonColumnSettings)
  44174. },
  44175. isColumnOptionUsed: function(optionName) {
  44176. for (var i = 0; i < this._columns.length; i++)
  44177. if (this._columns[i][optionName])
  44178. return true
  44179. },
  44180. isAllDataTypesDefined: function() {
  44181. var columns = this._columns,
  44182. i;
  44183. if (!columns.length)
  44184. return false;
  44185. for (i = 0; i < columns.length; i++)
  44186. if (!columns[i].dataType)
  44187. return false;
  44188. return true
  44189. },
  44190. getColumns: function() {
  44191. return $.extend(true, [], this._columns)
  44192. },
  44193. getGroupColumns: function() {
  44194. var result = [];
  44195. $.each(this._columns, function() {
  44196. var column = this;
  44197. if (isDefined(column.groupIndex))
  44198. result[column.groupIndex] = column
  44199. });
  44200. return result
  44201. },
  44202. getVisibleColumns: function() {
  44203. this._visibleColumns = this._visibleColumns || this._getVisibleColumnsCore();
  44204. return this._visibleColumns
  44205. },
  44206. getFixedColumns: function() {
  44207. var that = this,
  44208. result = [],
  44209. isColumnFixing = that._isColumnFixing(),
  44210. notFixedColumnCount = 0,
  44211. transparentColumnIndex,
  44212. visibleColumns;
  44213. if (isColumnFixing) {
  44214. visibleColumns = that.getVisibleColumns();
  44215. $.each(visibleColumns, function(index, column) {
  44216. if (!column.command && !column.fixed) {
  44217. notFixedColumnCount++;
  44218. if (!isDefined(transparentColumnIndex))
  44219. transparentColumnIndex = index
  44220. }
  44221. });
  44222. if (notFixedColumnCount < visibleColumns.length) {
  44223. result = visibleColumns.slice(0);
  44224. result.splice(transparentColumnIndex, notFixedColumnCount, {
  44225. command: "transparent",
  44226. colspan: notFixedColumnCount
  44227. })
  44228. }
  44229. }
  44230. return result
  44231. },
  44232. _isColumnFixing: function() {
  44233. var isColumnFixing = this.option("columnFixing.enabled");
  44234. !isColumnFixing && $.each(this._columns, function(_, column) {
  44235. if (column.fixed) {
  44236. isColumnFixing = true;
  44237. return false
  44238. }
  44239. });
  44240. return isColumnFixing
  44241. },
  44242. _getExpandColumnsCore: function() {
  44243. return this.getGroupColumns()
  44244. },
  44245. getExpandColumns: function() {
  44246. var expandColumns = this._getExpandColumnsCore(),
  44247. expandColumn;
  44248. if (expandColumns.length)
  44249. expandColumn = this.columnOption("command:expand");
  44250. expandColumns = $.map(expandColumns, function(column) {
  44251. return $.extend({}, column, {visibleWidth: "auto"}, expandColumn, {index: column.index})
  44252. });
  44253. return expandColumns
  44254. },
  44255. _getVisibleColumnsCore: function() {
  44256. var result = this.getExpandColumns(),
  44257. positiveIndexedColumns = [{}, {}, {}],
  44258. negativeIndexedColumns = {},
  44259. notGroupedColumnsCount = 0,
  44260. isFixedToEnd,
  44261. rtlEnabled = this.option("rtlEnabled"),
  44262. columns = this._columns.length ? this._commandColumns.concat(this._columns) : [];
  44263. $.each(columns, function() {
  44264. var column = this,
  44265. visibleIndex = column.visibleIndex,
  44266. indexedColumns;
  44267. if (column.visible && (!isDefined(column.groupIndex) || column.showWhenGrouped)) {
  44268. column = $.extend(true, {}, column);
  44269. if (visibleIndex < 0) {
  44270. visibleIndex = -visibleIndex;
  44271. indexedColumns = negativeIndexedColumns
  44272. }
  44273. else if (column.fixed || column.command) {
  44274. isFixedToEnd = column.fixedPosition === "right";
  44275. if (rtlEnabled)
  44276. isFixedToEnd = !isFixedToEnd;
  44277. if (isFixedToEnd || column.command)
  44278. indexedColumns = positiveIndexedColumns[2];
  44279. else
  44280. indexedColumns = positiveIndexedColumns[0]
  44281. }
  44282. else
  44283. indexedColumns = positiveIndexedColumns[1];
  44284. indexedColumns[visibleIndex] = indexedColumns[visibleIndex] || [];
  44285. indexedColumns[visibleIndex].push(column);
  44286. notGroupedColumnsCount++
  44287. }
  44288. });
  44289. utils.orderEach(negativeIndexedColumns, function(_, columns) {
  44290. result.unshift.apply(result, columns)
  44291. });
  44292. $.each(positiveIndexedColumns, function(index, positiveColumns) {
  44293. utils.orderEach(positiveColumns, function(_, columns) {
  44294. result.push.apply(result, columns)
  44295. })
  44296. });
  44297. if (!notGroupedColumnsCount && this._columns.length)
  44298. result.push({command: 'empty'});
  44299. return result
  44300. },
  44301. getHiddenColumns: function() {
  44302. var result = [];
  44303. $.each(this._columns, function(_, column) {
  44304. if (!column.visible)
  44305. result.push(column)
  44306. });
  44307. return result
  44308. },
  44309. getChooserColumns: function() {
  44310. return $.grep(this.getHiddenColumns(), function(column) {
  44311. return column.showInColumnChooser
  44312. })
  44313. },
  44314. allowMoveColumn: function(fromVisibleIndex, toVisibleIndex, sourceLocation, targetLocation) {
  44315. var that = this,
  44316. columnIndex = getColumnIndexByVisibleIndex(that, fromVisibleIndex, sourceLocation),
  44317. sourceColumn = that._columns[columnIndex];
  44318. if (sourceColumn && (sourceColumn.allowReordering || sourceColumn.allowGrouping || sourceColumn.allowHiding)) {
  44319. if (sourceLocation === targetLocation) {
  44320. if (sourceLocation === COLUMN_CHOOSER_LOCATION)
  44321. return false;
  44322. return fromVisibleIndex !== toVisibleIndex && fromVisibleIndex + 1 !== toVisibleIndex
  44323. }
  44324. else if (sourceLocation === GROUP_LOCATION && targetLocation !== COLUMN_CHOOSER_LOCATION || targetLocation === GROUP_LOCATION)
  44325. return sourceColumn && sourceColumn.allowGrouping;
  44326. else if (sourceLocation === COLUMN_CHOOSER_LOCATION || targetLocation === COLUMN_CHOOSER_LOCATION)
  44327. return sourceColumn && sourceColumn.allowHiding;
  44328. return true
  44329. }
  44330. return false
  44331. },
  44332. moveColumn: function(fromVisibleIndex, toVisibleIndex, sourceLocation, targetLocation) {
  44333. var that = this,
  44334. fromIndex,
  44335. toIndex,
  44336. targetGroupIndex,
  44337. isGroupMoving = sourceLocation === GROUP_LOCATION || targetLocation === GROUP_LOCATION,
  44338. column;
  44339. fromIndex = getColumnIndexByVisibleIndex(that, fromVisibleIndex, sourceLocation);
  44340. toIndex = getColumnIndexByVisibleIndex(that, toVisibleIndex, targetLocation);
  44341. if (fromIndex >= 0) {
  44342. column = that._columns[fromIndex];
  44343. targetGroupIndex = toIndex >= 0 ? that._columns[toIndex].groupIndex : -1;
  44344. if (isDefined(column.groupIndex) && sourceLocation === GROUP_LOCATION) {
  44345. if (targetGroupIndex > column.groupIndex)
  44346. targetGroupIndex--;
  44347. delete column.groupIndex;
  44348. delete column.sortOrder;
  44349. updateColumnGroupIndexes(that)
  44350. }
  44351. if (targetLocation === GROUP_LOCATION) {
  44352. moveColumnToGroup(that, column, targetGroupIndex);
  44353. updateColumnGroupIndexes(that)
  44354. }
  44355. else if (toVisibleIndex >= 0) {
  44356. if (toIndex < 0)
  44357. column.visibleIndex = undefined;
  44358. else {
  44359. var targetColumn = that._columns[toIndex];
  44360. if (column.fixed ^ targetColumn.fixed)
  44361. column.visibleIndex = undefined;
  44362. else
  44363. column.visibleIndex = targetColumn.visibleIndex
  44364. }
  44365. updateColumnVisibleIndexes(that, column)
  44366. }
  44367. column.visible = targetLocation !== COLUMN_CHOOSER_LOCATION;
  44368. updateColumnChanges(that, isGroupMoving ? 'grouping' : 'columns');
  44369. fireColumnsChanged(that)
  44370. }
  44371. },
  44372. changeSortOrder: function(columnIndex, sortOrder) {
  44373. var that = this,
  44374. sortingOptions = that.option('sorting'),
  44375. sortingMode = sortingOptions && sortingOptions.mode,
  44376. needResetSorting = sortingMode === 'single' || !sortOrder,
  44377. allowSorting = sortingMode === 'single' || sortingMode === 'multiple',
  44378. column = that._columns[columnIndex],
  44379. nextSortOrder = function(column) {
  44380. if (sortOrder === "ctrl") {
  44381. if (!("sortOrder" in column && "sortIndex" in column))
  44382. return false;
  44383. delete column.sortOrder;
  44384. delete column.sortIndex
  44385. }
  44386. else if (isDefined(column.groupIndex) || isDefined(column.sortIndex))
  44387. column.sortOrder = column.sortOrder === 'desc' ? 'asc' : 'desc';
  44388. else
  44389. column.sortOrder = 'asc';
  44390. return true
  44391. },
  44392. isSortingChanged = false;
  44393. if (allowSorting && column && column.allowSorting) {
  44394. if (needResetSorting && !isDefined(column.groupIndex))
  44395. $.each(that._columns, function(index) {
  44396. if (index !== columnIndex && this.sortOrder && !isDefined(this.groupIndex)) {
  44397. delete this.sortOrder;
  44398. delete this.sortIndex;
  44399. isSortingChanged = true
  44400. }
  44401. });
  44402. if (isSortOrderValid(sortOrder)) {
  44403. if (column.sortOrder !== sortOrder) {
  44404. column.sortOrder = sortOrder;
  44405. isSortingChanged = true
  44406. }
  44407. }
  44408. else if (sortOrder === 'none') {
  44409. if (column.sortOrder) {
  44410. delete column.sortIndex;
  44411. delete column.sortOrder;
  44412. isSortingChanged = true
  44413. }
  44414. }
  44415. else
  44416. isSortingChanged = nextSortOrder(column)
  44417. }
  44418. if (isSortingChanged) {
  44419. updateColumnSortIndexes(that);
  44420. updateColumnChanges(that, 'sorting');
  44421. fireColumnsChanged(that)
  44422. }
  44423. },
  44424. getSortDataSourceParameters: function() {
  44425. var that = this,
  44426. sortColumns = [],
  44427. sort = [];
  44428. $.each(that._columns, function() {
  44429. if ((this.dataField || this.selector || this.calculateCellValue) && isDefined(this.sortIndex) && !isDefined(this.groupIndex))
  44430. sortColumns[this.sortIndex] = this
  44431. });
  44432. $.each(sortColumns, function() {
  44433. var sortOrder = this && this.sortOrder;
  44434. if (isSortOrderValid(sortOrder))
  44435. sort.push({
  44436. selector: this.calculateSortValue || this.selector || this.dataField || this.calculateCellValue,
  44437. desc: this.sortOrder === 'desc'
  44438. })
  44439. });
  44440. return sort.length > 0 ? sort : null
  44441. },
  44442. getGroupDataSourceParameters: function(useLocalSelector) {
  44443. var group = [];
  44444. $.each(this.getGroupColumns(), function() {
  44445. var selector = this.calculateGroupValue || this.selector || useLocalSelector && this.groupSelector || this.dataField || this.calculateCellValue;
  44446. if (selector)
  44447. group.push({
  44448. selector: selector,
  44449. desc: this.sortOrder === 'desc',
  44450. isExpanded: !!this.autoExpandGroup
  44451. })
  44452. });
  44453. return group.length > 0 ? group : null
  44454. },
  44455. refresh: function(updateNewLookupsOnly) {
  44456. var deferreds = [];
  44457. $.each(this._columns, function() {
  44458. var lookup = this.lookup;
  44459. if (lookup) {
  44460. if (updateNewLookupsOnly && lookup.valueMap)
  44461. return;
  44462. if (lookup.update)
  44463. deferreds.push(lookup.update())
  44464. }
  44465. });
  44466. return $.when.apply($, deferreds)
  44467. },
  44468. updateColumnDataTypes: function(dataSource) {
  44469. var firstItems = getFirstItems(dataSource),
  44470. isLocalData = isLocalDataSource(dataSource),
  44471. rtlEnabled = this.option("rtlEnabled");
  44472. $.each(this._columns, function(index, column) {
  44473. var i,
  44474. value,
  44475. dataType,
  44476. lookupDataType,
  44477. valueDataType,
  44478. lookup = column.lookup;
  44479. if (column.calculateCellValue && firstItems.length) {
  44480. if (!column.dataType || lookup && !lookup.dataType) {
  44481. for (i = 0; i < firstItems.length; i++) {
  44482. value = column.calculateCellValue(firstItems[i]);
  44483. valueDataType = column.dataType || getValueDataType(value);
  44484. dataType = dataType || valueDataType;
  44485. if (dataType && valueDataType && dataType !== valueDataType)
  44486. dataType = "string";
  44487. if (lookup) {
  44488. valueDataType = lookup.dataType || getValueDataType(lookup.calculateCellValue(value));
  44489. lookupDataType = lookupDataType || valueDataType;
  44490. if (lookupDataType && valueDataType && lookupDataType !== valueDataType)
  44491. lookupDataType = "string"
  44492. }
  44493. }
  44494. column.dataType = dataType;
  44495. if (lookup)
  44496. lookup.dataType = lookupDataType
  44497. }
  44498. if (!column.serializationFormat || lookup && !lookup.serializationFormat)
  44499. for (i = 0; i < firstItems.length; i++) {
  44500. value = column.calculateCellValue(firstItems[i], true);
  44501. column.serializationFormat = column.serializationFormat || getSerializationFormat(column.dataType, value);
  44502. if (lookup)
  44503. lookup.serializationFormat = lookup.serializationFormat || getSerializationFormat(lookup.dataType, lookup.calculateCellValue(value, true))
  44504. }
  44505. }
  44506. if (isLocalData && column.userDataType || !column.dataField)
  44507. column.selector = column.selector || $.proxy(column, 'calculateCellValue');
  44508. else if (column.userDataType)
  44509. column.groupSelector = column.groupSelector || $.proxy(column, 'calculateCellValue');
  44510. updateSerializers(column, column.dataType);
  44511. if (lookup)
  44512. updateSerializers(lookup, lookup.dataType);
  44513. dataType = lookup ? lookup.dataType : column.dataType;
  44514. if (dataType) {
  44515. column.alignment = column.alignment || getAlignmentByDataType(dataType, rtlEnabled);
  44516. column.format = column.format || getFormatByDataType(dataType);
  44517. column.customizeText = column.customizeText || getCustomizeTextByDataType(dataType);
  44518. if (!isDefined(column.filterOperations))
  44519. column.filterOperations = !lookup && DATATYPE_OPERATIONS[dataType] || [];
  44520. column.defaultFilterOperation = column.filterOperations && column.filterOperations[0] || '=';
  44521. column.defaultSelectedFilterOperation = column.selectedFilterOperation;
  44522. column.showEditorAlways = isDefined(column.showEditorAlways) ? column.showEditorAlways : dataType === 'boolean' && !column.cellTemplate
  44523. }
  44524. })
  44525. },
  44526. _customizeColumns: function(columns) {
  44527. var that = this,
  44528. customizeColumns = that.option('customizeColumns');
  44529. if (customizeColumns) {
  44530. customizeColumns(columns);
  44531. assignColumns(that, createColumnsFromOptions(that, columns))
  44532. }
  44533. },
  44534. updateColumns: function(dataSource, forceApplying) {
  44535. var that = this,
  44536. sortParameters,
  44537. groupParameters;
  44538. if (!forceApplying)
  44539. that.updateSortingGrouping(dataSource);
  44540. if (!dataSource || dataSource.isLoaded()) {
  44541. sortParameters = dataSource ? dataSource.sort() || [] : that.getSortDataSourceParameters();
  44542. groupParameters = dataSource ? dataSource.group() || [] : that.getGroupDataSourceParameters();
  44543. that._customizeColumns(that._columns);
  44544. updateIndexes(that);
  44545. return $.when(that.refresh(true)).always(function() {
  44546. if (dataSource) {
  44547. that.updateColumnDataTypes(dataSource);
  44548. that._dataSourceApplied = true
  44549. }
  44550. if (!equalSortParameters(sortParameters, that.getSortDataSourceParameters()))
  44551. updateColumnChanges(that, 'sorting');
  44552. if (!equalSortParameters(groupParameters, that.getGroupDataSourceParameters()))
  44553. updateColumnChanges(that, 'grouping');
  44554. updateColumnChanges(that, 'columns');
  44555. fireColumnsChanged(that)
  44556. })
  44557. }
  44558. },
  44559. updateSortingGrouping: function(dataSource, fromDataSource) {
  44560. var that = this,
  44561. sortParameters,
  44562. groupParameters,
  44563. columnsGroupParameters,
  44564. columnsSortParameters,
  44565. isColumnsChanged,
  44566. updateSortGroupParameterIndexes = function(columns, sortParameters, indexParameterName) {
  44567. var i,
  44568. selector,
  44569. isExpanded;
  44570. $.each(columns, function(index, column) {
  44571. delete column[indexParameterName];
  44572. if (sortParameters)
  44573. for (i = 0; i < sortParameters.length; i++) {
  44574. selector = sortParameters[i].selector;
  44575. isExpanded = sortParameters[i].isExpanded;
  44576. if (selector === column.dataField || selector === column.name || selector === column.selector || selector === column.calculateCellValue || selector === column.calculateGroupValue) {
  44577. column.sortOrder = column.sortOrder || (sortParameters[i].desc ? 'desc' : 'asc');
  44578. if (isExpanded !== undefined)
  44579. column.autoExpandGroup = isExpanded;
  44580. column[indexParameterName] = i;
  44581. break
  44582. }
  44583. }
  44584. })
  44585. };
  44586. if (dataSource) {
  44587. sortParameters = normalizeSortingInfo(dataSource.sort());
  44588. groupParameters = normalizeSortingInfo(dataSource.group());
  44589. columnsGroupParameters = that.getGroupDataSourceParameters();
  44590. columnsSortParameters = that.getSortDataSourceParameters();
  44591. if (!that._columns.length) {
  44592. $.each(groupParameters, function(index, group) {
  44593. that._columns.push(group.selector)
  44594. });
  44595. $.each(sortParameters, function(index, sort) {
  44596. that._columns.push(sort.selector)
  44597. });
  44598. assignColumns(that, createColumnsFromOptions(that, that._columns))
  44599. }
  44600. if ((fromDataSource || !columnsGroupParameters && !that._hasUserState) && !equalSortParameters(groupParameters, columnsGroupParameters)) {
  44601. that.__groupingUpdated = true;
  44602. updateSortGroupParameterIndexes(that._columns, groupParameters, 'groupIndex');
  44603. if (fromDataSource) {
  44604. updateColumnChanges(that, 'grouping');
  44605. isColumnsChanged = true
  44606. }
  44607. }
  44608. if ((fromDataSource || !columnsSortParameters && !that._hasUserState) && !equalSortParameters(sortParameters, columnsSortParameters)) {
  44609. that.__sortingUpdated = true;
  44610. updateSortGroupParameterIndexes(that._columns, sortParameters, 'sortIndex');
  44611. if (fromDataSource) {
  44612. updateColumnChanges(that, 'sorting');
  44613. isColumnsChanged = true
  44614. }
  44615. }
  44616. if (isColumnsChanged)
  44617. fireColumnsChanged(that)
  44618. }
  44619. },
  44620. updateFilter: function(dataSource, filter) {
  44621. var that = this,
  44622. isLocalData = isLocalDataSource(dataSource);
  44623. var updateFilterCore = function(filter) {
  44624. if (!utils.isArray(filter))
  44625. return;
  44626. var column,
  44627. i;
  44628. if (utils.isString(filter[0])) {
  44629. column = that.columnOption(filter[0]);
  44630. if (column && column.calculateCellValue)
  44631. filter[0] = $.proxy(column, 'calculateCellValue')
  44632. }
  44633. for (i = 0; i < filter.length; i++)
  44634. updateFilterCore(filter[i])
  44635. };
  44636. if (isLocalData)
  44637. updateFilterCore(filter)
  44638. },
  44639. columnCount: function() {
  44640. return this._columns.length
  44641. },
  44642. columnOption: function(identificator, option, value, notFireEvent) {
  44643. var that = this,
  44644. i,
  44645. identificatorOptionName = utils.isString(identificator) && identificator.substr(0, identificator.indexOf(":")),
  44646. columns = identificator < 0 || identificatorOptionName === "command" ? that._commandColumns : that._columns,
  44647. column;
  44648. if (identificator === undefined)
  44649. return;
  44650. if (identificatorOptionName)
  44651. identificator = identificator.substr(identificatorOptionName.length + 1);
  44652. for (i = 0; i < columns.length; i++)
  44653. if (identificatorOptionName) {
  44654. if ("" + columns[i][identificatorOptionName] === identificator) {
  44655. column = columns[i];
  44656. break
  44657. }
  44658. }
  44659. else if (columns[i].index === identificator || columns[i].name === identificator || columns[i].dataField === identificator || columns[i].caption === identificator) {
  44660. column = columns[i];
  44661. break
  44662. }
  44663. if (column) {
  44664. if (arguments.length === 1)
  44665. return $.extend({}, column);
  44666. if (utils.isString(option))
  44667. if (arguments.length === 2)
  44668. return columnOptionCore(that, column, option);
  44669. else
  44670. columnOptionCore(that, column, option, value, notFireEvent);
  44671. else if (utils.isObject(option))
  44672. $.each(option, function(optionName, value) {
  44673. columnOptionCore(that, column, optionName, value, notFireEvent)
  44674. });
  44675. updateIndexes(that, column);
  44676. fireColumnsChanged(that)
  44677. }
  44678. },
  44679. clearSorting: function() {
  44680. var that = this,
  44681. columnCount = this.columnCount(),
  44682. i;
  44683. that.beginUpdate();
  44684. for (i = 0; i < columnCount; i++)
  44685. that.columnOption(i, "sortOrder", undefined);
  44686. that.endUpdate()
  44687. },
  44688. clearGrouping: function() {
  44689. var that = this,
  44690. columnCount = this.columnCount(),
  44691. i;
  44692. that.beginUpdate();
  44693. for (i = 0; i < columnCount; i++)
  44694. that.columnOption(i, "groupIndex", undefined);
  44695. that.endUpdate()
  44696. },
  44697. getVisibleIndex: function(index) {
  44698. var i,
  44699. visibleColumns = this.getVisibleColumns();
  44700. for (i = 0; i < visibleColumns.length; i++)
  44701. if (visibleColumns[i].index === index)
  44702. return i;
  44703. return -1
  44704. },
  44705. addColumn: function(options) {
  44706. var that = this,
  44707. column = createColumn(that, options);
  44708. that._columns.push(column);
  44709. updateIndexes(that, column);
  44710. that.updateColumns(that._dataSource)
  44711. },
  44712. addCommandColumn: function(options) {
  44713. var commandColumns = this._commandColumns,
  44714. i;
  44715. for (i = 0; i < commandColumns.length; i++)
  44716. if (commandColumns[i].command === options.command)
  44717. return;
  44718. commandColumns.push(options)
  44719. },
  44720. getUserState: function() {
  44721. var columns = this._columns,
  44722. result = [],
  44723. i;
  44724. function handleStateField(index, value) {
  44725. if (columns[i][value] !== undefined)
  44726. result[i][value] = columns[i][value]
  44727. }
  44728. for (i = 0; i < columns.length; i++) {
  44729. result[i] = {};
  44730. $.each(USER_STATE_FIELD_NAMES, handleStateField)
  44731. }
  44732. return result
  44733. },
  44734. setUserState: function(state) {
  44735. this._columnsUserState = state;
  44736. this._hasUserState = !!state;
  44737. this.init()
  44738. },
  44739. _createCalculatedColumnOptions: function(columnOptions) {
  44740. var calculatedColumnOptions = {},
  44741. dataField = columnOptions.dataField,
  44742. getter;
  44743. if (dataField && utils.isString(dataField)) {
  44744. getter = dataUtils.compileGetter(dataField);
  44745. calculatedColumnOptions = {
  44746. caption: convertNameToCaption(dataField),
  44747. calculateCellValue: function(data, skipDeserialization) {
  44748. var value = getter(data);
  44749. return this.deserializeValue && !skipDeserialization ? this.deserializeValue(value) : value
  44750. },
  44751. setCellValue: function(data, value) {
  44752. var path = this.dataField.split("."),
  44753. dotCount = path.length - 1,
  44754. name,
  44755. i;
  44756. if (this.serializeValue)
  44757. value = this.serializeValue(value);
  44758. for (i = 0; i < dotCount; i++) {
  44759. name = path[i];
  44760. data = data[name] = data[name] || {}
  44761. }
  44762. data[path[dotCount]] = value
  44763. },
  44764. parseValue: function(text) {
  44765. var column = this,
  44766. result,
  44767. parsedValue;
  44768. if (column.dataType === 'number') {
  44769. if (utils.isString(text)) {
  44770. parsedValue = Globalize.parseFloat(text);
  44771. if (utils.isNumber(parsedValue))
  44772. result = parsedValue
  44773. }
  44774. else if (utils.isDefined(text))
  44775. result = Number(text)
  44776. }
  44777. else if (column.dataType === 'boolean') {
  44778. if (text === column.trueText)
  44779. result = true;
  44780. else if (text === column.falseText)
  44781. result = false
  44782. }
  44783. else if (column.dataType === 'date') {
  44784. parsedValue = Globalize.parseDate(text);
  44785. if (parsedValue)
  44786. result = parsedValue
  44787. }
  44788. else
  44789. result = text;
  44790. return result
  44791. }
  44792. }
  44793. }
  44794. else
  44795. $.extend(true, calculatedColumnOptions, {
  44796. allowSorting: false,
  44797. allowGrouping: false,
  44798. calculateCellValue: function() {
  44799. return null
  44800. }
  44801. });
  44802. if (columnOptions.dataType)
  44803. calculatedColumnOptions.userDataType = columnOptions.dataType;
  44804. if (columnOptions.lookup)
  44805. calculatedColumnOptions.lookup = {
  44806. calculateCellValue: function(value, skipDeserialization) {
  44807. value = this.valueMap && this.valueMap[value];
  44808. return this.deserializeValue && !skipDeserialization ? this.deserializeValue(value) : value
  44809. },
  44810. updateValueMap: function() {
  44811. var calculateValue,
  44812. calculateDisplayValue,
  44813. item,
  44814. i;
  44815. this.valueMap = {};
  44816. if (this.items) {
  44817. calculateValue = dataUtils.compileGetter(this.valueExpr);
  44818. calculateDisplayValue = dataUtils.compileGetter(this.displayExpr);
  44819. for (i = 0; i < this.items.length; i++) {
  44820. item = this.items[i];
  44821. this.valueMap[calculateValue(item)] = calculateDisplayValue(item)
  44822. }
  44823. }
  44824. },
  44825. update: function() {
  44826. var that = this,
  44827. dataSource = that.dataSource,
  44828. dataSourceOptions;
  44829. if (dataSource)
  44830. if (utils.isObject(dataSource) || utils.isArray(dataSource)) {
  44831. dataSourceOptions = dataUtils.normalizeDataSourceOptions(dataSource);
  44832. dataSourceOptions.paginate = false;
  44833. dataSource = new DX.data.DataSource(dataSourceOptions);
  44834. return dataSource.load().done(function(data) {
  44835. that.items = data;
  44836. that.updateValueMap && that.updateValueMap()
  44837. })
  44838. }
  44839. else
  44840. DX.log("E1016");
  44841. else
  44842. that.updateValueMap && that.updateValueMap()
  44843. }
  44844. };
  44845. calculatedColumnOptions.resizedCallbacks = $.Callbacks();
  44846. if (columnOptions.resized)
  44847. calculatedColumnOptions.resizedCallbacks.add($.proxy(columnOptions.resized, columnOptions));
  44848. updateSerializers(calculatedColumnOptions, columnOptions.dataType);
  44849. return calculatedColumnOptions
  44850. }
  44851. }
  44852. }());
  44853. ui.dxDataGrid.ColumnsController = ColumnsController;
  44854. dataGrid.registerModule('columns', {
  44855. defaultOptions: function() {
  44856. return {
  44857. commonColumnSettings: {
  44858. allowFiltering: true,
  44859. allowHiding: true,
  44860. allowSorting: true,
  44861. allowEditing: true,
  44862. encodeHtml: true,
  44863. trueText: Globalize.localize("dxDataGrid-trueText"),
  44864. falseText: Globalize.localize("dxDataGrid-falseText")
  44865. },
  44866. allowColumnReordering: false,
  44867. allowColumnResizing: false,
  44868. columns: undefined,
  44869. regenerateColumnsByVisibleItems: false,
  44870. customizeColumns: null
  44871. }
  44872. },
  44873. controllers: {columns: ColumnsController}
  44874. })
  44875. })(jQuery, DevExpress);
  44876. /*! Module widgets-web, file ui.dataGrid.selection.js */
  44877. (function($, DX) {
  44878. var dataGrid = DX.ui.dxDataGrid,
  44879. events = DX.ui.events,
  44880. utils = DX.utils;
  44881. var DATAGRID_EDITOR_CELL_CLASS = "dx-editor-cell",
  44882. DATAGRID_ROW_CLASS = "dx-row",
  44883. DATAGRID_ROW_SELECTION_CLASS = "dx-selection",
  44884. DATAGRID_SELECT_CHECKBOX_CLASS = "dx-select-checkbox",
  44885. DATAGRID_CHECKBOXES_HIDDEN_CLASS = "dx-select-checkboxes-hidden",
  44886. DATAGRID_COMMAND_SELECT_CLASS = "dx-command-select",
  44887. DATAGRID_SELECTION_DISABLED_CLASS = "dx-selection-disabled",
  44888. DATAGRID_DATA_ROW_CLASS = "dx-data-row";
  44889. $.extend(dataGrid.__internals, {
  44890. DATAGRID_ROW_SELECTION_CLASS: DATAGRID_ROW_SELECTION_CLASS,
  44891. DATAGRID_SELECTION_DISABLED_CLASS: DATAGRID_SELECTION_DISABLED_CLASS,
  44892. DATAGRID_COMMAND_SELECT_CLASS: DATAGRID_COMMAND_SELECT_CLASS
  44893. });
  44894. var SHOW_CHECKBOXES_MODE = 'selection.showCheckBoxesInMultipleMode';
  44895. var SELECTION_MODE = 'selection.mode';
  44896. var isSelectable = function(selectionMode) {
  44897. return selectionMode === 'single' || selectionMode === 'multiple'
  44898. };
  44899. dataGrid.SelectionController = dataGrid.Controller.inherit(function() {
  44900. var indexOfSelectedItemKey = function(that, key, isSelectAll) {
  44901. var index,
  44902. selectedItemKeys = isSelectAll ? that._unselectedItemKeys : that._selectedItemKeys;
  44903. if (utils.isObject(key)) {
  44904. for (index = 0; index < selectedItemKeys.length; index++)
  44905. if (equalKeys(selectedItemKeys[index], key))
  44906. return index;
  44907. return -1
  44908. }
  44909. else
  44910. return $.inArray(key, selectedItemKeys)
  44911. };
  44912. var addSelectedItem = function(that, itemData) {
  44913. var key = that.getController('data').keyOf(itemData);
  44914. if (indexOfSelectedItemKey(that, key) === -1) {
  44915. that._selectedItemKeys.push(key);
  44916. that._addedItemKeys.push(key);
  44917. that._selectedItems.push(itemData)
  44918. }
  44919. };
  44920. var removeSelectedItem = function(that, key) {
  44921. var keyIndex = indexOfSelectedItemKey(that, key);
  44922. if (keyIndex >= 0) {
  44923. that._selectedItemKeys.splice(keyIndex, 1);
  44924. that._removedItemKeys.push(key);
  44925. that._selectedItems.splice(keyIndex, 1)
  44926. }
  44927. };
  44928. var clearSelectedItems = function(that) {
  44929. setSelectedItems(that, [], [])
  44930. };
  44931. var setSelectedItems = function(that, keys, items) {
  44932. var i,
  44933. oldSelectedItemKeys = that._selectedItemKeys;
  44934. that._selectedItemKeys = keys;
  44935. that._selectedItems = items;
  44936. that._unselectedItemKeys = [];
  44937. for (i = 0; i < oldSelectedItemKeys.length; i++)
  44938. if ($.inArray(oldSelectedItemKeys[i], keys) === -1)
  44939. that._removedItemKeys.push(oldSelectedItemKeys[i]);
  44940. for (i = 0; i < keys.length; i++)
  44941. if ($.inArray(keys[i], oldSelectedItemKeys) === -1)
  44942. that._addedItemKeys.push(keys[i])
  44943. };
  44944. var equalKeys = dataGrid.equalKeys;
  44945. var resetItemSelectionWhenShiftKeyPressed = function(that) {
  44946. delete that._shiftFocusedItemIndex
  44947. };
  44948. var isDataItem = function(row) {
  44949. return row && row.rowType === "data" && !row.inserted
  44950. };
  44951. var changeItemSelectionWhenShiftKeyPressed = function(that, itemIndex, items) {
  44952. var isSelectedItemsChanged = false,
  44953. itemIndexStep,
  44954. index,
  44955. dataController = that.getController('data'),
  44956. isFocusedItemSelected = items[that._focusedItemIndex] && that.isRowSelected(dataController.keyOf(items[that._focusedItemIndex].data));
  44957. var addRemoveSelectedItem = function(that, data, isRemove) {
  44958. if (isRemove)
  44959. removeSelectedItem(that, dataController.keyOf(data));
  44960. else
  44961. addSelectedItem(that, data)
  44962. };
  44963. if (!utils.isDefined(that._shiftFocusedItemIndex))
  44964. that._shiftFocusedItemIndex = that._focusedItemIndex;
  44965. if (that._shiftFocusedItemIndex !== that._focusedItemIndex) {
  44966. itemIndexStep = that._focusedItemIndex < that._shiftFocusedItemIndex ? 1 : -1;
  44967. for (index = that._focusedItemIndex; index !== that._shiftFocusedItemIndex; index += itemIndexStep)
  44968. if (isDataItem(items[index])) {
  44969. addRemoveSelectedItem(that, items[index].data, true);
  44970. isSelectedItemsChanged = true
  44971. }
  44972. }
  44973. if (itemIndex !== that._shiftFocusedItemIndex) {
  44974. itemIndexStep = itemIndex < that._shiftFocusedItemIndex ? 1 : -1;
  44975. for (index = itemIndex; index !== that._shiftFocusedItemIndex; index += itemIndexStep)
  44976. if (isDataItem(items[index])) {
  44977. addRemoveSelectedItem(that, items[index].data, false);
  44978. isSelectedItemsChanged = true
  44979. }
  44980. }
  44981. if (isDataItem(items[that._focusedItemIndex]) && !isFocusedItemSelected) {
  44982. addRemoveSelectedItem(that, items[that._focusedItemIndex].data, false);
  44983. isSelectedItemsChanged = true
  44984. }
  44985. return isSelectedItemsChanged
  44986. };
  44987. var createSelectedItemsFilterCriteria = function(dataSource, selectedItemKeys, isSelectAll) {
  44988. var keyCriteria,
  44989. i,
  44990. key = dataSource && dataSource.key(),
  44991. criteria = [];
  44992. if (dataSource)
  44993. if (key)
  44994. $.each(selectedItemKeys, function(index, keyValue) {
  44995. if (criteria.length > 0)
  44996. criteria.push(isSelectAll ? 'and' : 'or');
  44997. if ($.isArray(key)) {
  44998. keyCriteria = [];
  44999. for (i = 0; i < key.length; i++) {
  45000. if (i > 0)
  45001. keyCriteria.push(isSelectAll ? 'or' : 'and');
  45002. keyCriteria.push([key[i], isSelectAll ? '<>' : '=', keyValue[key[i]]])
  45003. }
  45004. criteria.push(keyCriteria)
  45005. }
  45006. else
  45007. criteria.push([key, isSelectAll ? '<>' : '=', keyValue])
  45008. });
  45009. else
  45010. criteria = function(item) {
  45011. var i;
  45012. for (i = 0; i < selectedItemKeys.length; i++)
  45013. if (equalKeys(selectedItemKeys[i], item))
  45014. return !isSelectAll;
  45015. return isSelectAll
  45016. };
  45017. if (criteria.length > 0 || $.isFunction(criteria))
  45018. return criteria
  45019. };
  45020. var updateSelectedItems = function(that) {
  45021. var changedItemIndexes = [],
  45022. dataController = that.getController('data'),
  45023. addedItemKeys,
  45024. removedItemKeys;
  45025. if (dataController) {
  45026. $.each(dataController.items(), function(index, row) {
  45027. if (isDataItem(row) && row.isSelected !== that.isRowSelected(row.key))
  45028. changedItemIndexes.push(index)
  45029. });
  45030. if (that.option(SHOW_CHECKBOXES_MODE) === 'onClick')
  45031. if (that._selectedItemKeys.length > 1)
  45032. that.startSelectionWithCheckboxes();
  45033. else if (that._selectedItemKeys.length === 0 && changedItemIndexes.length)
  45034. that.stopSelectionWithCheckboxes();
  45035. if (changedItemIndexes.length)
  45036. dataController.updateItems({
  45037. changeType: 'updateSelection',
  45038. itemIndexes: changedItemIndexes
  45039. });
  45040. addedItemKeys = that._addedItemKeys;
  45041. removedItemKeys = that._removedItemKeys;
  45042. if (addedItemKeys.length || removedItemKeys.length) {
  45043. that._selectedItemsInternalChange = true;
  45044. that.option("selectedRowKeys", that._selectedItemKeys.slice(0));
  45045. that._selectedItemsInternalChange = false;
  45046. that.selectionChanged.fire(that._selectedItemKeys);
  45047. that._addedItemKeys = [];
  45048. that._removedItemKeys = [];
  45049. that.executeAction("onSelectionChanged", {
  45050. selectedRowsData: that._selectedItems,
  45051. selectedRowKeys: that._selectedItemKeys,
  45052. currentSelectedRowKeys: addedItemKeys,
  45053. currentDeselectedRowKeys: removedItemKeys
  45054. })
  45055. }
  45056. }
  45057. };
  45058. var updateSelectColumn = function(that) {
  45059. var columnsController = that.getController("columns"),
  45060. isSelectColumnVisible = that.isSelectColumnVisible();
  45061. columnsController.addCommandColumn({
  45062. command: 'select',
  45063. visible: isSelectColumnVisible,
  45064. visibleIndex: -1,
  45065. dataType: 'boolean',
  45066. alignment: 'center',
  45067. cssClass: DATAGRID_COMMAND_SELECT_CLASS,
  45068. width: "auto"
  45069. });
  45070. columnsController.columnOption("command:select", "visible", isSelectColumnVisible)
  45071. };
  45072. return {
  45073. init: function() {
  45074. var that = this;
  45075. that._isSelectionWithCheckboxes = false;
  45076. that._focusedItemIndex = -1;
  45077. that._selectedItemKeys = [];
  45078. that._unselectedItemKeys = [];
  45079. that._selectedItems = [];
  45080. that._addedItemKeys = [];
  45081. that._removedItemKeys = [];
  45082. updateSelectColumn(that);
  45083. that.createAction("onSelectionChanged", {excludeValidators: ["disabled", "readOnly"]})
  45084. },
  45085. callbackNames: function() {
  45086. return ['selectionChanged']
  45087. },
  45088. optionChanged: function(args) {
  45089. var that = this;
  45090. that.callBase(args);
  45091. switch (args.name) {
  45092. case"selection":
  45093. that.init();
  45094. that.getController('columns').updateColumns();
  45095. args.handled = true;
  45096. break;
  45097. case"selectedRowKeys":
  45098. if (utils.isArray(args.value) && !that._selectedItemsInternalChange)
  45099. that.selectRows(args.value);
  45100. args.handled = true;
  45101. break
  45102. }
  45103. },
  45104. publicMethods: function() {
  45105. return ['selectRows', 'deselectRows', 'selectRowsByIndexes', 'getSelectedRowKeys', 'getSelectedRowsData', 'clearSelection', 'selectAll', 'startSelectionWithCheckboxes', 'stopSelectionWithCheckboxes', 'isRowSelected']
  45106. },
  45107. isRowSelected: function(key) {
  45108. var index = indexOfSelectedItemKey(this, key);
  45109. return index !== -1
  45110. },
  45111. isSelectColumnVisible: function() {
  45112. var showCheckboxesMode = this.option(SHOW_CHECKBOXES_MODE);
  45113. return this.option(SELECTION_MODE) === 'multiple' && (showCheckboxesMode === 'always' || showCheckboxesMode === 'onClick' || this._isSelectionWithCheckboxes)
  45114. },
  45115. isSelectAll: function() {
  45116. var dataController = this.getController('data'),
  45117. items = dataController.items(),
  45118. combinedFilter = dataController.getCombinedFilter(),
  45119. selectedItems = this.getSelectedRowsData(),
  45120. i;
  45121. if (combinedFilter)
  45122. DX.data.query(selectedItems).filter(combinedFilter).enumerate().done(function(items) {
  45123. selectedItems = items
  45124. });
  45125. if (!selectedItems.length) {
  45126. for (i = 0; i < items.length; i++)
  45127. if (items[i].selected)
  45128. return;
  45129. return false
  45130. }
  45131. else if (selectedItems.length >= dataController.totalCount())
  45132. return true
  45133. },
  45134. selectAll: function() {
  45135. if (this.option(SHOW_CHECKBOXES_MODE) === 'onClick')
  45136. this.startSelectionWithCheckboxes();
  45137. return this.selectedItemKeys([], true, false, true)
  45138. },
  45139. deselectAll: function() {
  45140. return this.selectedItemKeys([], true, true, true)
  45141. },
  45142. clearSelection: function() {
  45143. this.selectedItemKeys([])
  45144. },
  45145. refresh: function() {
  45146. return this.selectedItemKeys(this.option("selectedRowKeys") || [])
  45147. },
  45148. selectedItemKeys: function(value, preserve, isDeselect, isSelectAll) {
  45149. var that = this,
  45150. keys,
  45151. criteria,
  45152. isFunctionCriteria,
  45153. deferred,
  45154. dataController = that.getController('data'),
  45155. dataSource = dataController.dataSource(),
  45156. store = dataSource && dataSource.store(),
  45157. dataSourceFilter,
  45158. filter,
  45159. deselectItems = [];
  45160. if (utils.isDefined(value)) {
  45161. if (store) {
  45162. keys = $.isArray(value) ? $.extend([], value) : [value];
  45163. if (keys.length || isSelectAll) {
  45164. criteria = createSelectedItemsFilterCriteria(dataSource, keys, isSelectAll);
  45165. isFunctionCriteria = $.isFunction(criteria);
  45166. if (criteria || isSelectAll) {
  45167. if (isSelectAll)
  45168. dataSourceFilter = dataController.getCombinedFilter();
  45169. if (criteria && !isFunctionCriteria && dataSourceFilter) {
  45170. filter = [];
  45171. filter.push(criteria);
  45172. filter.push(dataSourceFilter)
  45173. }
  45174. else if (dataSourceFilter)
  45175. filter = dataSourceFilter;
  45176. else if (criteria && !isFunctionCriteria)
  45177. filter = criteria;
  45178. deferred = $.Deferred();
  45179. if (isDeselect)
  45180. new DX.data.ArrayStore(that._selectedItems).load({filter: filter}).done(function(items) {
  45181. deselectItems = items
  45182. });
  45183. dataController.setSelectionLoading(true);
  45184. $.when(deselectItems.length ? deselectItems : store.load({filter: filter})).done(function(items) {
  45185. new DX.data.ArrayStore(items).load({filter: criteria}).done(deferred.resolve)
  45186. }).fail($.proxy(deferred.reject, deferred)).always(function() {
  45187. dataController.setSelectionLoading(false)
  45188. })
  45189. }
  45190. }
  45191. }
  45192. deferred = deferred || $.Deferred().resolve([]);
  45193. deferred.done(function(items) {
  45194. var i,
  45195. key,
  45196. item,
  45197. keys = [];
  45198. if (store && items.length > 0)
  45199. for (i = 0; i < items.length; i++) {
  45200. item = items[i];
  45201. key = store.keyOf(item);
  45202. if (preserve)
  45203. if (isDeselect)
  45204. removeSelectedItem(that, key);
  45205. else
  45206. addSelectedItem(that, item);
  45207. else
  45208. keys.push(key)
  45209. }
  45210. if (!preserve)
  45211. setSelectedItems(that, keys, items);
  45212. updateSelectedItems(that)
  45213. });
  45214. return deferred
  45215. }
  45216. else
  45217. return that._selectedItemKeys
  45218. },
  45219. getSelectedRowKeys: function() {
  45220. return this.selectedItemKeys()
  45221. },
  45222. selectRows: function(keys, preserve) {
  45223. return this.selectedItemKeys(keys, preserve)
  45224. },
  45225. deselectRows: function(keys) {
  45226. return this.selectedItemKeys(keys, true, true)
  45227. },
  45228. selectRowsByIndexes: function(indexes) {
  45229. var items = this.getController('data').items(),
  45230. keys = [];
  45231. if (!utils.isArray(indexes))
  45232. indexes = Array.prototype.slice.call(arguments, 0);
  45233. $.each(indexes, function() {
  45234. var item = items[this];
  45235. if (item && item.rowType === 'data')
  45236. keys.push(item.key)
  45237. });
  45238. return this.selectRows(keys)
  45239. },
  45240. getSelectedRowsData: function() {
  45241. return this._selectedItems
  45242. },
  45243. changeItemSelection: function(itemIndex, keys) {
  45244. var that = this,
  45245. dataController = that.getController('data'),
  45246. items = dataController.items(),
  45247. item = items[itemIndex],
  45248. itemData = item && item.data,
  45249. selectionMode = that.option(SELECTION_MODE),
  45250. isSelectedItemsChanged,
  45251. isSelected,
  45252. itemKey;
  45253. if (isSelectable(selectionMode) && isDataItem(item)) {
  45254. itemKey = dataController.keyOf(itemData);
  45255. keys = keys || {};
  45256. if (that.isSelectionWithCheckboxes())
  45257. keys.control = true;
  45258. if (keys.shift && selectionMode === 'multiple' && that._focusedItemIndex >= 0)
  45259. isSelectedItemsChanged = changeItemSelectionWhenShiftKeyPressed(that, itemIndex, items);
  45260. else if (keys.control) {
  45261. resetItemSelectionWhenShiftKeyPressed(that);
  45262. isSelected = that.isRowSelected(itemKey);
  45263. if (selectionMode === 'single')
  45264. clearSelectedItems(that);
  45265. if (isSelected)
  45266. removeSelectedItem(that, itemKey);
  45267. else
  45268. addSelectedItem(that, itemData);
  45269. isSelectedItemsChanged = true
  45270. }
  45271. else {
  45272. resetItemSelectionWhenShiftKeyPressed(that);
  45273. if (that._selectedItemKeys.length !== 1 || !equalKeys(that._selectedItemKeys[0], itemKey)) {
  45274. setSelectedItems(that, [itemKey], [itemData]);
  45275. isSelectedItemsChanged = true
  45276. }
  45277. }
  45278. if (isSelectedItemsChanged) {
  45279. that._focusedItemIndex = itemIndex;
  45280. updateSelectedItems(that);
  45281. return true
  45282. }
  45283. }
  45284. return false
  45285. },
  45286. focusedItemIndex: function(itemIndex) {
  45287. var that = this;
  45288. if (utils.isDefined(itemIndex))
  45289. that._focusedItemIndex = itemIndex;
  45290. else
  45291. return that._focusedItemIndex
  45292. },
  45293. isSelectionWithCheckboxes: function() {
  45294. var selectionMode = this.option(SELECTION_MODE),
  45295. showCheckboxesMode = this.option(SHOW_CHECKBOXES_MODE);
  45296. return selectionMode === 'multiple' && (showCheckboxesMode === 'always' || this._isSelectionWithCheckboxes)
  45297. },
  45298. startSelectionWithCheckboxes: function() {
  45299. var that = this,
  45300. isSelectColumnVisible = that.isSelectColumnVisible();
  45301. if (that.option(SELECTION_MODE) === 'multiple' && !that.isSelectionWithCheckboxes()) {
  45302. that._isSelectionWithCheckboxes = true;
  45303. updateSelectColumn(that);
  45304. if (isSelectColumnVisible === that.isSelectColumnVisible() && that.option(SHOW_CHECKBOXES_MODE) === 'onClick')
  45305. updateSelectedItems(that);
  45306. return true
  45307. }
  45308. return false
  45309. },
  45310. stopSelectionWithCheckboxes: function() {
  45311. var that = this;
  45312. if (that._isSelectionWithCheckboxes) {
  45313. that._isSelectionWithCheckboxes = false;
  45314. updateSelectColumn(that);
  45315. return true
  45316. }
  45317. return false
  45318. }
  45319. }
  45320. }());
  45321. $.extend(dataGrid.__internals, {DATAGRID_CHECKBOXES_HIDDEN_CLASS: DATAGRID_CHECKBOXES_HIDDEN_CLASS});
  45322. dataGrid.registerModule('selection', {
  45323. defaultOptions: function() {
  45324. return {
  45325. selection: {
  45326. mode: 'none',
  45327. showCheckBoxesInMultipleMode: 'onClick',
  45328. allowSelectAll: true
  45329. },
  45330. selectedRowKeys: []
  45331. }
  45332. },
  45333. controllers: {selection: dataGrid.SelectionController},
  45334. extenders: {
  45335. controllers: {data: {
  45336. setDataSource: function(dataSource) {
  45337. this.callBase(dataSource);
  45338. if (dataSource)
  45339. this.getController('selection').refresh()
  45340. },
  45341. setSelectionLoading: function(isLoading) {
  45342. this._isSelectionLoading = isLoading;
  45343. this._fireLoadingChanged()
  45344. },
  45345. isLoading: function() {
  45346. var isLoading = this.callBase();
  45347. return isLoading || !!this._isSelectionLoading
  45348. },
  45349. pageIndex: function(value) {
  45350. var that = this,
  45351. dataSource = that._dataSource;
  45352. if (dataSource && value && dataSource.pageIndex() !== value)
  45353. that.getController('selection').focusedItemIndex(-1);
  45354. return that.callBase(value)
  45355. },
  45356. _processDataItem: function() {
  45357. var that = this,
  45358. selectionController = that.getController('selection'),
  45359. hasSelectColumn = selectionController.isSelectColumnVisible(),
  45360. dataItem = this.callBase.apply(this, arguments);
  45361. dataItem.isSelected = selectionController.isRowSelected(dataItem.key);
  45362. if (hasSelectColumn && dataItem.values)
  45363. dataItem.values[0] = dataItem.isSelected;
  45364. return dataItem
  45365. },
  45366. refresh: function() {
  45367. return $.when(this.getController('selection').refresh(), this.callBase.apply(this, arguments))
  45368. }
  45369. }},
  45370. views: {
  45371. columnHeadersView: {
  45372. _renderCore: function(options) {
  45373. var that = this;
  45374. that.getController('selection').selectionChanged.remove(that._selectionChangedHandler);
  45375. that.callBase(options)
  45376. },
  45377. _getDefaultTemplate: function(column) {
  45378. var that = this,
  45379. groupElement,
  45380. selectionController = that.getController('selection'),
  45381. dataController = that.getController('data');
  45382. if (column.command === "select")
  45383. return function($cell, options) {
  45384. var column = options.column;
  45385. if (column.command === 'select') {
  45386. $cell.addClass(DATAGRID_EDITOR_CELL_CLASS);
  45387. groupElement = $('<div />').appendTo($cell).addClass(DATAGRID_SELECT_CHECKBOX_CLASS);
  45388. that.setAria("label", Globalize.localize("dxDataGrid-ariaSelectAll"), $cell);
  45389. that.getController('editorFactory').createEditor(groupElement, $.extend({}, column, {
  45390. parentType: "headerRow",
  45391. value: selectionController.isSelectAll(),
  45392. setValue: function(value, e) {
  45393. if (e.jQueryEvent && selectionController.isSelectAll() !== value) {
  45394. if (e.previousValue === undefined || e.previousValue) {
  45395. selectionController.deselectAll();
  45396. e.component.option('value', false)
  45397. }
  45398. if (e.previousValue === false)
  45399. if (that.option("selection.allowSelectAll"))
  45400. selectionController.selectAll();
  45401. else
  45402. e.component.option('value', false);
  45403. e.jQueryEvent.preventDefault()
  45404. }
  45405. }
  45406. }));
  45407. $cell.on('dxclick', that.createAction(function(e) {
  45408. var event = e.jQueryEvent;
  45409. if (!$(event.target).closest('.' + DATAGRID_SELECT_CHECKBOX_CLASS).length)
  45410. $(event.currentTarget).children().trigger('dxclick');
  45411. event.preventDefault()
  45412. }));
  45413. that._selectionChangedHandler = function() {
  45414. if (that.option("selection.mode") === "multiple")
  45415. groupElement.dxCheckBox("instance").option("value", selectionController.isSelectAll())
  45416. };
  45417. that._dataChangedHandler = function(e) {
  45418. if (!e || e.changeType === "refresh")
  45419. that._selectionChangedHandler()
  45420. };
  45421. dataController.changed.add(that._dataChangedHandler);
  45422. selectionController.selectionChanged.add(that._selectionChangedHandler)
  45423. }
  45424. };
  45425. else
  45426. return that.callBase(column)
  45427. }
  45428. },
  45429. rowsView: {
  45430. _getDefaultTemplate: function(column) {
  45431. var that = this,
  45432. groupElement;
  45433. if (column.command === 'select')
  45434. return function(container, options) {
  45435. if (options.rowType === 'data' && !options.row.inserted) {
  45436. container.addClass(DATAGRID_EDITOR_CELL_CLASS);
  45437. container.on('dxclick', that.createAction(function(e) {
  45438. var selectionController = that.getController('selection'),
  45439. event = e.jQueryEvent,
  45440. rowIndex = that.getRowIndex($(event.currentTarget).closest('.' + DATAGRID_ROW_CLASS));
  45441. if (rowIndex >= 0) {
  45442. selectionController.startSelectionWithCheckboxes();
  45443. selectionController.changeItemSelection(rowIndex, {shift: event.shiftKey})
  45444. }
  45445. }));
  45446. that.setAria("label", Globalize.localize("dxDataGrid-ariaSelectRow"), container);
  45447. groupElement = $('<div />').addClass(DATAGRID_SELECT_CHECKBOX_CLASS).appendTo(container);
  45448. that.getController('editorFactory').createEditor(groupElement, $.extend({}, column, {
  45449. parentType: "dataRow",
  45450. value: options.value,
  45451. setValue: function(value, e) {
  45452. if (e && e.jQueryEvent && e.jQueryEvent.type === 'keydown')
  45453. container.trigger('dxclick', e)
  45454. }
  45455. }))
  45456. }
  45457. };
  45458. else
  45459. return that.callBase(column)
  45460. },
  45461. _update: function(change) {
  45462. var that = this,
  45463. tableElements = that._getTableElements();
  45464. if (change.changeType === 'updateSelection') {
  45465. if (tableElements.length > 0) {
  45466. $.each(tableElements, function(_, tableElement) {
  45467. $.each(change.itemIndexes || [], function(_, index) {
  45468. var $row,
  45469. isSelected;
  45470. if (change.items[index]) {
  45471. $row = that._getRowElements($(tableElement)).eq(index);
  45472. isSelected = !!change.items[index].isSelected;
  45473. $row.toggleClass(DATAGRID_ROW_SELECTION_CLASS, isSelected).find('.' + DATAGRID_SELECT_CHECKBOX_CLASS).dxCheckBox('option', 'value', isSelected);
  45474. that.setAria("selected", isSelected, $row)
  45475. }
  45476. })
  45477. });
  45478. that._updateCheckboxesClass()
  45479. }
  45480. }
  45481. else
  45482. that.callBase(change)
  45483. },
  45484. _createTable: function() {
  45485. var that = this,
  45486. selectionMode = that.option("selection.mode"),
  45487. $table = that.callBase.apply(that, arguments);
  45488. if (selectionMode !== "none")
  45489. $table.on(events.addNamespace("dxhold", "dxDataGridRowsView"), "." + DATAGRID_DATA_ROW_CLASS, that.createAction(function(e) {
  45490. var selectionController = that.getController('selection'),
  45491. event = e.jQueryEvent,
  45492. rowIndex = $(event.target).closest("." + DATAGRID_DATA_ROW_CLASS).index();
  45493. if (that.option(SHOW_CHECKBOXES_MODE) === 'onLongTap')
  45494. if (selectionController.isSelectionWithCheckboxes())
  45495. selectionController.stopSelectionWithCheckboxes();
  45496. else
  45497. selectionController.startSelectionWithCheckboxes();
  45498. else {
  45499. if (that.option(SHOW_CHECKBOXES_MODE) === 'onClick')
  45500. selectionController.startSelectionWithCheckboxes();
  45501. selectionController.changeItemSelection(rowIndex, {control: true})
  45502. }
  45503. })).on('mousedown selectstart', that.createAction(function(e) {
  45504. var event = e.jQueryEvent;
  45505. if (event.shiftKey)
  45506. event.preventDefault()
  45507. }));
  45508. return $table
  45509. },
  45510. _createRow: function(row) {
  45511. var $row = this.callBase(row),
  45512. isSelected;
  45513. if (row) {
  45514. isSelected = !!row.isSelected;
  45515. $row.toggleClass(DATAGRID_ROW_SELECTION_CLASS, isSelected);
  45516. this.setAria("selected", isSelected, $row)
  45517. }
  45518. return $row
  45519. },
  45520. _rowClick: function(e) {
  45521. var that = this,
  45522. jQueryEvent = e.jQueryEvent,
  45523. isCommandSelect = $(jQueryEvent.target).closest("." + DATAGRID_COMMAND_SELECT_CLASS).length,
  45524. isSelectionDisabled = $(jQueryEvent.target).closest("." + DATAGRID_SELECTION_DISABLED_CLASS).length;
  45525. if (!isCommandSelect) {
  45526. if (!isSelectionDisabled)
  45527. if (that.getController('selection').changeItemSelection(e.rowIndex, {
  45528. control: jQueryEvent.ctrlKey,
  45529. shift: jQueryEvent.shiftKey
  45530. })) {
  45531. jQueryEvent.preventDefault();
  45532. e.handled = true
  45533. }
  45534. that.callBase(e)
  45535. }
  45536. },
  45537. _renderCore: function(change) {
  45538. this.callBase(change);
  45539. this._updateCheckboxesClass()
  45540. },
  45541. _updateCheckboxesClass: function() {
  45542. var tableElements = this._getTableElements(),
  45543. selectionController = this.getController('selection'),
  45544. isCheckBoxesHidden = selectionController.isSelectColumnVisible() && !selectionController.isSelectionWithCheckboxes();
  45545. $.each(tableElements, function(_, tableElement) {
  45546. $(tableElement).toggleClass(DATAGRID_CHECKBOXES_HIDDEN_CLASS, isCheckBoxesHidden)
  45547. })
  45548. }
  45549. }
  45550. }
  45551. }
  45552. })
  45553. })(jQuery, DevExpress);
  45554. /*! Module widgets-web, file ui.dataGrid.editorFactory.js */
  45555. (function($, DX) {
  45556. var dataGrid = DX.ui.dxDataGrid,
  45557. utils = DX.utils,
  45558. addNamespace = DX.ui.events.addNamespace;
  45559. var DATAGRID_CHECKBOX_SIZE_CLASS = "dx-datagrid-checkbox-size",
  45560. DATAGRID_CELL_FOCUS_DISABLED_CLASS = "dx-cell-focus-disabled",
  45561. DATAGRID_MODULE_NAMESPACE = 'dxDataGridEditorFactory',
  45562. DATAGRID_UPDATE_FOCUS_EVENTS = addNamespace('focusin dxpointerdown dxclick', DATAGRID_MODULE_NAMESPACE),
  45563. DATAGRID_FOCUS_OVERLAY_CLASS = 'dx-datagrid-focus-overlay',
  45564. DATAGRID_FOCUSED_ELEMENT_CLASS = 'dx-focused',
  45565. DATAGRID_CONTENT_CLASS = 'dx-datagrid-content',
  45566. DATAGRID_POINTER_EVENTS_TARGET_CLASS = "dx-pointer-events-target",
  45567. DATAGRID_POINTER_EVENTS_NONE_CLASS = "dx-pointer-events-none",
  45568. DX_HIDDEN = "dx-hidden",
  45569. TAB_KEY = 9;
  45570. dataGrid.EditorFactoryController = dataGrid.ViewController.inherit(function() {
  45571. var getResultConfig = function(config, options) {
  45572. return $.extend(config, {
  45573. readOnly: options.readOnly,
  45574. rtlEnabled: options.rtlEnabled,
  45575. disabled: options.disabled
  45576. })
  45577. };
  45578. var getTextEditorConfig = function(options) {
  45579. return getResultConfig({
  45580. placeholder: options.placeholder,
  45581. width: options.width,
  45582. value: options.value,
  45583. onValueChanged: function(e) {
  45584. var updateValue = function(e) {
  45585. options && options.setValue(e.value)
  45586. };
  45587. window.clearTimeout(e.component._valueChangeTimeoutID);
  45588. if (e.jQueryEvent && e.jQueryEvent.type === 'keyup')
  45589. e.component._valueChangeTimeoutID = window.setTimeout(function() {
  45590. updateValue(e)
  45591. }, utils.isDefined(options.updateValueTimeout) ? options.updateValueTimeout : 0);
  45592. else
  45593. updateValue(e)
  45594. },
  45595. valueChangeEvent: 'change' + (options.parentType === 'filterRow' ? ' keyup' : '')
  45596. }, options)
  45597. };
  45598. var prepareDateBox = function(options) {
  45599. options.editorName = "dxDateBox";
  45600. options.editorOptions = getResultConfig({
  45601. value: options.value,
  45602. pickerType: "calendar",
  45603. customOverlayCssClass: 'dx-datagrid',
  45604. onValueChanged: function(args) {
  45605. options.setValue(args.value)
  45606. },
  45607. formatString: DX.utils.isString(options.format) && DX.DateTimeFormat[options.format.toLowerCase()] || options.format,
  45608. formatWidthCalculator: null,
  45609. width: "auto"
  45610. }, options)
  45611. };
  45612. var prepareTextBox = function(options) {
  45613. var config = getTextEditorConfig(options),
  45614. isSearching = options.parentType === 'searchPanel',
  45615. toString = function(value) {
  45616. return DX.utils.isDefined(value) ? value.toString() : ''
  45617. };
  45618. config.value = toString(options.value);
  45619. config.valueChangeEvent += isSearching ? ' keyup search' : '';
  45620. config.mode = isSearching ? 'search' : 'text';
  45621. options.editorName = "dxTextBox";
  45622. options.editorOptions = config
  45623. };
  45624. var prepareNumberBox = function(options) {
  45625. var config = getTextEditorConfig(options);
  45626. config.value = utils.isDefined(options.value) ? options.value : null;
  45627. options.editorName = "dxNumberBox";
  45628. options.editorOptions = config
  45629. };
  45630. var prepareBooleanEditor = function(options) {
  45631. if (options.parentType === 'filterRow')
  45632. prepareSelectBox($.extend(options, {lookup: {
  45633. displayExpr: function(data) {
  45634. if (data === true)
  45635. return options.trueText || 'true';
  45636. else if (data === false)
  45637. return options.falseText || 'false'
  45638. },
  45639. dataSource: [true, false],
  45640. rtlEnabled: options.rtlEnabled,
  45641. disabled: options.disabled
  45642. }}));
  45643. else
  45644. prepareCheckBox(options)
  45645. };
  45646. var prepareSelectBox = function(options) {
  45647. var lookup = options.lookup,
  45648. displayGetter,
  45649. dataSource,
  45650. postProcess,
  45651. isFilterRow = options.parentType === "filterRow";
  45652. if (lookup) {
  45653. displayGetter = DX.data.utils.compileGetter(lookup.displayExpr);
  45654. if (utils.isObject(lookup.dataSource) || utils.isArray(lookup.dataSource)) {
  45655. dataSource = DX.data.utils.normalizeDataSourceOptions(lookup.dataSource);
  45656. if (isFilterRow) {
  45657. postProcess = dataSource.postProcess;
  45658. dataSource.postProcess = function(items) {
  45659. if (this.pageIndex() === 0) {
  45660. items = items.slice(0);
  45661. items.unshift(null)
  45662. }
  45663. if (postProcess)
  45664. return postProcess.call(this, items);
  45665. return items
  45666. }
  45667. }
  45668. }
  45669. options.editorName = "dxSelectBox";
  45670. options.editorOptions = getResultConfig({
  45671. searchEnabled: true,
  45672. value: options.value,
  45673. valueExpr: options.lookup.valueExpr,
  45674. showClearButton: lookup.allowClearing && !isFilterRow,
  45675. displayExpr: function(data) {
  45676. if (data === null)
  45677. return options.showAllText;
  45678. return displayGetter(data)
  45679. },
  45680. dataSource: dataSource,
  45681. onValueChanged: function(e) {
  45682. options.setValue(e.value, e)
  45683. }
  45684. }, options)
  45685. }
  45686. };
  45687. var prepareCheckBox = function(options) {
  45688. options.editorName = "dxCheckBox";
  45689. options.editorOptions = getResultConfig({
  45690. value: options.value,
  45691. onValueChanged: function(e) {
  45692. options.setValue && options.setValue(e.value, e)
  45693. }
  45694. }, options)
  45695. };
  45696. var createEditorCore = function(options) {
  45697. if (options.editorName && options.editorOptions && options.editorElement[options.editorName]) {
  45698. if (options.editorName === "dxCheckBox")
  45699. options.editorElement.addClass(DATAGRID_CHECKBOX_SIZE_CLASS);
  45700. options.editorElement[options.editorName](options.editorOptions);
  45701. if (options.editorName === "dxTextBox")
  45702. options.editorElement.dxTextBox("instance").registerKeyHandler("enter", $.noop)
  45703. }
  45704. };
  45705. return {
  45706. _getFocusedElement: function($dataGridElement) {
  45707. return $dataGridElement.find('[tabindex]:focus, input:focus')
  45708. },
  45709. _updateFocusCore: function() {
  45710. var $focus = this._$focusedElement,
  45711. $dataGridElement = this.component && this.component.element();
  45712. if ($dataGridElement) {
  45713. $focus = this._getFocusedElement($dataGridElement);
  45714. if ($focus.length) {
  45715. if (!$focus.hasClass(DATAGRID_CELL_FOCUS_DISABLED_CLASS))
  45716. $focus = $focus.closest('.dx-row > td, .' + DATAGRID_CELL_FOCUS_DISABLED_CLASS);
  45717. if ($focus.length && !$focus.hasClass(DATAGRID_CELL_FOCUS_DISABLED_CLASS)) {
  45718. this.focus($focus);
  45719. return
  45720. }
  45721. }
  45722. }
  45723. this.loseFocus()
  45724. },
  45725. _updateFocus: function(e) {
  45726. var that = this,
  45727. isFocusOverlay = e && e.jQueryEvent && $(e.jQueryEvent.target).hasClass(DATAGRID_FOCUS_OVERLAY_CLASS);
  45728. that._isFocusOverlay = that._isFocusOverlay || isFocusOverlay;
  45729. clearTimeout(that._updateFocusTimeoutID);
  45730. that._updateFocusTimeoutID = setTimeout(function() {
  45731. delete that._updateFocusTimeoutID;
  45732. if (!that._isFocusOverlay)
  45733. that._updateFocusCore();
  45734. that._isFocusOverlay = false
  45735. })
  45736. },
  45737. _updateFocusOverlaySize: function($element, position) {
  45738. var location = DX.calculatePosition($element, position);
  45739. if (location.h.oversize > 0)
  45740. $element.outerWidth($element.outerWidth() - location.h.oversize);
  45741. if (location.v.oversize > 0)
  45742. $element.outerHeight($element.outerHeight() - location.v.oversize)
  45743. },
  45744. callbackNames: function() {
  45745. return ["focused"]
  45746. },
  45747. focus: function($element, hideBorder) {
  45748. var that = this;
  45749. if ($element === undefined)
  45750. return that._$focusedElement;
  45751. else if ($element)
  45752. setTimeout(function() {
  45753. var $focusOverlay = that._$focusOverlay = that._$focusOverlay || $('<div>').addClass(DATAGRID_FOCUS_OVERLAY_CLASS + " " + DATAGRID_POINTER_EVENTS_TARGET_CLASS),
  45754. focusOverlayPosition;
  45755. if (hideBorder)
  45756. that._$focusOverlay && that._$focusOverlay.addClass(DX_HIDDEN);
  45757. else {
  45758. var align = DevExpress.browser.mozilla ? "right bottom" : "left top",
  45759. $content = $element.closest('.' + DATAGRID_CONTENT_CLASS);
  45760. $focusOverlay.removeClass(DX_HIDDEN).appendTo($content).outerWidth($element.outerWidth() + 1).outerHeight($element.outerHeight() + 1);
  45761. focusOverlayPosition = {
  45762. my: align,
  45763. at: align,
  45764. of: $element,
  45765. boundary: $content.length && $content
  45766. };
  45767. that._updateFocusOverlaySize($focusOverlay, focusOverlayPosition);
  45768. DX.position($focusOverlay, focusOverlayPosition);
  45769. $focusOverlay.css('visibility', 'visible')
  45770. }
  45771. that._$focusedElement && that._$focusedElement.removeClass(DATAGRID_FOCUSED_ELEMENT_CLASS);
  45772. $element.addClass(DATAGRID_FOCUSED_ELEMENT_CLASS);
  45773. that._$focusedElement = $element;
  45774. that.focused.fire($element)
  45775. })
  45776. },
  45777. resize: function() {
  45778. var $focusedElement = this._$focusedElement;
  45779. if ($focusedElement)
  45780. this.focus($focusedElement)
  45781. },
  45782. loseFocus: function() {
  45783. this._$focusedElement && this._$focusedElement.removeClass(DATAGRID_FOCUSED_ELEMENT_CLASS);
  45784. this._$focusedElement = null;
  45785. this._$focusOverlay && this._$focusOverlay.addClass(DX_HIDDEN)
  45786. },
  45787. init: function() {
  45788. this.createAction("onEditorPreparing", {
  45789. excludeValidators: ["designMode", "disabled", "readOnly"],
  45790. category: "rendering"
  45791. });
  45792. this.createAction("onEditorPrepared", {
  45793. excludeValidators: ["designMode", "disabled", "readOnly"],
  45794. category: "rendering"
  45795. });
  45796. this._updateFocusHandler = this._updateFocusHandler || this.createAction($.proxy(this._updateFocus, this));
  45797. $(document).on(DATAGRID_UPDATE_FOCUS_EVENTS, this._updateFocusHandler);
  45798. this._attachContainerEventHandlers()
  45799. },
  45800. _attachContainerEventHandlers: function() {
  45801. var that = this,
  45802. $container = that.component && that.component.element(),
  45803. isIE10OrLower = DX.browser.msie && parseInt(DX.browser.version) < 11;
  45804. if ($container) {
  45805. $container.on(addNamespace('keydown', DATAGRID_MODULE_NAMESPACE), function(e) {
  45806. if (e.which === TAB_KEY)
  45807. that._updateFocusHandler(e)
  45808. });
  45809. isIE10OrLower && $container.on('dxclick dxpointerup dxpointerdown', "." + DATAGRID_POINTER_EVENTS_TARGET_CLASS, $.proxy(that._focusOverlayEventProxy, that))
  45810. }
  45811. },
  45812. _focusOverlayEventProxy: function(e) {
  45813. var $target = $(e.target),
  45814. $currentTarget = $(e.currentTarget),
  45815. element,
  45816. needProxy = $target.hasClass(DATAGRID_POINTER_EVENTS_TARGET_CLASS) || $target.hasClass(DATAGRID_POINTER_EVENTS_NONE_CLASS),
  45817. $focusedElement = this._$focusedElement;
  45818. if (!needProxy || $currentTarget.hasClass(DX_HIDDEN))
  45819. return;
  45820. $currentTarget.addClass(DX_HIDDEN);
  45821. element = $target.get(0).ownerDocument.elementFromPoint(e.clientX, e.clientY);
  45822. $(element).trigger(jQuery.Event(e.type, {
  45823. clientX: e.clientX,
  45824. clientY: e.clientY
  45825. }));
  45826. $currentTarget.removeClass(DX_HIDDEN);
  45827. $focusedElement && $focusedElement.find('input').focus()
  45828. },
  45829. dispose: function() {
  45830. clearTimeout(this._updateFocusTimeoutID);
  45831. $(document).off(DATAGRID_UPDATE_FOCUS_EVENTS, this._updateFocusHandler)
  45832. },
  45833. createEditor: function($container, options) {
  45834. this.component._suppressDeprecatedWarnings();
  45835. var editorPreparing = this.option("editorPreparing"),
  45836. editorPrepared = this.option("editorPrepared");
  45837. this.component._resumeDeprecatedWarnings();
  45838. options.rtlEnabled = this.option('rtlEnabled');
  45839. options.disabled = options.disabled || this.option("disabled");
  45840. options.cancel = false;
  45841. options.editorElement = $container;
  45842. if (options.lookup)
  45843. prepareSelectBox(options);
  45844. else
  45845. switch (options.dataType) {
  45846. case'date':
  45847. prepareDateBox(options);
  45848. break;
  45849. case'boolean':
  45850. prepareBooleanEditor(options);
  45851. break;
  45852. case'number':
  45853. prepareNumberBox(options);
  45854. break;
  45855. default:
  45856. prepareTextBox(options);
  45857. break
  45858. }
  45859. editorPreparing && editorPreparing($container, options);
  45860. this.executeAction("onEditorPreparing", options);
  45861. if (options.cancel)
  45862. return;
  45863. createEditorCore(options);
  45864. editorPrepared && editorPrepared($container, options);
  45865. this.executeAction("onEditorPrepared", options)
  45866. }
  45867. }
  45868. }());
  45869. $.extend(dataGrid.__internals, {DATAGRID_FOCUSED_ELEMENT_CLASS: DATAGRID_FOCUSED_ELEMENT_CLASS});
  45870. dataGrid.registerModule('editorFactory', {
  45871. defaultOptions: function() {
  45872. return {}
  45873. },
  45874. controllers: {editorFactory: dataGrid.EditorFactoryController}
  45875. })
  45876. })(jQuery, DevExpress);
  45877. /*! Module widgets-web, file ui.dataGrid.columnsView.js */
  45878. (function($, DX, undefined) {
  45879. var ui = DX.ui,
  45880. utils = DX.utils,
  45881. dataGrid = ui.dxDataGrid;
  45882. var DATAGRID_SCROLL_CONTAINER_CLASS = "dx-datagrid-scroll-container",
  45883. DATAGRID_ROW_CLASS = "dx-row",
  45884. DATAGRID_GROUP_SPACE_CLASS = "dx-datagrid-group-space",
  45885. DATAGRID_GROUP_ROW_CLASS = "dx-group-row",
  45886. DATAGRID_CONTENT_CLASS = "dx-datagrid-content",
  45887. DATAGRID_TABLE_CLASS = "dx-datagrid-table",
  45888. DATAGRID_CELL_CONTENT_CLASS = "dx-datagrid-text-content",
  45889. DATAGRID_COLUMN_INDICATORS_CLASS = "dx-column-indicators",
  45890. DATAGRID_TABLE_FIXED_CLASS = "dx-datagrid-table-fixed",
  45891. DATAGRID_INDICATOR_ALIGNMENT_CLASS = "dx-indicator-alignment-",
  45892. DATAGRID_HEADER_ROW_CLASS = "dx-header-row",
  45893. DATAGRID_CELL_HINT_VISIBLE = "dxCellHintVisible",
  45894. indicatorNamesClass = {
  45895. sort: "dx-sort",
  45896. headerFilter: "dx-header-filter"
  45897. };
  45898. var appendElementTemplate = {render: function(element, container) {
  45899. container.append(element)
  45900. }};
  45901. dataGrid.getWidths = function($tableElement) {
  45902. var cells,
  45903. result = [],
  45904. width,
  45905. clientRect;
  45906. if ($tableElement) {
  45907. cells = $tableElement.children('tbody').children('tr').filter(':not(.' + DATAGRID_GROUP_ROW_CLASS + ')').first().find('td');
  45908. $.each(cells, function(index, item) {
  45909. width = $(item).outerWidth(true);
  45910. if (item.getBoundingClientRect) {
  45911. clientRect = item.getBoundingClientRect();
  45912. if (clientRect.width > width)
  45913. width = Math.ceil(clientRect.width)
  45914. }
  45915. result.push(width)
  45916. })
  45917. }
  45918. return result
  45919. };
  45920. dataGrid.ColumnsView = dataGrid.View.inherit({
  45921. _getColumnAlignment: function(alignment) {
  45922. var rtlEnabled = this.option('rtlEnabled');
  45923. return alignment !== 'center' ? alignment : rtlEnabled ? 'right' : 'left'
  45924. },
  45925. _applyColumnState: function(options) {
  45926. var that = this,
  45927. $span,
  45928. columnAlignment,
  45929. indicatorAlignment,
  45930. column = options.column,
  45931. $rootElement = options.rootElement,
  45932. $indicatorsContainer = $rootElement.find("." + DATAGRID_COLUMN_INDICATORS_CLASS),
  45933. nameClass = indicatorNamesClass[options.name],
  45934. getIndicatorAlignment = function(columnAlignment) {
  45935. return columnAlignment === 'right' ? 'left' : 'right'
  45936. };
  45937. columnAlignment = that._getColumnAlignment(column.alignment);
  45938. indicatorAlignment = getIndicatorAlignment(columnAlignment);
  45939. $span = $('<span />').addClass(nameClass);
  45940. if (!$indicatorsContainer.length)
  45941. $indicatorsContainer = $("<div/>").addClass(DATAGRID_COLUMN_INDICATORS_CLASS);
  45942. $indicatorsContainer.append($span).css('float', options.showColumnLines ? indicatorAlignment : column.alignment !== 'center' ? columnAlignment : null);
  45943. if (!options.showColumnLines)
  45944. $indicatorsContainer.addClass(DATAGRID_INDICATOR_ALIGNMENT_CLASS + columnAlignment).appendTo($rootElement);
  45945. else
  45946. $indicatorsContainer.prependTo($rootElement);
  45947. return $span
  45948. },
  45949. _updateIndicatorHeights: function(indicatorName) {
  45950. var that = this,
  45951. columnElements = that.getColumnElements(),
  45952. $cell,
  45953. i;
  45954. if (columnElements)
  45955. for (i = 0; i < columnElements.length; i++) {
  45956. $cell = columnElements.eq(i);
  45957. that._updateIndicatorHeight($cell, indicatorName)
  45958. }
  45959. },
  45960. _updateIndicatorHeight: function($cell, indicatorName) {
  45961. var $textContent = $cell.find('.' + DATAGRID_CELL_CONTENT_CLASS),
  45962. $indicator = $cell.find('.' + indicatorNamesClass[indicatorName]);
  45963. if ($indicator.length) {
  45964. $indicator.height("auto");
  45965. $indicator.height($textContent.height() || $cell.height())
  45966. }
  45967. },
  45968. _updateIndicators: function(indicatorName) {
  45969. var that = this,
  45970. columns = that.getColumns(),
  45971. $cells = that.getColumnElements(),
  45972. i;
  45973. for (i = 0; i < columns.length; i++)
  45974. that._updateIndicator($cells.eq(i), columns[i], indicatorName);
  45975. that._updateIndicatorHeights(indicatorName)
  45976. },
  45977. _updateIndicator: function($cell, column, indicatorName) {
  45978. if (!column.command)
  45979. return this._applyColumnState({
  45980. name: indicatorName,
  45981. rootElement: $cell,
  45982. column: column,
  45983. showColumnLines: this.option('showColumnLines')
  45984. })
  45985. },
  45986. _updateCell: function($cell, parameters) {
  45987. if (parameters.rowType)
  45988. this._cellPrepared($cell, parameters)
  45989. },
  45990. _createCell: function(column) {
  45991. return $("<td/>").css('text-align', column.alignment || 'left').toggleClass(column.cssClass, !utils.isDefined(column.groupIndex)).attr('role', 'gridcell').toggleClass(DATAGRID_GROUP_SPACE_CLASS, column.command === "expand")
  45992. },
  45993. _createRow: function(row) {
  45994. return $("<tr />").addClass(DATAGRID_ROW_CLASS).attr('role', 'row')
  45995. },
  45996. _createTable: function(columns) {
  45997. var that = this,
  45998. $table = $('<table />').addClass(DATAGRID_TABLE_CLASS).addClass(DATAGRID_TABLE_FIXED_CLASS).attr('role', 'grid');
  45999. if (columns) {
  46000. $table.append(that._createColGroup(columns));
  46001. if (DX.devices.real().ios)
  46002. $table.append("<thead><tr></tr></thead>")
  46003. }
  46004. if (that.option("cellHintEnabled"))
  46005. $table.on("mousemove", ".dx-row > td", this.createAction(function(args) {
  46006. var e = args.jQueryEvent,
  46007. $element = $(e.target),
  46008. $cell = $(e.currentTarget),
  46009. $row = $cell.parent(),
  46010. isDataRow = $row.hasClass('dx-data-row'),
  46011. $cells = $row.children(),
  46012. visibleColumns = that._columnsController.getVisibleColumns(),
  46013. visibleColumnIndex = $cells.index($cell),
  46014. column = visibleColumns[visibleColumnIndex];
  46015. if (!isDataRow || isDataRow && column && !column.cellTemplate) {
  46016. if ($element.data(DATAGRID_CELL_HINT_VISIBLE)) {
  46017. $element.removeAttr("title");
  46018. $element.data(DATAGRID_CELL_HINT_VISIBLE, false)
  46019. }
  46020. if ($element[0].scrollWidth > $element[0].clientWidth && !$element.attr("title")) {
  46021. $element.attr("title", $element.text());
  46022. $element.data(DATAGRID_CELL_HINT_VISIBLE, true)
  46023. }
  46024. }
  46025. }));
  46026. return $table
  46027. },
  46028. _createColGroup: function(columns) {
  46029. var i,
  46030. j,
  46031. colgroupElement = $('<colgroup />'),
  46032. colspan,
  46033. columnsLength = columns.length;
  46034. for (i = 0; i < columnsLength; i++) {
  46035. colspan = columns[i].colspan || 1;
  46036. for (j = 0; j < colspan; j++)
  46037. colgroupElement.append(this._createCol(columns[i]))
  46038. }
  46039. return colgroupElement
  46040. },
  46041. _createCol: function(column) {
  46042. return $('<col />').width(column.visibleWidth || column.width)
  46043. },
  46044. renderDelayedTemplates: function() {
  46045. var templateParameters,
  46046. delayedTemplates = this._delayedTemplates;
  46047. while (delayedTemplates.length) {
  46048. templateParameters = delayedTemplates.shift();
  46049. templateParameters.template.render(templateParameters.options, templateParameters.container);
  46050. if (templateParameters.options.column)
  46051. this._updateCell(templateParameters.container, templateParameters.options)
  46052. }
  46053. },
  46054. _processTemplate: function(template, options) {
  46055. var that = this,
  46056. renderingTemplate;
  46057. if ($.isFunction(template))
  46058. renderingTemplate = {render: function(options, container) {
  46059. template(container, options)
  46060. }};
  46061. else {
  46062. if (!that._templatesCache[template])
  46063. that._templatesCache[template] = that.getTemplate(template);
  46064. renderingTemplate = that._templatesCache[template]
  46065. }
  46066. return renderingTemplate
  46067. },
  46068. _renderTemplate: function(container, template, options) {
  46069. var that = this,
  46070. renderingTemplate = that._processTemplate(template, options);
  46071. if (renderingTemplate)
  46072. if (options.denyRenderToDetachedContainer || renderingTemplate.denyRenderToDetachedContainer)
  46073. that._delayedTemplates.push({
  46074. template: renderingTemplate,
  46075. container: container,
  46076. options: options
  46077. });
  46078. else {
  46079. renderingTemplate.render(options, container);
  46080. return true
  46081. }
  46082. return false
  46083. },
  46084. _appendRow: function($table, $row) {
  46085. var that = this;
  46086. if (that.option("rowTemplate") && that._delayedTemplates.length && $row)
  46087. that._delayedTemplates.push({
  46088. container: $table,
  46089. template: appendElementTemplate,
  46090. options: $row
  46091. });
  46092. else
  46093. $table.append($row)
  46094. },
  46095. _renderCore: function(change) {
  46096. var $root = this.element().parent();
  46097. if (!$root || $root.parent().length)
  46098. this.renderDelayedTemplates()
  46099. },
  46100. _renderTable: function(options) {
  46101. options = options || {};
  46102. var that = this,
  46103. $table;
  46104. options.columns = that._columnsController.getVisibleColumns();
  46105. $table = that._createTable(options.columns);
  46106. that._renderRows($table, options);
  46107. return $table
  46108. },
  46109. _renderRows: function($table, options) {
  46110. var that = this,
  46111. i,
  46112. rows = that._getRows(options.change);
  46113. for (i = 0; i < rows.length; i++)
  46114. that._renderRow($table, $.extend({row: rows[i]}, options))
  46115. },
  46116. _renderRow: function($table, options) {
  46117. var that = this,
  46118. $row;
  46119. $row = that._createRow(options.row);
  46120. that._renderCells($row, options);
  46121. that._appendRow($table, $row);
  46122. that._rowPrepared($row, $.extend({columns: options.columns}, options.row))
  46123. },
  46124. _renderCells: function($row, options) {
  46125. var that = this,
  46126. i,
  46127. columnIndex = 0,
  46128. row = options.row,
  46129. columns = options.columns;
  46130. for (i = 0; i < columns.length; i++) {
  46131. that._renderCell($row, $.extend({
  46132. column: columns[i],
  46133. columnIndex: columnIndex,
  46134. value: row.values && row.values[columnIndex]
  46135. }, options));
  46136. if (utils.isDefined(columns[i].colspan))
  46137. columnIndex += columns[i].colspan;
  46138. else
  46139. columnIndex++
  46140. }
  46141. },
  46142. _renderCell: function($row, options) {
  46143. var that = this,
  46144. cellOptions = that._getCellOptions(options),
  46145. column = options.column,
  46146. $cell;
  46147. $cell = that._createCell(column);
  46148. if (!utils.isDefined(column.command))
  46149. that.setAria("label", Globalize.localize("dxDataGrid-ariaColumn") + " " + column.caption + ", " + Globalize.localize("dxDataGrid-ariaValue") + " " + cellOptions.text, $cell);
  46150. that._renderCellContent($cell, cellOptions);
  46151. $row.append($cell);
  46152. return $cell
  46153. },
  46154. _renderCellContent: function($cell, options) {
  46155. var template = this._getCellTemplate(options);
  46156. if (!template || this._renderTemplate($cell, template, options))
  46157. this._updateCell($cell, options)
  46158. },
  46159. _getCellTemplate: function(options){},
  46160. _getRows: function() {
  46161. return []
  46162. },
  46163. _getCellOptions: function(options) {
  46164. return {
  46165. column: options.column,
  46166. columnIndex: options.columnIndex,
  46167. rowType: options.row.rowType
  46168. }
  46169. },
  46170. _cellPrepared: function($cell, options) {
  46171. var that = this,
  46172. cellPrepared,
  46173. extendOptions = function(event) {
  46174. return {
  46175. cellElement: $(event.target).closest('td'),
  46176. jQueryEvent: event,
  46177. eventType: event.type
  46178. }
  46179. };
  46180. if (that.option("onCellClick"))
  46181. $cell.on("dxclick", function(e) {
  46182. that.executeAction("onCellClick", $.extend({}, options, extendOptions(e)))
  46183. });
  46184. if (that.option("onCellHoverChanged")) {
  46185. $cell.on("mouseover", function(e) {
  46186. that.executeAction("onCellHoverChanged", $.extend({}, options, extendOptions(e)))
  46187. });
  46188. $cell.on("mouseout", function(e) {
  46189. that.executeAction("onCellHoverChanged", $.extend({}, options, extendOptions(e)))
  46190. })
  46191. }
  46192. this.component._suppressDeprecatedWarnings();
  46193. cellPrepared = that.option("cellPrepared");
  46194. this.component._resumeDeprecatedWarnings();
  46195. cellPrepared && cellPrepared($cell, options);
  46196. options.cellElement = $cell;
  46197. that.executeAction("onCellPrepared", options)
  46198. },
  46199. _rowPrepared: function($row, options) {
  46200. var that = this,
  46201. rowPrepared;
  46202. this.component._suppressDeprecatedWarnings();
  46203. rowPrepared = that.option("rowPrepared");
  46204. this.component._resumeDeprecatedWarnings();
  46205. rowPrepared && rowPrepared($row, options);
  46206. options.rowElement = $row;
  46207. this.executeAction("onRowPrepared", options)
  46208. },
  46209. _columnOptionChanged: function(e) {
  46210. var optionNames = e.optionNames;
  46211. if (dataGrid.checkChanges(optionNames, ['width', 'visibleWidth'])) {
  46212. var visibleColumns = this._columnsController.getVisibleColumns();
  46213. var widths = $.map(visibleColumns, function(column) {
  46214. return column.visibleWidth || column.width || 'auto'
  46215. });
  46216. this.setColumnWidths(widths);
  46217. return
  46218. }
  46219. this.render()
  46220. },
  46221. _getTableElements: function() {
  46222. return this._tableElement || $()
  46223. },
  46224. _getTableElement: function() {
  46225. return this._tableElement
  46226. },
  46227. _setTableElement: function(tableElement) {
  46228. this._tableElement = tableElement
  46229. },
  46230. optionChanged: function(args) {
  46231. this.callBase(args);
  46232. switch (args.name) {
  46233. case'cellHintEnabled':
  46234. case'onCellPrepared':
  46235. case'onRowPrepared':
  46236. case'onCellHoverChanged':
  46237. this.render();
  46238. this.component.resize();
  46239. args.handled = true;
  46240. break
  46241. }
  46242. },
  46243. init: function() {
  46244. var that = this;
  46245. that._columnsController = that.getController('columns');
  46246. that._dataController = that.getController('data');
  46247. that._delayedTemplates = [];
  46248. that._templatesCache = {};
  46249. that.createAction("onCellClick");
  46250. that.createAction("onCellHoverChanged", {excludeValidators: ["disabled", "readOnly"]});
  46251. that.createAction("onCellPrepared", {
  46252. excludeValidators: ["designMode", "disabled", "readOnly"],
  46253. category: "rendering"
  46254. });
  46255. that.createAction("onRowPrepared", {
  46256. excludeValidators: ["designMode", "disabled", "readOnly"],
  46257. category: "rendering"
  46258. });
  46259. that._columnsController.columnsChanged.add($.proxy(that._columnOptionChanged, that));
  46260. that._dataController && that._dataController.changed.add($.proxy(that._handleDataChanged, that))
  46261. },
  46262. _handleDataChanged: function(e){},
  46263. scrollOffset: function(pos) {
  46264. var that = this,
  46265. $element = that.element(),
  46266. $scrollContainer = $element && $element.find('.' + DATAGRID_SCROLL_CONTAINER_CLASS);
  46267. if (pos === undefined)
  46268. return $scrollContainer && $scrollContainer.scrollLeft();
  46269. else if (that._scrollLeft !== pos) {
  46270. that._scrollLeft = pos;
  46271. $scrollContainer && $scrollContainer.scrollLeft(pos)
  46272. }
  46273. },
  46274. wrapTableInScrollContainer: function($table) {
  46275. return $('<div/>').addClass(DATAGRID_CONTENT_CLASS).addClass(DATAGRID_SCROLL_CONTAINER_CLASS).append($table)
  46276. },
  46277. getColumnWidths: function() {
  46278. var that = this,
  46279. result = [],
  46280. tableElement = that._getTableElement();
  46281. if (tableElement)
  46282. result = dataGrid.getWidths(tableElement);
  46283. return result
  46284. },
  46285. setColumnWidths: function(widths) {
  46286. var $cols,
  46287. i,
  46288. j,
  46289. columnIndex,
  46290. columns,
  46291. tableElements = this._getTableElements(true);
  46292. if (tableElements.length && widths)
  46293. for (i = 0; i < tableElements.length; i++) {
  46294. columnIndex = 0;
  46295. $cols = $(tableElements[i]).find('col');
  46296. columns = this.getColumns($(tableElements[i]));
  46297. for (j = 0; j < columns.length; j++) {
  46298. if (columns[j].colspan) {
  46299. columnIndex += columns[j].colspan;
  46300. continue
  46301. }
  46302. $cols.eq(columnIndex).width(widths[columnIndex] || 'auto');
  46303. columnIndex++
  46304. }
  46305. }
  46306. },
  46307. getCellElements: function(rowIndex) {
  46308. var $row = this._getRowElements().eq(rowIndex);
  46309. return $row.children()
  46310. },
  46311. getCellElement: function(rowIndex, columnIdentificator) {
  46312. var that = this,
  46313. $cells = that.getCellElements(rowIndex),
  46314. $cell,
  46315. columnsController = that._columnsController,
  46316. columnIndex,
  46317. columnVisibleIndex = columnIdentificator;
  46318. if (utils.isString(columnIdentificator)) {
  46319. columnIndex = columnsController.columnOption(columnIdentificator, 'index');
  46320. columnVisibleIndex = columnsController.getVisibleIndex(columnIndex)
  46321. }
  46322. if ($cells.length && columnVisibleIndex >= 0)
  46323. $cell = $cells.eq(columnVisibleIndex);
  46324. if ($cell && $cell.length)
  46325. return $cell
  46326. },
  46327. getColumnElements: function(){},
  46328. getColumns: function() {
  46329. return this._columnsController.getVisibleColumns()
  46330. },
  46331. getCell: function(cellPosition) {
  46332. var row,
  46333. tableElement = this._getTableElement();
  46334. if (tableElement && tableElement.length === 1) {
  46335. row = tableElement[0].rows[cellPosition.rowIndex];
  46336. return row ? $(row.cells[cellPosition.columnIndex]) : null
  46337. }
  46338. },
  46339. getRowsCount: function() {
  46340. var tableElement = this._getTableElement();
  46341. if (tableElement && tableElement.length === 1)
  46342. return tableElement[0].rows.length;
  46343. return 0
  46344. },
  46345. _getRowElements: function(tableElement) {
  46346. tableElement = tableElement || this._getTableElement();
  46347. return tableElement && tableElement.children('tbody').children('.' + DATAGRID_ROW_CLASS) || $()
  46348. },
  46349. getRowIndex: function($row) {
  46350. return this._getRowElements().index($row)
  46351. },
  46352. getBoundingRect: function(){},
  46353. getName: function(){}
  46354. });
  46355. $.extend(dataGrid.__internals, {
  46356. DATAGRID_INDICATOR_ALIGNMENT_CLASS: DATAGRID_INDICATOR_ALIGNMENT_CLASS,
  46357. DATAGRID_GROUP_SPACE_CLASS: DATAGRID_GROUP_SPACE_CLASS,
  46358. DATAGRID_CELL_CONTENT_CLASS: DATAGRID_CELL_CONTENT_CLASS,
  46359. DATAGRID_ROW_CLASS: DATAGRID_ROW_CLASS,
  46360. DATAGRID_GROUP_ROW_CLASS: DATAGRID_GROUP_ROW_CLASS,
  46361. DATAGRID_TABLE_CLASS: DATAGRID_TABLE_CLASS,
  46362. DATAGRID_TABLE_FIXED_CLASS: DATAGRID_TABLE_FIXED_CLASS,
  46363. DATAGRID_SCROLL_CONTAINER_CLASS: DATAGRID_SCROLL_CONTAINER_CLASS,
  46364. DATAGRID_COLUMN_INDICATORS_CLASS: DATAGRID_COLUMN_INDICATORS_CLASS,
  46365. DATAGRID_HEADER_ROW_CLASS: DATAGRID_HEADER_ROW_CLASS
  46366. })
  46367. })(jQuery, DevExpress);
  46368. /*! Module widgets-web, file ui.dataGrid.columnChooserModule.js */
  46369. (function($, DX) {
  46370. var ui = DX.ui,
  46371. utils = DX.utils,
  46372. dataGrid = ui.dxDataGrid;
  46373. var DATAGRID_COLUMN_CHOOSER_CLASS = 'dx-datagrid-column-chooser',
  46374. DATAGRID_COLUMN_CHOOSER_BUTTON_CLASS = 'dx-datagrid-column-chooser-button',
  46375. DATAGRID_COLUMN_CHOOSER_ICON_NAME = 'column-chooser',
  46376. DATAGRID_COLUMN_CHOOSER_ITEM_CLASS = "dx-column-chooser-item",
  46377. DATAGRID_COLUMN_CHOOSER_MESSAGE_CLASS = "dx-column-chooser-message",
  46378. DATAGRID_HEADERS_DRAG_ACTION_CLASS = "dx-datagrid-drag-action";
  46379. dataGrid.ColumnChooserController = dataGrid.ViewController.inherit({
  46380. renderShowColumnChooserButton: function($element) {
  46381. var that = this,
  46382. columnChooserEnabled = that.option("columnChooser.enabled"),
  46383. $showColumnChooserButton = $element.find("." + DATAGRID_COLUMN_CHOOSER_BUTTON_CLASS),
  46384. $columnChooserButton;
  46385. if (columnChooserEnabled)
  46386. if (!$showColumnChooserButton.length) {
  46387. $columnChooserButton = $('<div />').addClass(DATAGRID_COLUMN_CHOOSER_BUTTON_CLASS).appendTo($element);
  46388. that._createComponent($columnChooserButton, "dxButton", {
  46389. icon: DATAGRID_COLUMN_CHOOSER_ICON_NAME,
  46390. onClick: function() {
  46391. that.getView("columnChooserView").showColumnChooser()
  46392. },
  46393. hint: that.option("columnChooser.title"),
  46394. _templates: {}
  46395. })
  46396. }
  46397. else
  46398. $showColumnChooserButton.show();
  46399. else
  46400. $showColumnChooserButton.hide()
  46401. },
  46402. getPosition: function() {
  46403. var rowsView = this.getView("rowsView");
  46404. return {
  46405. my: "right bottom",
  46406. at: "right bottom",
  46407. of: rowsView && rowsView.element(),
  46408. collision: 'fit',
  46409. offset: "-2 -2",
  46410. boundaryOffset: "2 2"
  46411. }
  46412. }
  46413. });
  46414. dataGrid.ColumnChooserView = dataGrid.ColumnsView.inherit({
  46415. _updateItems: function() {
  46416. var chooserColumns = this._columnsController.getChooserColumns(),
  46417. columnChooserOptions = this.option("columnChooser"),
  46418. $content = this._popupContainer.content(),
  46419. scrollableInstance = this._createComponent($content, "dxScrollable", dataGrid.createScrollableOptions(this));
  46420. this._renderColumnChooserItems($content, chooserColumns);
  46421. if (!chooserColumns.length)
  46422. $('<span />').addClass(DATAGRID_COLUMN_CHOOSER_MESSAGE_CLASS).text(columnChooserOptions ? columnChooserOptions.emptyPanelText : "").appendTo(scrollableInstance.content())
  46423. },
  46424. _initializePopupContainer: function() {
  46425. var that = this,
  46426. $element = that.element().addClass(DATAGRID_COLUMN_CHOOSER_CLASS),
  46427. columnChooserOptions = that.option("columnChooser"),
  46428. theme = DevExpress.ui.themes.current(),
  46429. isGenericTheme = theme && theme.indexOf("generic") > -1,
  46430. isAndroid5Theme = theme && theme.indexOf("android5") > -1,
  46431. dxPopupOptions = {
  46432. visible: false,
  46433. shading: false,
  46434. showCloseButton: false,
  46435. dragEnabled: true,
  46436. buttons: [{
  46437. text: columnChooserOptions.title,
  46438. toolbar: "top",
  46439. location: isGenericTheme || isAndroid5Theme ? "before" : "center"
  46440. }],
  46441. position: that.getController("columnChooser").getPosition(),
  46442. width: columnChooserOptions.width,
  46443. height: columnChooserOptions.height,
  46444. rtlEnabled: that.option('rtlEnabled'),
  46445. container: columnChooserOptions.container
  46446. };
  46447. if (isGenericTheme)
  46448. $.extend(dxPopupOptions, {showCloseButton: true});
  46449. else
  46450. dxPopupOptions.buttons[dxPopupOptions.buttons.length] = {shortcut: "cancel"};
  46451. if (!utils.isDefined(this._popupContainer)) {
  46452. that._popupContainer = that._createComponent($element, "dxPopup", dxPopupOptions);
  46453. that._popupContainer.on("optionChanged", function(args) {
  46454. if (args.name === "visible")
  46455. that.renderCompleted.fire()
  46456. })
  46457. }
  46458. else
  46459. this._popupContainer.option(dxPopupOptions)
  46460. },
  46461. _renderCore: function() {
  46462. if (this._popupContainer)
  46463. this._updateItems()
  46464. },
  46465. _renderColumnChooserItems: function($container, chooserColumns) {
  46466. var dxScrollable = $container.dxScrollable("instance"),
  46467. $scrollableContainer = dxScrollable.content(),
  46468. $item;
  46469. $scrollableContainer.empty();
  46470. $.each(chooserColumns, function(index, chooserColumn) {
  46471. $item = $('<div />').addClass(chooserColumn.cssClass).addClass(DATAGRID_COLUMN_CHOOSER_ITEM_CLASS).toggleClass(DATAGRID_HEADERS_DRAG_ACTION_CLASS, chooserColumn.allowHiding).text(chooserColumn.caption).appendTo($scrollableContainer)
  46472. });
  46473. dxScrollable.update()
  46474. },
  46475. getColumnElements: function() {
  46476. var $content = this._popupContainer && this._popupContainer.content();
  46477. return $content && $content.find('.' + DATAGRID_COLUMN_CHOOSER_ITEM_CLASS)
  46478. },
  46479. getName: function() {
  46480. return 'columnChooser'
  46481. },
  46482. getColumns: function() {
  46483. return this._columnsController.getChooserColumns()
  46484. },
  46485. allowDragging: function(column) {
  46486. return this.isColumnChooserVisible() && column && column.allowHiding
  46487. },
  46488. getBoundingRect: function() {
  46489. var that = this,
  46490. container = that._popupContainer && that._popupContainer._container(),
  46491. offset;
  46492. if (container && container.is(':visible')) {
  46493. offset = container.offset();
  46494. return {
  46495. left: offset.left,
  46496. top: offset.top,
  46497. right: offset.left + container.outerWidth(),
  46498. bottom: offset.top + container.outerHeight()
  46499. }
  46500. }
  46501. return null
  46502. },
  46503. showColumnChooser: function() {
  46504. this._isPopupContainerShown = true;
  46505. if (!this._popupContainer) {
  46506. this._initializePopupContainer();
  46507. this.render()
  46508. }
  46509. this._popupContainer.show()
  46510. },
  46511. hideColumnChooser: function() {
  46512. if (this._popupContainer) {
  46513. this._popupContainer.hide();
  46514. this._isPopupContainerShown = false
  46515. }
  46516. },
  46517. isColumnChooserVisible: function() {
  46518. var popupContainer = this._popupContainer;
  46519. return popupContainer && popupContainer.option("visible")
  46520. },
  46521. publicMethods: function() {
  46522. return ['showColumnChooser', 'hideColumnChooser']
  46523. }
  46524. });
  46525. $.extend(dataGrid.__internals, {
  46526. DATAGRID_COLUMN_CHOOSER_CLASS: DATAGRID_COLUMN_CHOOSER_CLASS,
  46527. DATAGRID_COLUMN_CHOOSER_ITEM_CLASS: DATAGRID_COLUMN_CHOOSER_ITEM_CLASS,
  46528. DATAGRID_COLUMN_CHOOSER_BUTTON_CLASS: DATAGRID_COLUMN_CHOOSER_BUTTON_CLASS,
  46529. DATAGRID_COLUMN_CHOOSER_MESSAGE_CLASS: DATAGRID_COLUMN_CHOOSER_MESSAGE_CLASS
  46530. });
  46531. dataGrid.registerModule('columnChooser', {
  46532. defaultOptions: function() {
  46533. return {columnChooser: {
  46534. enabled: false,
  46535. width: 250,
  46536. height: 260,
  46537. title: Globalize.localize("dxDataGrid-columnChooserTitle"),
  46538. emptyPanelText: Globalize.localize("dxDataGrid-columnChooserEmptyText"),
  46539. container: undefined
  46540. }}
  46541. },
  46542. controllers: {columnChooser: dataGrid.ColumnChooserController},
  46543. views: {columnChooserView: dataGrid.ColumnChooserView},
  46544. extenders: {views: {headerPanel: {
  46545. _renderShowColumnChooserButton: function() {
  46546. this.getController("columnChooser").renderShowColumnChooserButton(this.element())
  46547. },
  46548. _renderCore: function() {
  46549. this.callBase();
  46550. this._renderShowColumnChooserButton()
  46551. },
  46552. optionChanged: function(args) {
  46553. switch (args.name) {
  46554. case'columnChooser':
  46555. this._renderShowColumnChooserButton();
  46556. args.handled = true;
  46557. break;
  46558. default:
  46559. this.callBase(args)
  46560. }
  46561. },
  46562. isVisible: function() {
  46563. var that = this,
  46564. columnChooserEnabled = that.option('columnChooser.enabled');
  46565. return that.callBase() || columnChooserEnabled
  46566. }
  46567. }}}
  46568. })
  46569. })(jQuery, DevExpress);
  46570. /*! Module widgets-web, file ui.dataGrid.editing.js */
  46571. (function($, DX) {
  46572. var dataGrid = DX.ui.dxDataGrid,
  46573. events = DX.ui.events,
  46574. addNamespace = events.addNamespace,
  46575. utils = DX.utils,
  46576. getIndexByKey = dataGrid.getIndexByKey;
  46577. var DATAGRID_LINK_CLASS = "dx-link",
  46578. DATAGRID_EDITOR_CELL_CLASS = "dx-editor-cell",
  46579. DATAGRID_ROW_SELECTED = "dx-selection",
  46580. DATAGRID_EDIT_ROW = "dx-edit-row",
  46581. DATAGRID_EDIT_BUTTON_CLASS = "dx-edit-button",
  46582. DATAGRID_INSERT_INDEX = "__DX_INSERT_INDEX__",
  46583. DATAGRID_ROW_REMOVED = "dx-row-removed",
  46584. DATAGRID_ROW_INSERTED = "dx-row-inserted",
  46585. DATAGRID_ROW_MODIFIED = "dx-row-modified",
  46586. DATAGRID_CELL_MODIFIED = "dx-cell-modified",
  46587. DATAGRID_CELL_HIGHLIGHT_OUTLINE = "dx-highlight-outline",
  46588. DATAGRID_EDITING_NAMESPACE = "dxDataGridEditing",
  46589. DATAGRID_FOCUS_OVERLAY_CLASS = "dx-datagrid-focus-overlay",
  46590. DATAGRID_READONLY_CLASS = "dx-datagrid-readonly",
  46591. DATAGRID_DATA_ROW_CLASS = "dx-data-row",
  46592. CHECKBOX_CLASS = "dx-checkbox",
  46593. DATAGRID_EDITOR_INLINE_BLOCK = "dx-editor-inline-block",
  46594. DATAGRID_CELL_FOCUS_DISABLED_CLASS = "dx-cell-focus-disabled",
  46595. DATAGRID_EDIT_MODE_BATCH = "batch",
  46596. DATAGRID_EDIT_MODE_ROW = "row",
  46597. DATAGRID_EDIT_MODE_CELL = "cell",
  46598. DATA_EDIT_DATA_INSERT_TYPE = "insert",
  46599. DATA_EDIT_DATA_UPDATE_TYPE = "update",
  46600. DATA_EDIT_DATA_REMOVE_TYPE = "remove",
  46601. DATAGRID_POINTER_EVENTS_NONE_CLASS = "dx-pointer-events-none",
  46602. DATAGRID_POINTER_EVENTS_TARGET_CLASS = "dx-pointer-events-target";
  46603. var getEditMode = function(that) {
  46604. var editMode = that.option('editing.editMode');
  46605. if (editMode === DATAGRID_EDIT_MODE_BATCH || editMode === DATAGRID_EDIT_MODE_CELL)
  46606. return editMode;
  46607. return DATAGRID_EDIT_MODE_ROW
  46608. };
  46609. dataGrid.EditingController = dataGrid.ViewController.inherit(function() {
  46610. var getDefaultEditorTemplate = function(that) {
  46611. return function(container, options) {
  46612. var $editor = $('<div/>').appendTo(container);
  46613. that.getController('editorFactory').createEditor($editor, $.extend({}, options.column, {
  46614. value: options.value,
  46615. setValue: options.setValue,
  46616. row: options.row,
  46617. parentType: 'dataRow',
  46618. width: null,
  46619. readOnly: options.setValue === undefined
  46620. }))
  46621. }
  46622. };
  46623. var getDataController = function(that) {
  46624. return that.getController('data')
  46625. };
  46626. return {
  46627. init: function() {
  46628. var that = this;
  46629. that._insertIndex = 1;
  46630. that._editRowIndex = -1;
  46631. that._editData = [];
  46632. that._editColumnIndex = -1;
  46633. that._columnsController = that.getController("columns");
  46634. that.createAction("onInitNewRow", {excludeValidators: ["disabled", "readOnly"]});
  46635. that.createAction("onRowInserting", {excludeValidators: ["disabled", "readOnly"]});
  46636. that.createAction("onRowInserted", {excludeValidators: ["disabled", "readOnly"]});
  46637. that.createAction("onEditingStart", {excludeValidators: ["disabled", "readOnly"]});
  46638. that.createAction("onRowUpdating", {excludeValidators: ["disabled", "readOnly"]});
  46639. that.createAction("onRowUpdated", {excludeValidators: ["disabled", "readOnly"]});
  46640. that.createAction("onRowRemoving", {excludeValidators: ["disabled", "readOnly"]});
  46641. that.createAction("onRowRemoved", {excludeValidators: ["disabled", "readOnly"]});
  46642. if (!that._saveEditorHandler) {
  46643. that._saveEditorHandler = that.createAction(function(e) {
  46644. var event = e.jQueryEvent,
  46645. visibleColumns,
  46646. isEditorPopup,
  46647. isDomElement,
  46648. isFocusOverlay,
  46649. $targetCell,
  46650. allowEditing,
  46651. cellIndex,
  46652. isDataRow;
  46653. if (getEditMode(that) !== DATAGRID_EDIT_MODE_ROW && that.isEditing() && !that._editCellInProgress) {
  46654. isEditorPopup = $(event.target).closest('.dx-overlay-wrapper').length;
  46655. isDomElement = $(event.target).closest(document).length;
  46656. isFocusOverlay = $(event.target).hasClass(DATAGRID_FOCUS_OVERLAY_CLASS);
  46657. isDataRow = $(event.target).closest('.' + DATAGRID_DATA_ROW_CLASS).length;
  46658. visibleColumns = that._columnsController.getVisibleColumns();
  46659. $targetCell = $(event.target).closest('td');
  46660. cellIndex = $targetCell[0] && $targetCell[0].cellIndex;
  46661. allowEditing = visibleColumns[cellIndex] && visibleColumns[cellIndex].allowEditing;
  46662. if ((!isDataRow || isDataRow && !allowEditing) && !isEditorPopup && !isFocusOverlay && isDomElement)
  46663. that.closeEditCell()
  46664. }
  46665. });
  46666. $(document).on('dxclick', that._saveEditorHandler)
  46667. }
  46668. that._updateEditColumn();
  46669. that._updateEditButtons()
  46670. },
  46671. getEditMode: function() {
  46672. return getEditMode(this)
  46673. },
  46674. getFirstEditableColumnIndex: function() {
  46675. var columnsController = this.getController("columns"),
  46676. visibleColumns = columnsController.getVisibleColumns(),
  46677. columnIndex;
  46678. $.each(visibleColumns, function(index, column) {
  46679. if (column.allowEditing) {
  46680. columnIndex = index;
  46681. return false
  46682. }
  46683. });
  46684. return columnIndex
  46685. },
  46686. getFirstEditableCellInRow: function(rowIndex) {
  46687. return this.getView('rowsView').getCellElement(rowIndex ? rowIndex : 0, this.getFirstEditableColumnIndex())
  46688. },
  46689. getIndexByKey: function(key, items) {
  46690. return getIndexByKey(key, items)
  46691. },
  46692. hasChanges: function() {
  46693. var that = this,
  46694. result = false;
  46695. $.each(that._editData, function(_, editData) {
  46696. result = result || !!editData.type
  46697. });
  46698. return result
  46699. },
  46700. dispose: function() {
  46701. this.callBase();
  46702. $(document).off('dxclick', this._saveEditorHandler)
  46703. },
  46704. optionChanged: function(args) {
  46705. if (args.name === "editing") {
  46706. this.init();
  46707. args.handled = true
  46708. }
  46709. else
  46710. this.callBase(args)
  46711. },
  46712. publicMethods: function() {
  46713. return ['insertRow', 'editRow', 'editCell', 'closeEditCell', 'removeRow', 'saveEditData', 'undeleteRow', 'cancelEditData']
  46714. },
  46715. refresh: function() {
  46716. if (getEditMode(this) === DATAGRID_EDIT_MODE_ROW || getEditMode(this) === DATAGRID_EDIT_MODE_CELL)
  46717. this.init();
  46718. else {
  46719. this._editRowIndex = -1;
  46720. this._editColumnIndex = -1
  46721. }
  46722. },
  46723. isEditing: function() {
  46724. return this._editRowIndex > -1
  46725. },
  46726. isEditRow: function(rowIndex) {
  46727. return getEditMode(this) === DATAGRID_EDIT_MODE_ROW && this._editRowIndex === rowIndex
  46728. },
  46729. isEditCell: function(rowIndex, columnIndex) {
  46730. return this._editRowIndex === rowIndex && this._editColumnIndex === columnIndex
  46731. },
  46732. processItems: function(items, changeType) {
  46733. var that = this,
  46734. editData = that._editData,
  46735. i,
  46736. key,
  46737. data;
  46738. that.update();
  46739. for (i = 0; i < editData.length; i++) {
  46740. key = editData[i].key;
  46741. data = {key: key};
  46742. if (editData[i].type === DATA_EDIT_DATA_INSERT_TYPE && key.pageIndex === that._pageIndex) {
  46743. data[DATAGRID_INSERT_INDEX] = key[DATAGRID_INSERT_INDEX];
  46744. items.splice(key.rowIndex, 0, data)
  46745. }
  46746. }
  46747. return items
  46748. },
  46749. processDataItem: function(item, columns, generateDataValues) {
  46750. var that = this,
  46751. editIndex,
  46752. editData,
  46753. data,
  46754. key = item.data[DATAGRID_INSERT_INDEX] ? item.data.key : item.key,
  46755. editMode = getEditMode(that);
  46756. editIndex = getIndexByKey(key, that._editData);
  46757. if (editIndex >= 0) {
  46758. editData = that._editData[editIndex];
  46759. data = editData.data;
  46760. switch (editData.type) {
  46761. case DATA_EDIT_DATA_INSERT_TYPE:
  46762. item.inserted = true;
  46763. item.key = key;
  46764. item.data = data;
  46765. break;
  46766. case DATA_EDIT_DATA_UPDATE_TYPE:
  46767. item.modified = true;
  46768. item.data = $.extend(true, {}, item.data, data);
  46769. item.modifiedValues = generateDataValues(data, columns);
  46770. break;
  46771. case DATA_EDIT_DATA_REMOVE_TYPE:
  46772. if (editMode === DATAGRID_EDIT_MODE_BATCH)
  46773. item.data = $.extend(true, {}, item.data, data);
  46774. item.removed = true;
  46775. break
  46776. }
  46777. }
  46778. },
  46779. insertRow: function() {
  46780. var that = this,
  46781. dataController = getDataController(that),
  46782. rowsView = that.getView('rowsView'),
  46783. param = {data: {}},
  46784. insertKey = {
  46785. pageIndex: dataController.pageIndex(),
  46786. rowIndex: rowsView ? rowsView.getTopVisibleItemIndex() : 0
  46787. },
  46788. oldEditRowIndex = that._editRowIndex,
  46789. editMode = getEditMode(that),
  46790. $firstCell;
  46791. that.refresh();
  46792. if (editMode !== DATAGRID_EDIT_MODE_BATCH) {
  46793. if (that._insertIndex > 1)
  46794. return;
  46795. that._editRowIndex = insertKey.rowIndex
  46796. }
  46797. that.executeAction("onInitNewRow", param);
  46798. insertKey[DATAGRID_INSERT_INDEX] = that._insertIndex++;
  46799. that._addEditData({
  46800. key: insertKey,
  46801. data: param.data,
  46802. type: DATA_EDIT_DATA_INSERT_TYPE
  46803. });
  46804. dataController.updateItems({
  46805. changeType: 'update',
  46806. rowIndices: [oldEditRowIndex, insertKey.rowIndex]
  46807. });
  46808. $firstCell = that.getFirstEditableCellInRow();
  46809. that._delayedInputFocus($firstCell, function() {
  46810. var $cell = that.getFirstEditableCellInRow();
  46811. $cell && $cell.trigger("dxclick")
  46812. });
  46813. that._afterInsertRow({
  46814. key: insertKey,
  46815. data: param.data
  46816. })
  46817. },
  46818. _isEditingStart: function(options) {
  46819. this.executeAction("onEditingStart", options);
  46820. return options.cancel
  46821. },
  46822. editRow: function(rowIndex) {
  46823. var that = this,
  46824. dataController = getDataController(that),
  46825. items = dataController.items(),
  46826. item = items[rowIndex],
  46827. params = {
  46828. data: item.data,
  46829. cancel: false
  46830. },
  46831. oldEditRowIndex = that._editRowIndex,
  46832. $firstCell;
  46833. if (rowIndex === oldEditRowIndex)
  46834. return true;
  46835. if (!item.inserted)
  46836. params.key = item.key;
  46837. if (that._isEditingStart(params))
  46838. return;
  46839. that.init();
  46840. that._pageIndex = dataController.pageIndex();
  46841. that._editRowIndex = items[0].inserted ? rowIndex - 1 : rowIndex;
  46842. that._addEditData({
  46843. data: {},
  46844. key: item.key,
  46845. oldData: item.data
  46846. });
  46847. dataController.updateItems({
  46848. changeType: 'update',
  46849. rowIndices: [oldEditRowIndex, rowIndex]
  46850. });
  46851. $firstCell = that.getFirstEditableCellInRow(that._editRowIndex);
  46852. that._delayedInputFocus($firstCell, function() {
  46853. $firstCell && that.component.focus($firstCell)
  46854. })
  46855. },
  46856. editCell: function(rowIndex, columnIndex) {
  46857. var that = this,
  46858. dataController = getDataController(that),
  46859. items = dataController.items(),
  46860. item = items[rowIndex],
  46861. params = {
  46862. data: item && item.data,
  46863. cancel: false,
  46864. column: that._columnsController.getVisibleColumns()[columnIndex]
  46865. },
  46866. editMode = getEditMode(that),
  46867. oldEditRowIndex = that._editRowIndex,
  46868. oldEditColumnIndex = that._editColumnIndex,
  46869. columns = that._columnsController.getVisibleColumns(),
  46870. isCellEditingAllowed = params.column && params.column.allowEditing,
  46871. showEditorAlways = params.column && params.column.showEditorAlways,
  46872. $editCell;
  46873. if (isCellEditingAllowed && item && item.rowType === 'data' && !item.removed && editMode !== DATAGRID_EDIT_MODE_ROW) {
  46874. if (that.isEditCell(rowIndex, columnIndex))
  46875. return true;
  46876. if (editMode === DATAGRID_EDIT_MODE_CELL && !item.inserted && that.hasChanges()) {
  46877. that.saveEditData();
  46878. if (that.hasChanges())
  46879. return true
  46880. }
  46881. if (!item.inserted)
  46882. params.key = item.key;
  46883. if (that._isEditingStart(params))
  46884. return true;
  46885. that._editRowIndex = rowIndex;
  46886. that._editColumnIndex = columnIndex;
  46887. that._pageIndex = dataController.pageIndex();
  46888. that._addEditData({
  46889. data: {},
  46890. key: item.key,
  46891. oldData: item.data
  46892. });
  46893. if (!showEditorAlways || columns[oldEditColumnIndex] && !columns[oldEditColumnIndex].showEditorAlways) {
  46894. that._editCellInProgress = true;
  46895. dataController.updateItems({
  46896. changeType: 'update',
  46897. rowIndices: [oldEditRowIndex, that._editRowIndex]
  46898. })
  46899. }
  46900. $editCell = that.getView("rowsView").getCellElement(that._editRowIndex, that._editColumnIndex);
  46901. that._delayedInputFocus($editCell, function() {
  46902. that._editCellInProgress = false
  46903. });
  46904. return true
  46905. }
  46906. return false
  46907. },
  46908. _delayedInputFocus: function($cell, afterFocusCallback) {
  46909. setTimeout(function() {
  46910. $cell && $cell.find('[tabindex], input').focus();
  46911. afterFocusCallback && afterFocusCallback()
  46912. })
  46913. },
  46914. removeRow: function(rowIndex) {
  46915. var that = this,
  46916. editingOptions = that.option("editing"),
  46917. editingTexts = editingOptions && editingOptions.texts,
  46918. confirmDeleteTitle = editingTexts && editingTexts.confirmDeleteTitle,
  46919. isBatchMode = editingOptions && editingOptions.editMode === DATAGRID_EDIT_MODE_BATCH,
  46920. confirmDeleteMessage = editingTexts && editingTexts.confirmDeleteMessage,
  46921. dataController = getDataController(that),
  46922. removeByKey,
  46923. showDialogTitle,
  46924. oldEditRowIndex = that._editRowIndex,
  46925. item = dataController.items()[rowIndex],
  46926. key = item && item.key;
  46927. if (item) {
  46928. removeByKey = function(key) {
  46929. that.refresh();
  46930. var editIndex = getIndexByKey(key, that._editData);
  46931. if (editIndex >= 0)
  46932. if (that._editData[editIndex].type === DATA_EDIT_DATA_INSERT_TYPE)
  46933. that._editData.splice(editIndex, 1);
  46934. else
  46935. that._editData[editIndex].type = DATA_EDIT_DATA_REMOVE_TYPE;
  46936. else
  46937. that._addEditData({
  46938. key: key,
  46939. oldData: item.data,
  46940. type: DATA_EDIT_DATA_REMOVE_TYPE
  46941. });
  46942. if (isBatchMode)
  46943. dataController.updateItems({
  46944. changeType: 'update',
  46945. rowIndices: [oldEditRowIndex, rowIndex]
  46946. });
  46947. else
  46948. that.saveEditData()
  46949. };
  46950. if (isBatchMode || !confirmDeleteMessage)
  46951. removeByKey(key);
  46952. else {
  46953. showDialogTitle = utils.isDefined(confirmDeleteTitle) && confirmDeleteTitle.length > 0;
  46954. DX.ui.dialog.confirm(confirmDeleteMessage, confirmDeleteTitle, showDialogTitle).done(function(confirmResult) {
  46955. if (confirmResult)
  46956. removeByKey(key)
  46957. })
  46958. }
  46959. }
  46960. },
  46961. undeleteRow: function(rowIndex) {
  46962. var that = this,
  46963. dataController = getDataController(that),
  46964. item = dataController.items()[rowIndex],
  46965. oldEditRowIndex = that._editRowIndex,
  46966. key = item && item.key;
  46967. if (item) {
  46968. var editIndex = getIndexByKey(key, that._editData),
  46969. editData;
  46970. if (editIndex >= 0) {
  46971. editData = that._editData[editIndex];
  46972. if ($.isEmptyObject(editData.data))
  46973. that._editData.splice(editIndex, 1);
  46974. else
  46975. editData.type = DATA_EDIT_DATA_UPDATE_TYPE;
  46976. dataController.updateItems({
  46977. changeType: 'update',
  46978. rowIndices: [oldEditRowIndex, rowIndex]
  46979. })
  46980. }
  46981. }
  46982. },
  46983. _saveEditDataCore: function(deferreds, processedKeys) {
  46984. var that = this,
  46985. store = getDataController(that).store();
  46986. $.each(that._editData, function(index, editData) {
  46987. var data = editData.data,
  46988. oldData = editData.oldData,
  46989. key = editData.key,
  46990. type = editData.type,
  46991. deferred,
  46992. doneDeferred,
  46993. params;
  46994. if (that._beforeSaveEditData(editData, index))
  46995. return;
  46996. switch (type) {
  46997. case DATA_EDIT_DATA_REMOVE_TYPE:
  46998. params = {
  46999. data: oldData,
  47000. key: key,
  47001. cancel: false
  47002. };
  47003. that.executeAction("onRowRemoving", params);
  47004. if (params.cancel)
  47005. return;
  47006. deferred = store.remove(key);
  47007. break;
  47008. case DATA_EDIT_DATA_INSERT_TYPE:
  47009. params = {
  47010. data: data,
  47011. cancel: false
  47012. };
  47013. that.executeAction("onRowInserting", params);
  47014. if (params.cancel)
  47015. return;
  47016. deferred = store.insert(params.data);
  47017. break;
  47018. case DATA_EDIT_DATA_UPDATE_TYPE:
  47019. params = {
  47020. newData: data,
  47021. oldData: oldData,
  47022. key: key,
  47023. cancel: false
  47024. };
  47025. that.executeAction("onRowUpdating", params);
  47026. if (params.cancel)
  47027. return;
  47028. deferred = store.update(key, params.newData);
  47029. break
  47030. }
  47031. if (deferred) {
  47032. doneDeferred = $.Deferred();
  47033. deferred.always(function() {
  47034. processedKeys.push(key)
  47035. }).always(doneDeferred.resolve);
  47036. deferreds.push(doneDeferred.promise())
  47037. }
  47038. })
  47039. },
  47040. _processSaveEditDataResult: function(results, processedKeys) {
  47041. var that = this,
  47042. dataController = getDataController(that),
  47043. i,
  47044. arg,
  47045. editIndex,
  47046. isError,
  47047. editMode = getEditMode(that);
  47048. for (i = 0; i < results.length; i++) {
  47049. arg = results[i];
  47050. editIndex = getIndexByKey(processedKeys[i], that._editData);
  47051. if (that._editData[editIndex]) {
  47052. isError = arg && arg instanceof Error;
  47053. if (isError) {
  47054. that._editData[editIndex].error = arg;
  47055. dataController.dataErrorOccurred.fire(arg);
  47056. if (editMode !== DATAGRID_EDIT_MODE_BATCH)
  47057. return false
  47058. }
  47059. else
  47060. that._editData.splice(editIndex, 1)
  47061. }
  47062. }
  47063. return true
  47064. },
  47065. _fireSaveEditDataEvents: function(editData) {
  47066. var that = this;
  47067. $.each(editData, function(_, itemData) {
  47068. var data = itemData.data,
  47069. key = itemData.key,
  47070. type = itemData.type,
  47071. params = {
  47072. key: key,
  47073. data: data
  47074. };
  47075. if (itemData.error)
  47076. params.error = itemData.error;
  47077. switch (type) {
  47078. case DATA_EDIT_DATA_REMOVE_TYPE:
  47079. that.executeAction("onRowRemoved", $.extend({}, params, {data: itemData.oldData}));
  47080. break;
  47081. case DATA_EDIT_DATA_INSERT_TYPE:
  47082. that.executeAction("onRowInserted", params);
  47083. break;
  47084. case DATA_EDIT_DATA_UPDATE_TYPE:
  47085. that.executeAction("onRowUpdated", params);
  47086. break
  47087. }
  47088. })
  47089. },
  47090. saveEditData: function() {
  47091. var that = this,
  47092. processedKeys = [],
  47093. deferreds = [],
  47094. dataController = getDataController(that),
  47095. rowIndex = that._editRowIndex,
  47096. editData = $.extend({}, that._editData),
  47097. editMode = getEditMode(that);
  47098. var resetEditIndices = function(that) {
  47099. that._editColumnIndex = -1;
  47100. that._editRowIndex = -1
  47101. };
  47102. if (that._beforeSaveEditData())
  47103. return;
  47104. that._saveEditDataCore(deferreds, processedKeys);
  47105. if (deferreds.length) {
  47106. $.when.apply($, deferreds).done(function() {
  47107. if (that._processSaveEditDataResult(arguments, processedKeys)) {
  47108. resetEditIndices(that);
  47109. $.when(dataController.refresh()).always(function() {
  47110. that._fireSaveEditDataEvents(editData);
  47111. that._afterSaveEditData()
  47112. })
  47113. }
  47114. });
  47115. return
  47116. }
  47117. if (editMode === DATAGRID_EDIT_MODE_ROW) {
  47118. if (!that.hasChanges())
  47119. that.cancelEditData()
  47120. }
  47121. else {
  47122. resetEditIndices(that);
  47123. dataController.updateItems(rowIndex >= 0 && {
  47124. changeType: 'update',
  47125. rowIndices: [rowIndex]
  47126. })
  47127. }
  47128. that._afterSaveEditData()
  47129. },
  47130. _updateEditColumn: function() {
  47131. var that = this,
  47132. editing = that.option('editing'),
  47133. isEditColumnVisible = editing && ((editing.editEnabled || editing.insertEnabled) && getEditMode(that) === DATAGRID_EDIT_MODE_ROW || editing.removeEnabled);
  47134. that._columnsController.addCommandColumn({
  47135. command: 'edit',
  47136. visible: isEditColumnVisible,
  47137. cssClass: "dx-command-edit",
  47138. width: "auto"
  47139. });
  47140. that._columnsController.columnOption("command:edit", "visible", isEditColumnVisible)
  47141. },
  47142. _updateEditButtons: function() {
  47143. var that = this,
  47144. saveChangesButton = that._saveChangesButton,
  47145. cancelChangesButton = that._cancelChangesButton,
  47146. hasChanges = that.hasChanges();
  47147. if (saveChangesButton)
  47148. saveChangesButton.option('disabled', !hasChanges);
  47149. if (cancelChangesButton)
  47150. cancelChangesButton.option('disabled', !hasChanges)
  47151. },
  47152. cancelEditData: function() {
  47153. var that = this,
  47154. dataController = getDataController(that);
  47155. that._beforeCancelEditData();
  47156. that.init();
  47157. dataController.updateItems()
  47158. },
  47159. closeEditCell: function() {
  47160. var that = this,
  47161. editMode = getEditMode(that),
  47162. oldEditRowIndex = that._editRowIndex,
  47163. dataController = getDataController(that);
  47164. if (editMode !== DATAGRID_EDIT_MODE_ROW)
  47165. setTimeout(function() {
  47166. if (editMode === DATAGRID_EDIT_MODE_CELL && that.hasChanges())
  47167. that.saveEditData();
  47168. else if (oldEditRowIndex >= 0) {
  47169. that._editRowIndex = -1;
  47170. that._editColumnIndex = -1;
  47171. dataController.updateItems({
  47172. changeType: 'update',
  47173. rowIndices: [oldEditRowIndex]
  47174. })
  47175. }
  47176. })
  47177. },
  47178. update: function() {
  47179. var that = this,
  47180. dataController = getDataController(that);
  47181. if (that._pageIndex !== dataController.pageIndex()) {
  47182. that.refresh();
  47183. that._pageIndex = dataController.pageIndex()
  47184. }
  47185. that._updateEditButtons()
  47186. },
  47187. updateFieldValue: function(options, value) {
  47188. var that = this,
  47189. data = {},
  47190. rowKey = options.key,
  47191. $cellElement = options.cellElement,
  47192. params;
  47193. if (rowKey !== undefined && options.column.setCellValue) {
  47194. $cellElement && $cellElement.addClass(DATAGRID_CELL_MODIFIED);
  47195. options.value = value;
  47196. options.column.setCellValue(data, value);
  47197. params = {
  47198. data: data,
  47199. key: rowKey,
  47200. oldData: options.data,
  47201. type: DATA_EDIT_DATA_UPDATE_TYPE
  47202. };
  47203. that._addEditData(params);
  47204. that._updateEditButtons()
  47205. }
  47206. },
  47207. _addEditData: function(options) {
  47208. var that = this,
  47209. editDataIndex = getIndexByKey(options.key, that._editData);
  47210. if (editDataIndex < 0) {
  47211. editDataIndex = that._editData.length;
  47212. that._editData.push(options)
  47213. }
  47214. if (that._editData[editDataIndex]) {
  47215. options.type = that._editData[editDataIndex].type || options.type;
  47216. $.extend(true, that._editData[editDataIndex], {
  47217. data: options.data,
  47218. type: options.type
  47219. })
  47220. }
  47221. return editDataIndex
  47222. },
  47223. getColumnTemplate: function(options) {
  47224. var that = this,
  47225. column = options.column,
  47226. rowIndex = options.row && options.row.rowIndex,
  47227. template,
  47228. editingOptions,
  47229. editingTexts,
  47230. editEnabled = that.option("editing.editEnabled"),
  47231. isRowMode = getEditMode(that) === DATAGRID_EDIT_MODE_ROW,
  47232. isRowEditing = that.isEditRow(rowIndex),
  47233. isCellEditing = that.isEditCell(rowIndex, options.columnIndex);
  47234. if ((column.showEditorAlways || column.allowEditing && column.setCellValue && (isRowEditing || isCellEditing)) && options.rowType === 'data' && !utils.isDefined(column.command)) {
  47235. if (column.allowEditing && (editEnabled || isRowEditing || isCellEditing) && (isRowMode && isRowEditing || !isRowMode))
  47236. options.setValue = function(value) {
  47237. that.updateFieldValue(options, value)
  47238. };
  47239. template = column.editCellTemplate || getDefaultEditorTemplate(that)
  47240. }
  47241. else if (column.command === 'edit' && options.rowType === 'data')
  47242. template = function(container, options) {
  47243. var createLink = function(container, text, methodName, options) {
  47244. var $link = $('<a />').addClass(DATAGRID_LINK_CLASS).text(text).on(addNamespace('dxclick', DATAGRID_EDITING_NAMESPACE), that.createAction(function(params) {
  47245. var e = params.jQueryEvent;
  47246. e.stopPropagation();
  47247. setTimeout(function() {
  47248. options.row && that[methodName](options.row.rowIndex)
  47249. })
  47250. }));
  47251. options.rtlEnabled ? container.prepend($link, "&nbsp;") : container.append($link, "&nbsp;")
  47252. };
  47253. container.css('text-align', 'center');
  47254. options.rtlEnabled = that.option('rtlEnabled');
  47255. editingOptions = that.option("editing") || {};
  47256. editingTexts = editingOptions.texts || {};
  47257. if (options.row && options.row.rowIndex === that._editRowIndex && isRowMode) {
  47258. createLink(container, editingTexts.saveRowChanges, 'saveEditData', options);
  47259. createLink(container, editingTexts.cancelRowChanges, 'cancelEditData', options)
  47260. }
  47261. else {
  47262. if (editingOptions.editEnabled && isRowMode)
  47263. createLink(container, editingTexts.editRow, 'editRow', options);
  47264. if (editingOptions.removeEnabled)
  47265. if (options.row.removed)
  47266. createLink(container, editingTexts.undeleteRow, 'undeleteRow', options);
  47267. else
  47268. createLink(container, editingTexts.deleteRow, 'removeRow', options)
  47269. }
  47270. };
  47271. return template
  47272. },
  47273. renderEditButtons: function(rootElement) {
  47274. var that = this,
  47275. insertButton = rootElement.find('.' + DATAGRID_EDIT_BUTTON_CLASS),
  47276. editingOptions = that.option("editing") || {},
  47277. editingTexts = that.option("editing.texts") || {},
  47278. titleButtonTextByClassNames = {
  47279. cancel: editingTexts.cancelAllChanges,
  47280. save: editingTexts.saveAllChanges,
  47281. addrow: editingTexts.addRow
  47282. };
  47283. var createEditButton = function(rootElement, className, methodName) {
  47284. return $('<div />').addClass(DATAGRID_EDIT_BUTTON_CLASS).addClass("dx-datagrid-" + className + "-button").appendTo(rootElement).dxButton({
  47285. icon: "edit-button-" + className,
  47286. onClick: function(options) {
  47287. var e = options.jQueryEvent;
  47288. e.stopPropagation();
  47289. that[methodName]()
  47290. },
  47291. hint: titleButtonTextByClassNames && titleButtonTextByClassNames[className]
  47292. }).dxButton('instance')
  47293. };
  47294. if (insertButton.length)
  47295. insertButton.remove();
  47296. if ((editingOptions.editEnabled || editingOptions.insertEnabled || editingOptions.removeEnabled) && getEditMode(that) === DATAGRID_EDIT_MODE_BATCH) {
  47297. that._cancelChangesButton = createEditButton(rootElement, "cancel", 'cancelEditData');
  47298. that._saveChangesButton = createEditButton(rootElement, "save", 'saveEditData');
  47299. that._updateEditButtons()
  47300. }
  47301. if (editingOptions.insertEnabled)
  47302. createEditButton(rootElement, "addrow", 'insertRow')
  47303. },
  47304. createHighlightCell: function($cell) {
  47305. var $highlight = $cell.find("." + DATAGRID_CELL_HIGHLIGHT_OUTLINE);
  47306. if (!$highlight.length)
  47307. $cell.wrapInner($("<div>").addClass(DATAGRID_CELL_HIGHLIGHT_OUTLINE + " " + DATAGRID_POINTER_EVENTS_TARGET_CLASS))
  47308. },
  47309. _afterInsertRow: function(options){},
  47310. _beforeEditCell: function(){},
  47311. _beforeSaveEditData: function(editData, editIndex){},
  47312. _afterSaveEditData: function(){},
  47313. _beforeCancelEditData: function(){}
  47314. }
  47315. }());
  47316. dataGrid.registerModule('editing', {
  47317. defaultOptions: function() {
  47318. return {editing: {
  47319. editMode: 'row',
  47320. insertEnabled: false,
  47321. editEnabled: false,
  47322. removeEnabled: false,
  47323. texts: {
  47324. editRow: Globalize.localize("dxDataGrid-editingEditRow"),
  47325. saveAllChanges: Globalize.localize("dxDataGrid-editingSaveAllChanges"),
  47326. saveRowChanges: Globalize.localize("dxDataGrid-editingSaveRowChanges"),
  47327. cancelAllChanges: Globalize.localize("dxDataGrid-editingCancelAllChanges"),
  47328. cancelRowChanges: Globalize.localize("dxDataGrid-editingCancelRowChanges"),
  47329. addRow: Globalize.localize("dxDataGrid-editingAddRow"),
  47330. deleteRow: Globalize.localize("dxDataGrid-editingDeleteRow"),
  47331. undeleteRow: Globalize.localize("dxDataGrid-editingUndeleteRow"),
  47332. confirmDeleteMessage: Globalize.localize("dxDataGrid-editingConfirmDeleteMessage"),
  47333. confirmDeleteTitle: Globalize.localize("dxDataGrid-editingConfirmDeleteTitle")
  47334. }
  47335. }}
  47336. },
  47337. controllers: {editing: dataGrid.EditingController},
  47338. extenders: {
  47339. controllers: {data: {
  47340. init: function() {
  47341. this._editingController = this.getController('editing');
  47342. this.callBase()
  47343. },
  47344. reload: function() {
  47345. this._editingController.refresh();
  47346. return this.callBase()
  47347. },
  47348. _processItems: function(items, changeType) {
  47349. items = this._editingController.processItems(items, changeType);
  47350. return this.callBase(items, changeType)
  47351. },
  47352. _processDataItem: function(dataItem, options) {
  47353. this._editingController.processDataItem(dataItem, options.visibleColumns, this._generateDataValues);
  47354. return this.callBase(dataItem, options)
  47355. }
  47356. }},
  47357. views: {
  47358. rowsView: {
  47359. _getColumnTemplate: function(options) {
  47360. var that = this,
  47361. template = that.getController('editing').getColumnTemplate(options);
  47362. return template || that.callBase(options)
  47363. },
  47364. _createTable: function() {
  47365. var that = this,
  47366. editing = that.option("editing"),
  47367. $table = that.callBase.apply(that, arguments);
  47368. if (editing && editing.editMode !== DATAGRID_EDIT_MODE_ROW && editing.editEnabled)
  47369. $table.on(events.addNamespace("dxhold", "dxDataGridRowsView"), "td:not(." + DATAGRID_EDITOR_CELL_CLASS + ")", that.createAction(function(e) {
  47370. var editingController = that.getController("editing");
  47371. if (editingController.isEditing())
  47372. editingController.closeEditCell()
  47373. }));
  47374. return $table
  47375. },
  47376. _createRow: function(row) {
  47377. var $row = this.callBase(row),
  47378. editingController,
  47379. isEditRow,
  47380. isRowRemoved,
  47381. isRowInserted,
  47382. isRowModified;
  47383. if (row) {
  47384. editingController = this.getController('editing');
  47385. isEditRow = editingController.isEditRow(row.rowIndex);
  47386. isRowRemoved = !!row.removed;
  47387. isRowInserted = !!row.inserted;
  47388. isRowModified = !!row.modified;
  47389. if (getEditMode(this) === DATAGRID_EDIT_MODE_BATCH)
  47390. $row.toggleClass(DATAGRID_ROW_REMOVED, isRowRemoved);
  47391. else
  47392. $row.toggleClass(DATAGRID_EDIT_ROW, isEditRow);
  47393. $row.toggleClass(DATAGRID_ROW_INSERTED, isRowInserted);
  47394. $row.toggleClass(DATAGRID_ROW_MODIFIED, isRowModified);
  47395. if (isEditRow || isRowInserted || isRowRemoved)
  47396. $row.removeClass(DATAGRID_ROW_SELECTED)
  47397. }
  47398. return $row
  47399. },
  47400. _rowClick: function(e) {
  47401. var that = this,
  47402. editingController = that.getController('editing'),
  47403. $targetCell = $(e.jQueryEvent.target).closest('td'),
  47404. columnIndex = that.getCellIndex($targetCell),
  47405. editEnabled = that.option("editing.editEnabled");
  47406. if ($targetCell.hasClass(DATAGRID_POINTER_EVENTS_NONE_CLASS))
  47407. return;
  47408. if (!(editEnabled && editingController.editCell(e.rowIndex, columnIndex)) && !editingController.isEditRow(e.rowIndex))
  47409. that.callBase(e)
  47410. },
  47411. _cellPrepared: function($cell, parameters) {
  47412. var modifiedValues = parameters.row && (parameters.row.inserted ? parameters.row.values : parameters.row.modifiedValues),
  47413. columnIndex = parameters.columnIndex,
  47414. alignment = parameters.column.alignment,
  47415. editingController = this.getController('editing'),
  47416. editMode = editingController.getEditMode();
  47417. parameters.isEditing = editingController.isEditCell(parameters.rowIndex, parameters.columnIndex) || editingController.isEditRow(parameters.rowIndex) && parameters.column.allowEditing;
  47418. if (!utils.isDefined(parameters.column.command) && (parameters.isEditing || parameters.column.showEditorAlways)) {
  47419. $cell.addClass(DATAGRID_EDITOR_CELL_CLASS).toggleClass(DATAGRID_READONLY_CLASS, !parameters.setValue);
  47420. if (alignment)
  47421. $cell.find('input').first().css('text-align', alignment)
  47422. }
  47423. if ($cell.children('.' + CHECKBOX_CLASS).length === 1)
  47424. $cell.addClass(DATAGRID_EDITOR_INLINE_BLOCK).toggleClass(DATAGRID_CELL_FOCUS_DISABLED_CLASS, !!parameters.column.command);
  47425. if (editMode === DATAGRID_EDIT_MODE_BATCH || editMode === DATAGRID_EDIT_MODE_CELL && parameters.row.inserted)
  47426. if (modifiedValues && modifiedValues[columnIndex] !== undefined && parameters.column && parameters.column.allowEditing) {
  47427. editingController.createHighlightCell($cell);
  47428. $cell.addClass(DATAGRID_CELL_MODIFIED)
  47429. }
  47430. else if (parameters.setValue)
  47431. editingController.createHighlightCell($cell, true);
  47432. this.callBase.apply(this, arguments)
  47433. },
  47434. _update: function(change) {
  47435. this.callBase(change);
  47436. if (change.changeType === 'updateSelection')
  47437. this._getTableElement().children('tbody').children('.' + DATAGRID_EDIT_ROW).removeClass(DATAGRID_ROW_SELECTED)
  47438. }
  47439. },
  47440. headerPanel: {
  47441. _renderCore: function() {
  47442. this.callBase();
  47443. this.getController('editing').renderEditButtons(this.element())
  47444. },
  47445. isVisible: function() {
  47446. var that = this,
  47447. editingOptions = that.getController('editing').option('editing');
  47448. return that.callBase() || editingOptions && (editingOptions.insertEnabled || (editingOptions.editEnabled || editingOptions.removeEnabled) && editingOptions.editMode === DATAGRID_EDIT_MODE_BATCH)
  47449. }
  47450. }
  47451. }
  47452. }
  47453. });
  47454. $.extend(dataGrid.__internals, {
  47455. DATAGRID_LINK_CLASS: DATAGRID_LINK_CLASS,
  47456. DATAGRID_EDITOR_CELL_CLASS: DATAGRID_EDITOR_CELL_CLASS,
  47457. DATAGRID_EDIT_ROW: DATAGRID_EDIT_ROW,
  47458. DATAGRID_EDIT_BUTTON_CLASS: DATAGRID_EDIT_BUTTON_CLASS,
  47459. DATAGRID_CELL_MODIFIED: DATAGRID_CELL_MODIFIED,
  47460. DATAGRID_ROW_REMOVED: DATAGRID_ROW_REMOVED,
  47461. DATAGRID_ROW_INSERTED: DATAGRID_ROW_INSERTED,
  47462. DATAGRID_ROW_MODIFIED: DATAGRID_ROW_MODIFIED,
  47463. DATAGRID_CELL_HIGHLIGHT_OUTLINE: DATAGRID_CELL_HIGHLIGHT_OUTLINE,
  47464. DATAGRID_FOCUS_OVERLAY_CLASS: DATAGRID_FOCUS_OVERLAY_CLASS,
  47465. DATAGRID_READONLY_CLASS: DATAGRID_READONLY_CLASS,
  47466. DATAGRID_CELL_FOCUS_DISABLED_CLASS: DATAGRID_CELL_FOCUS_DISABLED_CLASS
  47467. })
  47468. })(jQuery, DevExpress);
  47469. /*! Module widgets-web, file ui.dataGrid.validationModule.js */
  47470. (function($, DX) {
  47471. var dataGrid = DX.ui.dxDataGrid,
  47472. utils = DX.utils;
  47473. var DATAGRID_INVALIDATE_CLASS = "dx-datagrid-invalid",
  47474. DATAGRID_INVALID_MESSAGE_CLASS = "dx-invalid-message",
  47475. DATAGRID_INVALID_MESSAGE_ALWAYS_CLASS = "dx-invalid-message-always",
  47476. DATAGRID_INSERT_INDEX = "__DX_INSERT_INDEX__",
  47477. DATAGRID_EDIT_MODE_ROW = "row",
  47478. DATAGRID_EDIT_MODE_BATCH = "batch",
  47479. DATAGRID_EDIT_MODE_CELL = "cell";
  47480. dataGrid.ValidatingController = dataGrid.Controller.inherit(function() {
  47481. return {
  47482. init: function() {
  47483. this._editingController = this.getController("editing");
  47484. this.createAction("onRowValidating")
  47485. },
  47486. _rowValidating: function(editData, validate) {
  47487. var that = this,
  47488. brokenRules = validate ? validate.brokenRules || validate.brokenRule && [validate.brokenRule] : [],
  47489. isValid = validate ? validate.isValid : editData.isValid,
  47490. parameters = {
  47491. brokenRules: brokenRules,
  47492. isValid: isValid,
  47493. key: editData.key,
  47494. newData: editData.data,
  47495. oldData: editData.oldData,
  47496. errorText: null
  47497. };
  47498. that.executeAction("onRowValidating", parameters);
  47499. editData.isValid = parameters.isValid;
  47500. editData.errorText = parameters.errorText;
  47501. return parameters
  47502. },
  47503. validate: function(isFull) {
  47504. var that = this,
  47505. isValid = true,
  47506. editingController = that._editingController;
  47507. isFull = isFull || editingController.getEditMode() === DATAGRID_EDIT_MODE_ROW;
  47508. if (that._isValidationInProgress)
  47509. return false;
  47510. that._isValidationInProgress = true;
  47511. if (isFull)
  47512. $.each(editingController._editData, function(index, editData) {
  47513. var validationResult;
  47514. if (editData.type) {
  47515. validationResult = that.validateGroup(editData);
  47516. if (!validationResult.isValid)
  47517. $.each(validationResult.brokenRules, function() {
  47518. if (this.validator.option("adapter").getValue() === undefined)
  47519. editingController.updateFieldValue({
  47520. key: editData.key,
  47521. column: this.column
  47522. }, null, true)
  47523. });
  47524. isValid = isValid && validationResult.isValid
  47525. }
  47526. });
  47527. else if (that._currentCellValidator)
  47528. isValid = that.validateGroup(that._currentCellValidator._findGroup()).isValid;
  47529. that._isValidationInProgress = false;
  47530. return isValid
  47531. },
  47532. validateGroup: function(editData) {
  47533. var that = this,
  47534. validateGroup = DX.validationEngine.getGroupConfig(editData),
  47535. validationResults;
  47536. if (validateGroup && validateGroup.validators.length)
  47537. validationResults = DX.validationEngine.validateGroup(editData);
  47538. return that._rowValidating(editData, validationResults)
  47539. },
  47540. updateEditData: function(editData) {
  47541. this.setDisableApplyValidationResults(true);
  47542. editData.isValid = DX.validationEngine.getGroupConfig(editData) ? DX.validationEngine.validateGroup(editData).isValid : true;
  47543. this.setDisableApplyValidationResults(false)
  47544. },
  47545. setValidator: function(validator) {
  47546. this._currentCellValidator = validator
  47547. },
  47548. getValidator: function() {
  47549. return this._currentCellValidator
  47550. },
  47551. removeValidators: function(editIndex) {
  47552. var that = this,
  47553. editingController = that._editingController;
  47554. $.each(editingController._editData, function(index, editData) {
  47555. var validateGroup = DX.validationEngine.getGroupConfig(editData);
  47556. if (!utils.isDefined(editIndex) || editIndex === index)
  47557. if (validateGroup)
  47558. for (var i = 0; i < validateGroup.validators.length; i++) {
  47559. validateGroup.validators[i]._dispose();
  47560. i--
  47561. }
  47562. })
  47563. },
  47564. createValidator: function(parameters, $container) {
  47565. var that = this,
  47566. editingController = that._editingController,
  47567. column = parameters.column,
  47568. editData,
  47569. editIndex = editingController.getIndexByKey(parameters.key, editingController._editData),
  47570. defaultValidationResult = function(options) {
  47571. if (options.brokenRule) {
  47572. options.brokenRule.columnIndex = column.index;
  47573. options.brokenRule.column = column
  47574. }
  47575. if ($container && !that.getDisableApplyValidationResults()) {
  47576. !options.isValid && editingController.createHighlightCell($container, true);
  47577. $container.toggleClass(DATAGRID_INVALIDATE_CLASS, !options.isValid)
  47578. }
  47579. };
  47580. if (editIndex < 0 && column.showEditorAlways)
  47581. editIndex = editingController._addEditData({key: parameters.key});
  47582. if (editIndex >= 0) {
  47583. editData = editingController._editData[editIndex];
  47584. return new DX.ui.dxValidator($container || {}, {
  47585. name: column.caption,
  47586. validationRules: $.extend(true, [], column.validationRules),
  47587. validationGroup: editData,
  47588. adapter: {
  47589. getValue: function() {
  47590. return parameters.value
  47591. },
  47592. applyValidationResults: defaultValidationResult
  47593. }
  47594. })
  47595. }
  47596. },
  47597. setDisableApplyValidationResults: function(flag) {
  47598. this._disableApplyValidationResults = flag
  47599. },
  47600. getDisableApplyValidationResults: function() {
  47601. return this._disableApplyValidationResults
  47602. }
  47603. }
  47604. }());
  47605. dataGrid.registerModule('validating', {
  47606. defaultOptions: function() {
  47607. return {}
  47608. },
  47609. controllers: {validating: dataGrid.ValidatingController},
  47610. extenders: {
  47611. controllers: {
  47612. data: {reload: function() {
  47613. var d = this.callBase(),
  47614. editingController = this.getController("editing");
  47615. return d.done(function() {
  47616. editingController.resetRowAndPageIndeces(true)
  47617. })
  47618. }},
  47619. editing: {
  47620. _addEditData: function(options) {
  47621. var that = this,
  47622. validatingController = that.getController("validating"),
  47623. editDataIndex = that.callBase(options),
  47624. editData;
  47625. if (editDataIndex >= 0) {
  47626. editData = that._editData[editDataIndex];
  47627. validatingController.updateEditData(editData)
  47628. }
  47629. return editDataIndex
  47630. },
  47631. _updateRowAndPageIndices: function() {
  47632. var that = this,
  47633. startInsertIndex = that.getView('rowsView').getTopVisibleItemIndex(),
  47634. rowIndex = startInsertIndex;
  47635. $.each(that._editData, function(_, editData) {
  47636. if (!editData.isValid && editData.pageIndex !== that._pageIndex) {
  47637. editData.pageIndex = that._pageIndex;
  47638. if (editData.type === "insert")
  47639. editData.rowIndex = startInsertIndex;
  47640. else
  47641. editData.rowIndex = rowIndex;
  47642. rowIndex++
  47643. }
  47644. })
  47645. },
  47646. resetRowAndPageIndeces: function(alwaysRest) {
  47647. var that = this;
  47648. $.each(that._editData, function(_, editData) {
  47649. if (editData.pageIndex !== that._pageIndex || alwaysRest) {
  47650. delete editData.pageIndex;
  47651. delete editData.rowIndex
  47652. }
  47653. })
  47654. },
  47655. init: function() {
  47656. var that = this;
  47657. that.callBase();
  47658. that.getController("data").changed.add(function(change) {
  47659. if (that.option("scrolling.mode") === "standard")
  47660. that.resetRowAndPageIndeces();
  47661. $.each(that._editData, function(_, editData) {
  47662. if (change && change.changeType === 'prepend')
  47663. editData.rowIndex += change.items.length
  47664. })
  47665. })
  47666. },
  47667. processItems: function(items, changeType) {
  47668. var that = this,
  47669. dataController = that.getController("data"),
  47670. i,
  47671. editData = that._editData,
  47672. itemsCount = items.length,
  47673. insertCount = 0,
  47674. getIndexByEditData = function(editData, items) {
  47675. var index = -1,
  47676. isInsert = editData.type === "insert",
  47677. key = editData.key;
  47678. $.each(items, function(i, item) {
  47679. if (dataGrid.equalKeys(key, isInsert ? item : dataController.keyOf(item))) {
  47680. index = i;
  47681. return false
  47682. }
  47683. });
  47684. return index
  47685. },
  47686. addInValidItem = function(editData) {
  47687. var data = {key: editData.key},
  47688. index = getIndexByEditData(editData, items),
  47689. rowIndex;
  47690. if (index >= 0 && that.option("scrolling.mode") === "standard")
  47691. return;
  47692. editData.rowIndex = editData.rowIndex > itemsCount ? editData.rowIndex % itemsCount : editData.rowIndex;
  47693. rowIndex = editData.rowIndex;
  47694. data[DATAGRID_INSERT_INDEX] = 1;
  47695. if (index >= 0) {
  47696. items.splice(index, 1);
  47697. rowIndex -= insertCount
  47698. }
  47699. items.splice(rowIndex, 0, data);
  47700. insertCount++
  47701. };
  47702. that.update();
  47703. if (that.getEditMode() === DATAGRID_EDIT_MODE_BATCH && changeType !== "prepend" && changeType !== "append")
  47704. for (i = 0; i < editData.length; i++)
  47705. if (editData[i].type && editData[i].pageIndex === that._pageIndex && editData[i].key.pageIndex !== that._pageIndex)
  47706. addInValidItem(editData[i]);
  47707. return that.callBase(items, changeType)
  47708. },
  47709. processDataItem: function(item, columns, generateDataValues) {
  47710. var that = this,
  47711. editIndex,
  47712. editData,
  47713. isInserted = item.data[DATAGRID_INSERT_INDEX],
  47714. key = isInserted ? item.data.key : item.key,
  47715. editMode = that.getEditMode();
  47716. if (editMode === DATAGRID_EDIT_MODE_BATCH && isInserted && key) {
  47717. editIndex = dataGrid.getIndexByKey(key, that._editData);
  47718. if (editIndex >= 0) {
  47719. editData = that._editData[editIndex];
  47720. if (editData.type !== "insert") {
  47721. item.data = $.extend(true, {}, editData.oldData, editData.data);
  47722. item.key = key
  47723. }
  47724. }
  47725. }
  47726. that.callBase.apply(that, arguments)
  47727. },
  47728. _afterInsertRow: function(options) {
  47729. var validatingController = this.getController("validating"),
  47730. hiddenColumns = this.getController("columns").getHiddenColumns();
  47731. $.each(hiddenColumns, function(_, column) {
  47732. if (utils.isArray(column.validationRules))
  47733. validatingController.createValidator({
  47734. column: column,
  47735. key: options.key,
  47736. value: options.data[column.dataField]
  47737. })
  47738. });
  47739. this.callBase(options)
  47740. },
  47741. _beforeSaveEditData: function(editData, editIndex) {
  47742. var that = this,
  47743. isValid,
  47744. isFullValid,
  47745. result = that.callBase.apply(that, arguments),
  47746. validatingController = that.getController("validating");
  47747. if (editData) {
  47748. isValid = editData.type === "remove" || editData.isValid;
  47749. if (isValid)
  47750. validatingController.removeValidators(editIndex);
  47751. else if (utils.isDefined(that._hasInvalidRules))
  47752. that._hasInvalidRules = true;
  47753. result = result || !isValid
  47754. }
  47755. else {
  47756. isFullValid = validatingController.validate(true);
  47757. that._updateRowAndPageIndices();
  47758. if (that.getEditMode() === DATAGRID_EDIT_MODE_CELL) {
  47759. isValid = validatingController.validate();
  47760. if (isValid && that._hasInvalidRules) {
  47761. that.cancelEditData();
  47762. that._hasInvalidRules = false;
  47763. result = true
  47764. }
  47765. else if (!isFullValid) {
  47766. that._hasInvalidRules = true;
  47767. result = true
  47768. }
  47769. }
  47770. }
  47771. return result
  47772. },
  47773. _afterSaveEditData: function() {
  47774. var that = this;
  47775. $.each(that._editData, function(_, editData) {
  47776. that._showErrorRow(editData)
  47777. })
  47778. },
  47779. _beforeCancelEditData: function() {
  47780. var validatingController = this.getController("validating");
  47781. validatingController.removeValidators();
  47782. this.callBase()
  47783. },
  47784. _showErrorRow: function(editData) {
  47785. var errorHandling = this.getController("errorHandling"),
  47786. items = this.getController("data").items(),
  47787. rowIndex = this.getIndexByKey(editData.key, items);
  47788. if (!editData.isValid && editData.errorText && rowIndex >= 0)
  47789. errorHandling && errorHandling.renderErrorRow(editData.errorText, rowIndex)
  47790. },
  47791. createHighlightCell: function($cell, skipValidation) {
  47792. var isValid = true,
  47793. validator;
  47794. if (!skipValidation) {
  47795. validator = $cell.data("dxValidator");
  47796. if (validator)
  47797. isValid = validator.validate().isValid
  47798. }
  47799. if (isValid)
  47800. this.callBase($cell)
  47801. },
  47802. updateFieldValue: function(options, value, skipInvalidRules) {
  47803. var that = this;
  47804. that.callBase.apply(that, arguments);
  47805. if (!skipInvalidRules)
  47806. that._hasInvalidRules = false
  47807. }
  47808. },
  47809. editorFactory: {
  47810. loseFocus: function(skipValidator) {
  47811. if (!skipValidator)
  47812. this.getController('validating').setValidator(null);
  47813. this.callBase()
  47814. },
  47815. focus: function($element) {
  47816. var that = this,
  47817. hideBorder = false,
  47818. rowsView = that.getView("rowsView"),
  47819. $tdElement = $element && $element.closest("td"),
  47820. validator = $tdElement && $tdElement.data("dxValidator"),
  47821. validatingController = that.getController('validating'),
  47822. $tooltip = $tdElement && $tdElement.closest(".dx-datagrid-rowsview").find(".dx-tooltip"),
  47823. column = $tdElement && that.getController("columns").getVisibleColumns()[$tdElement.index()];
  47824. $tooltip && $tooltip.remove();
  47825. if (validator) {
  47826. var value = validator.option("adapter").getValue();
  47827. validatingController.setValidator(validator);
  47828. if (value !== undefined) {
  47829. var validationResult = validator.validate();
  47830. if (!validationResult.isValid) {
  47831. var alignment = column.alignment;
  47832. hideBorder = true;
  47833. $("<div/>").addClass(DATAGRID_INVALID_MESSAGE_CLASS).addClass(DATAGRID_INVALID_MESSAGE_ALWAYS_CLASS).text(validationResult.brokenRule.message).appendTo($tdElement).dxTooltip({
  47834. target: $tdElement,
  47835. container: $tdElement,
  47836. visible: true,
  47837. closeOnOutsideClick: false,
  47838. closeOnTargetScroll: false,
  47839. arrowPosition: {
  47840. offset: alignment === "left" ? "5 0" : "-5 0",
  47841. my: "bottom " + alignment,
  47842. at: "top " + alignment
  47843. },
  47844. position: {
  47845. collision: "fit flip",
  47846. boundary: rowsView.element(),
  47847. boundaryOffset: "0 0",
  47848. offset: "0 -9",
  47849. my: "top " + alignment,
  47850. at: "bottom " + alignment
  47851. },
  47852. onPositioned: function() {
  47853. rowsView.element() && rowsView.updateFreeSpaceRowHeight()
  47854. }
  47855. })
  47856. }
  47857. }
  47858. }
  47859. !hideBorder && rowsView.element() && rowsView.updateFreeSpaceRowHeight();
  47860. return that.callBase($element, hideBorder)
  47861. }
  47862. }
  47863. },
  47864. views: {rowsView: {
  47865. updateFreeSpaceRowHeight: function() {
  47866. var that = this,
  47867. $rowElements = that._getRowElements(),
  47868. $freeSpaceRowElements = that._getFreeSpaceRowElements(),
  47869. $freeSpaceRowElement = $freeSpaceRowElements.first(),
  47870. $tooltipContent = that.element().find(".dx-invalid-message .dx-overlay-content");
  47871. that.callBase();
  47872. if ($tooltipContent.length && $freeSpaceRowElement && $rowElements.length === 1 && (!$freeSpaceRowElement.is(":visible") || $tooltipContent.outerHeight() > $freeSpaceRowElement.outerHeight())) {
  47873. $freeSpaceRowElements.show();
  47874. $freeSpaceRowElements.height($tooltipContent.outerHeight())
  47875. }
  47876. },
  47877. _cellPrepared: function($cell, parameters) {
  47878. var validatingController = this.getController("validating"),
  47879. column = parameters.column;
  47880. if (utils.isArray(column.validationRules))
  47881. validatingController.createValidator(parameters, $cell);
  47882. this.callBase.apply(this, arguments)
  47883. }
  47884. }}
  47885. }
  47886. })
  47887. })(jQuery, DevExpress);
  47888. /*! Module widgets-web, file ui.dataGrid.dataController.js */
  47889. (function($, DX, undefined) {
  47890. var ui = DX.ui,
  47891. dataGrid = ui.dxDataGrid,
  47892. utils = DX.utils;
  47893. dataGrid.proxyMethod = function(instance, methodName, defaultResult) {
  47894. if (!instance[methodName])
  47895. instance[methodName] = function() {
  47896. var dataSource = this._dataSource;
  47897. return dataSource ? dataSource[methodName].apply(dataSource, arguments) : defaultResult
  47898. }
  47899. };
  47900. dataGrid.combineFilters = function(filters, operation) {
  47901. var resultFilter = [],
  47902. i;
  47903. operation = operation || 'and';
  47904. for (i = 0; i < filters.length; i++) {
  47905. if (!filters[i])
  47906. continue;
  47907. if (resultFilter.length)
  47908. resultFilter.push(operation);
  47909. resultFilter.push(filters[i])
  47910. }
  47911. if (resultFilter.length === 1)
  47912. resultFilter = resultFilter[0];
  47913. if (resultFilter.length)
  47914. return resultFilter
  47915. };
  47916. dataGrid.DataController = dataGrid.Controller.inherit({}).include(ui.DataHelperMixin).inherit(function() {
  47917. var members = {
  47918. init: function() {
  47919. var that = this;
  47920. that._items = [];
  47921. that._columnsController = that.getController('columns');
  47922. that._columnsChangedHandler = $.proxy(that._handleColumnsChanged, that);
  47923. that._dataChangedHandler = $.proxy(that._handleDataChanged, that);
  47924. that._loadingChangedHandler = $.proxy(that._handleLoadingChanged, that);
  47925. that._loadErrorHandler = $.proxy(that._handleLoadError, that);
  47926. that._customizeStoreLoadOptionsHandler = $.proxy(that._handleCustomizeStoreLoadOptions, that);
  47927. that._columnsController.columnsChanged.add(that._columnsChangedHandler);
  47928. that._isLoading = false;
  47929. that._isCustomLoading = false;
  47930. that._refreshDataSource();
  47931. that.createAction('onDataErrorOccurred');
  47932. that.dataErrorOccurred.add(function(error) {
  47933. return that.executeAction('onDataErrorOccurred', {error: error})
  47934. })
  47935. },
  47936. callbackNames: function() {
  47937. return ['changed', 'loadingChanged', 'dataErrorOccurred', 'pageIndexChanged', 'pageSizeChanged', 'filterChanged', 'dataSourceChanged']
  47938. },
  47939. callbackFlags: function(name) {
  47940. if (name === 'dataErrorOccurred')
  47941. return 'stopOnFalse'
  47942. },
  47943. publicMethods: function() {
  47944. return ['beginCustomLoading', 'endCustomLoading', 'refresh', 'filter', 'clearFilter', 'getCombinedFilter', 'keyOf', 'byKey', 'getDataByKeys', 'pageIndex', 'pageSize', 'pageCount', 'totalCount', '_disposeDataSource', 'getKeyByRowIndex', 'getRowIndexByKey']
  47945. },
  47946. optionChanged: function(args) {
  47947. var that = this;
  47948. function handled() {
  47949. args.handled = true
  47950. }
  47951. function reload() {
  47952. that._columnsController.reset();
  47953. that._refreshDataSource()
  47954. }
  47955. switch (args.name) {
  47956. case'loadingTimeout':
  47957. case'remoteOperations':
  47958. handled();
  47959. break;
  47960. case'dataSource':
  47961. case'scrolling':
  47962. case'paging':
  47963. handled();
  47964. reload();
  47965. break;
  47966. case'rtlEnabled':
  47967. reload();
  47968. break;
  47969. default:
  47970. that.callBase(args)
  47971. }
  47972. },
  47973. isReady: function() {
  47974. return !this._isLoading
  47975. },
  47976. getCombinedFilter: function() {
  47977. return this.combinedFilter()
  47978. },
  47979. combinedFilter: function(filter) {
  47980. var that = this,
  47981. dataSource = that._dataSource,
  47982. columnsController = that._columnsController,
  47983. additionalFilter;
  47984. if (dataSource) {
  47985. if (filter === undefined)
  47986. filter = dataSource.filter();
  47987. additionalFilter = that._calculateAdditionalFilter();
  47988. if (additionalFilter)
  47989. if (columnsController.isDataSourceApplied() || columnsController.isAllDataTypesDefined())
  47990. filter = dataGrid.combineFilters([additionalFilter, filter]);
  47991. columnsController.updateFilter(dataSource, filter)
  47992. }
  47993. return filter
  47994. },
  47995. _handleCustomizeStoreLoadOptions: function(e) {
  47996. var columnsController = this._columnsController,
  47997. dataSource = this._dataSource,
  47998. storeLoadOptions = e.storeLoadOptions;
  47999. if (this._isLoadingAll) {
  48000. storeLoadOptions.isLoadingAll = true;
  48001. delete storeLoadOptions.skip;
  48002. delete storeLoadOptions.take
  48003. }
  48004. storeLoadOptions.filter = this.combinedFilter(storeLoadOptions.filter);
  48005. if (!columnsController.isDataSourceApplied())
  48006. columnsController.updateColumnDataTypes(dataSource);
  48007. this._columnsUpdating = true;
  48008. columnsController.updateSortingGrouping(dataSource, !this._isFirstLoading);
  48009. this._columnsUpdating = false;
  48010. storeLoadOptions.sort = columnsController.getSortDataSourceParameters();
  48011. storeLoadOptions.group = columnsController.getGroupDataSourceParameters();
  48012. dataSource.sort(storeLoadOptions.sort);
  48013. dataSource.group(storeLoadOptions.group);
  48014. e.group = columnsController.getGroupDataSourceParameters(true);
  48015. this._isFirstLoading = false
  48016. },
  48017. _handleColumnsChanged: function(e) {
  48018. var that = this,
  48019. changeTypes = e.changeTypes,
  48020. optionNames = e.optionNames,
  48021. filterValue,
  48022. filterValues;
  48023. var updateItemsHandler = function() {
  48024. that._columnsController.columnsChanged.remove(updateItemsHandler);
  48025. that.updateItems()
  48026. };
  48027. if (changeTypes.sorting || changeTypes.grouping) {
  48028. if (that._dataSource && !that._columnsUpdating) {
  48029. that._dataSource.group(that._columnsController.getGroupDataSourceParameters());
  48030. that._dataSource.sort(that._columnsController.getSortDataSourceParameters());
  48031. that.reload()
  48032. }
  48033. }
  48034. else if (changeTypes.columns) {
  48035. if (optionNames.filterValues || optionNames.filterValue || optionNames.selectedFilterOperation)
  48036. if (this.option("filterRow.applyFilter") !== "onClick" || optionNames.filterValues) {
  48037. filterValue = that._columnsController.columnOption(e.columnIndex, 'filterValue');
  48038. filterValues = that._columnsController.columnOption(e.columnIndex, 'filterValues');
  48039. if (utils.isArray(filterValues) || e.columnIndex === undefined || utils.isDefined(filterValue) || !optionNames.selectedFilterOperation || optionNames.filterValue)
  48040. that._applyFilter()
  48041. }
  48042. if (!that._needApplyFilter && !dataGrid.checkChanges(optionNames, ['width', 'visibleWidth', 'filterValue', 'selectedFilterOperation', 'filterValues']))
  48043. that._columnsController.columnsChanged.add(updateItemsHandler)
  48044. }
  48045. },
  48046. _handleDataChanged: function(e) {
  48047. var that = this,
  48048. dataSource = that._dataSource,
  48049. columnsController = that._columnsController,
  48050. isAllDataTypesDefined = columnsController.isAllDataTypesDefined();
  48051. if (dataSource && !that._isDataSourceApplying && !that._isLoadingAll) {
  48052. that._isDataSourceApplying = true;
  48053. $.when(that._columnsController.applyDataSource(dataSource)).done(function() {
  48054. if (that._isLoading)
  48055. that._handleLoadingChanged(false);
  48056. that._isDataSourceApplying = false;
  48057. var additionalFilter = that._calculateAdditionalFilter(),
  48058. needApplyFilter = that._needApplyFilter;
  48059. that._needApplyFilter = false;
  48060. if (needApplyFilter && additionalFilter && additionalFilter.length && !isAllDataTypesDefined) {
  48061. DX.log("W1005", that.component.NAME);
  48062. that._applyFilter()
  48063. }
  48064. else
  48065. that.updateItems(e)
  48066. });
  48067. if (that._isDataSourceApplying)
  48068. that._handleLoadingChanged(true);
  48069. that._needApplyFilter = !that._columnsController.isDataSourceApplied()
  48070. }
  48071. },
  48072. _handleLoadingChanged: function(isLoading) {
  48073. this._isLoading = isLoading;
  48074. this._fireLoadingChanged()
  48075. },
  48076. _handleLoadError: function(e) {
  48077. this.dataErrorOccurred.fire(e)
  48078. },
  48079. _initDataSource: function() {
  48080. var that = this,
  48081. dataSource = this.option("dataSource"),
  48082. pageIndex = this.option("paging.pageIndex"),
  48083. pageSize = this.option("paging.pageSize"),
  48084. scrollingMode = that.option('scrolling.mode'),
  48085. pagingEnabled = this.option("paging.enabled"),
  48086. appendMode = scrollingMode === 'infinite',
  48087. virtualMode = scrollingMode === 'virtual',
  48088. oldDataSource = this._dataSource;
  48089. that.callBase();
  48090. dataSource = that._dataSource;
  48091. that._dataSource = oldDataSource;
  48092. that._isFirstLoading = true;
  48093. if (dataSource) {
  48094. dataSource.requireTotalCount(!appendMode);
  48095. if (pagingEnabled !== undefined)
  48096. dataSource.paginate(pagingEnabled || virtualMode || appendMode);
  48097. if (pageSize !== undefined)
  48098. dataSource.pageSize(pageSize);
  48099. if (pageIndex !== undefined)
  48100. dataSource.pageIndex(pageIndex);
  48101. that.setDataSource(dataSource)
  48102. }
  48103. },
  48104. _loadDataSource: function() {
  48105. var dataSource = this._dataSource;
  48106. dataSource && dataSource.load()
  48107. },
  48108. _processItems: function(items) {
  48109. var that = this,
  48110. visibleColumns = that._columnsController.getVisibleColumns(),
  48111. options = {
  48112. visibleColumns: visibleColumns,
  48113. dataIndex: 0
  48114. },
  48115. result = [];
  48116. $.each(items, function(index, item) {
  48117. if (utils.isDefined(item)) {
  48118. item = that._processItem(item, options);
  48119. result.push(item)
  48120. }
  48121. });
  48122. return result
  48123. },
  48124. _processItem: function(item, options) {
  48125. item = this._generateDataItem(item);
  48126. item = this._processDataItem(item, options);
  48127. item.dataIndex = options.dataIndex++;
  48128. return item
  48129. },
  48130. _generateDataItem: function(data) {
  48131. return {
  48132. rowType: 'data',
  48133. data: data,
  48134. key: this.keyOf(data)
  48135. }
  48136. },
  48137. _processDataItem: function(dataItem, options) {
  48138. dataItem.values = this._generateDataValues(dataItem.data, options.visibleColumns);
  48139. return dataItem
  48140. },
  48141. _generateDataValues: function(data, columns) {
  48142. var values = [];
  48143. $.each(columns, function() {
  48144. var value = null;
  48145. if (this.command)
  48146. value = null;
  48147. else if (this.calculateCellValue)
  48148. value = this.calculateCellValue(data);
  48149. else if (this.dataField)
  48150. value = data[this.dataField];
  48151. values.push(value)
  48152. });
  48153. return values
  48154. },
  48155. _updateItemsCore: function(change) {
  48156. var that = this,
  48157. items,
  48158. dataSource = that._dataSource,
  48159. changeType = change.changeType;
  48160. if (dataSource) {
  48161. items = change.items || dataSource.items();
  48162. items = that._processItems(items.slice(0), changeType);
  48163. change.items = items;
  48164. change.changeType = changeType || 'refresh';
  48165. switch (changeType) {
  48166. case'prepend':
  48167. that._items.unshift.apply(that._items, items);
  48168. break;
  48169. case'append':
  48170. that._items.push.apply(that._items, items);
  48171. break;
  48172. case'update':
  48173. var rowIndices = change.rowIndices.slice(0),
  48174. rowIndexCorrection = 0;
  48175. rowIndices.sort(function(a, b) {
  48176. return a - b
  48177. });
  48178. for (var i = 0; i < rowIndices.length; i++)
  48179. if (rowIndices[i] < 0 || rowIndices[i - 1] === rowIndices[i]) {
  48180. rowIndices.splice(i, 1);
  48181. i--
  48182. }
  48183. change.items = [];
  48184. change.rowIndices = [];
  48185. change.changeTypes = [];
  48186. var equalItems = function(item1, item2) {
  48187. return dataGrid.equalKeys(item1.key, item2.key) && item1.rowType === item2.rowType
  48188. };
  48189. $.each(rowIndices, function(index, rowIndex) {
  48190. var oldItem,
  48191. newItem,
  48192. oldNextItem,
  48193. newNextItem;
  48194. rowIndex += rowIndexCorrection;
  48195. change.rowIndices.push(rowIndex);
  48196. oldItem = that._items[rowIndex];
  48197. oldNextItem = that._items[rowIndex + 1];
  48198. newItem = items[rowIndex];
  48199. newNextItem = items[rowIndex + 1];
  48200. if (newItem)
  48201. change.items.push(newItem);
  48202. if (oldItem && newItem && equalItems(oldItem, newItem)) {
  48203. changeType = 'update';
  48204. that._items[rowIndex] = newItem;
  48205. if (oldItem.visible !== newItem.visible)
  48206. change.items.splice(-1, 1, {visible: newItem.visible})
  48207. }
  48208. else if (newItem && !oldItem || newNextItem && equalItems(oldItem, newNextItem)) {
  48209. changeType = 'insert';
  48210. that._items.splice(rowIndex, 0, newItem);
  48211. rowIndexCorrection++
  48212. }
  48213. else if (oldItem && !newItem || oldNextItem && equalItems(newItem, oldNextItem)) {
  48214. changeType = 'remove';
  48215. that._items.splice(rowIndex, 1);
  48216. rowIndexCorrection--
  48217. }
  48218. change.changeTypes.push(changeType)
  48219. });
  48220. break;
  48221. default:
  48222. that._items = items.slice(0);
  48223. break
  48224. }
  48225. $.each(that._items, function(index, item) {
  48226. item.rowIndex = index
  48227. })
  48228. }
  48229. },
  48230. updateItems: function(change) {
  48231. var that = this;
  48232. change = change || {};
  48233. if (that._dataSource && that._columnsController.isDataSourceApplied()) {
  48234. that._updateItemsCore(change);
  48235. that.changed.fire(change)
  48236. }
  48237. },
  48238. isLoading: function() {
  48239. return this._isLoading || this._isCustomLoading
  48240. },
  48241. _fireLoadingChanged: function(messageText) {
  48242. this.loadingChanged.fire(this.isLoading(), messageText)
  48243. },
  48244. _calculateAdditionalFilter: function() {
  48245. return null
  48246. },
  48247. _applyFilter: function() {
  48248. var that = this,
  48249. dataSource = that._dataSource;
  48250. if (dataSource) {
  48251. dataSource.pageIndex(0);
  48252. return that.reload().done($.proxy(that.filterChanged, 'fire'))
  48253. }
  48254. },
  48255. filter: function(filterExpr) {
  48256. var dataSource = this._dataSource;
  48257. if (arguments.length === 0)
  48258. return dataSource ? dataSource.filter() : undefined;
  48259. filterExpr = arguments.length > 1 ? Array.prototype.slice.call(arguments, 0) : filterExpr;
  48260. if (dataSource)
  48261. dataSource.filter(filterExpr);
  48262. this._applyFilter()
  48263. },
  48264. clearFilter: function(filterName) {
  48265. var that = this,
  48266. columnsController = that._columnsController,
  48267. clearColumnOption = function(optionName) {
  48268. var columnCount = columnsController.columnCount(),
  48269. index;
  48270. for (index = 0; index < columnCount; index++)
  48271. columnsController.columnOption(index, optionName, undefined)
  48272. };
  48273. that.component.beginUpdate();
  48274. if (arguments.length > 0)
  48275. switch (filterName) {
  48276. case"dataSource":
  48277. that.filter(null);
  48278. break;
  48279. case"search":
  48280. that.searchByText("");
  48281. break;
  48282. case"header":
  48283. clearColumnOption("filterValues");
  48284. break;
  48285. case"row":
  48286. clearColumnOption("filterValue");
  48287. break
  48288. }
  48289. else {
  48290. that.filter(null);
  48291. that.searchByText("");
  48292. clearColumnOption("filterValue");
  48293. clearColumnOption("filterValues")
  48294. }
  48295. that.component.endUpdate()
  48296. },
  48297. _fireDataSourceChanged: function() {
  48298. var that = this;
  48299. var changedHandler = function() {
  48300. that.changed.remove(changedHandler);
  48301. that.dataSourceChanged.fire()
  48302. };
  48303. that.changed.add(changedHandler)
  48304. },
  48305. _getDataSourceAdapterType: function(remoteOperations) {
  48306. return remoteOperations && remoteOperations.filtering && remoteOperations.sorting && remoteOperations.paging ? dataGrid.DataSourceAdapterServer : dataGrid.DataSourceAdapterClient
  48307. },
  48308. _createDataSourceAdapterCore: function(dataSource, remoteOperations) {
  48309. var dataSourceAdapterType,
  48310. dataSourceAdapter;
  48311. if (remoteOperations === 'auto')
  48312. remoteOperations = !(dataSource.store() instanceof DX.data.ArrayStore);
  48313. if (remoteOperations === true)
  48314. remoteOperations = {
  48315. filtering: true,
  48316. sorting: true,
  48317. paging: true
  48318. };
  48319. dataSourceAdapterType = this._getDataSourceAdapterType(remoteOperations);
  48320. dataSourceAdapter = new dataSourceAdapterType(this.component);
  48321. dataSourceAdapter.init(dataSource, remoteOperations);
  48322. return dataSourceAdapter
  48323. },
  48324. _createDataSourceAdapter: function(dataSource) {
  48325. var remoteOperations = this.option("remoteOperations");
  48326. return this._createDataSourceAdapterCore(dataSource, remoteOperations)
  48327. },
  48328. setDataSource: function(dataSource) {
  48329. var that = this;
  48330. if (that._dataSource) {
  48331. that._dataSource.changed.remove(that._dataChangedHandler);
  48332. that._dataSource.loadingChanged.remove(that._loadingChangedHandler);
  48333. that._dataSource.loadError.remove(that._loadErrorHandler);
  48334. that._dataSource.customizeStoreLoadOptions.remove(that._customizeStoreLoadOptionsHandler);
  48335. that._dataSource.dispose(that._isSharedDataSource)
  48336. }
  48337. if (dataSource)
  48338. dataSource = that._createDataSourceAdapter(dataSource);
  48339. that._dataSource = dataSource;
  48340. if (dataSource) {
  48341. that._fireDataSourceChanged();
  48342. that._isLoading = !dataSource.isLoaded();
  48343. that._needApplyFilter = true;
  48344. dataSource.changed.add(that._dataChangedHandler);
  48345. dataSource.loadingChanged.add(that._loadingChangedHandler);
  48346. dataSource.loadError.add(that._loadErrorHandler);
  48347. dataSource.customizeStoreLoadOptions.add(that._customizeStoreLoadOptionsHandler)
  48348. }
  48349. },
  48350. items: function() {
  48351. return this._items
  48352. },
  48353. isEmpty: function() {
  48354. return !this.items().length
  48355. },
  48356. pageCount: function() {
  48357. return this._dataSource ? this._dataSource.pageCount() : 1
  48358. },
  48359. dataSource: function() {
  48360. return this._dataSource
  48361. },
  48362. store: function() {
  48363. var dataSource = this._dataSource;
  48364. return dataSource && dataSource.store()
  48365. },
  48366. loadAll: function(data) {
  48367. var that = this,
  48368. d = $.Deferred(),
  48369. dataSource = that._dataSource;
  48370. if (dataSource)
  48371. if (data) {
  48372. var options = {
  48373. data: data,
  48374. loadOptions: {
  48375. isLoadingAll: true,
  48376. group: dataSource.group(),
  48377. sort: dataSource.sort()
  48378. }
  48379. };
  48380. dataSource._handleDataLoaded(options);
  48381. d.resolve(that._processItems(options.data), options.totalAggregates)
  48382. }
  48383. else if (!that.isLoading()) {
  48384. that._isLoadingAll = true;
  48385. dataSource.load(true).done(function(items) {
  48386. items = that._processItems(items.slice(0));
  48387. d.resolve(items)
  48388. }).fail(d.reject).always(function() {
  48389. that._isLoadingAll = false
  48390. })
  48391. }
  48392. else
  48393. d.reject();
  48394. else
  48395. d.resolve([]);
  48396. return d
  48397. },
  48398. getKeyByRowIndex: function(rowIndex) {
  48399. var item = this.items()[rowIndex];
  48400. if (item)
  48401. return item.key
  48402. },
  48403. getRowIndexByKey: function(key) {
  48404. return dataGrid.getIndexByKey(key, this.items())
  48405. },
  48406. keyOf: function(data) {
  48407. var store = this.store();
  48408. if (store)
  48409. return store.keyOf(data)
  48410. },
  48411. byKey: function(key) {
  48412. var store = this.store(),
  48413. rowIndex = this.getRowIndexByKey(key),
  48414. result;
  48415. if (!store)
  48416. return;
  48417. if (rowIndex >= 0)
  48418. result = $.Deferred().resolve(this.items()[rowIndex].data);
  48419. return result || store.byKey(key)
  48420. },
  48421. getDataByKeys: function(rowKeys) {
  48422. var that = this,
  48423. result = $.Deferred(),
  48424. deferreds = [],
  48425. data = [];
  48426. $.each(rowKeys, function(index, key) {
  48427. deferreds.push(that.byKey(key).done(function(keyData) {
  48428. data[index] = keyData
  48429. }))
  48430. });
  48431. $.when.apply($, deferreds).always(function() {
  48432. result.resolve(data)
  48433. });
  48434. return result
  48435. },
  48436. pageIndex: function(value) {
  48437. var that = this,
  48438. dataSource = that._dataSource;
  48439. if (dataSource) {
  48440. if (value !== undefined)
  48441. if (dataSource.pageIndex() !== value) {
  48442. dataSource.pageIndex(value);
  48443. return dataSource.load().done($.proxy(that.pageIndexChanged, 'fire'))
  48444. }
  48445. return dataSource.pageIndex()
  48446. }
  48447. return 0
  48448. },
  48449. pageSize: function(value) {
  48450. var that = this,
  48451. pagingOptions = that.option("paging"),
  48452. dataSource = that._dataSource;
  48453. if (value === undefined)
  48454. return dataSource ? dataSource.pageSize() : 0;
  48455. if (dataSource)
  48456. if (dataSource.pageSize() !== value) {
  48457. dataSource.pageIndex(0);
  48458. dataSource.pageSize(value);
  48459. if (pagingOptions)
  48460. pagingOptions.pageSize = value;
  48461. return dataSource.reload().done($.proxy(that.pageSizeChanged, 'fire'))
  48462. }
  48463. },
  48464. beginCustomLoading: function(messageText) {
  48465. this._isCustomLoading = true;
  48466. this._fireLoadingChanged(messageText)
  48467. },
  48468. endCustomLoading: function() {
  48469. this._isCustomLoading = false;
  48470. this._fireLoadingChanged()
  48471. },
  48472. refresh: function() {
  48473. var that = this,
  48474. d = $.Deferred();
  48475. $.when(this._columnsController.refresh()).always(function() {
  48476. $.when(that.reload()).done(d.resolve).fail(d.reject)
  48477. });
  48478. return d
  48479. },
  48480. _disposeDataSource: function() {
  48481. this.setDataSource(null)
  48482. }
  48483. };
  48484. dataGrid.proxyMethod(members, 'load');
  48485. dataGrid.proxyMethod(members, 'reload');
  48486. dataGrid.proxyMethod(members, 'itemsCount', 0);
  48487. dataGrid.proxyMethod(members, 'totalItemsCount', 0);
  48488. dataGrid.proxyMethod(members, 'hasKnownLastPage', true);
  48489. dataGrid.proxyMethod(members, 'isLoaded', false);
  48490. dataGrid.proxyMethod(members, 'totalCount', 0);
  48491. return members
  48492. }());
  48493. dataGrid.registerModule('data', {
  48494. defaultOptions: function() {
  48495. return {
  48496. loadingTimeout: 0,
  48497. dataSource: null,
  48498. onDataErrorOccurred: null,
  48499. remoteOperations: 'auto',
  48500. paging: {
  48501. enabled: true,
  48502. pageSize: undefined,
  48503. pageIndex: undefined
  48504. }
  48505. }
  48506. },
  48507. controllers: {data: ui.dxDataGrid.DataController}
  48508. })
  48509. })(jQuery, DevExpress);
  48510. /*! Module widgets-web, file ui.dataGrid.dataSourceAdapter.js */
  48511. (function($, DX) {
  48512. var ui = DX.ui,
  48513. dataGrid = ui.dxDataGrid;
  48514. dataGrid.DataSourceAdapterServer = dataGrid.Controller.inherit(function() {
  48515. return {
  48516. init: function(dataSource, remoteOperations) {
  48517. var that = this;
  48518. that._dataSource = dataSource;
  48519. that._remoteOperations = remoteOperations;
  48520. that._isLastPage = !dataSource.isLastPage();
  48521. that._hasLastPage = false;
  48522. that._currentTotalCount = 0;
  48523. that.changed = $.Callbacks();
  48524. that.loadingChanged = $.Callbacks();
  48525. that.loadError = $.Callbacks();
  48526. that.customizeStoreLoadOptions = $.Callbacks();
  48527. that._dataChangedHandler = $.proxy(that._handleDataChanged, that);
  48528. that._dataLoadingHandler = $.proxy(that._handleDataLoading, that);
  48529. that._dataLoadedHandler = $.proxy(that._handleDataLoaded, that);
  48530. that._loadingChangedHandler = $.proxy(that._handleLoadingChanged, that);
  48531. that._loadErrorHandler = $.proxy(that._handleLoadError, that);
  48532. dataSource.on("changed", that._dataChangedHandler);
  48533. dataSource.on("customizeStoreLoadOptions", that._dataLoadingHandler);
  48534. dataSource.on("customizeLoadResult", that._dataLoadedHandler);
  48535. dataSource.on("loadingChanged", that._loadingChangedHandler);
  48536. dataSource.on("loadError", that._loadErrorHandler);
  48537. $.each(dataSource, function(memberName, member) {
  48538. if (!that[memberName] && $.isFunction(member))
  48539. that[memberName] = function() {
  48540. return this._dataSource[memberName].apply(this._dataSource, arguments)
  48541. }
  48542. })
  48543. },
  48544. dispose: function(isSharedDataSource) {
  48545. var that = this,
  48546. dataSource = that._dataSource;
  48547. dataSource.off("changed", that._dataChangedHandler);
  48548. dataSource.off("customizeStoreLoadOptions", that._dataLoadingHandler);
  48549. dataSource.off("customizeLoadResult", that._dataLoadedHandler);
  48550. dataSource.off("loadingChanged", that._loadingChangedHandler);
  48551. dataSource.off("loadError", that._loadErrorHandler);
  48552. if (!isSharedDataSource)
  48553. dataSource.dispose()
  48554. },
  48555. refresh: function(storeLoadOptions, isReload) {
  48556. var that = this,
  48557. dataSource = that._dataSource;
  48558. if (isReload) {
  48559. that._currentTotalCount = 0;
  48560. that._isLastPage = !dataSource.paginate();
  48561. that._hasLastPage = that._isLastPage
  48562. }
  48563. },
  48564. _handleDataLoading: function(options) {
  48565. var that = this;
  48566. that.customizeStoreLoadOptions.fire(options);
  48567. options.delay = this.option("loadingTimeout");
  48568. options.originalStoreLoadOptions = options.storeLoadOptions;
  48569. var isReload = !that.isLoaded() && !that._isRefreshing;
  48570. that._isRefreshing = true;
  48571. $.when(that.refresh(options.storeLoadOptions, isReload)).always(function() {
  48572. if (that._lastOperationId === options.operationId)
  48573. that.load();
  48574. that._isRefreshing = false
  48575. });
  48576. that._dataSource.cancel(that._lastOperationId);
  48577. that._lastOperationId = options.operationId;
  48578. if (that._isRefreshing)
  48579. that._dataSource.cancel(that._lastOperationId)
  48580. },
  48581. _handleDataLoaded: function(options) {
  48582. options.storeLoadOptions = options.originalStoreLoadOptions
  48583. },
  48584. _handleLoadingChanged: function(isLoading) {
  48585. this.loadingChanged.fire(isLoading)
  48586. },
  48587. _handleLoadError: function(error) {
  48588. this.changed.fire({
  48589. changeType: 'loadError',
  48590. error: error
  48591. });
  48592. this.loadError.fire(error)
  48593. },
  48594. _handleDataChanged: function(args) {
  48595. var that = this,
  48596. currentTotalCount,
  48597. dataSource = that._dataSource,
  48598. itemsCount = that.itemsCount();
  48599. that._isLastPage = !itemsCount || !that.pageSize() || itemsCount < that.pageSize();
  48600. if (that._isLastPage)
  48601. that._hasLastPage = true;
  48602. if (dataSource.totalCount() >= 0) {
  48603. if (dataSource.pageIndex() >= that.pageCount()) {
  48604. dataSource.pageIndex(that.pageCount() - 1);
  48605. dataSource.load()
  48606. }
  48607. }
  48608. else {
  48609. currentTotalCount = dataSource.pageIndex() * that.pageSize() + itemsCount;
  48610. that._currentTotalCount = Math.max(that._currentTotalCount, currentTotalCount);
  48611. if (itemsCount === 0 && dataSource.pageIndex() >= that.pageCount()) {
  48612. dataSource.pageIndex(that.pageCount() - 1);
  48613. dataSource.load()
  48614. }
  48615. }
  48616. if (!dataSource.isLoading())
  48617. this.changed.fire(args)
  48618. },
  48619. isLastPage: function() {
  48620. return this._isLastPage
  48621. },
  48622. totalCount: function() {
  48623. return parseInt(this._currentTotalCount || this._dataSource.totalCount())
  48624. },
  48625. itemsCount: function() {
  48626. return this._dataSource.items().length
  48627. },
  48628. totalItemsCount: function() {
  48629. return this.totalCount()
  48630. },
  48631. pageSize: function() {
  48632. var dataSource = this._dataSource;
  48633. if (!arguments.length && !dataSource.paginate())
  48634. return 0;
  48635. return dataSource.pageSize.apply(dataSource, arguments)
  48636. },
  48637. pageCount: function() {
  48638. var that = this,
  48639. count = that.totalItemsCount(),
  48640. pageSize = that.pageSize();
  48641. if (pageSize && count > 0)
  48642. return Math.max(1, Math.ceil(count / pageSize));
  48643. return 1
  48644. },
  48645. hasKnownLastPage: function() {
  48646. return this._hasLastPage || this._dataSource.totalCount() >= 0
  48647. }
  48648. }
  48649. }());
  48650. dataGrid.DataSourceAdapterClient = dataGrid.DataSourceAdapterServer.inherit({
  48651. _handleDataLoading: function(options) {
  48652. this.callBase(options);
  48653. var remoteOperations = this._remoteOperations || {},
  48654. loadOptions = options.loadOptions = options.storeLoadOptions;
  48655. options.storeLoadOptions = {userData: loadOptions.userData};
  48656. if (remoteOperations.filtering) {
  48657. options.storeLoadOptions.filter = loadOptions.filter;
  48658. delete loadOptions.filter
  48659. }
  48660. if (remoteOperations.sorting) {
  48661. options.storeLoadOptions.sort = loadOptions.sort;
  48662. delete loadOptions.sort
  48663. }
  48664. this._handleDataLoadingCore(options)
  48665. },
  48666. _handleDataLoadingCore: function(){},
  48667. _handleDataLoaded: function(options) {
  48668. var callBase = this.callBase,
  48669. loadOptions = options.loadOptions;
  48670. if (!loadOptions) {
  48671. this._dataSource.cancel(options.operationId);
  48672. return
  48673. }
  48674. options.skip = loadOptions.skip;
  48675. options.take = loadOptions.take;
  48676. delete loadOptions.skip;
  48677. delete loadOptions.take;
  48678. new DX.data.ArrayStore(options.data).load(loadOptions).done(function(data) {
  48679. options.data = data;
  48680. if (loadOptions.requireTotalCount)
  48681. options.extra = options.extra || {totalCount: data.length}
  48682. });
  48683. this._handleDataLoadedCore(options);
  48684. callBase.apply(this, arguments)
  48685. },
  48686. _handleDataLoadedCore: function(options) {
  48687. if (options.skip !== undefined)
  48688. options.data = options.data.slice(options.skip);
  48689. if (options.take !== undefined)
  48690. options.data = options.data.slice(0, options.take)
  48691. }
  48692. })
  48693. })(jQuery, DevExpress);
  48694. /*! Module widgets-web, file ui.dataGrid.groupingModule.js */
  48695. (function($, DX) {
  48696. var ui = DX.ui,
  48697. dataGrid = ui.dxDataGrid,
  48698. utils = DX.utils,
  48699. normalizeSortingInfo = DX.data.utils.normalizeSortingInfo;
  48700. var DATAGRID_GROUP_PANEL_CLASS = "dx-datagrid-group-panel",
  48701. DATAGRID_GROUP_PANEL_MESSAGE_CLASS = "dx-group-panel-message",
  48702. DATAGRID_GROUP_PANEL_ITEM_CLASS = "dx-group-panel-item",
  48703. DATAGRID_GROUP_OPENED_CLASS = "dx-datagrid-group-opened",
  48704. DATAGRID_GROUP_CLOSED_CLASS = "dx-datagrid-group-closed",
  48705. DATAGRID_EXPAND_CLASS = "dx-datagrid-expand",
  48706. DATAGRID_SELECTION_DISABLED_CLASS = "dx-selection-disabled";
  48707. var GroupingDataSourceAdapterExtender = function() {
  48708. var findGroupInfoByKey = function(groupsInfo, key) {
  48709. var i;
  48710. for (i = 0; i < groupsInfo.length; i++)
  48711. if (DX.data.utils.keysEqual(null, groupsInfo[i].key, key))
  48712. return groupsInfo[i]
  48713. };
  48714. var getGroupInfoIndexByOffset = function(groupsInfo, offset) {
  48715. var index;
  48716. for (index = 0; index < groupsInfo.length; index++)
  48717. if (groupsInfo[index].offset > offset)
  48718. break;
  48719. return index
  48720. };
  48721. var updateGroupInfoOffsets = function(groupsInfo) {
  48722. var groupInfo,
  48723. index,
  48724. newIndex;
  48725. for (index = 0; index < groupsInfo.length; index++) {
  48726. groupInfo = groupsInfo[index];
  48727. if (groupInfo.data && groupInfo.data.offset !== groupInfo.offset) {
  48728. groupsInfo.splice(index, 1);
  48729. groupInfo.offset = groupInfo.data.offset;
  48730. newIndex = getGroupInfoIndexByOffset(groupsInfo, groupInfo.offset);
  48731. groupsInfo.splice(newIndex, 0, groupInfo);
  48732. if (newIndex > index)
  48733. index--
  48734. }
  48735. }
  48736. };
  48737. var cleanGroupsInfo = function(groupsInfo, groupIndex, groupsCount) {
  48738. var i;
  48739. for (i = 0; i < groupsInfo.length; i++)
  48740. if (groupIndex + 1 >= groupsCount)
  48741. groupsInfo[i].children = [];
  48742. else
  48743. cleanGroupsInfo(groupsInfo[i].children, groupIndex + 1, groupsCount)
  48744. };
  48745. return {
  48746. init: function() {
  48747. this.callBase.apply(this, arguments);
  48748. this.reset()
  48749. },
  48750. reset: function() {
  48751. this._groupsInfo = [];
  48752. this._totalCountCorrection = 0
  48753. },
  48754. totalItemsCount: function() {
  48755. var that = this,
  48756. totalCount = that.callBase();
  48757. return totalCount > 0 && that._dataSource.group() && that._dataSource.requireTotalCount() ? totalCount + that._totalCountCorrection : totalCount
  48758. },
  48759. itemsCount: function() {
  48760. return this._dataSource.group() ? this._itemsCount || 0 : this.callBase()
  48761. },
  48762. updateTotalItemsCount: function(totalCountCorrection) {
  48763. this._totalCountCorrection = totalCountCorrection || 0
  48764. },
  48765. _isGroupItemCountable: function(item) {
  48766. return !this._isVirtualPaging() || !item.isContinuation
  48767. },
  48768. _isVirtualPaging: function() {
  48769. var scrollingMode = this.option("scrolling.mode");
  48770. return scrollingMode === 'virtual' || scrollingMode === 'infinite'
  48771. },
  48772. updateItemsCount: function(data, groupsCount) {
  48773. function calculateItemsCount(that, items, groupsCount) {
  48774. var i,
  48775. result = 0;
  48776. if (items)
  48777. if (!groupsCount)
  48778. result = items.length;
  48779. else
  48780. for (i = 0; i < items.length; i++) {
  48781. if (that._isGroupItemCountable(items[i]))
  48782. result++;
  48783. result += calculateItemsCount(that, items[i].items, groupsCount - 1)
  48784. }
  48785. return result
  48786. }
  48787. this._itemsCount = calculateItemsCount(this, data, groupsCount)
  48788. },
  48789. foreachGroups: function(callback, childrenAtFirst, foreachCollapsedGroups) {
  48790. var that = this;
  48791. function foreachGroupsCore(groupsInfo, callback, childrenAtFirst, parents) {
  48792. var i,
  48793. callbackResult,
  48794. callbackResults = [];
  48795. function executeCallback(callback, data, parents, callbackResults) {
  48796. var callbackResult = data && callback(data, parents);
  48797. callbackResults.push(callbackResult);
  48798. return callbackResult
  48799. }
  48800. for (i = 0; i < groupsInfo.length; i++) {
  48801. parents.push(groupsInfo[i].data);
  48802. if (!childrenAtFirst && executeCallback(callback, groupsInfo[i].data, parents, callbackResults) === false)
  48803. return false;
  48804. if (!groupsInfo[i].data || groupsInfo[i].data.isExpanded || foreachCollapsedGroups) {
  48805. callbackResult = foreachGroupsCore(groupsInfo[i].children, callback, childrenAtFirst, parents);
  48806. callbackResults.push(callbackResult);
  48807. if (callbackResult === false)
  48808. return false
  48809. }
  48810. if (childrenAtFirst && executeCallback(callback, groupsInfo[i].data, parents, callbackResults) === false)
  48811. return false;
  48812. parents.pop()
  48813. }
  48814. return $.when.apply($, callbackResults).always(function() {
  48815. updateGroupInfoOffsets(groupsInfo)
  48816. })
  48817. }
  48818. return foreachGroupsCore(that._groupsInfo, callback, childrenAtFirst, [])
  48819. },
  48820. findGroupInfo: function(path) {
  48821. var that = this,
  48822. pathIndex,
  48823. groupInfo,
  48824. groupsInfo = that._groupsInfo;
  48825. for (pathIndex = 0; groupsInfo && pathIndex < path.length; pathIndex++) {
  48826. groupInfo = findGroupInfoByKey(groupsInfo, path[pathIndex]);
  48827. groupsInfo = groupInfo && groupInfo.children
  48828. }
  48829. return groupInfo && groupInfo.data
  48830. },
  48831. addGroupInfo: function(groupInfoData) {
  48832. var that = this,
  48833. index,
  48834. groupInfo,
  48835. path = groupInfoData.path,
  48836. pathIndex,
  48837. groupsInfo = that._groupsInfo;
  48838. for (pathIndex = 0; pathIndex < path.length; pathIndex++) {
  48839. groupInfo = findGroupInfoByKey(groupsInfo, path[pathIndex]);
  48840. if (!groupInfo) {
  48841. groupInfo = {
  48842. key: path[pathIndex],
  48843. offset: groupInfoData.offset,
  48844. children: []
  48845. };
  48846. index = getGroupInfoIndexByOffset(groupsInfo, groupInfoData.offset);
  48847. groupsInfo.splice(index, 0, groupInfo)
  48848. }
  48849. if (pathIndex === path.length - 1) {
  48850. groupInfo.data = groupInfoData;
  48851. updateGroupInfoOffsets(groupsInfo)
  48852. }
  48853. groupsInfo = groupInfo.children
  48854. }
  48855. },
  48856. allowCollapseAll: function() {
  48857. return true
  48858. },
  48859. isRowExpanded: function(key) {
  48860. var groupInfo = this.findGroupInfo(key);
  48861. return groupInfo ? groupInfo.isExpanded : !this.allowCollapseAll()
  48862. },
  48863. collapseAll: function(groupIndex) {
  48864. if (!this.allowCollapseAll()) {
  48865. DX.log("E1018");
  48866. return false
  48867. }
  48868. return this._collapseExpandAll(groupIndex, false)
  48869. },
  48870. expandAll: function(groupIndex) {
  48871. return this._collapseExpandAll(groupIndex, true)
  48872. },
  48873. _collapseExpandAll: function(groupIndex, isExpand) {
  48874. var that = this,
  48875. dataSource = that._dataSource,
  48876. group = dataSource.group(),
  48877. groups = normalizeSortingInfo(group || []),
  48878. i;
  48879. if (groups.length) {
  48880. for (i = 0; i < groups.length; i++)
  48881. if (groupIndex === undefined || groupIndex === i)
  48882. groups[i].isExpanded = isExpand;
  48883. else if (group && group[i])
  48884. groups[i].isExpanded = group[i].isExpanded;
  48885. dataSource.group(groups);
  48886. that.foreachGroups(function(groupInfo, parents) {
  48887. if (groupIndex === undefined || groupIndex === parents.length - 1)
  48888. groupInfo.isExpanded = isExpand
  48889. }, false, true)
  48890. }
  48891. return true
  48892. },
  48893. refresh: function(storeLoadOptions) {
  48894. this.callBase.apply(this, arguments);
  48895. var that = this,
  48896. groupIndex,
  48897. oldGroups = normalizeSortingInfo(that._group || []),
  48898. groups = normalizeSortingInfo(storeLoadOptions.group || []),
  48899. groupsCount = Math.min(oldGroups.length, groups.length);
  48900. that._group = storeLoadOptions.group;
  48901. for (groupIndex = 0; groupIndex < groupsCount; groupIndex++)
  48902. if (oldGroups[groupIndex].selector !== groups[groupIndex].selector) {
  48903. groupsCount = groupIndex;
  48904. break
  48905. }
  48906. if (!groupsCount)
  48907. that.reset();
  48908. else
  48909. cleanGroupsInfo(that._groupsInfo, 0, groupsCount)
  48910. },
  48911. changeRowExpand: function(path) {
  48912. var that = this,
  48913. dataSource = that._dataSource;
  48914. if (dataSource.group()) {
  48915. dataSource._changeLoadingCount(1);
  48916. return that._changeRowExpandCore(path).always(function() {
  48917. dataSource._changeLoadingCount(-1)
  48918. })
  48919. }
  48920. }
  48921. }
  48922. }();
  48923. dataGrid.DataSourceAdapterClient = dataGrid.DataSourceAdapterClient.inherit(GroupingDataSourceAdapterExtender);
  48924. dataGrid.DataSourceAdapterServer = dataGrid.DataSourceAdapterServer.inherit(GroupingDataSourceAdapterExtender);
  48925. var GroupingDataControllerExtender = function() {
  48926. return {
  48927. init: function() {
  48928. var that = this;
  48929. that.callBase();
  48930. that.createAction('onRowExpanding');
  48931. that.createAction('onRowExpanded');
  48932. that.createAction('onRowCollapsing');
  48933. that.createAction('onRowCollapsed')
  48934. },
  48935. _processItems: function(items) {
  48936. var groupColumns = this._columnsController.getGroupColumns();
  48937. if (items.length && groupColumns.length)
  48938. items = this._processGroupItems(items, groupColumns.length);
  48939. return this.callBase(items)
  48940. },
  48941. _processItem: function(item, options) {
  48942. if (utils.isDefined(item.groupIndex) && utils.isString(item.rowType) && item.rowType.indexOf("group") === 0) {
  48943. item = this._processGroupItem(item, options);
  48944. options.dataIndex = 0
  48945. }
  48946. else
  48947. item = this.callBase.apply(this, arguments);
  48948. return item
  48949. },
  48950. _processGroupItem: function(item, options) {
  48951. return item
  48952. },
  48953. _processGroupItems: function(items, groupsCount, options) {
  48954. var that = this,
  48955. scrollingMode,
  48956. i,
  48957. item,
  48958. resultItems,
  48959. path;
  48960. if (!options) {
  48961. scrollingMode = that.option('scrolling.mode');
  48962. options = {
  48963. collectContinuationItems: scrollingMode !== 'virtual' && scrollingMode !== 'infinite',
  48964. resultItems: [],
  48965. path: []
  48966. }
  48967. }
  48968. resultItems = options.resultItems;
  48969. path = options.path;
  48970. if (options.data)
  48971. if (options.collectContinuationItems || !options.data.isContinuation)
  48972. resultItems.push({
  48973. rowType: 'group',
  48974. data: options.data,
  48975. groupIndex: path.length - 1,
  48976. isExpanded: !!options.data.items,
  48977. key: path,
  48978. values: path
  48979. });
  48980. if (items)
  48981. if (groupsCount === 0)
  48982. resultItems.push.apply(resultItems, items);
  48983. else
  48984. for (i = 0; i < items.length; i++) {
  48985. item = items[i];
  48986. if (item) {
  48987. options.data = item;
  48988. options.path = path.concat(item.key);
  48989. that._processGroupItems(item.items, groupsCount - 1, options);
  48990. options.data = undefined;
  48991. options.path = path
  48992. }
  48993. }
  48994. return resultItems
  48995. },
  48996. publicMethods: function() {
  48997. return this.callBase().concat(['collapseAll', 'expandAll', 'isRowExpanded', 'expandRow', 'collapseRow'])
  48998. },
  48999. collapseAll: function(groupIndex) {
  49000. var dataSource = this._dataSource;
  49001. if (dataSource && dataSource.collapseAll(groupIndex)) {
  49002. dataSource.pageIndex(0);
  49003. dataSource.reload()
  49004. }
  49005. },
  49006. expandAll: function(groupIndex) {
  49007. var dataSource = this._dataSource;
  49008. if (dataSource && dataSource.expandAll(groupIndex)) {
  49009. dataSource.pageIndex(0);
  49010. dataSource.reload()
  49011. }
  49012. },
  49013. changeRowExpand: function(key) {
  49014. var that = this,
  49015. expanded = that.isRowExpanded(key),
  49016. args = {
  49017. key: key,
  49018. expanded: expanded
  49019. };
  49020. that.executeAction(expanded ? "onRowCollapsing" : "onRowExpanding", args);
  49021. if (!args.cancel)
  49022. return $.when(that._changeRowExpandCore(key)).done(function() {
  49023. args.expanded = !expanded;
  49024. that.executeAction(expanded ? "onRowCollapsed" : "onRowExpanded", args)
  49025. })
  49026. },
  49027. _changeRowExpandCore: function(key) {
  49028. var that = this,
  49029. dataSource = this._dataSource,
  49030. d;
  49031. if (!dataSource)
  49032. return;
  49033. d = $.Deferred();
  49034. $.when(dataSource.changeRowExpand(key)).done(function() {
  49035. that.load().done(d.resolve).fail(d.reject)
  49036. }).fail(d.reject);
  49037. return d
  49038. },
  49039. isRowExpanded: function(key) {
  49040. var dataSource = this._dataSource;
  49041. return dataSource && dataSource.isRowExpanded(key)
  49042. },
  49043. expandRow: function(key) {
  49044. if (!this.isRowExpanded(key))
  49045. this.changeRowExpand(key)
  49046. },
  49047. collapseRow: function(key) {
  49048. if (this.isRowExpanded(key))
  49049. this.changeRowExpand(key)
  49050. },
  49051. optionChanged: function(args) {
  49052. if (args.name === "grouping")
  49053. args.name = "dataSource";
  49054. this.callBase(args)
  49055. }
  49056. }
  49057. }();
  49058. var GroupingHeaderPanelExtender = function() {
  49059. return {
  49060. _renderGroupPanel: function() {
  49061. var that = this,
  49062. $element = that.element(),
  49063. groupPanelOptions = that.option("groupPanel"),
  49064. $groupPanel,
  49065. groupColumns = that.getController('columns').getGroupColumns();
  49066. $groupPanel = $element.find('.' + DATAGRID_GROUP_PANEL_CLASS);
  49067. if (groupPanelOptions && groupPanelOptions.visible) {
  49068. if (!$groupPanel.length)
  49069. $groupPanel = $('<div />').addClass(DATAGRID_GROUP_PANEL_CLASS).prependTo($element);
  49070. else
  49071. $groupPanel.show();
  49072. that._renderGroupPanelItems($groupPanel, groupColumns);
  49073. if (groupPanelOptions.allowColumnDragging && !groupColumns.length)
  49074. $('<div />').addClass(DATAGRID_GROUP_PANEL_MESSAGE_CLASS).text(groupPanelOptions.emptyPanelText).appendTo($groupPanel)
  49075. }
  49076. else
  49077. $groupPanel.hide()
  49078. },
  49079. _renderGroupPanelItems: function($groupPanel, groupColumns) {
  49080. var that = this;
  49081. $groupPanel.empty();
  49082. $.each(groupColumns, function(index, groupColumn) {
  49083. that._createGroupPanelItem($groupPanel, groupColumn)
  49084. })
  49085. },
  49086. _createGroupPanelItem: function($rootElement, groupColumn) {
  49087. return $('<div />').addClass(groupColumn.cssClass).addClass(DATAGRID_GROUP_PANEL_ITEM_CLASS).appendTo($rootElement).text(groupColumn.caption)
  49088. },
  49089. _renderCore: function() {
  49090. this.callBase.apply(this, arguments);
  49091. this._renderGroupPanel()
  49092. },
  49093. allowDragging: function(column) {
  49094. var groupPanelOptions = this.option("groupPanel");
  49095. return groupPanelOptions && groupPanelOptions.visible && groupPanelOptions.allowColumnDragging && column && column.allowGrouping
  49096. },
  49097. getColumnElements: function() {
  49098. var $element = this.element();
  49099. return $element && $element.find('.' + DATAGRID_GROUP_PANEL_ITEM_CLASS)
  49100. },
  49101. getColumns: function() {
  49102. return this.getController('columns').getGroupColumns()
  49103. },
  49104. getBoundingRect: function() {
  49105. var that = this,
  49106. $element = that.element(),
  49107. offset;
  49108. if ($element && $element.find('.' + DATAGRID_GROUP_PANEL_CLASS).length) {
  49109. offset = $element.offset();
  49110. return {
  49111. top: offset.top,
  49112. bottom: offset.top + $element.height()
  49113. }
  49114. }
  49115. return null
  49116. },
  49117. getName: function() {
  49118. return 'group'
  49119. },
  49120. isVisible: function() {
  49121. return this.callBase() || this.option('groupPanel.visible')
  49122. },
  49123. optionChanged: function(args) {
  49124. if (args.name === "groupPanel") {
  49125. this._renderGroupPanel();
  49126. args.handled = true
  49127. }
  49128. else
  49129. this.callBase(args)
  49130. }
  49131. }
  49132. }();
  49133. dataGrid.GroupingHeaderPanelExtender = GroupingHeaderPanelExtender;
  49134. var GroupingRowsViewExtender = function() {
  49135. return {
  49136. _rowClick: function(e) {
  49137. var that = this,
  49138. dataController = that.getController('data'),
  49139. $expandElement = $(e.jQueryEvent.target).closest('.' + DATAGRID_EXPAND_CLASS),
  49140. key;
  49141. if ($expandElement.length) {
  49142. key = dataController.getKeyByRowIndex(e.rowIndex);
  49143. dataController.changeRowExpand(key);
  49144. e.jQueryEvent.preventDefault();
  49145. e.handled = true
  49146. }
  49147. that.callBase(e)
  49148. },
  49149. _getDefaultTemplate: function(column) {
  49150. var that = this;
  49151. if (column.command === "expand")
  49152. return function(container, options) {
  49153. if (utils.isDefined(options.value) && !(options.data && options.data.isContinuation) && !options.row.inserted) {
  49154. container.addClass(DATAGRID_EXPAND_CLASS).addClass(DATAGRID_SELECTION_DISABLED_CLASS);
  49155. $("<div>").addClass(options.value ? DATAGRID_GROUP_OPENED_CLASS : DATAGRID_GROUP_CLOSED_CLASS).appendTo(container);
  49156. that.setAria("label", options.value ? Globalize.localize("dxDataGrid-ariaCollapse") : Globalize.localize("dxDataGrid-ariaExpand"), container)
  49157. }
  49158. };
  49159. return that.callBase(column)
  49160. }
  49161. }
  49162. }();
  49163. $.extend(dataGrid.__internals, {
  49164. DATAGRID_GROUP_PANEL_CLASS: DATAGRID_GROUP_PANEL_CLASS,
  49165. DATAGRID_GROUP_PANEL_MESSAGE_CLASS: DATAGRID_GROUP_PANEL_MESSAGE_CLASS,
  49166. DATAGRID_GROUP_PANEL_ITEM_CLASS: DATAGRID_GROUP_PANEL_ITEM_CLASS,
  49167. DATAGRID_GROUP_OPENED_CLASS: DATAGRID_GROUP_OPENED_CLASS,
  49168. DATAGRID_GROUP_CLOSED_CLASS: DATAGRID_GROUP_CLOSED_CLASS,
  49169. DATAGRID_EXPAND_CLASS: DATAGRID_EXPAND_CLASS,
  49170. DATAGRID_SELECTION_DISABLED_CLASS: DATAGRID_SELECTION_DISABLED_CLASS
  49171. });
  49172. dataGrid.registerModule('grouping', {
  49173. defaultOptions: function() {
  49174. return {
  49175. grouping: {
  49176. autoExpandAll: true,
  49177. allowCollapsing: true,
  49178. groupContinuesMessage: Globalize.localize("dxDataGrid-groupContinuesMessage"),
  49179. groupContinuedMessage: Globalize.localize("dxDataGrid-groupContinuedMessage")
  49180. },
  49181. groupPanel: {
  49182. visible: false,
  49183. emptyPanelText: Globalize.localize("dxDataGrid-groupPanelEmptyText"),
  49184. allowColumnDragging: true
  49185. }
  49186. }
  49187. },
  49188. extenders: {
  49189. controllers: {data: GroupingDataControllerExtender},
  49190. views: {
  49191. headerPanel: GroupingHeaderPanelExtender,
  49192. rowsView: GroupingRowsViewExtender
  49193. }
  49194. }
  49195. })
  49196. })(jQuery, DevExpress);
  49197. /*! Module widgets-web, file ui.dataGrid.grouping.server.js */
  49198. (function($, DX) {
  49199. var dataUtils = DX.data.utils,
  49200. dataGrid = DX.ui.dxDataGrid,
  49201. normalizeSortingInfo = dataGrid.normalizeSortingInfo,
  49202. keysEqual = dataUtils.keysEqual;
  49203. var loadTotalCount = function(store, options) {
  49204. var d = $.Deferred(),
  49205. loadOptions = $.extend({
  49206. skip: 0,
  49207. take: 1,
  49208. requireTotalCount: true
  49209. }, options);
  49210. store.load(loadOptions).done(function(data, extra) {
  49211. if (extra && isFinite(extra.totalCount))
  49212. d.resolve(extra.totalCount);
  49213. else
  49214. store.totalCount(options).done($.proxy(d.resolve, d)).fail($.proxy(d.reject, d))
  49215. }).fail($.proxy(d.reject, d));
  49216. return d
  49217. };
  49218. dataGrid.DataSourceAdapterServer = dataGrid.DataSourceAdapterServer.inherit(function() {
  49219. var foreachCollapsedGroups = function(that, callback) {
  49220. return that.foreachGroups(function(groupInfo) {
  49221. if (!groupInfo.isExpanded)
  49222. return callback(groupInfo)
  49223. })
  49224. };
  49225. var correctSkipLoadOption = function(that, skip) {
  49226. var skipCorrection = 0,
  49227. resultSkip = skip || 0;
  49228. if (skip) {
  49229. foreachCollapsedGroups(that, function(groupInfo) {
  49230. if (groupInfo.offset - skipCorrection >= skip)
  49231. return false;
  49232. skipCorrection += groupInfo.count - 1
  49233. });
  49234. resultSkip += skipCorrection
  49235. }
  49236. return resultSkip
  49237. };
  49238. var processGroupItems = function(that, items, path, offset, skipFirstItem, take) {
  49239. var i,
  49240. item,
  49241. offsetInfo,
  49242. removeLastItemsCount = 0,
  49243. needRemoveFirstItem = false;
  49244. for (i = 0; i < items.length; i++) {
  49245. item = items[i];
  49246. if (item.items !== undefined) {
  49247. path.push(item.key);
  49248. var groupInfo = that.findGroupInfo(path);
  49249. if (groupInfo && !groupInfo.isExpanded) {
  49250. item.collapsedItems = item.items;
  49251. item.items = null;
  49252. offset += groupInfo.count;
  49253. take--;
  49254. if (take < 0)
  49255. removeLastItemsCount++;
  49256. if (skipFirstItem)
  49257. needRemoveFirstItem = true
  49258. }
  49259. else if (item.items) {
  49260. offsetInfo = processGroupItems(that, item.items, path, offset, skipFirstItem, take);
  49261. if (skipFirstItem)
  49262. if (offsetInfo.offset - offset > 1)
  49263. item.isContinuation = true;
  49264. else
  49265. needRemoveFirstItem = true;
  49266. offset = offsetInfo.offset;
  49267. take = offsetInfo.take;
  49268. if (take < 0)
  49269. if (item.items.length)
  49270. item.isContinuationOnNextPage = true;
  49271. else
  49272. removeLastItemsCount++
  49273. }
  49274. path.pop()
  49275. }
  49276. else {
  49277. if (skipFirstItem)
  49278. needRemoveFirstItem = true;
  49279. offset++;
  49280. take--;
  49281. if (take < 0)
  49282. removeLastItemsCount++
  49283. }
  49284. skipFirstItem = false
  49285. }
  49286. if (needRemoveFirstItem)
  49287. items.splice(0, 1);
  49288. if (removeLastItemsCount)
  49289. items.splice(-removeLastItemsCount, removeLastItemsCount);
  49290. return {
  49291. offset: offset,
  49292. take: take
  49293. }
  49294. };
  49295. var pathEquals = function(path1, path2) {
  49296. var i;
  49297. if (path1.length !== path2.length)
  49298. return false;
  49299. for (i = 0; i < path1.length; i++)
  49300. if (!keysEqual(null, path1[i], path2[i]))
  49301. return false;
  49302. return true
  49303. };
  49304. var updateGroupOffsets = function(that, items, path, offset, additionalGroupInfo) {
  49305. var i,
  49306. item;
  49307. if (!items)
  49308. return;
  49309. for (i = 0; i < items.length; i++) {
  49310. item = items[i];
  49311. if ('key' in item && item.items !== undefined) {
  49312. path.push(item.key);
  49313. if (additionalGroupInfo && pathEquals(additionalGroupInfo.path, path) && !item.isContinuation)
  49314. additionalGroupInfo.offset = offset;
  49315. var groupInfo = that.findGroupInfo(path);
  49316. if (groupInfo && !groupInfo.isExpanded) {
  49317. if (!item.isContinuation) {
  49318. groupInfo.offset = offset;
  49319. offset += groupInfo.count
  49320. }
  49321. }
  49322. else
  49323. offset = updateGroupOffsets(that, item.items, path, offset, additionalGroupInfo);
  49324. path.pop()
  49325. }
  49326. else
  49327. offset++
  49328. }
  49329. return offset
  49330. };
  49331. var removeGroupLoadOption = function(storeLoadOptions) {
  49332. var groups,
  49333. sorts;
  49334. if (storeLoadOptions.group) {
  49335. groups = normalizeSortingInfo(storeLoadOptions.group);
  49336. sorts = normalizeSortingInfo(storeLoadOptions.sort);
  49337. storeLoadOptions.sort = dataUtils.arrangeSortingInfo(groups, sorts);
  49338. delete storeLoadOptions.group
  49339. }
  49340. };
  49341. var createGroupFilter = function(path, storeLoadOptions) {
  49342. var groups = normalizeSortingInfo(storeLoadOptions.group),
  49343. i,
  49344. filter = [];
  49345. for (i = 0; i < path.length; i++)
  49346. filter.push([groups[i].selector, '=', path[i]]);
  49347. if (storeLoadOptions.filter)
  49348. filter.push(storeLoadOptions.filter);
  49349. return dataGrid.combineFilters(filter)
  49350. };
  49351. var createNotGroupFilter = function(path, storeLoadOptions, group) {
  49352. var groups = normalizeSortingInfo(group || storeLoadOptions.group),
  49353. i,
  49354. j,
  49355. filterElement,
  49356. filter = [];
  49357. for (i = 0; i < path.length; i++) {
  49358. filterElement = [];
  49359. for (j = 0; j <= i; j++)
  49360. filterElement.push([groups[j].selector, i === j ? '<>' : '=', path[j]]);
  49361. filter.push(dataGrid.combineFilters(filterElement))
  49362. }
  49363. filter = dataGrid.combineFilters(filter, "or");
  49364. return dataGrid.combineFilters([filter, storeLoadOptions.filter])
  49365. };
  49366. var createOffsetFilter = function(path, storeLoadOptions) {
  49367. var groups = normalizeSortingInfo(storeLoadOptions.group),
  49368. i,
  49369. j,
  49370. filterElement,
  49371. filter = [];
  49372. for (i = 0; i < path.length; i++) {
  49373. filterElement = [];
  49374. for (j = 0; j <= i; j++)
  49375. filterElement.push([groups[j].selector, i === j ? groups[j].desc ? '>' : '<' : '=', path[j]]);
  49376. if (filter.length)
  49377. filter.push('or');
  49378. filter.push(filterElement)
  49379. }
  49380. if (storeLoadOptions.filter)
  49381. filter.push(storeLoadOptions.filter);
  49382. return filter
  49383. };
  49384. return {
  49385. _handleDataLoading: function(options) {
  49386. this.callBase(options);
  49387. var that = this,
  49388. storeLoadOptions = options.storeLoadOptions,
  49389. loadOptions,
  49390. collapsedPaths = [],
  49391. collapsedItemsCount = 0,
  49392. skipFirstItem = false,
  49393. take,
  49394. group = storeLoadOptions.group,
  49395. skipCorrection = 0;
  49396. removeGroupLoadOption(storeLoadOptions);
  49397. options.group = options.group || group;
  49398. if (storeLoadOptions.isLoadingAll)
  49399. return;
  49400. loadOptions = $.extend({}, storeLoadOptions);
  49401. loadOptions.skip = correctSkipLoadOption(that, storeLoadOptions.skip);
  49402. if (loadOptions.skip && loadOptions.take && group) {
  49403. loadOptions.skip--;
  49404. loadOptions.take++;
  49405. skipFirstItem = true
  49406. }
  49407. if (loadOptions.take && group) {
  49408. take = loadOptions.take;
  49409. loadOptions.take++
  49410. }
  49411. foreachCollapsedGroups(that, function(groupInfo) {
  49412. if (groupInfo.offset >= loadOptions.skip + loadOptions.take + skipCorrection)
  49413. return false;
  49414. else if (groupInfo.offset >= loadOptions.skip + skipCorrection && groupInfo.count) {
  49415. skipCorrection += groupInfo.count - 1;
  49416. collapsedPaths.push(groupInfo.path);
  49417. collapsedItemsCount += groupInfo.count
  49418. }
  49419. });
  49420. $.each(collapsedPaths, function() {
  49421. loadOptions.filter = createNotGroupFilter(this, loadOptions, group)
  49422. });
  49423. options.storeLoadOptions = loadOptions;
  49424. options.collapsedPaths = collapsedPaths;
  49425. options.collapsedItemsCount = collapsedItemsCount;
  49426. options.skip = loadOptions.skip || 0;
  49427. options.skipFirstItem = skipFirstItem;
  49428. options.take = take
  49429. },
  49430. _handleDataLoaded: function(options) {
  49431. var that = this,
  49432. data = options.data,
  49433. pathIndex,
  49434. query,
  49435. collapsedPaths = options.collapsedPaths,
  49436. groups = normalizeSortingInfo(options.group),
  49437. groupCount = groups.length;
  49438. function appendCollapsedPath(data, path, groups) {
  49439. if (!data || !path.length || !groups.length)
  49440. return;
  49441. var i,
  49442. keyValue,
  49443. pathValue = dataUtils.toComparable(path[0], true);
  49444. for (i = 0; i < data.length; i++) {
  49445. keyValue = dataUtils.toComparable(data[i].key, true);
  49446. if (groups[0].desc ? pathValue >= keyValue : pathValue <= keyValue)
  49447. break
  49448. }
  49449. if (!data.length || pathValue !== keyValue)
  49450. data.splice(i, 0, {
  49451. key: path[0],
  49452. items: []
  49453. });
  49454. appendCollapsedPath(data[i].items, path.slice(1), groups.slice(1))
  49455. }
  49456. this.callBase(options);
  49457. if (groupCount) {
  49458. query = DX.data.query(data);
  49459. DX.data.utils.multiLevelGroup(query, groups).enumerate().done(function(groupedData) {
  49460. data = groupedData
  49461. });
  49462. if (collapsedPaths)
  49463. for (pathIndex = 0; pathIndex < collapsedPaths.length; pathIndex++)
  49464. appendCollapsedPath(data, collapsedPaths[pathIndex], groups);
  49465. if (!options.storeLoadOptions.isLoadingAll) {
  49466. processGroupItems(that, data, [], options.skip, options.skipFirstItem, options.take);
  49467. that.updateItemsCount(data, groupCount)
  49468. }
  49469. options.data = data;
  49470. if (options.collapsedItemsCount && options.extra && options.extra.totalCount >= 0)
  49471. options.extra.totalCount += options.collapsedItemsCount
  49472. }
  49473. },
  49474. updateTotalItemsCount: function() {
  49475. var itemsCountCorrection = 0;
  49476. foreachCollapsedGroups(this, function(groupInfo) {
  49477. if (groupInfo.count)
  49478. itemsCountCorrection -= groupInfo.count - 1
  49479. });
  49480. this.callBase(itemsCountCorrection)
  49481. },
  49482. _changeRowExpandCore: function(path) {
  49483. var that = this,
  49484. dataSource = that._dataSource,
  49485. basePageIndex = that.basePageIndex && that.basePageIndex() || that.pageIndex(),
  49486. dataSourceItems = that.items(),
  49487. offset = correctSkipLoadOption(that, basePageIndex * that.pageSize()),
  49488. groupInfo = that.findGroupInfo(path),
  49489. groupCountQuery;
  49490. if (groupInfo && !groupInfo.isExpanded)
  49491. groupCountQuery = $.Deferred().resolve(groupInfo.count);
  49492. else
  49493. groupCountQuery = loadTotalCount(dataSource.store(), {filter: createGroupFilter(path, {
  49494. filter: dataSource.filter(),
  49495. group: dataSource.group()
  49496. })});
  49497. return $.when(groupCountQuery).done(function(count) {
  49498. count = parseInt(count.length ? count[0] : count);
  49499. if (groupInfo) {
  49500. updateGroupOffsets(that, dataSourceItems, [], offset);
  49501. groupInfo.isExpanded = !groupInfo.isExpanded;
  49502. groupInfo.count = count
  49503. }
  49504. else {
  49505. groupInfo = {
  49506. offset: -1,
  49507. count: count,
  49508. path: path,
  49509. isExpanded: false
  49510. };
  49511. updateGroupOffsets(that, dataSourceItems, [], offset, groupInfo);
  49512. if (groupInfo.offset >= 0)
  49513. that.addGroupInfo(groupInfo)
  49514. }
  49515. that.updateTotalItemsCount()
  49516. }).fail($.proxy(dataSource.loadError.fire, dataSource.loadError))
  49517. },
  49518. allowCollapseAll: function() {
  49519. return false
  49520. },
  49521. refresh: function(storeLoadOptions, isReload) {
  49522. var that = this,
  49523. dataSource = that._dataSource,
  49524. store = dataSource.store();
  49525. this.callBase.apply(this, arguments);
  49526. if (isReload)
  49527. return foreachCollapsedGroups(that, function(groupInfo) {
  49528. var groupCountQuery = loadTotalCount(store, {filter: createGroupFilter(groupInfo.path, storeLoadOptions)}),
  49529. groupOffsetQuery = loadTotalCount(store, {filter: createOffsetFilter(groupInfo.path, storeLoadOptions)});
  49530. dataSource._changeLoadingCount(1);
  49531. return $.when(groupOffsetQuery, groupCountQuery).done(function(offset, count) {
  49532. offset = parseInt(offset.length ? offset[0] : offset);
  49533. count = parseInt(count.length ? count[0] : count);
  49534. groupInfo.offset = offset;
  49535. if (groupInfo.count !== count) {
  49536. groupInfo.count = count;
  49537. that.updateTotalItemsCount()
  49538. }
  49539. }).fail($.proxy(that._dataSource.loadError.fire, that._dataSource.loadError)).always(function() {
  49540. dataSource._changeLoadingCount(-1)
  49541. })
  49542. })
  49543. }
  49544. }
  49545. }());
  49546. $.extend(DX.ui.dxDataGrid.__internals, {loadTotalCount: loadTotalCount})
  49547. })(jQuery, DevExpress);
  49548. /*! Module widgets-web, file ui.dataGrid.grouping.client.js */
  49549. (function($, DX) {
  49550. var dataGrid = DX.ui.dxDataGrid,
  49551. normalizeSortingInfo = dataGrid.normalizeSortingInfo;
  49552. dataGrid.DataSourceAdapterClient = dataGrid.DataSourceAdapterClient.inherit(function() {
  49553. var foreachExpandedGroups = function(that, callback) {
  49554. return that.foreachGroups(function(groupInfo, parents) {
  49555. if (groupInfo.isExpanded)
  49556. return callback(groupInfo, parents)
  49557. }, true)
  49558. };
  49559. var processGroupItems = function(that, items, path, groupsCount) {
  49560. var i,
  49561. item;
  49562. if (!groupsCount)
  49563. return;
  49564. for (i = 0; i < items.length; i++) {
  49565. item = items[i];
  49566. if (item.items !== undefined) {
  49567. path.push(item.key);
  49568. var groupInfo = that.findGroupInfo(path);
  49569. if (!groupInfo || !groupInfo.isExpanded) {
  49570. item.collapsedItems = item.items;
  49571. item.items = null
  49572. }
  49573. else
  49574. processGroupItems(that, item.items, path, groupsCount - 1);
  49575. path.pop()
  49576. }
  49577. }
  49578. };
  49579. var updateGroupInfos = function(that, items, groupsCount, offset) {
  49580. return updateGroupInfosCore(that, items, 0, groupsCount, [], offset)
  49581. };
  49582. var updateGroupInfosCore = function(that, items, groupIndex, groupsCount, path, offset) {
  49583. var item,
  49584. totalCount = 0,
  49585. i,
  49586. groupInfo;
  49587. if (groupIndex >= groupsCount)
  49588. return items.length;
  49589. for (i = 0; i < items.length; i++) {
  49590. item = items[i];
  49591. if (item) {
  49592. path.push(item.key);
  49593. groupInfo = that.findGroupInfo(path);
  49594. if (!groupInfo)
  49595. that.addGroupInfo({
  49596. isExpanded: that._isGroupExpanded(groupIndex),
  49597. path: path.slice(0),
  49598. offset: offset + i,
  49599. count: item.items.length
  49600. });
  49601. else {
  49602. groupInfo.count = item.items.length;
  49603. groupInfo.offset = offset + i
  49604. }
  49605. totalCount += updateGroupInfosCore(that, item.items, groupIndex + 1, groupsCount, path, 0);
  49606. path.pop()
  49607. }
  49608. }
  49609. return totalCount
  49610. };
  49611. var isGroupExpanded = function(groups, groupIndex) {
  49612. return groups && groups.length && groups[groupIndex] && !!groups[groupIndex].isExpanded
  49613. };
  49614. var getTotalOffset = function(groupInfos, pageSize, offset) {
  49615. var groupIndex,
  49616. groupSize,
  49617. totalOffset = offset;
  49618. for (groupIndex = 0; groupIndex < groupInfos.length; groupIndex++) {
  49619. groupSize = groupInfos[groupIndex].offset + 1;
  49620. if (groupIndex > 0) {
  49621. groupSize += groupInfos[groupIndex - 1].childrenTotalCount;
  49622. if (pageSize)
  49623. groupSize += getContinuationGroupCount(totalOffset, pageSize, groupSize, groupIndex - 1) * groupIndex
  49624. }
  49625. totalOffset += groupSize
  49626. }
  49627. return totalOffset
  49628. };
  49629. var getContinuationGroupCount = function(groupOffset, pageSize, groupSize, groupIndex) {
  49630. groupIndex = groupIndex || 0;
  49631. if (pageSize > 1 && groupSize > 0) {
  49632. var pageOffset = groupOffset - Math.floor(groupOffset / pageSize) * pageSize || pageSize;
  49633. pageOffset += groupSize - groupIndex - 2;
  49634. if (pageOffset < 0)
  49635. pageOffset += pageSize;
  49636. return Math.floor(pageOffset / (pageSize - groupIndex - 1))
  49637. }
  49638. return 0
  49639. };
  49640. DX.ui.dxDataGrid.getContinuationGroupCount = getContinuationGroupCount;
  49641. return {
  49642. updateTotalItemsCount: function(options) {
  49643. var totalItemsCount = 0,
  49644. totalCount = options.extra && options.extra.totalCount || 0,
  49645. pageSize = this.pageSize(),
  49646. isVirtualPaging = this._isVirtualPaging();
  49647. foreachExpandedGroups(this, function(groupInfo, parents) {
  49648. groupInfo.childrenTotalCount = 0
  49649. });
  49650. foreachExpandedGroups(this, function(groupInfo, parents) {
  49651. var totalOffset = getTotalOffset(parents, isVirtualPaging ? 0 : pageSize, totalItemsCount),
  49652. count = groupInfo.count + groupInfo.childrenTotalCount;
  49653. if (!isVirtualPaging)
  49654. count += getContinuationGroupCount(totalOffset, pageSize, count, parents.length - 1);
  49655. if (parents[parents.length - 2])
  49656. parents[parents.length - 2].childrenTotalCount += count;
  49657. else
  49658. totalItemsCount += count
  49659. });
  49660. this.callBase(totalItemsCount - totalCount + options.data.length)
  49661. },
  49662. _isGroupExpanded: function(groupIndex) {
  49663. var groups = this._dataSource.group();
  49664. return isGroupExpanded(groups, groupIndex)
  49665. },
  49666. _updatePagingOptions: function(options) {
  49667. var that = this,
  49668. isVirtualPaging = that._isVirtualPaging(),
  49669. pageSize = that.pageSize(),
  49670. skips = [],
  49671. takes = [],
  49672. skipChildrenTotalCount = 0,
  49673. childrenTotalCount = 0;
  49674. if (options.take) {
  49675. foreachExpandedGroups(this, function(groupInfo) {
  49676. groupInfo.childrenTotalCount = 0;
  49677. groupInfo.skipChildrenTotalCount = 0
  49678. });
  49679. foreachExpandedGroups(that, function(groupInfo, parents) {
  49680. var skip,
  49681. take,
  49682. takeCorrection = 0,
  49683. parentTakeCorrection = 0,
  49684. totalOffset = getTotalOffset(parents, isVirtualPaging ? 0 : pageSize, childrenTotalCount),
  49685. continuationGroupCount = 0,
  49686. skipContinuationGroupCount = 0,
  49687. groupInfoCount = groupInfo.count + groupInfo.childrenTotalCount,
  49688. childrenGroupInfoCount = groupInfoCount;
  49689. skip = options.skip - totalOffset;
  49690. if (totalOffset <= options.skip + options.take && groupInfoCount) {
  49691. take = options.take;
  49692. if (!isVirtualPaging) {
  49693. continuationGroupCount = getContinuationGroupCount(totalOffset, pageSize, groupInfoCount, parents.length - 1);
  49694. groupInfoCount += continuationGroupCount * parents.length;
  49695. childrenGroupInfoCount += continuationGroupCount;
  49696. if (pageSize && skip >= 0) {
  49697. takeCorrection = parents.length;
  49698. parentTakeCorrection = parents.length - 1;
  49699. skipContinuationGroupCount = Math.floor(skip / pageSize)
  49700. }
  49701. }
  49702. if (skip >= 0) {
  49703. if (totalOffset + groupInfoCount > options.skip)
  49704. skips.unshift(skip - skipContinuationGroupCount * takeCorrection - groupInfo.skipChildrenTotalCount);
  49705. if (totalOffset + groupInfoCount >= options.skip + take)
  49706. takes.unshift(take - takeCorrection - groupInfo.childrenTotalCount + groupInfo.skipChildrenTotalCount)
  49707. }
  49708. else if (totalOffset + groupInfoCount >= options.skip + take)
  49709. takes.unshift(take + skip - groupInfo.childrenTotalCount)
  49710. }
  49711. if (totalOffset <= options.skip)
  49712. if (parents[parents.length - 2])
  49713. parents[parents.length - 2].skipChildrenTotalCount += Math.min(childrenGroupInfoCount, skip + 1 - skipContinuationGroupCount * parentTakeCorrection);
  49714. else
  49715. skipChildrenTotalCount += Math.min(childrenGroupInfoCount, skip + 1);
  49716. if (totalOffset <= options.skip + take) {
  49717. groupInfoCount = Math.min(childrenGroupInfoCount, skip + take - (skipContinuationGroupCount + 1) * parentTakeCorrection);
  49718. if (parents[parents.length - 2])
  49719. parents[parents.length - 2].childrenTotalCount += groupInfoCount;
  49720. else
  49721. childrenTotalCount += groupInfoCount
  49722. }
  49723. });
  49724. options.skip -= skipChildrenTotalCount;
  49725. options.take -= childrenTotalCount - skipChildrenTotalCount
  49726. }
  49727. options.skips = skips;
  49728. options.takes = takes
  49729. },
  49730. _changeRowExpandCore: function(path) {
  49731. var that = this,
  49732. groupInfo = that.findGroupInfo(path);
  49733. if (groupInfo) {
  49734. groupInfo.isExpanded = !groupInfo.isExpanded;
  49735. return $.Deferred().resolve()
  49736. }
  49737. return $.Deferred().reject()
  49738. },
  49739. _handleDataLoadedCore: function(options) {
  49740. var that = this,
  49741. callBase = that.callBase,
  49742. groupCount = normalizeSortingInfo(options.loadOptions.group).length,
  49743. totalCount,
  49744. skips,
  49745. takes,
  49746. i,
  49747. item,
  49748. items;
  49749. if (options.loadOptions.isLoadingAll) {
  49750. callBase.call(that, options);
  49751. return
  49752. }
  49753. totalCount = updateGroupInfos(that, options.data, groupCount, 0);
  49754. if (groupCount && options.extra)
  49755. options.extra.totalCount = totalCount;
  49756. that.updateTotalItemsCount(options);
  49757. that._updatePagingOptions(options);
  49758. callBase.call(that, options);
  49759. skips = options.skips;
  49760. takes = options.takes;
  49761. items = options.data;
  49762. for (i = 0; items && i < groupCount; i++) {
  49763. item = items[0];
  49764. items = item && item.items;
  49765. if (items && skips[i] !== undefined) {
  49766. item.isContinuation = true;
  49767. items = items.slice(skips[i]);
  49768. item.items = items
  49769. }
  49770. }
  49771. items = options.data;
  49772. for (i = 0; items && i < groupCount; i++) {
  49773. item = items[items.length - 1];
  49774. items = item && item.items;
  49775. if (items && takes[i] !== undefined && items.length > takes[i]) {
  49776. item.isContinuationOnNextPage = true;
  49777. items = items.slice(0, takes[i]);
  49778. item.items = items
  49779. }
  49780. }
  49781. processGroupItems(that, options.data, [], groupCount);
  49782. that.updateItemsCount(options.data, groupCount)
  49783. },
  49784. refresh: function(storeLoadOptions) {
  49785. var that = this,
  49786. oldGroups = normalizeSortingInfo(that._group),
  49787. isExpanded,
  49788. groupIndex;
  49789. function handleGroup(groupInfo, parents) {
  49790. if (parents.length === groupIndex + 1)
  49791. groupInfo.isExpanded = isExpanded
  49792. }
  49793. for (groupIndex = 0; groupIndex < oldGroups.length; groupIndex++) {
  49794. isExpanded = isGroupExpanded(storeLoadOptions.group, groupIndex);
  49795. if (isGroupExpanded(that._group, groupIndex) !== isExpanded)
  49796. that.foreachGroups(handleGroup)
  49797. }
  49798. that.callBase.apply(this, arguments);
  49799. that.foreachGroups(function(groupInfo) {
  49800. groupInfo.count = 0
  49801. })
  49802. }
  49803. }
  49804. }())
  49805. })(jQuery, DevExpress);
  49806. /*! Module widgets-web, file ui.dataGrid.virtualScrollingModule.js */
  49807. (function($, DX) {
  49808. var ui = DX.ui,
  49809. dataGrid = ui.dxDataGrid;
  49810. var DATAGRID_TABLE_CLASS = "dx-datagrid-table",
  49811. DATAGRID_ROW_CLASS = "dx-row",
  49812. DATAGRID_FREESPACE_CLASS = "dx-freespace-row",
  49813. DATAGRID_COLUMN_LINES_CLASS = "dx-column-lines",
  49814. DATAGRID_BOTTOM_LOAD_PANEL_CLASS = "dx-datagrid-bottom-load-panel",
  49815. DATAGRID_TABLE_CONTENT_CLASS = "dx-datagrid-table-content",
  49816. DATAGRID_GROUP_SPACE_CLASS = "dx-datagrid-group-space",
  49817. DATAGRID_SCROLLABLE_CONTAINER = "dx-scrollable-container",
  49818. DATAGRID_SCROLLABLE_CONTENT = "dx-scrollable-content",
  49819. DATAGRID_CONTENT_CLASS = "dx-datagrid-content",
  49820. SCROLLING_MODE_INFINITE = 'infinite',
  49821. SCROLLING_MODE_VIRTUAL = 'virtual',
  49822. PIXELS_LIMIT = 250000;
  49823. var VirtualScrollingDataSourceAdapterExtender = function() {
  49824. var getPreloadPageCount = function(that) {
  49825. return that.option('scrolling.preloadEnabled') ? 2 : 1
  49826. };
  49827. var isVirtualMode = function(that) {
  49828. return !that._isLoadingAll && that.option('scrolling.mode') === SCROLLING_MODE_VIRTUAL
  49829. };
  49830. var isAppendMode = function(that) {
  49831. return !that._isLoadingAll && that.option('scrolling.mode') === SCROLLING_MODE_INFINITE
  49832. };
  49833. var getBasePageIndex = function(that) {
  49834. return that._cache[0] ? that._cache[0].pageIndex : -1
  49835. };
  49836. var updateLoading = function(that) {
  49837. var basePageIndex = getBasePageIndex(that);
  49838. if (isVirtualMode(that))
  49839. if (basePageIndex < 0 || that._viewportItemIndex >= 0 && (basePageIndex * that.pageSize() > that._viewportItemIndex || basePageIndex * that.pageSize() + that.itemsCount() < that._viewportItemIndex + that._viewportSize) && that._dataSource.isLoading()) {
  49840. if (!that._isLoading) {
  49841. that._isLoading = true;
  49842. that.loadingChanged.fire(true)
  49843. }
  49844. }
  49845. else if (that._isLoading) {
  49846. that._isLoading = false;
  49847. that.loadingChanged.fire(false)
  49848. }
  49849. };
  49850. var processDelayChanged = function(that, changed) {
  49851. if (that._isDelayChanged) {
  49852. that._isDelayChanged = false;
  49853. changed.call(that)
  49854. }
  49855. };
  49856. var processChanged = function(that, changed, changeType, isDelayChanged) {
  49857. var dataSource = that._dataSource,
  49858. items = dataSource.items();
  49859. if (changeType === 'append')
  49860. that._items.push.apply(that._items, items);
  49861. else if (changeType === 'prepend')
  49862. that._items.unshift.apply(that._items, items);
  49863. else
  49864. that._items = items;
  49865. updateLoading(that);
  49866. that._lastPageIndex = that.pageIndex();
  49867. that._isDelayChanged = isDelayChanged;
  49868. that._isLoadingAll = false;
  49869. if (!isDelayChanged)
  49870. changed.call(that, changeType && {
  49871. changeType: changeType,
  49872. items: items
  49873. })
  49874. };
  49875. return {
  49876. init: function(dataSource) {
  49877. var that = this;
  49878. that.callBase.apply(that, arguments);
  49879. that._isLoading = true;
  49880. that._pageIndex = dataSource.pageIndex();
  49881. that._lastPageIndex = that._pageIndex;
  49882. that._viewportSize = 0;
  49883. that._viewportItemIndex = -1;
  49884. that._userPageSize = that.option("paging.pageSize");
  49885. that._items = [];
  49886. that._isLoaded = true;
  49887. that._cache = [];
  49888. if (dataSource.isLoaded())
  49889. that._handleDataChanged()
  49890. },
  49891. _handleLoadingChanged: function(isLoading) {
  49892. var that = this;
  49893. if (!isVirtualMode(that)) {
  49894. that._isLoading = isLoading;
  49895. that.callBase.apply(that, arguments)
  49896. }
  49897. },
  49898. _handleLoadError: function() {
  49899. var that = this;
  49900. that._isLoadingAll = false;
  49901. that._isLoading = false;
  49902. that.loadingChanged.fire(false);
  49903. that.callBase.apply(that, arguments)
  49904. },
  49905. _handleDataChanged: function() {
  49906. var that = this,
  49907. basePageIndex,
  49908. callBase = that.callBase,
  49909. dataSource = that._dataSource,
  49910. lastCacheLength = that._cache.length,
  49911. changeType,
  49912. cacheItem;
  49913. if (isVirtualMode(that)) {
  49914. basePageIndex = getBasePageIndex(that);
  49915. if (basePageIndex >= 0)
  49916. if (basePageIndex + that._cache.length === dataSource.pageIndex());
  49917. else if (basePageIndex - 1 === dataSource.pageIndex());
  49918. else
  49919. that._cache = [];
  49920. cacheItem = {
  49921. pageIndex: dataSource.pageIndex(),
  49922. itemsCount: that.itemsCount(true)
  49923. };
  49924. processDelayChanged(that, callBase);
  49925. if (basePageIndex === dataSource.pageIndex() + 1) {
  49926. changeType = 'prepend';
  49927. that._cache.unshift(cacheItem)
  49928. }
  49929. else {
  49930. changeType = 'append';
  49931. that._cache.push(cacheItem)
  49932. }
  49933. processChanged(that, callBase, that._cache.length > 1 ? changeType : undefined, lastCacheLength === 0);
  49934. that.load().done(function() {
  49935. processDelayChanged(that, callBase)
  49936. })
  49937. }
  49938. else
  49939. processChanged(that, callBase, isAppendMode(that) && dataSource.pageIndex() !== 0 ? 'append' : undefined)
  49940. },
  49941. items: function() {
  49942. return this._items
  49943. },
  49944. itemsCount: function(isBase) {
  49945. var itemsCount = 0;
  49946. if (!isBase && isVirtualMode(this))
  49947. $.each(this._cache, function() {
  49948. itemsCount += this.itemsCount
  49949. });
  49950. else
  49951. itemsCount = this.callBase();
  49952. return itemsCount
  49953. },
  49954. virtualItemsCount: function() {
  49955. var that = this,
  49956. pageIndex,
  49957. itemsCount = 0,
  49958. beginItemsCount,
  49959. endItemsCount;
  49960. if (isVirtualMode(that)) {
  49961. pageIndex = getBasePageIndex(that);
  49962. if (pageIndex < 0)
  49963. pageIndex = 0;
  49964. beginItemsCount = pageIndex * that.pageSize();
  49965. itemsCount = that._cache.length * that.pageSize();
  49966. endItemsCount = Math.max(0, that.totalItemsCount() - itemsCount - beginItemsCount);
  49967. return {
  49968. begin: beginItemsCount,
  49969. end: endItemsCount
  49970. }
  49971. }
  49972. },
  49973. setViewportItemIndex: function(itemIndex) {
  49974. var that = this,
  49975. pageSize = that.pageSize(),
  49976. pageCount = that.pageCount(),
  49977. virtualMode = isVirtualMode(that),
  49978. appendMode = isAppendMode(that),
  49979. totalItemsCount = that.totalItemsCount(),
  49980. lastPageSize,
  49981. needLoad = that._viewportItemIndex < 0,
  49982. maxPageIndex,
  49983. newPageIndex;
  49984. that._viewportItemIndex = itemIndex;
  49985. if (pageSize && (virtualMode || appendMode) && totalItemsCount >= 0) {
  49986. if (that._viewportSize && itemIndex + that._viewportSize >= totalItemsCount)
  49987. if (that.hasKnownLastPage()) {
  49988. newPageIndex = pageCount - 1;
  49989. lastPageSize = totalItemsCount % pageSize;
  49990. if (newPageIndex > 0 && lastPageSize > 0 && lastPageSize < pageSize / 2)
  49991. newPageIndex--
  49992. }
  49993. else
  49994. newPageIndex = pageCount;
  49995. else {
  49996. newPageIndex = Math.floor(itemIndex / pageSize);
  49997. maxPageIndex = pageCount - 1;
  49998. newPageIndex = Math.max(newPageIndex, 0);
  49999. newPageIndex = Math.min(newPageIndex, maxPageIndex)
  50000. }
  50001. if (that.pageIndex() !== newPageIndex || needLoad) {
  50002. that.pageIndex(newPageIndex);
  50003. that.load()
  50004. }
  50005. }
  50006. },
  50007. setViewportSize: function(size) {
  50008. var that = this,
  50009. pageSize;
  50010. if (that._viewportSize !== size) {
  50011. that._viewportSize = size;
  50012. if ((isVirtualMode(that) || isAppendMode(that)) && !that._userPageSize) {
  50013. pageSize = Math.ceil(size / 5) * 10;
  50014. if (pageSize !== that.pageSize()) {
  50015. that.pageSize(pageSize);
  50016. that.reload()
  50017. }
  50018. }
  50019. }
  50020. },
  50021. getViewportSize: function() {
  50022. return this._viewportSize
  50023. },
  50024. pageIndex: function(pageIndex) {
  50025. if (isVirtualMode(this) || isAppendMode(this)) {
  50026. if (pageIndex !== undefined)
  50027. this._pageIndex = pageIndex;
  50028. return this._pageIndex
  50029. }
  50030. else
  50031. return this._dataSource.pageIndex(pageIndex)
  50032. },
  50033. basePageIndex: function() {
  50034. var basePageIndex = getBasePageIndex(this);
  50035. return basePageIndex > 0 ? basePageIndex : 0
  50036. },
  50037. load: function(isLoadingAll) {
  50038. var basePageIndex = getBasePageIndex(this),
  50039. pageIndexForLoad = -1,
  50040. dataSource = this._dataSource,
  50041. result;
  50042. var loadCore = function(that, pageIndex) {
  50043. var dataSource = that._dataSource;
  50044. if (pageIndex === that.pageIndex() || !dataSource.isLoading() && pageIndex < that.pageCount() || !that.hasKnownLastPage() && pageIndex === that.pageCount()) {
  50045. dataSource.pageIndex(pageIndex);
  50046. return dataSource.load()
  50047. }
  50048. };
  50049. this._isLoadingAll = isLoadingAll;
  50050. if (isVirtualMode(this)) {
  50051. if (basePageIndex < 0 || !this._cache[this._pageIndex - basePageIndex])
  50052. pageIndexForLoad = this._pageIndex;
  50053. if (basePageIndex >= 0 && pageIndexForLoad < 0 && this._viewportItemIndex >= 0 && basePageIndex + this._cache.length <= this._pageIndex + getPreloadPageCount(this))
  50054. pageIndexForLoad = basePageIndex + this._cache.length;
  50055. if (pageIndexForLoad >= 0)
  50056. result = loadCore(this, pageIndexForLoad);
  50057. updateLoading(this)
  50058. }
  50059. else if (isAppendMode(this)) {
  50060. if (!dataSource.isLoaded() || this.pageIndex() === this.pageCount()) {
  50061. dataSource.pageIndex(this.pageIndex());
  50062. result = dataSource.load()
  50063. }
  50064. }
  50065. else
  50066. result = dataSource.load();
  50067. if (!result && this._lastPageIndex !== this.pageIndex())
  50068. this.changed.fire({changeType: 'pageIndex'});
  50069. return result || $.Deferred().resolve()
  50070. },
  50071. isLoading: function() {
  50072. return this._isLoading
  50073. },
  50074. isLoaded: function() {
  50075. return this._dataSource.isLoaded() && this._isLoaded
  50076. },
  50077. changeRowExpand: function() {
  50078. this._cache = [];
  50079. updateLoading(this);
  50080. return this.callBase.apply(this, arguments)
  50081. },
  50082. refresh: function(storeLoadOptions, isReload) {
  50083. var that = this,
  50084. dataSource = that._dataSource;
  50085. if (isReload) {
  50086. that._cache = [];
  50087. that._isLoaded = false;
  50088. updateLoading(that);
  50089. that._isLoaded = true;
  50090. if (isAppendMode(that)) {
  50091. that.pageIndex(0);
  50092. dataSource.pageIndex(0);
  50093. storeLoadOptions.pageIndex = 0;
  50094. storeLoadOptions.skip = 0
  50095. }
  50096. else {
  50097. dataSource.pageIndex(that.pageIndex());
  50098. if (dataSource.paginate())
  50099. storeLoadOptions.skip = that.pageIndex() * that.pageSize()
  50100. }
  50101. }
  50102. return that.callBase.apply(that, arguments)
  50103. }
  50104. }
  50105. }();
  50106. dataGrid.DataSourceAdapterServer = dataGrid.DataSourceAdapterServer.inherit(VirtualScrollingDataSourceAdapterExtender);
  50107. dataGrid.DataSourceAdapterClient = dataGrid.DataSourceAdapterClient.inherit(VirtualScrollingDataSourceAdapterExtender);
  50108. var VirtualScrollingRowsViewExtender = function() {
  50109. return {
  50110. _renderCore: function() {
  50111. var that = this;
  50112. that.callBase.apply(that, arguments);
  50113. that._updateContentPosition()
  50114. },
  50115. _renderContent: function(contentElement, tableElement) {
  50116. var that = this,
  50117. virtualItemsCount = that._dataController.virtualItemsCount();
  50118. if (virtualItemsCount) {
  50119. tableElement.addClass(DATAGRID_TABLE_CONTENT_CLASS);
  50120. if (!contentElement.children().length)
  50121. contentElement.append(tableElement);
  50122. else
  50123. contentElement.children().first().replaceWith(tableElement);
  50124. if (contentElement.children('table').length === 1) {
  50125. contentElement.append(that._createTable());
  50126. that._contentHeight = 0
  50127. }
  50128. return contentElement
  50129. }
  50130. else
  50131. return that.callBase.apply(that, arguments)
  50132. },
  50133. _updateContent: function(contentElement, change, tableElement) {
  50134. var that = this,
  50135. contentTable,
  50136. changeType = change && change.changeType;
  50137. if (changeType === 'append' || changeType === 'prepend') {
  50138. contentTable = contentElement.children().first();
  50139. tableElement.children('tbody').children('tr')[changeType === 'append' ? 'appendTo' : 'prependTo'](contentTable)
  50140. }
  50141. else
  50142. that.callBase.apply(that, arguments);
  50143. that._updateBottomLoading()
  50144. },
  50145. _updateContentPosition: function() {
  50146. var that = this,
  50147. contentElement,
  50148. contentHeight,
  50149. $tables,
  50150. $contentTable,
  50151. virtualTable,
  50152. rowHeight = that._rowHeight || 20,
  50153. virtualItemsCount = that._dataController.virtualItemsCount(),
  50154. isRenderVirtualTableContentRequired;
  50155. if (virtualItemsCount) {
  50156. contentElement = that._findContentElement();
  50157. $tables = contentElement.children();
  50158. $contentTable = $tables.first();
  50159. virtualTable = $tables.eq(1);
  50160. DX.translator.move($contentTable, {top: Math.floor(virtualItemsCount.begin * rowHeight)});
  50161. contentHeight = (virtualItemsCount.begin + virtualItemsCount.end) * rowHeight + $contentTable.outerHeight();
  50162. isRenderVirtualTableContentRequired = that._contentHeight !== contentHeight || contentHeight === 0 || !that._isTableLinesDisplaysCorrect(virtualTable) || !that._isColumnElementsEqual($contentTable.find("col"), virtualTable.find("col"));
  50163. if (isRenderVirtualTableContentRequired) {
  50164. that._contentHeight = contentHeight;
  50165. that._renderVirtualTableContent(virtualTable, contentHeight)
  50166. }
  50167. return true
  50168. }
  50169. return false
  50170. },
  50171. _isTableLinesDisplaysCorrect: function(table) {
  50172. var hasColumnLines = table.find("." + DATAGRID_COLUMN_LINES_CLASS).length > 0;
  50173. return hasColumnLines === this.option('showColumnLines')
  50174. },
  50175. _isColumnElementsEqual: function($columns, $virtualColumns) {
  50176. var result = $columns.length === $virtualColumns.length;
  50177. if (result)
  50178. $.each($columns, function(index, element) {
  50179. if (element.style.width !== $virtualColumns[index].style.width) {
  50180. result = false;
  50181. return result
  50182. }
  50183. });
  50184. return result
  50185. },
  50186. _renderVirtualTableContent: function(container, height) {
  50187. var that = this,
  50188. columns = that._columnsController.getVisibleColumns(),
  50189. html = that._createColGroup(columns).prop('outerHTML'),
  50190. freeSpaceCellsHtml = '',
  50191. i,
  50192. columnLinesClass = that.option('showColumnLines') ? DATAGRID_COLUMN_LINES_CLASS : '',
  50193. createFreeSpaceRowHtml = function(height) {
  50194. return '<tr style="height:' + height + 'px;" class="' + DATAGRID_FREESPACE_CLASS + ' ' + DATAGRID_ROW_CLASS + ' ' + columnLinesClass + '" >' + freeSpaceCellsHtml + '</tr>'
  50195. };
  50196. for (i = 0; i < columns.length; i++)
  50197. freeSpaceCellsHtml += columns[i].command === "expand" ? '<td class="' + DATAGRID_GROUP_SPACE_CLASS + '"/>' : '<td />';
  50198. while (height > PIXELS_LIMIT) {
  50199. html += createFreeSpaceRowHtml(PIXELS_LIMIT);
  50200. height -= PIXELS_LIMIT
  50201. }
  50202. html += createFreeSpaceRowHtml(height);
  50203. container.addClass(DATAGRID_TABLE_CLASS);
  50204. container.html(html)
  50205. },
  50206. _findBottomLoadPanel: function() {
  50207. var $bottomLoadPanel = this.element().find('.' + DATAGRID_BOTTOM_LOAD_PANEL_CLASS);
  50208. if ($bottomLoadPanel.length)
  50209. return $bottomLoadPanel
  50210. },
  50211. _updateBottomLoading: function() {
  50212. var that = this,
  50213. scrollingMode = that.option("scrolling.mode"),
  50214. virtualMode = scrollingMode === SCROLLING_MODE_VIRTUAL,
  50215. appendMode = scrollingMode === SCROLLING_MODE_INFINITE,
  50216. showBottomLoading = !that._dataController.hasKnownLastPage() && that._dataController.isLoaded() && (virtualMode || appendMode),
  50217. bottomLoadPanelElement = that._findBottomLoadPanel();
  50218. if (showBottomLoading) {
  50219. if (!bottomLoadPanelElement)
  50220. $('<div />').addClass(DATAGRID_BOTTOM_LOAD_PANEL_CLASS).append($('<div />').dxLoadIndicator()).appendTo(that._findContentElement())
  50221. }
  50222. else if (bottomLoadPanelElement)
  50223. bottomLoadPanelElement.remove()
  50224. },
  50225. _handleScroll: function(e) {
  50226. var that = this;
  50227. if (that._hasHeight && that._rowHeight)
  50228. that._dataController.setViewportItemIndex(e.scrollOffset.top / that._rowHeight);
  50229. that.callBase.apply(that, arguments)
  50230. },
  50231. _renderScrollableCore: function($element) {
  50232. var that = this;
  50233. that.callBase.apply(that, arguments);
  50234. that._subscribeToWindowScrollEvents($element)
  50235. },
  50236. _subscribeToWindowScrollEvents: function($element) {
  50237. var that = this,
  50238. $componentContainer = that.component.element(),
  50239. $scrollElement;
  50240. if (!$componentContainer)
  50241. return;
  50242. if (!that._windowScrollEvents) {
  50243. that._windowScrollEvents = true;
  50244. var createWindowScrollHandler = function($scrollElement, oldHandler) {
  50245. var handler = function(e) {
  50246. var scrollTop = $scrollElement.scrollTop();
  50247. if (!that._hasHeight && that._rowHeight) {
  50248. scrollTop -= $element.offset().top;
  50249. scrollTop = scrollTop > 0 ? scrollTop : 0;
  50250. that._scrollTop = scrollTop;
  50251. that._dataController.setViewportItemIndex(scrollTop / that._rowHeight)
  50252. }
  50253. };
  50254. if (oldHandler)
  50255. return function(e) {
  50256. handler(e);
  50257. oldHandler(e)
  50258. };
  50259. return handler
  50260. };
  50261. var subscribeToScrollEvents = function($scrollElement) {
  50262. var dxScrollable = $scrollElement.data("dxScrollable"),
  50263. scrollHandler,
  50264. oldScrollHandler;
  50265. if (dxScrollable) {
  50266. oldScrollHandler = dxScrollable.option('onScroll');
  50267. scrollHandler = createWindowScrollHandler($scrollElement, oldScrollHandler);
  50268. dxScrollable.option('onScroll', scrollHandler);
  50269. that.on("disposing", function() {
  50270. if (dxScrollable.option('onScroll') === scrollHandler)
  50271. dxScrollable.option('onScroll', oldScrollHandler)
  50272. })
  50273. }
  50274. else if ($scrollElement.is(document) || $scrollElement.css("overflow-y") === "auto") {
  50275. if ($scrollElement.is(document))
  50276. $scrollElement = $(window);
  50277. scrollHandler = createWindowScrollHandler($scrollElement);
  50278. $scrollElement.on('scroll', scrollHandler);
  50279. that.on("disposing", function() {
  50280. $scrollElement.off('scroll', scrollHandler)
  50281. })
  50282. }
  50283. };
  50284. for ($scrollElement = that.component.element().parent(); $scrollElement.length; $scrollElement = $scrollElement.parent())
  50285. subscribeToScrollEvents($scrollElement)
  50286. }
  50287. },
  50288. _needUpdateRowHeight: function(itemsCount) {
  50289. var that = this;
  50290. return that.callBase.apply(that, arguments) || itemsCount > 0 && that.option('scrolling.mode') === SCROLLING_MODE_INFINITE
  50291. },
  50292. _updateRowHeight: function() {
  50293. var that = this,
  50294. lastRowHeight = that._rowHeight,
  50295. viewportHeight;
  50296. that.callBase.apply(that, arguments);
  50297. if (!lastRowHeight && that._rowHeight) {
  50298. that._updateContentPosition();
  50299. viewportHeight = that._hasHeight ? that.element().outerHeight() : $(window).outerHeight();
  50300. that._dataController.setViewportSize(Math.round(viewportHeight / that._rowHeight))
  50301. }
  50302. },
  50303. setLoading: function(isLoading, messageText) {
  50304. var that = this,
  50305. callBase = that.callBase,
  50306. hasBottomLoadPanel = !!that._findBottomLoadPanel() && that._dataController.isLoaded();
  50307. if (hasBottomLoadPanel)
  50308. isLoading = false;
  50309. callBase.call(that, isLoading, messageText)
  50310. },
  50311. _getTableElements: function(isVirtualTable) {
  50312. var result = this.callBase();
  50313. if (isVirtualTable && this.option("scrolling.mode") === "virtual")
  50314. result = result.add(this.element().find("> ." + DATAGRID_SCROLLABLE_CONTAINER + " > ." + DATAGRID_SCROLLABLE_CONTENT + "> ." + DATAGRID_CONTENT_CLASS).children(":not(." + DATAGRID_TABLE_CONTENT_CLASS + ")"));
  50315. return result
  50316. }
  50317. }
  50318. }();
  50319. $.extend(dataGrid.__internals, {
  50320. DATAGRID_BOTTOM_LOAD_PANEL_CLASS: DATAGRID_BOTTOM_LOAD_PANEL_CLASS,
  50321. DATAGRID_TABLE_CONTENT_CLASS: DATAGRID_TABLE_CONTENT_CLASS
  50322. });
  50323. dataGrid.registerModule('virtualScrolling', {
  50324. defaultOptions: function() {
  50325. return {scrolling: {
  50326. mode: 'standard',
  50327. preloadEnabled: false,
  50328. useNativeScrolling: 'auto'
  50329. }}
  50330. },
  50331. extenders: {
  50332. controllers: {data: function() {
  50333. var members = {};
  50334. dataGrid.proxyMethod(members, "virtualItemsCount");
  50335. dataGrid.proxyMethod(members, "setViewportSize");
  50336. dataGrid.proxyMethod(members, "setViewportItemIndex");
  50337. return members
  50338. }()},
  50339. views: {rowsView: VirtualScrollingRowsViewExtender}
  50340. }
  50341. })
  50342. })(jQuery, DevExpress);
  50343. /*! Module widgets-web, file ui.dataGrid.columnHeadersView.js */
  50344. (function($, DX) {
  50345. var ui = DX.ui,
  50346. utils = DX.utils,
  50347. dataGrid = ui.dxDataGrid;
  50348. var DATAGRID_CELL_CONTENT_CLASS = "dx-datagrid-text-content",
  50349. DATAGRID_HEADERS_CLASS = "dx-datagrid-headers",
  50350. DATAGRID_HEADER_ROW_CLASS = "dx-header-row",
  50351. DATAGRID_NOWRAP_CLASS = "dx-datagrid-nowrap",
  50352. DATAGRID_COLUMN_LINES_CLASS = "dx-column-lines",
  50353. DATAGRID_CONTEXT_MENU_SORT_ASC_ICON = "context-menu-sort-asc",
  50354. DATAGRID_CONTEXT_MENU_SORT_DESC_ICON = "context-menu-sort-desc",
  50355. DATAGRID_CONTEXT_MENU_SORT_NONE_ICON = "context-menu-sort-none",
  50356. DATAGRID_CELL_FOCUS_DISABLED_CLASS = "dx-cell-focus-disabled";
  50357. var createCellContent = function($cell, column, showColumnLines) {
  50358. var $content = $('<div />').addClass(DATAGRID_CELL_CONTENT_CLASS);
  50359. if (showColumnLines)
  50360. $content.appendTo($cell);
  50361. else
  50362. $content.css("float", column.alignment || 'left').prependTo($cell);
  50363. return $content
  50364. };
  50365. dataGrid.ColumnHeadersView = dataGrid.ColumnsView.inherit({
  50366. _getDefaultTemplate: function(column) {
  50367. var that = this,
  50368. template,
  50369. showColumnLines = that.option("showColumnLines");
  50370. if (column.command)
  50371. template = function($container, options) {
  50372. var column = options.column;
  50373. $container.html('&nbsp;');
  50374. $container.addClass(column.cssClass)
  50375. };
  50376. else
  50377. template = function($container, options) {
  50378. var $content = createCellContent($container, options.column, showColumnLines);
  50379. $content.text(column.caption)
  50380. };
  50381. return template
  50382. },
  50383. _getHeaderTemplate: function(column) {
  50384. return column.headerCellTemplate || this._getDefaultTemplate(column)
  50385. },
  50386. _processTemplate: function(template, options) {
  50387. var that = this,
  50388. resultTemplate,
  50389. column = options.column,
  50390. renderingTemplate = this.callBase(template);
  50391. if (renderingTemplate && column.headerCellTemplate)
  50392. resultTemplate = {render: function(options, $container) {
  50393. var $content = createCellContent($container, options.column, that.option("showColumnLines"));
  50394. renderingTemplate.render(options, $content)
  50395. }};
  50396. else
  50397. resultTemplate = renderingTemplate;
  50398. return resultTemplate
  50399. },
  50400. _handleDataChanged: function(e) {
  50401. if (this._isGroupingChanged) {
  50402. this._isGroupingChanged = false;
  50403. this.render()
  50404. }
  50405. },
  50406. _renderCell: function($row, options) {
  50407. var $cell = this.callBase($row, options);
  50408. if (options.row.rowType === "header") {
  50409. $cell.addClass(DATAGRID_CELL_FOCUS_DISABLED_CLASS);
  50410. if (!utils.isDefined(options.column.command))
  50411. this.setAria({
  50412. role: "columnheader",
  50413. label: options.column.caption + " " + Globalize.localize("dxDataGrid-ariaColumn")
  50414. }, $cell)
  50415. }
  50416. return $cell
  50417. },
  50418. _createRow: function(row) {
  50419. var $row = this.callBase(row).toggleClass(DATAGRID_COLUMN_LINES_CLASS, this.option('showColumnLines'));
  50420. if (row.rowType === "header")
  50421. $row.addClass(DATAGRID_HEADER_ROW_CLASS);
  50422. return $row
  50423. },
  50424. _renderCore: function() {
  50425. var that = this,
  50426. $container = that.element(),
  50427. scrollLeft = that._scrollLeft;
  50428. $container.addClass(DATAGRID_HEADERS_CLASS).toggleClass(DATAGRID_NOWRAP_CLASS, !!that.option("columnAutoWidth") || !that.option("wordWrapEnabled")).empty();
  50429. that._setTableElement(that._renderTable());
  50430. that._scrollLeft = 0;
  50431. that.scrollOffset(scrollLeft)
  50432. },
  50433. _renderTable: function() {
  50434. var $table = this.callBase.apply(this, arguments),
  50435. $content = this.element();
  50436. this.wrapTableInScrollContainer($table).appendTo($content);
  50437. return $table
  50438. },
  50439. _getRows: function() {
  50440. var result = [];
  50441. if (this.option('showColumnHeaders'))
  50442. result.push({rowType: "header"});
  50443. return result
  50444. },
  50445. _getCellTemplate: function(options) {
  50446. if (options.rowType === "header")
  50447. return this._getHeaderTemplate(options.column)
  50448. },
  50449. _afterRender: function($root) {
  50450. this.processSizeChanged()
  50451. },
  50452. _columnOptionChanged: function(e) {
  50453. var changeTypes = e.changeTypes,
  50454. optionNames = e.optionNames;
  50455. if (changeTypes.grouping) {
  50456. this._isGroupingChanged = true;
  50457. return
  50458. }
  50459. this.callBase(e);
  50460. if (optionNames.width || optionNames.visibleWidth)
  50461. this.resizeCompleted.fire()
  50462. },
  50463. _isElementVisible: function(elementOptions) {
  50464. return elementOptions && elementOptions.visible
  50465. },
  50466. getHeadersRowHeight: function() {
  50467. var tableElement = this._getTableElement();
  50468. if (tableElement) {
  50469. var $headerRow = tableElement.find('.' + DATAGRID_HEADER_ROW_CLASS).first();
  50470. return $headerRow && $headerRow.height()
  50471. }
  50472. return 0
  50473. },
  50474. setColumnWidths: function(widths) {
  50475. var that = this,
  50476. scrollLeft = that._scrollLeft;
  50477. that.callBase(widths);
  50478. that._scrollLeft = 0;
  50479. that.scrollOffset(scrollLeft)
  50480. },
  50481. processSizeChanged: function() {
  50482. var that = this,
  50483. $element = that.element();
  50484. if (!utils.isDefined(that._headersHeight) || that._headersHeight !== $element.height()) {
  50485. that._headersHeight = $element.height();
  50486. that.sizeChanged.fire()
  50487. }
  50488. },
  50489. getHeaderElement: function(index) {
  50490. var columnElements = this.getColumnElements();
  50491. return columnElements && columnElements.eq(index)
  50492. },
  50493. getColumnElements: function() {
  50494. if (this.option("showColumnHeaders"))
  50495. return this.getCellElements(0)
  50496. },
  50497. allowDragging: function(column, draggingPanels) {
  50498. var i,
  50499. columns = this.getColumns(),
  50500. draggableColumnCount = 0,
  50501. draggingPanel,
  50502. allowDrag = function(column) {
  50503. return column.allowReordering || column.allowGrouping || column.allowHiding
  50504. };
  50505. for (i = 0; i < columns.length; i++)
  50506. if (allowDrag(columns[i]))
  50507. draggableColumnCount++;
  50508. if (draggableColumnCount <= 1)
  50509. return false;
  50510. else if (!draggingPanels)
  50511. return (this.option("allowColumnReordering") || this._columnsController.isColumnOptionUsed("allowReordering")) && column && column.allowReordering;
  50512. for (i = 0; i < draggingPanels.length; i++) {
  50513. draggingPanel = draggingPanels[i];
  50514. if (draggingPanel && draggingPanel.allowDragging(column))
  50515. return true
  50516. }
  50517. return false
  50518. },
  50519. getBoundingRect: function() {
  50520. var that = this,
  50521. offset,
  50522. $columnElements = that.getColumnElements();
  50523. if ($columnElements && $columnElements.length) {
  50524. offset = that._getTableElement().offset();
  50525. return {top: offset.top}
  50526. }
  50527. return null
  50528. },
  50529. getName: function() {
  50530. return 'headers'
  50531. },
  50532. getColumnCount: function() {
  50533. var $columnElements = this.getColumnElements();
  50534. return $columnElements ? $columnElements.length : 0
  50535. },
  50536. init: function() {
  50537. var that = this;
  50538. that.callBase();
  50539. that._scrollerWidth = 0;
  50540. that.sizeChanged = $.Callbacks()
  50541. },
  50542. isVisible: function() {
  50543. return this.option('showColumnHeaders')
  50544. },
  50545. setScrollerSpacing: function(width) {
  50546. var that = this,
  50547. $element = that.element(),
  50548. rtlEnabled = that.option("rtlEnabled");
  50549. that._scrollerWidth = width;
  50550. $element && $element.css(rtlEnabled ? {paddingLeft: width} : {paddingRight: width})
  50551. },
  50552. optionChanged: function(args) {
  50553. var that = this;
  50554. switch (args.name) {
  50555. case'showColumnHeaders':
  50556. case'wordWrapEnabled':
  50557. case'showColumnLines':
  50558. that.render();
  50559. args.handled = true;
  50560. break;
  50561. default:
  50562. that.callBase(args)
  50563. }
  50564. },
  50565. getHeight: function() {
  50566. var that = this,
  50567. $element = that.element();
  50568. return $element ? $element.height() : 0
  50569. },
  50570. getContextMenuItems: function($targetElement) {
  50571. var that = this,
  50572. $cell,
  50573. column,
  50574. onItemClick,
  50575. sortingOptions;
  50576. if ($targetElement.closest("." + DATAGRID_HEADER_ROW_CLASS).length) {
  50577. $cell = $targetElement.closest("td");
  50578. column = $cell.length && that.getColumns($targetElement)[$cell[0].cellIndex];
  50579. sortingOptions = that.option("sorting");
  50580. if (sortingOptions && sortingOptions.mode !== "none" && column && column.allowSorting) {
  50581. onItemClick = function(params) {
  50582. setTimeout(function() {
  50583. that._columnsController.changeSortOrder(column.index, params.itemData.value)
  50584. })
  50585. };
  50586. return [{
  50587. text: sortingOptions.ascendingText,
  50588. value: "asc",
  50589. disabled: column.sortOrder === "asc",
  50590. icon: DATAGRID_CONTEXT_MENU_SORT_ASC_ICON,
  50591. onItemClick: onItemClick
  50592. }, {
  50593. text: sortingOptions.descendingText,
  50594. value: "desc",
  50595. disabled: column.sortOrder === "desc",
  50596. icon: DATAGRID_CONTEXT_MENU_SORT_DESC_ICON,
  50597. onItemClick: onItemClick
  50598. }, {
  50599. text: sortingOptions.clearText,
  50600. value: "none",
  50601. disabled: !column.sortOrder,
  50602. icon: DATAGRID_CONTEXT_MENU_SORT_NONE_ICON,
  50603. onItemClick: onItemClick
  50604. }]
  50605. }
  50606. return []
  50607. }
  50608. }
  50609. });
  50610. $.extend(dataGrid.__internals, {
  50611. DATAGRID_CELL_CONTENT_CLASS: DATAGRID_CELL_CONTENT_CLASS,
  50612. DATAGRID_HEADERS_CLASS: DATAGRID_HEADERS_CLASS,
  50613. DATAGRID_HEADER_ROW_CLASS: DATAGRID_HEADER_ROW_CLASS,
  50614. DATAGRID_NOWRAP_CLASS: DATAGRID_NOWRAP_CLASS
  50615. });
  50616. dataGrid.registerModule('columnHeaders', {
  50617. defaultOptions: function() {
  50618. return {
  50619. showColumnHeaders: true,
  50620. cellHintEnabled: true
  50621. }
  50622. },
  50623. views: {columnHeadersView: dataGrid.ColumnHeadersView}
  50624. })
  50625. })(jQuery, DevExpress);
  50626. /*! Module widgets-web, file ui.dataGrid.filterRow.js */
  50627. (function($, DX) {
  50628. var ui = DX.ui,
  50629. utils = DX.utils,
  50630. dataGrid = ui.dxDataGrid;
  50631. var OPERATION_ICONS = {
  50632. '=': 'filter-operation-equals',
  50633. '<>': 'filter-operation-not-equals',
  50634. '<': 'filter-operation-less',
  50635. '<=': 'filter-operation-less-equal',
  50636. '>': 'filter-operation-greater',
  50637. '>=': 'filter-operation-greater-equal',
  50638. 'default': 'filter-operation-default',
  50639. notcontains: 'filter-operation-not-contains',
  50640. contains: 'filter-operation-contains',
  50641. startswith: 'filter-operation-starts-with',
  50642. endswith: 'filter-operation-ends-with'
  50643. };
  50644. var FILTERING_TIMEOUT = 700,
  50645. DATAGRID_CLASS = "dx-datagrid",
  50646. DATAGRID_FILTER_ROW_CLASS = "dx-datagrid-filter-row",
  50647. DATAGRID_MENU_CLASS = "dx-menu",
  50648. DATAGRID_MENU_IMAGE_CLASS = 'dx-menu-image',
  50649. DATAGRID_CELL_CONTENT_CLASS = "dx-datagrid-text-content",
  50650. DATAGRID_EDITOR_WITH_MENU_CLASS = "dx-editor-with-menu",
  50651. DATAGRID_EDITOR_CONTAINER_CLASS = "dx-editor-container",
  50652. DATAGRID_EDITOR_CELL_CLASS = "dx-editor-cell",
  50653. DATAGRID_FILTER_MENU = "dx-filter-menu",
  50654. DATAGRID_APPLY_BUTTON_CLASS = "dx-apply-button",
  50655. DATAGRID_HIGHLIGHT_OUTLINE_CLASS = "dx-highlight-outline",
  50656. DATAGRID_FOCUSED_CLASS = "dx-focused",
  50657. DATAGRID_CELL_FOCUS_DISABLED_CLASS = "dx-cell-focus-disabled",
  50658. TEXTEDITOR_CLASS = "dx-texteditor";
  50659. var ColumnHeadersViewFilterRowExtender = {
  50660. _columnOptionChanged: function(e) {
  50661. var that = this,
  50662. optionNames = e.optionNames,
  50663. visibleIndex,
  50664. column,
  50665. $cell,
  50666. $editor,
  50667. componentNames,
  50668. editor,
  50669. $menu;
  50670. if (dataGrid.checkChanges(optionNames, ['filterValue', 'selectedFilterOperation']) && e.columnIndex !== undefined) {
  50671. visibleIndex = that.getController('columns').getVisibleIndex(e.columnIndex);
  50672. column = that.getController('columns').columnOption(e.columnIndex);
  50673. $cell = that.element().find('.' + DATAGRID_FILTER_ROW_CLASS).children().eq(visibleIndex);
  50674. $editor = $cell.find("." + TEXTEDITOR_CLASS);
  50675. if (optionNames.filterValue)
  50676. if ($editor.length) {
  50677. componentNames = $editor.data("dxComponents");
  50678. editor = componentNames.length && $editor.data(componentNames[0]);
  50679. if (editor instanceof ui.Editor)
  50680. editor && editor.option("value", column.filterValue)
  50681. }
  50682. if (optionNames.selectedFilterOperation)
  50683. if (visibleIndex >= 0 && column) {
  50684. $menu = $cell.find('.' + DATAGRID_MENU_CLASS);
  50685. if ($menu.length)
  50686. that._updateFilterOperationChooser($menu, column, $editor.parent())
  50687. }
  50688. return
  50689. }
  50690. that.callBase(e)
  50691. },
  50692. isFilterRowVisible: function() {
  50693. return this._isElementVisible(this.option('filterRow'))
  50694. },
  50695. isVisible: function() {
  50696. return this.callBase() || this.isFilterRowVisible()
  50697. },
  50698. init: function() {
  50699. this.callBase();
  50700. this._applyFilterViewController = this.getController("applyFilter")
  50701. },
  50702. _createRow: function(row) {
  50703. var $row = this.callBase(row);
  50704. if (row.rowType === "filter")
  50705. $row.addClass(DATAGRID_FILTER_ROW_CLASS);
  50706. return $row
  50707. },
  50708. _getRows: function() {
  50709. var result = this.callBase();
  50710. if (this.isFilterRowVisible())
  50711. result.push({rowType: "filter"});
  50712. return result
  50713. },
  50714. _renderCellContent: function($cell, options) {
  50715. var that = this,
  50716. column = options.column,
  50717. columnsController = that._columnsController,
  50718. $container,
  50719. $editorContainer,
  50720. $editor;
  50721. var updateFilterValue = function(that, column, value) {
  50722. if (value === '')
  50723. value = undefined;
  50724. if (!utils.isDefined(column.filterValue) && !utils.isDefined(value))
  50725. return;
  50726. that._applyFilterViewController.setHighLight($editorContainer, column.filterValue !== value);
  50727. column.filterValue = value;
  50728. columnsController.columnOption(column.index, 'filterValue', value)
  50729. };
  50730. if (options.rowType === "filter")
  50731. if (column.command)
  50732. $cell.html('&nbsp;');
  50733. else if (column.allowFiltering) {
  50734. that.setAria("label", Globalize.localize("dxDataGrid-ariaColumn") + " " + column.caption + ", " + Globalize.localize("dxDataGrid-ariaFilterCell"), $cell);
  50735. $cell.addClass(DATAGRID_EDITOR_CELL_CLASS);
  50736. $container = $('<div />').appendTo($cell),
  50737. $editorContainer = $('<div />').addClass(DATAGRID_EDITOR_CONTAINER_CLASS).appendTo($container),
  50738. $editor = $('<div />').appendTo($editorContainer);
  50739. that.getController('editorFactory').createEditor($editor, $.extend({}, column, {
  50740. value: columnsController.isDataSourceApplied() ? column.filterValue : undefined,
  50741. setValue: function(value) {
  50742. updateFilterValue(that, column, value)
  50743. },
  50744. parentType: "filterRow",
  50745. showAllText: that.option('filterRow.showAllText'),
  50746. updateValueTimeout: that.option("filterRow.applyFilter") === "onClick" ? 0 : FILTERING_TIMEOUT,
  50747. width: null
  50748. }));
  50749. if (column.alignment)
  50750. $cell.find('input').first().css('text-align', column.alignment);
  50751. if (column.filterOperations && column.filterOperations.length)
  50752. that._renderFilterOperationChooser($container, column, $editorContainer)
  50753. }
  50754. that.callBase($cell, options)
  50755. },
  50756. _updateFilterOperationChooser: function($menu, column, $editorContainer) {
  50757. var that = this,
  50758. isCellWasFocused;
  50759. $menu.dxMenu({
  50760. activeStateEnabled: false,
  50761. selectionMode: "single",
  50762. cssClass: DATAGRID_CLASS + " " + DATAGRID_CELL_FOCUS_DISABLED_CLASS + " " + DATAGRID_FILTER_MENU,
  50763. showFirstSubmenuMode: 'onHover',
  50764. hideSubmenuOnMouseLeave: true,
  50765. items: [{
  50766. disabled: column.filterOperations && column.filterOperations.length ? false : true,
  50767. icon: OPERATION_ICONS[column.selectedFilterOperation || "default"],
  50768. selectable: false,
  50769. items: that._getFilterOperationMenuItems(column)
  50770. }],
  50771. onItemClick: function(properties) {
  50772. var selectedFilterOperation = properties.itemData.name;
  50773. if (properties.itemData.items)
  50774. return;
  50775. if (selectedFilterOperation)
  50776. that._columnsController.columnOption(column.index, 'selectedFilterOperation', selectedFilterOperation);
  50777. else
  50778. that._columnsController.columnOption(column.index, {
  50779. selectedFilterOperation: column.defaultSelectedFilterOperation,
  50780. filterValue: undefined
  50781. });
  50782. that._applyFilterViewController.setHighLight($editorContainer, true);
  50783. that._focusEditor($editorContainer)
  50784. },
  50785. onSubmenuShown: function() {
  50786. isCellWasFocused = that._isEditorFocused($editorContainer);
  50787. that.getController('editorFactory').loseFocus()
  50788. },
  50789. onSubmenuHiding: function(e) {
  50790. $menu.blur();
  50791. $menu.dxMenu("instance").option("focusedElement", null);
  50792. isCellWasFocused && that._focusEditor($editorContainer)
  50793. },
  50794. rtlEnabled: that.option('rtlEnabled')
  50795. })
  50796. },
  50797. _isEditorFocused: function($container) {
  50798. return $container.hasClass(DATAGRID_FOCUSED_CLASS) || $container.parents("." + DATAGRID_FOCUSED_CLASS).length
  50799. },
  50800. _focusEditor: function($container, showCellFocus) {
  50801. this.getController('editorFactory').focus($container);
  50802. $container.find("input").focus()
  50803. },
  50804. _renderFilterOperationChooser: function($container, column, $editorContainer) {
  50805. var that = this,
  50806. $menu;
  50807. if (that.option("filterRow.showOperationChooser")) {
  50808. $container.addClass(DATAGRID_EDITOR_WITH_MENU_CLASS);
  50809. $menu = $('<div />').prependTo($container);
  50810. that._updateFilterOperationChooser($menu, column, $editorContainer)
  50811. }
  50812. },
  50813. _getFilterOperationMenuItems: function(column) {
  50814. var that = this,
  50815. result = [{}],
  50816. filterRowOptions = that.option("filterRow"),
  50817. operationDescriptions = filterRowOptions && filterRowOptions.operationDescriptions || {};
  50818. if (column.filterOperations && column.filterOperations.length) {
  50819. result = $.map(column.filterOperations, function(value) {
  50820. return {
  50821. name: value,
  50822. selected: (column.selectedFilterOperation || column.defaultFilterOperation) === value,
  50823. text: operationDescriptions[value],
  50824. icon: OPERATION_ICONS[value]
  50825. }
  50826. });
  50827. result.push({
  50828. name: null,
  50829. text: filterRowOptions && filterRowOptions.resetOperationText,
  50830. icon: OPERATION_ICONS['default']
  50831. })
  50832. }
  50833. return result
  50834. },
  50835. optionChanged: function(args) {
  50836. var that = this;
  50837. switch (args.name) {
  50838. case'filterRow':
  50839. case'showColumnLines':
  50840. case'disabled':
  50841. that.render();
  50842. args.handled = true;
  50843. break;
  50844. default:
  50845. that.callBase(args);
  50846. break
  50847. }
  50848. }
  50849. };
  50850. var DataControllerFilterRowExtender = {_calculateAdditionalFilter: function() {
  50851. var that = this,
  50852. filters = [that.callBase()],
  50853. columns = that._columnsController.getVisibleColumns();
  50854. $.each(columns, function() {
  50855. var filter;
  50856. if (this.allowFiltering && this.calculateFilterExpression && utils.isDefined(this.filterValue)) {
  50857. filter = this.calculateFilterExpression(this.filterValue, this.selectedFilterOperation || this.defaultFilterOperation);
  50858. filters.push(filter)
  50859. }
  50860. });
  50861. return dataGrid.combineFilters(filters)
  50862. }};
  50863. var ColumnsControllerFilterRowExtender = {_createCalculatedColumnOptions: function(columnOptions) {
  50864. var calculatedColumnOptions = this.callBase(columnOptions);
  50865. if (columnOptions.dataField)
  50866. $.extend(calculatedColumnOptions, {
  50867. calculateFilterExpression: function(value, selectedFilterOperation, filterInterval) {
  50868. var column = this,
  50869. dataField = column.dataField,
  50870. filter = null;
  50871. if (column.dataType === 'string' && !column.lookup)
  50872. filter = [dataField, selectedFilterOperation || 'contains', value];
  50873. else if (column.dataType === 'date' && utils.isDate(value)) {
  50874. var dateStart,
  50875. dateEnd;
  50876. switch (filterInterval) {
  50877. case"year":
  50878. dateStart = new Date(value.getFullYear(), 0, 1),
  50879. dateEnd = new Date(value.getFullYear() + 1, 0, 1);
  50880. break;
  50881. case"month":
  50882. dateStart = new Date(value.getFullYear(), value.getMonth(), 1),
  50883. dateEnd = new Date(value.getFullYear(), value.getMonth() + 1, 1);
  50884. break;
  50885. default:
  50886. dateStart = new Date(value.getFullYear(), value.getMonth(), value.getDate()),
  50887. dateEnd = new Date(value.getFullYear(), value.getMonth(), value.getDate() + 1)
  50888. }
  50889. switch (selectedFilterOperation) {
  50890. case'<':
  50891. return [dataField, '<', dateStart];
  50892. case'<=':
  50893. return [dataField, '<', dateEnd];
  50894. case'>':
  50895. return [dataField, '>=', dateEnd];
  50896. case'>=':
  50897. return [dataField, '>=', dateStart];
  50898. case'<>':
  50899. return [[dataField, '<', dateStart], 'or', [dataField, '>=', dateEnd]];
  50900. default:
  50901. return [[dataField, '>=', dateStart], 'and', [dataField, '<', dateEnd]]
  50902. }
  50903. }
  50904. else
  50905. filter = [dataField, selectedFilterOperation || '=', value];
  50906. return filter
  50907. },
  50908. allowFiltering: true
  50909. });
  50910. else
  50911. $.extend(calculatedColumnOptions, {allowFiltering: !!columnOptions.calculateFilterExpression});
  50912. return calculatedColumnOptions
  50913. }};
  50914. dataGrid.ApplyFilterViewController = dataGrid.ViewController.inherit({
  50915. _isOnClick: function() {
  50916. return this.option("filterRow.applyFilter") === "onClick"
  50917. },
  50918. _getHeaderPanel: function() {
  50919. if (!this._headerPanel)
  50920. this._headerPanel = this.getView("headerPanel");
  50921. return this._headerPanel
  50922. },
  50923. setHighLight: function($element, value) {
  50924. if (this._isOnClick()) {
  50925. $element && $element.toggleClass(DATAGRID_HIGHLIGHT_OUTLINE_CLASS, value);
  50926. this._getHeaderPanel().enableApplyButton(value)
  50927. }
  50928. },
  50929. removeHighLights: function() {
  50930. if (this._isOnClick()) {
  50931. var columnHeadersView = this.getView("columnHeadersView");
  50932. columnHeadersView.element().find("." + DATAGRID_FILTER_ROW_CLASS + " ." + DATAGRID_HIGHLIGHT_OUTLINE_CLASS).removeClass(DATAGRID_HIGHLIGHT_OUTLINE_CLASS);
  50933. this._getHeaderPanel().enableApplyButton(false)
  50934. }
  50935. }
  50936. });
  50937. dataGrid.registerModule('filterRow', {
  50938. defaultOptions: function() {
  50939. return {filterRow: {
  50940. visible: false,
  50941. showOperationChooser: true,
  50942. showAllText: Globalize.localize("dxDataGrid-filterRowShowAllText"),
  50943. resetOperationText: Globalize.localize("dxDataGrid-filterRowResetOperationText"),
  50944. applyFilter: "auto",
  50945. applyFilterText: Globalize.localize("dxDataGrid-applyFilterText"),
  50946. operationDescriptions: {
  50947. '=': Globalize.localize("dxDataGrid-filterRowOperationEquals"),
  50948. '<>': Globalize.localize("dxDataGrid-filterRowOperationNotEquals"),
  50949. '<': Globalize.localize("dxDataGrid-filterRowOperationLess"),
  50950. '<=': Globalize.localize("dxDataGrid-filterRowOperationLessOrEquals"),
  50951. '>': Globalize.localize("dxDataGrid-filterRowOperationGreater"),
  50952. '>=': Globalize.localize("dxDataGrid-filterRowOperationGreaterOrEquals"),
  50953. startswith: Globalize.localize("dxDataGrid-filterRowOperationStartsWith"),
  50954. contains: Globalize.localize("dxDataGrid-filterRowOperationContains"),
  50955. notcontains: Globalize.localize("dxDataGrid-filterRowOperationNotContains"),
  50956. endswith: Globalize.localize("dxDataGrid-filterRowOperationEndsWith")
  50957. }
  50958. }}
  50959. },
  50960. controllers: {applyFilter: dataGrid.ApplyFilterViewController},
  50961. extenders: {
  50962. controllers: {
  50963. data: DataControllerFilterRowExtender,
  50964. columns: ColumnsControllerFilterRowExtender
  50965. },
  50966. views: {
  50967. columnHeadersView: ColumnHeadersViewFilterRowExtender,
  50968. headerPanel: {
  50969. _isShowApplyFilterButton: function() {
  50970. var filterRowOptions = this.option("filterRow");
  50971. return filterRowOptions && filterRowOptions.visible && filterRowOptions.applyFilter === "onClick"
  50972. },
  50973. _renderCore: function() {
  50974. var that = this,
  50975. disabled = that._applyButton ? that._applyButton.option("disabled") : true;
  50976. that.callBase();
  50977. that._$applyButton && that._$applyButton.remove();
  50978. if (this._isShowApplyFilterButton()) {
  50979. that._$applyButton = $("<div>").addClass(DATAGRID_APPLY_BUTTON_CLASS).dxButton({
  50980. disabled: disabled,
  50981. hint: that.option("filterRow.applyFilterText"),
  50982. icon: "apply-filter",
  50983. onClick: function() {
  50984. that._dataController._applyFilter();
  50985. that._applyFilterViewController.removeHighLights()
  50986. }
  50987. }).appendTo(that.element());
  50988. that._applyButton = that._$applyButton.dxButton("instance")
  50989. }
  50990. },
  50991. init: function() {
  50992. this.callBase();
  50993. this._dataController = this.getController("data");
  50994. this._applyFilterViewController = this.getController("applyFilter")
  50995. },
  50996. enableApplyButton: function(value) {
  50997. this._applyButton && this._applyButton.option("disabled", !value)
  50998. },
  50999. isVisible: function() {
  51000. return this.callBase() || this._isShowApplyFilterButton()
  51001. },
  51002. optionChanged: function(args) {
  51003. if (args.name === "filterRow") {
  51004. this.render();
  51005. args.handled = true
  51006. }
  51007. else
  51008. this.callBase(args)
  51009. }
  51010. }
  51011. }
  51012. }
  51013. });
  51014. $.extend(dataGrid.__internals, {
  51015. DATAGRID_FILTER_ROW_CLASS: DATAGRID_FILTER_ROW_CLASS,
  51016. DATAGRID_MENU_CLASS: DATAGRID_MENU_CLASS,
  51017. DATAGRID_MENU_IMAGE_CLASS: DATAGRID_MENU_IMAGE_CLASS,
  51018. DATAGRID_CELL_CONTENT_CLASS: DATAGRID_CELL_CONTENT_CLASS,
  51019. DATAGRID_EDITOR_WITH_MENU_CLASS: DATAGRID_EDITOR_WITH_MENU_CLASS,
  51020. DATAGRID_EDITOR_CONTAINER_CLASS: DATAGRID_EDITOR_CONTAINER_CLASS,
  51021. DATAGRID_HIGHLIGHT_OUTLINE_CLASS: DATAGRID_HIGHLIGHT_OUTLINE_CLASS,
  51022. DATAGRID_APPLY_BUTTON_CLASS: DATAGRID_APPLY_BUTTON_CLASS
  51023. });
  51024. dataGrid.ColumnHeadersViewFilterRowExtender = ColumnHeadersViewFilterRowExtender;
  51025. dataGrid.DataControllerFilterRowExtender = DataControllerFilterRowExtender
  51026. })(jQuery, DevExpress);
  51027. /*! Module widgets-web, file ui.dataGrid.headerPanel.js */
  51028. (function($, DX) {
  51029. var ui = DX.ui,
  51030. dataGrid = ui.dxDataGrid;
  51031. var DATAGRID_HEADER_PANEL_CLASS = "dx-datagrid-header-panel";
  51032. dataGrid.HeaderPanel = dataGrid.ColumnsView.inherit({
  51033. _renderCore: function() {
  51034. this.element().addClass(DATAGRID_HEADER_PANEL_CLASS)
  51035. },
  51036. getHeaderPanel: function() {
  51037. return this.element()
  51038. },
  51039. getHeight: function() {
  51040. var $element = this.element();
  51041. return $element ? $element.outerHeight(true) : 0
  51042. },
  51043. isVisible: function() {
  51044. return false
  51045. },
  51046. optionChanged: function(args) {
  51047. var that = this;
  51048. switch (args.name) {
  51049. case'disabled':
  51050. that.render();
  51051. args.handled = true;
  51052. break;
  51053. default:
  51054. that.callBase(args)
  51055. }
  51056. }
  51057. });
  51058. $.extend(dataGrid.__internals, {DATAGRID_HEADER_PANEL_CLASS: DATAGRID_HEADER_PANEL_CLASS});
  51059. dataGrid.registerModule('headerPanel', {
  51060. defaultOptions: function() {
  51061. return {}
  51062. },
  51063. views: {headerPanel: dataGrid.HeaderPanel}
  51064. })
  51065. })(jQuery, DevExpress);
  51066. /*! Module widgets-web, file ui.dataGrid.headerFilter.js */
  51067. (function($, DX) {
  51068. var ui = DX.ui,
  51069. dataGrid = ui.dxDataGrid,
  51070. utils = DX.utils;
  51071. var DATAGRID_HEADER_FILTER_CLASS = "dx-header-filter",
  51072. DATAGRID_HEADER_FILTER_MENU_CLASS = "dx-header-filter-menu",
  51073. DATAGRID_HEADER_FILTER_SPACE_CLASS = "dx-header-filter-space",
  51074. DATAGRID_CELL_CONTENT_CLASS = "dx-datagrid-text-content";
  51075. dataGrid.HeaderFilterController = dataGrid.ViewController.inherit({
  51076. init: function() {
  51077. this._columnsController = this.getController("columns");
  51078. this._dataController = this.getController("data");
  51079. this._headerFilterView = this.getView("headerFilterView")
  51080. },
  51081. getDataSource: function(column) {
  51082. var that = this,
  51083. cutoffLevel,
  51084. group,
  51085. headerFilterOptions = that.option("headerFilter"),
  51086. store = that._dataController.dataSource().store();
  51087. var processGroupItems = function(groupItems, level, currentLevel, path) {
  51088. var value,
  51089. formatOptions;
  51090. currentLevel = currentLevel || 0;
  51091. path = path || [];
  51092. for (var i = 0; i < groupItems.length; i++) {
  51093. value = groupItems[i].key;
  51094. if (column.lookup)
  51095. value = column.lookup.calculateCellValue(value);
  51096. if (column.dataType === "date")
  51097. formatOptions = currentLevel === 1 ? {format: {
  51098. format: 'month',
  51099. dateType: 'full'
  51100. }} : {};
  51101. else
  51102. formatOptions = column;
  51103. groupItems[i].text = dataGrid.formatValue(value, formatOptions);
  51104. path.push(groupItems[i].key);
  51105. if (path.length === 1)
  51106. groupItems[i].filterValue = path[0];
  51107. else
  51108. groupItems[i].filterValue = path.join("/");
  51109. if ($.inArray(groupItems[i].filterValue, column.filterValues) > -1 ^ column.filterType === "exclude")
  51110. groupItems[i].selected = true;
  51111. delete groupItems[i].key;
  51112. if ("items" in groupItems[i])
  51113. if (currentLevel === level || !groupItems[i].text) {
  51114. delete groupItems[i].items;
  51115. if (!groupItems[i].text)
  51116. groupItems[i].text = headerFilterOptions.texts.emptyValue
  51117. }
  51118. else
  51119. processGroupItems(groupItems[i].items, level, currentLevel + 1, path);
  51120. path.pop()
  51121. }
  51122. };
  51123. if (column.dataType === "date") {
  51124. group = [function(data) {
  51125. var value = column.calculateCellValue(data);
  51126. return value && value.getFullYear()
  51127. }, function(data) {
  51128. var value = column.calculateCellValue(data);
  51129. return value && value.getMonth() + 1
  51130. }, function(data) {
  51131. var value = column.calculateCellValue(data);
  51132. return value && value.getDate()
  51133. }];
  51134. cutoffLevel = 2
  51135. }
  51136. else {
  51137. group = $.proxy(column.calculateCellValue, column);
  51138. cutoffLevel = 0
  51139. }
  51140. return {
  51141. filter: that._dataController.getCombinedFilter(),
  51142. store: store,
  51143. postProcess: function(data) {
  51144. var result;
  51145. new DX.data.ArrayStore(data).load({
  51146. filter: this.filter(),
  51147. group: group
  51148. }).done(function(data) {
  51149. result = data
  51150. });
  51151. processGroupItems(result, cutoffLevel);
  51152. return result
  51153. }
  51154. }
  51155. },
  51156. getCurrentColumn: function() {
  51157. return this._currentColumn
  51158. },
  51159. showHeaderFilterMenu: function(columnIndex) {
  51160. var that = this,
  51161. column = that._columnsController.getColumns()[columnIndex];
  51162. if (column) {
  51163. var visibleIndex = that._columnsController.getVisibleIndex(columnIndex),
  51164. isGroupColumn = column && utils.isDefined(column.groupIndex),
  51165. view = isGroupColumn ? that.getView("headerPanel") : that.getView("columnHeadersView"),
  51166. $columnElement = view.getColumnElements().eq(isGroupColumn ? column.groupIndex : visibleIndex);
  51167. that._currentColumn = column;
  51168. var options = $.extend({}, column, {
  51169. type: column.dataType === "date" ? "tree" : "list",
  51170. apply: function() {
  51171. that._currentColumn = null;
  51172. that._columnsController.columnOption(columnIndex, {
  51173. filterValues: this.filterValues,
  51174. filterType: this.filterType
  51175. })
  51176. },
  51177. cancel: function() {
  51178. that._currentColumn = null
  51179. }
  51180. });
  51181. options.dataSource = that.getDataSource(options),
  51182. that._headerFilterView.showHeaderFilterMenu($columnElement, options)
  51183. }
  51184. },
  51185. hideHeaderFilterMenu: function() {
  51186. this._headerFilterView.hideHeaderFilterMenu()
  51187. }
  51188. });
  51189. dataGrid.HeaderFilterView = dataGrid.View.inherit({
  51190. getPopupContainer: function() {
  51191. return this._popupContainer
  51192. },
  51193. getListContainer: function() {
  51194. return this._listContainer
  51195. },
  51196. applyHeaderFilter: function(options) {
  51197. var that = this,
  51198. list = that.getListContainer(),
  51199. isSelectAll = list.element().find(".dx-checkbox").eq(0).hasClass("dx-checkbox-checked"),
  51200. filterValues = [];
  51201. var fillSelectedItemKeys = function(filterValues, items, isExclude) {
  51202. $.each(items, function() {
  51203. if (!!this.selected ^ isExclude)
  51204. filterValues.push(this.filterValue);
  51205. else if (this.items && this.items.length)
  51206. fillSelectedItemKeys(filterValues, this.items)
  51207. })
  51208. };
  51209. if (!isSelectAll) {
  51210. if (options.type === "tree") {
  51211. fillSelectedItemKeys(filterValues, list.option("items"), options.filterType === 'exclude');
  51212. options.filterValues = filterValues
  51213. }
  51214. options.apply()
  51215. }
  51216. else if (utils.isArray(options.filterValues)) {
  51217. options.filterValues = [];
  51218. options.apply()
  51219. }
  51220. that.hideHeaderFilterMenu()
  51221. },
  51222. showHeaderFilterMenu: function($columnElement, options) {
  51223. var that = this,
  51224. popupContainer;
  51225. if (options) {
  51226. that._initializePopupContainer(options);
  51227. popupContainer = that.getPopupContainer();
  51228. that.hideHeaderFilterMenu();
  51229. that.updatePopup($columnElement, options);
  51230. popupContainer.show()
  51231. }
  51232. },
  51233. hideHeaderFilterMenu: function() {
  51234. var headerFilterMenu = this.getPopupContainer();
  51235. headerFilterMenu && headerFilterMenu.hide()
  51236. },
  51237. updatePopup: function($element, options) {
  51238. var that = this,
  51239. alignment = options.alignment === "right" ? "left" : "right";
  51240. if (that._popupContainer) {
  51241. that._cleanPopupContent();
  51242. that._popupContainer.option("position", {
  51243. my: alignment + " top",
  51244. at: alignment + " bottom",
  51245. of: $element,
  51246. collision: "flip"
  51247. })
  51248. }
  51249. },
  51250. _cleanPopupContent: function() {
  51251. this._popupContainer && this._popupContainer.content().empty()
  51252. },
  51253. _initializePopupContainer: function(options) {
  51254. var that = this,
  51255. $element = that.element(),
  51256. headerFilterOptions = that.option("headerFilter"),
  51257. dxPopupOptions = {
  51258. width: headerFilterOptions && headerFilterOptions.width || 250,
  51259. height: headerFilterOptions && headerFilterOptions.height || 300,
  51260. visible: false,
  51261. shading: false,
  51262. showTitle: false,
  51263. showCloseButton: false,
  51264. closeOnTargetScroll: true,
  51265. closeOnOutsideClick: true,
  51266. onShown: function() {
  51267. that._initializeListContainer(options)
  51268. },
  51269. buttons: [{
  51270. toolbar: "bottom",
  51271. location: "after",
  51272. widget: "button",
  51273. options: {
  51274. text: headerFilterOptions.texts.ok,
  51275. onClick: function() {
  51276. that.applyHeaderFilter(options)
  51277. }
  51278. }
  51279. }, {
  51280. toolbar: "bottom",
  51281. location: "after",
  51282. widget: "button",
  51283. options: {
  51284. text: headerFilterOptions.texts.cancel,
  51285. onClick: function() {
  51286. that.hideHeaderFilterMenu();
  51287. options.cancel && options.cancel()
  51288. }
  51289. }
  51290. }],
  51291. rtlEnabled: that.option('rtlEnabled')
  51292. };
  51293. if (!utils.isDefined(that._popupContainer))
  51294. that._popupContainer = that._createComponent($element, "dxPopup", dxPopupOptions);
  51295. else
  51296. that._popupContainer.option(dxPopupOptions)
  51297. },
  51298. _initializeListContainer: function(options) {
  51299. var that = this,
  51300. $content = that._popupContainer.content(),
  51301. widgetOptions = {
  51302. dataSource: options.dataSource,
  51303. onContentReady: function() {
  51304. that.renderCompleted.fire()
  51305. }
  51306. };
  51307. if (options.type === "tree")
  51308. that._listContainer = that._createComponent($("<div/>").appendTo($content), "dxTreeView", $.extend(widgetOptions, {
  51309. showCheckBoxes: true,
  51310. selectAllEnabled: true,
  51311. keyExpr: "id"
  51312. }));
  51313. else
  51314. that._listContainer = that._createComponent($("<div/>").appendTo($content), "dxList", $.extend(widgetOptions, {
  51315. pageLoadMode: "scrollBottom",
  51316. pullRefreshEnabled: true,
  51317. showSelectionControls: true,
  51318. selectionMode: "all",
  51319. onSelectionChanged: function(e) {
  51320. var items = e.component.option("items"),
  51321. selectedItems = e.component.option("selectedItems");
  51322. if (!e.component._selectedItemsUpdating)
  51323. if (selectedItems.length === 0 && items.length) {
  51324. options.filterType = "include";
  51325. options.filterValues = []
  51326. }
  51327. else if (selectedItems.length === items.length) {
  51328. options.filterType = "exclude";
  51329. options.filterValues = []
  51330. }
  51331. $.each(items, function(index, item) {
  51332. var selected = $.inArray(item, selectedItems) >= 0,
  51333. oldSelected = !!item.selected,
  51334. filterValueIndex;
  51335. if (oldSelected !== selected) {
  51336. item.selected = selected;
  51337. options.filterValues = options.filterValues || [];
  51338. filterValueIndex = $.inArray(item.filterValue, options.filterValues);
  51339. if (filterValueIndex >= 0)
  51340. options.filterValues.splice(filterValueIndex, 1);
  51341. if (selected ^ options.filterType === "exclude")
  51342. options.filterValues.push(item.filterValue)
  51343. }
  51344. })
  51345. },
  51346. onContentReady: function(e) {
  51347. var component = e.component,
  51348. items = component.option("items"),
  51349. selectedItems = component.option("selectedItems"),
  51350. selectAllCheckBox = e.element.find(".dx-list-select-all-checkbox").dxCheckBox("instance");
  51351. $.each(items, function() {
  51352. if (this.selected)
  51353. selectedItems.push(this)
  51354. });
  51355. component._selectedItemsUpdating = true;
  51356. component.option("selectedItems", selectedItems);
  51357. component._selectedItemsUpdating = false;
  51358. if (options.filterValues && options.filterValues.length)
  51359. selectAllCheckBox.option("value", undefined)
  51360. }
  51361. }))
  51362. },
  51363. _renderCore: function(options) {
  51364. this.element().addClass(DATAGRID_HEADER_FILTER_MENU_CLASS)
  51365. },
  51366. init: function() {
  51367. this._headerFilterController = this.getController("headerFilter")
  51368. }
  51369. });
  51370. var headerFilterMixin = dataGrid.headerFilterMixin = {
  51371. _applyColumnState: function(options) {
  51372. var rootElement = options.rootElement,
  51373. column = options.column;
  51374. if (options.name === "headerFilter") {
  51375. rootElement.find('.' + DATAGRID_HEADER_FILTER_CLASS + ', ' + '.' + DATAGRID_HEADER_FILTER_SPACE_CLASS).remove();
  51376. var $headerFilterIndicator = this.callBase(options).css("float", this._getColumnAlignment(column.alignment) === "right" ? "left" : "right");
  51377. $headerFilterIndicator.toggleClass("dx-header-filter-empty", !column.filterValues || !column.filterValues.length);
  51378. return $headerFilterIndicator
  51379. }
  51380. return this.callBase(options)
  51381. },
  51382. optionChanged: function(args) {
  51383. if (args.name === "headerFilter") {
  51384. this.render();
  51385. args.handled = true
  51386. }
  51387. else
  51388. this.callBase(args)
  51389. }
  51390. };
  51391. var ColumnHeadersViewHeaderFilterExtender = $.extend({}, headerFilterMixin, {
  51392. _renderCellContent: function($cell, options) {
  51393. var that = this,
  51394. $headerFilterIndicator,
  51395. column = options.column;
  51396. if (!column.command && !utils.isDefined(column.groupIndex) && column.allowFiltering && that.option("headerFilter.visible") && options.rowType === "header") {
  51397. $headerFilterIndicator = that._applyColumnState({
  51398. name: 'headerFilter',
  51399. rootElement: $cell,
  51400. column: column,
  51401. showColumnLines: that.option('showColumnLines')
  51402. });
  51403. that._subscribeToIndicatorEvent($headerFilterIndicator, column, 'headerFilter')
  51404. }
  51405. that.callBase($cell, options)
  51406. },
  51407. _subscribeToIndicatorEvent: function($indicator, column, indicatorName) {
  51408. var that = this;
  51409. if (indicatorName === "headerFilter")
  51410. $indicator.on("dxclick", that.createAction(function(e) {
  51411. var event = e.jQueryEvent;
  51412. event.stopPropagation();
  51413. that.getController("headerFilter").showHeaderFilterMenu(column.index)
  51414. }))
  51415. },
  51416. _updateIndicator: function($cell, column, indicatorName) {
  51417. var $indicator = this.callBase($cell, column, indicatorName);
  51418. $indicator && this._subscribeToIndicatorEvent($indicator, column, indicatorName)
  51419. },
  51420. _resizeCore: function() {
  51421. this.callBase();
  51422. this._updateIndicatorHeights('headerFilter')
  51423. },
  51424. _columnOptionChanged: function(e) {
  51425. var optionNames = e.optionNames;
  51426. if (dataGrid.checkChanges(optionNames, ["filterValues", "filterType"])) {
  51427. this._updateIndicators("headerFilter");
  51428. return
  51429. }
  51430. this.callBase(e)
  51431. },
  51432. _afterRender: function() {
  51433. this.callBase.apply(this, arguments);
  51434. this._updateIndicatorHeights('headerFilter')
  51435. }
  51436. });
  51437. var HeaderPanelHeaderFilterExtender = $.extend({}, headerFilterMixin, {
  51438. _createGroupPanelItem: function($rootElement, groupColumn) {
  51439. var that = this,
  51440. $item = that.callBase.apply(that, arguments),
  51441. $headerFilterIndicator;
  51442. if (!groupColumn.command && groupColumn.allowFiltering && that.option("headerFilter.visible")) {
  51443. $headerFilterIndicator = that._applyColumnState({
  51444. name: 'headerFilter',
  51445. rootElement: $item,
  51446. column: {alignment: that.option("rtlEnabled") ? 'right' : 'left'},
  51447. showColumnLines: true
  51448. });
  51449. $headerFilterIndicator.on("dxclick", that.createAction(function(e) {
  51450. var event = e.jQueryEvent;
  51451. event.stopPropagation();
  51452. that.getController("headerFilter").showHeaderFilterMenu(groupColumn.index)
  51453. }))
  51454. }
  51455. return $item
  51456. },
  51457. _renderGroupPanelItems: function($groupPanel, groupColumns) {
  51458. this.callBase.apply(this, arguments);
  51459. this._updateIndicatorHeights('headerFilter')
  51460. },
  51461. _resizeCore: function() {
  51462. this.callBase();
  51463. this._updateIndicatorHeights('headerFilter')
  51464. }
  51465. });
  51466. var DataControllerFilterRowExtender = {_calculateAdditionalFilter: function() {
  51467. var that = this,
  51468. filters = [that.callBase()],
  51469. columns = that._columnsController.getVisibleColumns(),
  51470. headerFilterController = that.getController("headerFilter"),
  51471. currentColumn = headerFilterController.getCurrentColumn();
  51472. if (currentColumn && currentColumn.filterValues && currentColumn.filterValues.length)
  51473. return;
  51474. $.each(columns, function(_, column) {
  51475. var filter;
  51476. if (column.allowFiltering && column.calculateFilterExpression && utils.isArray(column.filterValues) && column.filterValues.length) {
  51477. var filterValues = [];
  51478. var isExclude = column.filterType === "exclude";
  51479. $.each(column.filterValues, function(_, filterValue) {
  51480. var value = filterValue,
  51481. values,
  51482. filterIntervals,
  51483. dateInterval;
  51484. if (column.dataType === "date" && utils.isDefined(value)) {
  51485. values = ("" + value).split("/");
  51486. filterIntervals = ["year", "month", "day"];
  51487. dateInterval = filterIntervals[values.length - 1];
  51488. value = new Date(values[0], (values[1] || 1) - 1, values[2] || 1)
  51489. }
  51490. else if (column.deserializeValue)
  51491. value = column.deserializeValue(value);
  51492. filter = column.calculateFilterExpression(value, isExclude ? "<>" : "=", dateInterval);
  51493. if (filterValues.length > 0)
  51494. filterValues.push(isExclude ? "and" : "or");
  51495. filterValues.push(filter)
  51496. });
  51497. filters.push(filterValues)
  51498. }
  51499. });
  51500. return dataGrid.combineFilters(filters)
  51501. }};
  51502. dataGrid.registerModule('headerFilter', {
  51503. defaultOptions: function() {
  51504. return {headerFilter: {
  51505. visible: false,
  51506. width: 252,
  51507. height: 300,
  51508. texts: {
  51509. emptyValue: Globalize.localize("dxDataGrid-headerFilterEmptyValue"),
  51510. ok: Globalize.localize("dxDataGrid-headerFilterOK"),
  51511. cancel: Globalize.localize("dxDataGrid-headerFilterCancel")
  51512. }
  51513. }}
  51514. },
  51515. controllers: {headerFilter: dataGrid.HeaderFilterController},
  51516. views: {headerFilterView: dataGrid.HeaderFilterView},
  51517. extenders: {
  51518. controllers: {data: DataControllerFilterRowExtender},
  51519. views: {
  51520. columnHeadersView: ColumnHeadersViewHeaderFilterExtender,
  51521. headerPanel: HeaderPanelHeaderFilterExtender
  51522. }
  51523. }
  51524. });
  51525. $.extend(dataGrid.__internals, {
  51526. DATAGRID_HEADER_FILTER_CLASS: DATAGRID_HEADER_FILTER_CLASS,
  51527. DATAGRID_HEADER_FILTER_MENU_CLASS: DATAGRID_HEADER_FILTER_MENU_CLASS,
  51528. DATAGRID_HEADER_FILTER_SPACE_CLASS: DATAGRID_HEADER_FILTER_SPACE_CLASS,
  51529. DATAGRID_CELL_CONTENT_CLASS: DATAGRID_CELL_CONTENT_CLASS
  51530. })
  51531. })(jQuery, DevExpress);
  51532. /*! Module widgets-web, file ui.dataGrid.sortingModule.js */
  51533. (function($, DX) {
  51534. var ui = DX.ui,
  51535. dataGrid = ui.dxDataGrid,
  51536. events = ui.events,
  51537. utils = DX.utils;
  51538. var DATAGRID_SORT_CLASS = "dx-sort",
  51539. DATAGRID_SORT_SPACE_CLASS = "dx-sort-space",
  51540. DATAGRID_SORTUP_CLASS = "dx-sort-up",
  51541. DATAGRID_SORTDOWN_CLASS = "dx-sort-down",
  51542. DATAGRID_HEADERS_ACTION_CLASS = "dx-datagrid-action",
  51543. DATAGRID_CELL_CONTENT_CLASS = "dx-datagrid-text-content",
  51544. DATAGRID_INDICATOR_ALIGNMENT_CLASS = "dx-indicator-alignment-",
  51545. DATAGRID_COLUMN_INDICATORS_CLASS = "dx-column-indicators",
  51546. COLUMN_HEADERS_VIEW_NAMESPACE = 'dxDataGridColumnHeadersView',
  51547. DATAGRID_BORDER_COLLAPSE_CORRECTION = 1;
  51548. var sortingMixin = dataGrid.sortingMixin = {
  51549. _applyColumnState: function(options) {
  51550. var that = this,
  51551. sortingMode = that.option('sorting.mode'),
  51552. rootElement = options.rootElement,
  51553. column = options.column,
  51554. $indicatorsContainer = rootElement.find("." + DATAGRID_COLUMN_INDICATORS_CLASS),
  51555. getSortIndicatorAlignment = function(columnAlignment) {
  51556. return columnAlignment === 'right' ? 'left' : 'right'
  51557. };
  51558. if (options.name === 'sort') {
  51559. if ((sortingMode === 'single' || sortingMode === 'multiple') && column.allowSorting)
  51560. options.rootElement.addClass(DATAGRID_HEADERS_ACTION_CLASS);
  51561. rootElement.find('.' + DATAGRID_SORT_CLASS + ', ' + '.' + DATAGRID_SORT_SPACE_CLASS).remove();
  51562. !$indicatorsContainer.children().length && $indicatorsContainer.remove();
  51563. if (utils.isDefined(column.sortOrder)) {
  51564. var columnAlignment = that._getColumnAlignment(column.alignment),
  51565. sortIndicatorAlignment = getSortIndicatorAlignment(columnAlignment),
  51566. ariaSortState = column.sortOrder === 'asc' ? 'ascending' : 'descending';
  51567. that.setAria("sort", ariaSortState, rootElement);
  51568. if (column.alignment === "center")
  51569. $('<span />').addClass(DATAGRID_SORT_SPACE_CLASS).toggleClass(DATAGRID_INDICATOR_ALIGNMENT_CLASS + sortIndicatorAlignment, !options.showColumnLines).css("float", columnAlignment).prependTo(rootElement);
  51570. var $sortIndicator = that.callBase(options).toggleClass(DATAGRID_SORTUP_CLASS, column.sortOrder === 'asc').toggleClass(DATAGRID_SORTDOWN_CLASS, column.sortOrder === 'desc');
  51571. return $sortIndicator
  51572. }
  51573. else
  51574. that.setAria("sort", "none", rootElement)
  51575. }
  51576. else
  51577. return that.callBase(options)
  51578. },
  51579. _updateIndicator: function($cell, column, indicatorName) {
  51580. if (indicatorName === "sort" && utils.isDefined(column.groupIndex))
  51581. return;
  51582. this.callBase.apply(this, arguments)
  51583. }
  51584. };
  51585. var ColumnHeadersViewSortingExtender = $.extend({}, sortingMixin, {
  51586. _updateIndicatorHeight: function($cell, indicatorName) {
  51587. this.callBase($cell, indicatorName);
  51588. !this.option('showColumnLines') && this._setColumnTextWidth($cell, $cell.outerWidth())
  51589. },
  51590. _setColumnTextWidth: function($column, columnWidth) {
  51591. var $sortElement = $column.find("." + DATAGRID_SORT_CLASS),
  51592. indicatorOuterWidth = $sortElement.outerWidth(),
  51593. columnPaddings = $column.outerWidth() - $column.width(),
  51594. columnContentIndent = indicatorOuterWidth + columnPaddings;
  51595. $column.find("." + DATAGRID_CELL_CONTENT_CLASS).css("max-width", columnWidth - columnContentIndent - DATAGRID_BORDER_COLLAPSE_CORRECTION)
  51596. },
  51597. _renderCellContent: function($cell, options) {
  51598. var that = this,
  51599. column = options.column;
  51600. if (!column.command && options.rowType === "header") {
  51601. $cell.on(events.addNamespace("dxclick", COLUMN_HEADERS_VIEW_NAMESPACE), that.createAction(function(e) {
  51602. var keyName = null,
  51603. event = e.jQueryEvent;
  51604. setTimeout(function() {
  51605. if (event.shiftKey)
  51606. keyName = "shift";
  51607. else if (event.ctrlKey)
  51608. keyName = "ctrl";
  51609. if (column && !utils.isDefined(column.groupIndex))
  51610. that._columnsController.changeSortOrder(column.index, keyName)
  51611. })
  51612. }));
  51613. that._applyColumnState({
  51614. name: 'sort',
  51615. rootElement: $cell,
  51616. column: column,
  51617. showColumnLines: that.option('showColumnLines')
  51618. })
  51619. }
  51620. that.callBase($cell, options)
  51621. },
  51622. _columnOptionChanged: function(e) {
  51623. var changeTypes = e.changeTypes,
  51624. optionNames = e.optionNames;
  51625. if (changeTypes.length === 1 && changeTypes.sorting) {
  51626. this._updateIndicators("sort");
  51627. return
  51628. }
  51629. this.callBase(e);
  51630. if (optionNames.width || optionNames.visibleWidth)
  51631. this._updateIndicatorHeights('sort')
  51632. },
  51633. _resizeCore: function() {
  51634. this.callBase();
  51635. this._updateIndicatorHeights('sort')
  51636. },
  51637. _afterRender: function() {
  51638. this.callBase.apply(this, arguments);
  51639. this._updateIndicatorHeights('sort')
  51640. },
  51641. optionChanged: function(args) {
  51642. var that = this;
  51643. switch (args.name) {
  51644. case'sorting':
  51645. that.render();
  51646. args.handled = true;
  51647. break;
  51648. default:
  51649. that.callBase(args)
  51650. }
  51651. }
  51652. });
  51653. var HeaderPanelSortingExtender = $.extend({}, sortingMixin, {
  51654. _createGroupPanelItem: function($rootElement, groupColumn) {
  51655. var that = this,
  51656. $item = that.callBase.apply(that, arguments);
  51657. $item.on(events.addNamespace("dxclick", "dxDataGridHeaderPanel"), that.createAction(function(e) {
  51658. setTimeout(function() {
  51659. that.getController('columns').changeSortOrder(groupColumn.index)
  51660. })
  51661. }));
  51662. that._applyColumnState({
  51663. name: 'sort',
  51664. rootElement: $item,
  51665. column: {
  51666. alignment: that.option("rtlEnabled") ? 'right' : 'left',
  51667. allowSorting: groupColumn.allowSorting,
  51668. sortOrder: groupColumn.sortOrder === 'desc' ? 'desc' : 'asc'
  51669. },
  51670. showColumnLines: true
  51671. });
  51672. return $item
  51673. },
  51674. _renderGroupPanelItems: function($groupPanel, groupColumns) {
  51675. this.callBase.apply(this, arguments);
  51676. this._updateIndicatorHeights('sort')
  51677. },
  51678. _resizeCore: function() {
  51679. this.callBase();
  51680. this._updateIndicatorHeights('sort')
  51681. },
  51682. optionChanged: function(args) {
  51683. var that = this;
  51684. switch (args.name) {
  51685. case'sorting':
  51686. that.render();
  51687. args.handled = true;
  51688. break;
  51689. default:
  51690. that.callBase(args)
  51691. }
  51692. }
  51693. });
  51694. dataGrid.registerModule('sorting', {
  51695. defaultOptions: function() {
  51696. return {sorting: {
  51697. mode: 'single',
  51698. ascendingText: Globalize.localize("dxDataGrid-sortingAscendingText"),
  51699. descendingText: Globalize.localize("dxDataGrid-sortingDescendingText"),
  51700. clearText: Globalize.localize("dxDataGrid-sortingClearText")
  51701. }}
  51702. },
  51703. extenders: {views: {
  51704. columnHeadersView: ColumnHeadersViewSortingExtender,
  51705. headerPanel: HeaderPanelSortingExtender
  51706. }}
  51707. });
  51708. $.extend(dataGrid.__internals, {
  51709. DATAGRID_SORT_CLASS: DATAGRID_SORT_CLASS,
  51710. DATAGRID_SORTUP_CLASS: DATAGRID_SORTUP_CLASS,
  51711. DATAGRID_SORTDOWN_CLASS: DATAGRID_SORTDOWN_CLASS,
  51712. DATAGRID_HEADERS_ACTION_CLASS: DATAGRID_HEADERS_ACTION_CLASS,
  51713. DATAGRID_BORDER_COLLAPSE_CORRECTION: DATAGRID_BORDER_COLLAPSE_CORRECTION
  51714. })
  51715. })(jQuery, DevExpress);
  51716. /*! Module widgets-web, file ui.dataGrid.search.js */
  51717. (function($, DX) {
  51718. var ui = DX.ui,
  51719. utils = DX.utils,
  51720. dataGrid = ui.dxDataGrid;
  51721. var DATAGRID_SEARCH_PANEL_CLASS = "dx-datagrid-search-panel",
  51722. DATAGRID_SEARCH_TEXT_CLASS = "dx-datagrid-search-text",
  51723. FILTERING_TIMEOUT = 700;
  51724. function allowSearch(column) {
  51725. return utils.isDefined(column.allowSearch) ? column.allowSearch : column.allowFiltering
  51726. }
  51727. dataGrid.registerModule('search', {
  51728. defaultOptions: function() {
  51729. return {searchPanel: {
  51730. visible: false,
  51731. width: 160,
  51732. placeholder: Globalize.localize("dxDataGrid-searchPanelPlaceholder"),
  51733. highlightSearchText: true,
  51734. text: ""
  51735. }}
  51736. },
  51737. extenders: {
  51738. controllers: {data: function() {
  51739. var calculateSearchFilter = function(that, text) {
  51740. var i,
  51741. column,
  51742. columns = that._columnsController.getColumns(),
  51743. filterValue,
  51744. lookup,
  51745. filters = [];
  51746. if (!text)
  51747. return null;
  51748. function onQueryDone(items) {
  51749. var i,
  51750. valueGetter = DX.data.utils.compileGetter(lookup.valueExpr),
  51751. value;
  51752. for (i = 0; i < items.length; i++) {
  51753. value = valueGetter(items[i]);
  51754. filters.push(column.calculateFilterExpression(value))
  51755. }
  51756. }
  51757. for (i = 0; i < columns.length; i++) {
  51758. column = columns[i];
  51759. if (allowSearch(column) && column.calculateFilterExpression) {
  51760. lookup = column.lookup;
  51761. if (lookup && lookup.items) {
  51762. filterValue = column.parseValue.call(lookup, text);
  51763. DX.data.query(lookup.items).filter(column.calculateFilterExpression.call({
  51764. dataField: lookup.displayExpr,
  51765. dataType: lookup.dataType
  51766. }, filterValue)).enumerate().done(onQueryDone)
  51767. }
  51768. else {
  51769. filterValue = column.parseValue ? column.parseValue(text) : text;
  51770. if (filterValue !== undefined)
  51771. filters.push(column.calculateFilterExpression(filterValue))
  51772. }
  51773. }
  51774. }
  51775. return dataGrid.combineFilters(filters, 'or')
  51776. };
  51777. return {
  51778. publicMethods: function() {
  51779. return this.callBase().concat(['searchByText'])
  51780. },
  51781. _calculateAdditionalFilter: function() {
  51782. var that = this,
  51783. filter = that.callBase(),
  51784. searchFilter = calculateSearchFilter(that, that.option("searchPanel.text"));
  51785. return dataGrid.combineFilters([filter, searchFilter])
  51786. },
  51787. searchByText: function(text) {
  51788. this.option("searchPanel.text", text)
  51789. },
  51790. optionChanged: function(args) {
  51791. var that = this;
  51792. switch (args.fullName) {
  51793. case"searchPanel.text":
  51794. case"searchPanel":
  51795. that._applyFilter();
  51796. args.handled = true;
  51797. break;
  51798. default:
  51799. that.callBase(args)
  51800. }
  51801. }
  51802. }
  51803. }()},
  51804. views: {
  51805. headerPanel: function() {
  51806. var getSearchPanelOptions = function(that) {
  51807. return that.option('searchPanel')
  51808. };
  51809. return {
  51810. _renderSearchPanel: function() {
  51811. var that = this,
  51812. $element = that.element(),
  51813. dataController = that.getController('data'),
  51814. searchPanelOptions = getSearchPanelOptions(that);
  51815. if (searchPanelOptions && searchPanelOptions.visible) {
  51816. if (!that._$searchPanel) {
  51817. that._$searchPanel = $('<div/>').addClass(DATAGRID_SEARCH_PANEL_CLASS).prependTo($element);
  51818. that.setAria("label", Globalize.localize("dxDataGrid-ariaSearchInGrid"), that._$searchPanel)
  51819. }
  51820. else
  51821. that._$searchPanel.show();
  51822. that.getController('editorFactory').createEditor(that._$searchPanel, {
  51823. width: searchPanelOptions.width,
  51824. placeholder: searchPanelOptions.placeholder,
  51825. parentType: "searchPanel",
  51826. value: that.option("searchPanel.text"),
  51827. updateValueTimeout: FILTERING_TIMEOUT,
  51828. setValue: function(value) {
  51829. dataController.searchByText(value)
  51830. }
  51831. });
  51832. that.resize()
  51833. }
  51834. else
  51835. that._$searchPanel && that._$searchPanel.hide()
  51836. },
  51837. _renderCore: function() {
  51838. this.callBase();
  51839. this._renderSearchPanel()
  51840. },
  51841. focus: function() {
  51842. var textBox = this._$searchPanel.dxTextBox("instance");
  51843. if (textBox)
  51844. textBox.focus()
  51845. },
  51846. isVisible: function() {
  51847. var searchPanelOptions = getSearchPanelOptions(this);
  51848. return this.callBase() || searchPanelOptions && searchPanelOptions.visible
  51849. },
  51850. optionChanged: function(args) {
  51851. if (args.name === "searchPanel") {
  51852. this._renderSearchPanel();
  51853. args.handled = true
  51854. }
  51855. else
  51856. this.callBase(args)
  51857. }
  51858. }
  51859. }(),
  51860. rowsView: {
  51861. _highlightSearchText: function(cellElement, isEquals) {
  51862. var that = this,
  51863. $parent,
  51864. searchHTML,
  51865. searchText = that.option("searchPanel.text");
  51866. if (searchText && that.option("searchPanel.highlightSearchText")) {
  51867. searchHTML = $('<div>').text(searchText).html();
  51868. $parent = cellElement.parent();
  51869. if (!$parent.length)
  51870. $parent = $('<div>').append(cellElement);
  51871. $.each($parent.find(":dxicontains('" + searchText + "')"), function(index, element) {
  51872. $.each($(element).contents(), function(index, content) {
  51873. if (content.nodeType !== 3)
  51874. return;
  51875. var highlightSearchTextInTextNode = function($content, searchText) {
  51876. var $searchTextSpan = $('<span />').addClass(DATAGRID_SEARCH_TEXT_CLASS),
  51877. text = $content.text(),
  51878. index = text.toLowerCase().indexOf(searchText.toLowerCase());
  51879. if (index >= 0) {
  51880. if ($content[0].textContent)
  51881. $content[0].textContent = text.substr(0, index);
  51882. else
  51883. $content[0].nodeValue = text.substr(0, index);
  51884. $content.after($searchTextSpan.text(text.substr(index, searchText.length)));
  51885. $content = $(document.createTextNode(text.substr(index + searchText.length))).insertAfter($searchTextSpan);
  51886. return highlightSearchTextInTextNode($content, searchText)
  51887. }
  51888. };
  51889. if (isEquals) {
  51890. if ($(content).text().toLowerCase() === searchText.toLowerCase())
  51891. $(this).replaceWith($('<span />').addClass(DATAGRID_SEARCH_TEXT_CLASS).text($(content).text()))
  51892. }
  51893. else
  51894. highlightSearchTextInTextNode($(content), searchText)
  51895. })
  51896. })
  51897. }
  51898. },
  51899. _renderRows: function($table, options) {
  51900. this.callBase($table, options);
  51901. if (this.option("rowTemplate"))
  51902. this._highlightSearchText($table)
  51903. },
  51904. _updateCell: function($cell, parameters) {
  51905. var that = this,
  51906. column = parameters.column,
  51907. isEquals = column.dataType !== "string";
  51908. if (allowSearch(column))
  51909. that._highlightSearchText($cell, isEquals);
  51910. that.callBase($cell, parameters)
  51911. }
  51912. }
  51913. }
  51914. }
  51915. });
  51916. dataGrid.__internals = $.extend({}, dataGrid.__internals, {
  51917. DATAGRID_SEARCH_PANEL_CLASS: DATAGRID_SEARCH_PANEL_CLASS,
  51918. DATAGRID_SEARCH_TEXT_CLASS: DATAGRID_SEARCH_TEXT_CLASS
  51919. })
  51920. })(jQuery, DevExpress);
  51921. /*! Module widgets-web, file ui.dataGrid.rowsView.js */
  51922. (function($, DX) {
  51923. var ui = DX.ui,
  51924. utils = DX.utils,
  51925. dataGrid = ui.dxDataGrid;
  51926. var DATAGRID_CELL_CONTENT_CLASS = "dx-datagrid-text-content",
  51927. DATAGRID_GROUP_ROW_CLASS = "dx-group-row",
  51928. DATAGRID_ROWS_VIEW_CLASS = "dx-datagrid-rowsview",
  51929. DATAGRID_TABLE_CLASS = "dx-datagrid-table",
  51930. DATAGRID_DATA_ROW_CLASS = "dx-data-row",
  51931. DATAGRID_FREESPACE_CLASS = "dx-freespace-row",
  51932. DATAGRID_NODATA_TEXT_CLASS = "dx-datagrid-nodata",
  51933. DATAGRID_CONTENT_CLASS = "dx-datagrid-content",
  51934. DATAGRID_NOWRAP_CLASS = "dx-datagrid-nowrap",
  51935. DATAGRID_ROW_LINES_CLASS = "dx-row-lines",
  51936. DATAGRID_COLUMN_LINES_CLASS = "dx-column-lines",
  51937. DATAGRID_ROW_ALTERNATION_CLASS = "dx-row-alt",
  51938. DATAGRID_LOADPANEL_HIDE_TIMEOUT = 200;
  51939. var createScrollableOptions = function(that) {
  51940. var useNativeScrolling = that.option("scrolling.useNativeScrolling");
  51941. var options = {
  51942. direction: "both",
  51943. rtlEnabled: that.option("rtlEnabled") || DX.rtlEnabled,
  51944. disabled: that.option("disabled"),
  51945. bounceEnabled: false,
  51946. useKeyboard: false
  51947. };
  51948. if (useNativeScrolling === undefined)
  51949. useNativeScrolling = true;
  51950. if (useNativeScrolling !== 'auto') {
  51951. options.useNative = !!useNativeScrolling;
  51952. options.useSimulatedScrollbar = !useNativeScrolling
  51953. }
  51954. return options
  51955. };
  51956. dataGrid.createScrollableOptions = createScrollableOptions;
  51957. dataGrid.RowsView = dataGrid.ColumnsView.inherit({
  51958. _getDefaultTemplate: function(column) {
  51959. switch (column.command) {
  51960. case"empty":
  51961. return function(container) {
  51962. container.html('&nbsp;')
  51963. };
  51964. default:
  51965. return function(container, options) {
  51966. var isDataTextEmpty = !options.text && options.rowType === "data",
  51967. text = isDataTextEmpty ? "&nbsp;" : options.text;
  51968. if (column.encodeHtml && !isDataTextEmpty)
  51969. container.text(text);
  51970. else
  51971. container.html(text)
  51972. }
  51973. }
  51974. },
  51975. _getDefaultGroupTemplate: function() {
  51976. var that = this,
  51977. summaryTexts = that.option("summary.texts");
  51978. return function(container, options) {
  51979. var data = options.data,
  51980. text = options.column.caption + ": " + options.text;
  51981. if (options.summaryItems && options.summaryItems.length)
  51982. text += " " + dataGrid.getGroupRowSummaryText(options.summaryItems, summaryTexts);
  51983. if (data)
  51984. if (options.groupContinuedMessage && options.groupContinuesMessage)
  51985. text += ' (' + options.groupContinuedMessage + '. ' + options.groupContinuesMessage + ')';
  51986. else if (options.groupContinuesMessage)
  51987. text += ' (' + options.groupContinuesMessage + ')';
  51988. else if (options.groupContinuedMessage)
  51989. text += ' (' + options.groupContinuedMessage + ')';
  51990. container.text(text)
  51991. }
  51992. },
  51993. _update: function(change){},
  51994. _getColumnTemplate: function(options) {
  51995. var that = this,
  51996. column = options.column,
  51997. template;
  51998. if (options.rowType === 'group' && column.groupIndex !== undefined)
  51999. template = column.groupCellTemplate || that._getDefaultGroupTemplate();
  52000. else
  52001. template = column.cellTemplate || that._getDefaultTemplate(column);
  52002. return template
  52003. },
  52004. _getCellTemplate: function(options) {
  52005. return this._getColumnTemplate(options)
  52006. },
  52007. _createRow: function(row) {
  52008. var $row = this.callBase(row),
  52009. isGroup,
  52010. isDataRow,
  52011. isRowExpanded;
  52012. if (row) {
  52013. isGroup = row.rowType === 'group';
  52014. isDataRow = row.rowType === 'data';
  52015. $row.toggleClass(DATAGRID_DATA_ROW_CLASS, isDataRow).toggleClass(DATAGRID_ROW_ALTERNATION_CLASS, isDataRow && row.dataIndex % 2 === 1 && this.option('rowAlternationEnabled')).toggleClass(DATAGRID_ROW_LINES_CLASS, isDataRow && this.option('showRowLines')).toggleClass(DATAGRID_COLUMN_LINES_CLASS, this.option('showColumnLines')).toggleClass(DATAGRID_GROUP_ROW_CLASS, isGroup);
  52016. if (isGroup) {
  52017. isRowExpanded = row.isExpanded;
  52018. this.setAria({
  52019. role: "rowgroup",
  52020. expanded: utils.isDefined(isRowExpanded) && isRowExpanded.toString()
  52021. }, $row)
  52022. }
  52023. }
  52024. return $row
  52025. },
  52026. _createTable: function() {
  52027. var that = this;
  52028. return that.callBase.apply(that, arguments).on("dxclick", '.dx-row', that.createAction(function(e) {
  52029. var jQueryEvent = e.jQueryEvent;
  52030. if (!$(jQueryEvent.target).closest('a').length) {
  52031. e.rowIndex = that.getRowIndex(jQueryEvent.currentTarget);
  52032. e.rowElement = $(jQueryEvent.currentTarget);
  52033. that._rowClick(e)
  52034. }
  52035. }))
  52036. },
  52037. _renderScrollable: function($table) {
  52038. var that = this,
  52039. $element = that.element();
  52040. if (!$element.children().length)
  52041. $element.append('<div />');
  52042. that._renderLoadPanel($element);
  52043. that._renderScrollableCore($element)
  52044. },
  52045. _handleScroll: function(e) {
  52046. var that = this;
  52047. that._scrollTop = e.scrollOffset.top;
  52048. that._scrollLeft = e.scrollOffset.left;
  52049. that.scrollOffsetChanged.fire(e.scrollOffset)
  52050. },
  52051. _renderScrollableCore: function($element) {
  52052. var that = this,
  52053. dxScrollableOptions = createScrollableOptions(that),
  52054. scrollHandler = $.proxy(that._handleScroll, that);
  52055. dxScrollableOptions.onScroll = scrollHandler;
  52056. dxScrollableOptions.onStop = scrollHandler;
  52057. $element.dxScrollable(dxScrollableOptions);
  52058. that._scrollable = $element.data('dxScrollable');
  52059. that._scrollableContainer = that._scrollable._$container
  52060. },
  52061. _renderLoadPanel: function($element) {
  52062. var that = this,
  52063. loadPanelOptions;
  52064. if ($element.dxLoadPanel) {
  52065. that._loadPanel && that._loadPanel.element().remove();
  52066. loadPanelOptions = that.option("loadPanel");
  52067. if (loadPanelOptions && loadPanelOptions.enabled) {
  52068. loadPanelOptions = $.extend({
  52069. shading: false,
  52070. message: loadPanelOptions.text,
  52071. position: {of: $element},
  52072. container: $element
  52073. }, loadPanelOptions);
  52074. that._loadPanel = that._createComponent($('<div />').appendTo($element.parent()), "dxLoadPanel", loadPanelOptions)
  52075. }
  52076. else
  52077. that._loadPanel = null
  52078. }
  52079. },
  52080. _renderContent: function(contentElement, tableElement) {
  52081. contentElement.replaceWith($('<div>').addClass(DATAGRID_CONTENT_CLASS).append(tableElement));
  52082. return this._findContentElement()
  52083. },
  52084. _updateContent: function(contentElement, change, newTableElement) {
  52085. var that = this,
  52086. tableElement = that._getTableElement(),
  52087. changeType = change && change.changeType,
  52088. executors = [];
  52089. switch (changeType) {
  52090. case'update':
  52091. $.each(change.rowIndices, function(index, rowIndex) {
  52092. var $newRowElement = that._getRowElements(newTableElement).eq(index),
  52093. changeType = change.changeTypes[index],
  52094. item = change.items && change.items[index];
  52095. executors.push(function() {
  52096. var $rowsElement = that._getRowElements(),
  52097. $rowElement = $rowsElement.eq(rowIndex);
  52098. switch (changeType) {
  52099. case'update':
  52100. if (utils.isDefined(item.visible) && item.visible !== $rowElement.is(":visible"))
  52101. $rowElement.toggle(item.visible);
  52102. else
  52103. $rowElement.replaceWith($newRowElement);
  52104. break;
  52105. case'insert':
  52106. if (!$rowsElement.length)
  52107. $newRowElement.prependTo(tableElement);
  52108. else if ($rowElement.length)
  52109. $newRowElement.insertBefore($rowElement);
  52110. else
  52111. $newRowElement.insertAfter($rowsElement.last());
  52112. break;
  52113. case'remove':
  52114. $rowElement.remove();
  52115. break
  52116. }
  52117. })
  52118. });
  52119. $.each(executors, function() {
  52120. this()
  52121. });
  52122. break;
  52123. default:
  52124. that._setTableElement(newTableElement);
  52125. contentElement.addClass(DATAGRID_CONTENT_CLASS);
  52126. that._renderContent(contentElement, newTableElement);
  52127. break
  52128. }
  52129. },
  52130. _renderFreeSpaceRow: function(tableElement) {
  52131. var that = this,
  52132. i,
  52133. freeSpaceRowElement = that._createRow(),
  52134. columns = this.getColumns();
  52135. freeSpaceRowElement.addClass(DATAGRID_FREESPACE_CLASS).toggleClass(DATAGRID_COLUMN_LINES_CLASS, that.option('showColumnLines'));
  52136. for (i = 0; i < columns.length; i++)
  52137. freeSpaceRowElement.append(that._createCell(columns[i]));
  52138. that._appendRow(tableElement, freeSpaceRowElement)
  52139. },
  52140. _needUpdateRowHeight: function(itemsCount) {
  52141. return itemsCount > 0 && !this._rowHeight
  52142. },
  52143. _updateRowHeight: function() {
  52144. var that = this,
  52145. tableElement = that._getTableElement(),
  52146. tableHeight,
  52147. itemsCount = that._dataController.items().length,
  52148. $freeSpaceRowElement;
  52149. if (tableElement && that._needUpdateRowHeight(itemsCount)) {
  52150. tableHeight = tableElement.outerHeight();
  52151. $freeSpaceRowElement = that._getFreeSpaceRowElements().first();
  52152. if ($freeSpaceRowElement && $freeSpaceRowElement.is(':visible'))
  52153. tableHeight -= $freeSpaceRowElement.outerHeight();
  52154. that._rowHeight = tableHeight / itemsCount
  52155. }
  52156. },
  52157. _findContentElement: function() {
  52158. var $element = this.element(),
  52159. $scrollableContent;
  52160. if ($element) {
  52161. $scrollableContent = $element.find('.dx-scrollable-content');
  52162. if (!$scrollableContent)
  52163. $scrollableContent = $element;
  52164. return $scrollableContent.children().first()
  52165. }
  52166. },
  52167. _getRowElements: function(tableElement) {
  52168. var $rows = this.callBase(tableElement);
  52169. return $rows && $rows.not('.' + DATAGRID_FREESPACE_CLASS)
  52170. },
  52171. _getFreeSpaceRowElements: function() {
  52172. var tableElements = this._getTableElements();
  52173. return tableElements && tableElements.children('tbody').children('.' + DATAGRID_FREESPACE_CLASS)
  52174. },
  52175. _getNoDataText: function() {
  52176. return this.option("noDataText")
  52177. },
  52178. _updateNoDataText: function($element) {
  52179. $element = $element || this.element();
  52180. var noDataElement = $element.find('.' + DATAGRID_NODATA_TEXT_CLASS),
  52181. isVisible = this._dataController.isEmpty(),
  52182. isLoading = this._dataController.isLoading(),
  52183. rtlEnabled = this.option("rtlEnabled"),
  52184. noDataElementCSSConfig = {};
  52185. if (!noDataElement.length)
  52186. noDataElement = $('<span>').addClass(DATAGRID_NODATA_TEXT_CLASS).hide().appendTo($element);
  52187. noDataElement.text(this._getNoDataText());
  52188. noDataElementCSSConfig = {
  52189. marginTop: -Math.floor(noDataElement.height() / 2),
  52190. marginRight: rtlEnabled ? -Math.floor(noDataElement.width() / 2) : 0,
  52191. marginLeft: rtlEnabled ? 0 : -Math.floor(noDataElement.width() / 2)
  52192. };
  52193. noDataElement.css(noDataElementCSSConfig);
  52194. if (isVisible && !isLoading)
  52195. noDataElement.show();
  52196. else
  52197. noDataElement.hide()
  52198. },
  52199. _rowClick: function(e) {
  52200. var item = this._dataController.items()[e.rowIndex] || {};
  52201. this.executeAction("onRowClick", $.extend({
  52202. columns: this.getColumns(),
  52203. evaluate: function(expr) {
  52204. var getter = DX.data.utils.compileGetter(expr);
  52205. return getter(item.data)
  52206. }
  52207. }, e, item))
  52208. },
  52209. _getGroupCellOptions: function(options) {
  52210. var columnIndex = (options.row.groupIndex || 0) + options.columnsCountBeforeGroups;
  52211. return {
  52212. columnIndex: columnIndex,
  52213. colspan: options.columns.length - columnIndex - 1
  52214. }
  52215. },
  52216. _renderCells: function($row, options) {
  52217. if (options.row.rowType === 'group')
  52218. this._renderGroupedCells($row, options);
  52219. else if (options.row.values)
  52220. this.callBase($row, options)
  52221. },
  52222. _renderGroupedCells: function($row, options) {
  52223. var $groupCell,
  52224. row = options.row,
  52225. i,
  52226. columns = options.columns,
  52227. rowIndex = row.rowIndex,
  52228. isExpanded,
  52229. groupColumn,
  52230. groupColumnAlignment,
  52231. groupCellOptions = this._getGroupCellOptions(options);
  52232. for (i = 0; i <= groupCellOptions.columnIndex; i++) {
  52233. if (i === groupCellOptions.columnIndex && columns[i].allowCollapsing && options.scrollingMode !== "infinite")
  52234. isExpanded = !!row.isExpanded;
  52235. else
  52236. isExpanded = null;
  52237. this._renderCell($row, {
  52238. value: isExpanded,
  52239. row: row,
  52240. rowIndex: rowIndex,
  52241. column: {
  52242. command: "expand",
  52243. cssClass: columns[i].cssClass
  52244. },
  52245. columnIndex: i
  52246. })
  52247. }
  52248. groupColumnAlignment = this.option("rtlEnabled") ? "right" : "left";
  52249. groupColumn = $.extend({}, columns[groupCellOptions.columnIndex], {
  52250. command: null,
  52251. cssClass: null,
  52252. alignment: groupColumnAlignment
  52253. });
  52254. $groupCell = this._renderCell($row, {
  52255. value: row.values[row.groupIndex],
  52256. row: row,
  52257. rowIndex: rowIndex,
  52258. column: groupColumn,
  52259. columnIndex: groupCellOptions.columnIndex
  52260. });
  52261. $groupCell.attr('colspan', groupCellOptions.colspan)
  52262. },
  52263. _renderRows: function($table, options) {
  52264. var that = this,
  52265. i,
  52266. columns = options.columns,
  52267. columnsCountBeforeGroups = 0,
  52268. scrollingMode = that.option("scrolling.mode");
  52269. for (i = 0; i < columns.length; i++)
  52270. if (columns[i].command === 'expand') {
  52271. columnsCountBeforeGroups = i;
  52272. break
  52273. }
  52274. that.callBase($table, $.extend({
  52275. scrollingMode: scrollingMode,
  52276. columnsCountBeforeGroups: columnsCountBeforeGroups
  52277. }, options));
  52278. that._renderFreeSpaceRow($table)
  52279. },
  52280. _renderRow: function($table, options) {
  52281. var that = this,
  52282. row = options.row,
  52283. rowTemplate = that.option("rowTemplate");
  52284. if ((row.rowType === "data" || row.rowType === "group") && !utils.isDefined(row.groupIndex) && rowTemplate)
  52285. that._renderTemplate($table, rowTemplate, $.extend({columns: options.columns}, row));
  52286. else
  52287. that.callBase($table, options)
  52288. },
  52289. _renderTable: function(options) {
  52290. var $table = this.callBase(options);
  52291. if (!utils.isDefined(this._getTableElement())) {
  52292. this._setTableElement($table);
  52293. this._renderScrollable($table)
  52294. }
  52295. return $table
  52296. },
  52297. _renderCore: function(change) {
  52298. var that = this,
  52299. $table,
  52300. $content,
  52301. $element = that.element();
  52302. $element.addClass(DATAGRID_ROWS_VIEW_CLASS).toggleClass(DATAGRID_NOWRAP_CLASS, !that.option("wordWrapEnabled"));
  52303. $table = that._renderTable({change: change});
  52304. $content = that._findContentElement();
  52305. that._updateContent($content, change, $table);
  52306. that.callBase(change);
  52307. that._lastColumnWidths = null
  52308. },
  52309. _getRows: function(change) {
  52310. return change && change.items || this._dataController.items()
  52311. },
  52312. _getCellOptions: function(options) {
  52313. var that = this,
  52314. parameters,
  52315. column = options.column,
  52316. row = options.row,
  52317. data = row.data,
  52318. summaryCells = row && row.summaryCells,
  52319. value = options.value,
  52320. displayValue = dataGrid.getDisplayValue(column, value),
  52321. groupingOptions = that.option('grouping'),
  52322. scrollingMode = that.option('scrolling.mode');
  52323. parameters = $.extend(this.callBase(options), {
  52324. value: value,
  52325. displayValue: displayValue,
  52326. row: row,
  52327. key: row.key,
  52328. data: data,
  52329. rowType: row.rowType,
  52330. values: row.values,
  52331. text: !utils.isDefined(column.command) && dataGrid.formatValue(displayValue, column),
  52332. rowIndex: row.rowIndex,
  52333. summaryItems: summaryCells && summaryCells[options.columnIndex],
  52334. resized: column.resizedCallbacks
  52335. });
  52336. if (utils.isDefined(column.groupIndex) && scrollingMode !== 'virtual' && scrollingMode !== 'infinite') {
  52337. parameters.groupContinuesMessage = data && data.isContinuationOnNextPage && groupingOptions && groupingOptions.groupContinuesMessage;
  52338. parameters.groupContinuedMessage = data && data.isContinuation && groupingOptions && groupingOptions.groupContinuedMessage
  52339. }
  52340. return parameters
  52341. },
  52342. getRow: function(index) {
  52343. var rows = this._getRowElements();
  52344. if (rows.length > index)
  52345. return $(rows[index])
  52346. },
  52347. getCell: function(cellPosition, rows) {
  52348. var $rows = rows || this._getRowElements(),
  52349. cells;
  52350. if ($rows.length > 0 && cellPosition.rowIndex >= 0) {
  52351. cellPosition.rowIndex = cellPosition.rowIndex < $rows.length ? cellPosition.rowIndex : $rows.length - 1;
  52352. cells = $rows[cellPosition.rowIndex].cells;
  52353. if (cells && cells.length > 0)
  52354. return $(cells[cells.length > cellPosition.columnIndex ? cellPosition.columnIndex : cells.length - 1])
  52355. }
  52356. },
  52357. getCellIndex: function($cell) {
  52358. var cellIndex = $cell.length ? $cell[0].cellIndex : -1;
  52359. return cellIndex
  52360. },
  52361. updateFreeSpaceRowHeight: function() {
  52362. var that = this,
  52363. elementHeight,
  52364. contentElement = that._findContentElement(),
  52365. freeSpaceRowElements = that._getFreeSpaceRowElements(),
  52366. contentHeight = 0,
  52367. freespaceRowCount,
  52368. scrollingMode,
  52369. resultHeight;
  52370. if (freeSpaceRowElements && contentElement) {
  52371. freeSpaceRowElements.hide();
  52372. elementHeight = that.element().height();
  52373. contentHeight = contentElement.outerHeight();
  52374. resultHeight = elementHeight - contentHeight - that.getScrollbarWidth(true);
  52375. if (that._dataController.items().length > 0) {
  52376. if (resultHeight > 0 || !that._dataController.items().length) {
  52377. freeSpaceRowElements.height(resultHeight);
  52378. freeSpaceRowElements.show()
  52379. }
  52380. else if (!that._hasHeight) {
  52381. freespaceRowCount = that._dataController.pageSize() - that._dataController.items().length;
  52382. scrollingMode = that.option('scrolling.mode');
  52383. if (freespaceRowCount > 0 && that._dataController.pageCount() > 1 && scrollingMode !== 'virtual' && scrollingMode !== 'infinite') {
  52384. freeSpaceRowElements.height(freespaceRowCount * that._rowHeight);
  52385. freeSpaceRowElements.show()
  52386. }
  52387. }
  52388. }
  52389. else {
  52390. freeSpaceRowElements.height(0);
  52391. freeSpaceRowElements.show()
  52392. }
  52393. }
  52394. },
  52395. _columnOptionChanged: function(e) {
  52396. var optionNames = e.optionNames;
  52397. if (e.changeTypes.grouping)
  52398. return;
  52399. if (optionNames.width || optionNames.visibleWidth) {
  52400. this.callBase(e);
  52401. this._fireColumnResizedCallbacks()
  52402. }
  52403. },
  52404. getScrollable: function() {
  52405. return this._scrollable
  52406. },
  52407. callbackNames: function() {
  52408. return ['scrollOffsetChanged']
  52409. },
  52410. init: function() {
  52411. var that = this,
  52412. dataController = that.getController('data');
  52413. that.callBase();
  52414. that._editorFactoryController = that.getController("editorFactory");
  52415. that._rowHeight = 0;
  52416. that._scrollTop = 0;
  52417. that._scrollLeft = 0;
  52418. that._hasHeight = false;
  52419. dataController.loadingChanged.add(function(isLoading, messageText) {
  52420. that.setLoading(isLoading, messageText)
  52421. });
  52422. that.createAction("onRowClick");
  52423. var scrollToCurrentPageHandler = function() {
  52424. that.scrollToPage(dataController.pageIndex())
  52425. };
  52426. dataController.pageIndexChanged.add(scrollToCurrentPageHandler);
  52427. dataController.pageSizeChanged.add(scrollToCurrentPageHandler);
  52428. dataController.filterChanged.add(scrollToCurrentPageHandler);
  52429. dataController.dataSourceChanged.add(function() {
  52430. that._handleScroll({scrollOffset: {
  52431. top: that._scrollTop,
  52432. left: that._scrollLeft
  52433. }})
  52434. })
  52435. },
  52436. _handleDataChanged: function(change) {
  52437. var that = this;
  52438. switch (change.changeType) {
  52439. case'refresh':
  52440. case'prepend':
  52441. case'append':
  52442. case'update':
  52443. that.render(null, change);
  52444. break;
  52445. default:
  52446. that._update(change);
  52447. break
  52448. }
  52449. },
  52450. publicMethods: function() {
  52451. return ['isScrollbarVisible', 'getTopVisibleRowData', 'getScrollbarWidth', 'getCellElement']
  52452. },
  52453. contentWidth: function() {
  52454. return this.element().width() - this.getScrollbarWidth()
  52455. },
  52456. getScrollbarWidth: function(isHorizontal) {
  52457. var scrollableContainer = this._scrollableContainer && this._scrollableContainer.get(0),
  52458. scrollbarWidth = 0;
  52459. if (scrollableContainer)
  52460. if (!isHorizontal)
  52461. scrollbarWidth = scrollableContainer.offsetWidth - scrollableContainer.clientWidth;
  52462. else
  52463. scrollbarWidth = scrollableContainer.offsetHeight - scrollableContainer.clientHeight;
  52464. return scrollbarWidth
  52465. },
  52466. _fireColumnResizedCallbacks: function() {
  52467. var that = this,
  52468. lastColumnWidths = that._lastColumnWidths || [],
  52469. columnWidths = [],
  52470. columns = that.getColumns(),
  52471. i;
  52472. for (i = 0; i < columns.length; i++) {
  52473. columnWidths[i] = columns[i].visibleWidth;
  52474. if (columns[i].resizedCallbacks && !utils.isDefined(columns[i].groupIndex) && lastColumnWidths[i] !== columnWidths[i])
  52475. columns[i].resizedCallbacks.fire(columnWidths[i])
  52476. }
  52477. that._lastColumnWidths = columnWidths
  52478. },
  52479. _resizeCore: function() {
  52480. var that = this,
  52481. dxScrollable;
  52482. that.callBase();
  52483. that._fireColumnResizedCallbacks();
  52484. that._updateRowHeight();
  52485. that._updateNoDataText();
  52486. that.updateFreeSpaceRowHeight();
  52487. dxScrollable = that.element().data('dxScrollable');
  52488. if (dxScrollable)
  52489. dxScrollable.update();
  52490. that.setLoading(that._dataController.isLoading())
  52491. },
  52492. scrollToPage: function(pageIndex) {
  52493. var that = this,
  52494. scrollingMode = that.option('scrolling.mode'),
  52495. dataController = that._dataController,
  52496. pageSize = dataController ? dataController.pageSize() : 0,
  52497. scrollPosition;
  52498. if (scrollingMode === 'virtual' || scrollingMode === 'infinite')
  52499. scrollPosition = pageIndex * that._rowHeight * pageSize;
  52500. else
  52501. scrollPosition = 0;
  52502. that.scrollTo({
  52503. y: scrollPosition,
  52504. x: that._scrollLeft
  52505. })
  52506. },
  52507. scrollTo: function(location) {
  52508. var $element = this.element(),
  52509. dxScrollable = $element && $element.data('dxScrollable');
  52510. if (dxScrollable)
  52511. dxScrollable.scrollTo(location)
  52512. },
  52513. height: function(height) {
  52514. var that = this,
  52515. $element = this.element(),
  52516. freeSpaceRowElements;
  52517. if (utils.isDefined(height)) {
  52518. that._hasHeight = height !== 'auto';
  52519. if ($element)
  52520. $element.height(height);
  52521. freeSpaceRowElements = this._getFreeSpaceRowElements();
  52522. freeSpaceRowElements && freeSpaceRowElements.hide()
  52523. }
  52524. else
  52525. return $element ? $element.height() : 0
  52526. },
  52527. setLoading: function(isLoading, messageText) {
  52528. var that = this,
  52529. loadPanel = that._loadPanel,
  52530. dataController = that._dataController,
  52531. loadPanelOptions = that.option("loadPanel") || {},
  52532. animation = dataController.isLoaded() ? loadPanelOptions.animation : null,
  52533. visibilityOptions;
  52534. if (loadPanel) {
  52535. visibilityOptions = {
  52536. message: messageText || loadPanelOptions.text,
  52537. animation: animation,
  52538. visible: isLoading
  52539. };
  52540. clearTimeout(that._hideLoadingTimeoutID);
  52541. if (loadPanel.option('visible') && !isLoading)
  52542. that._hideLoadingTimeoutID = setTimeout(function() {
  52543. loadPanel.option(visibilityOptions)
  52544. }, DATAGRID_LOADPANEL_HIDE_TIMEOUT);
  52545. else
  52546. loadPanel.option(visibilityOptions);
  52547. that._updateNoDataText()
  52548. }
  52549. },
  52550. isScrollbarVisible: function() {
  52551. var $element = this.element();
  52552. return $element ? this._findContentElement().outerHeight() - $element.height() > 0 : false
  52553. },
  52554. setRowsOpacity: function(columnIndex, value) {
  52555. var that = this,
  52556. $rows = that._getRowElements().not('.' + DATAGRID_GROUP_ROW_CLASS) || [];
  52557. $.each($rows, function(_, row) {
  52558. $(row).children().eq(columnIndex).css({opacity: value})
  52559. })
  52560. },
  52561. getTopVisibleItemIndex: function() {
  52562. var that = this,
  52563. itemIndex = 0,
  52564. prevOffsetTop = 0,
  52565. offsetTop = 0,
  52566. rowElements,
  52567. scrollPosition = that._scrollTop,
  52568. contentElementOffsetTop = that._findContentElement().offset().top,
  52569. items = that._dataController.items(),
  52570. tableElement = that._getTableElement();
  52571. if (items.length && tableElement) {
  52572. rowElements = tableElement.children('tbody').children('.dx-row:visible, .dx-error-row').not('.' + DATAGRID_FREESPACE_CLASS);
  52573. for (itemIndex = 0; itemIndex < items.length; itemIndex++) {
  52574. prevOffsetTop = offsetTop;
  52575. offsetTop = rowElements.eq(itemIndex).offset().top - contentElementOffsetTop;
  52576. if (offsetTop > scrollPosition) {
  52577. if (scrollPosition * 2 < offsetTop + prevOffsetTop && itemIndex)
  52578. itemIndex--;
  52579. break
  52580. }
  52581. }
  52582. if (itemIndex && itemIndex === items.length)
  52583. itemIndex--
  52584. }
  52585. return itemIndex
  52586. },
  52587. getTopVisibleRowData: function() {
  52588. var itemIndex = this.getTopVisibleItemIndex(),
  52589. items = this._dataController.items();
  52590. if (items[itemIndex])
  52591. return items[itemIndex].data
  52592. },
  52593. optionChanged: function(args) {
  52594. var that = this;
  52595. that.callBase(args);
  52596. switch (args.name) {
  52597. case'wordWrapEnabled':
  52598. case'hoverStateEnabled':
  52599. case'showColumnLines':
  52600. case'showRowLines':
  52601. case'rowAlternationEnabled':
  52602. case'rowTemplate':
  52603. that.render();
  52604. that.component.resize();
  52605. args.handled = true;
  52606. break;
  52607. case'scrolling':
  52608. that._rowHeight = null;
  52609. that._tableElement = null;
  52610. args.handled = true;
  52611. break;
  52612. case'rtlEnabled':
  52613. that._rowHeight = null;
  52614. that._tableElement = null;
  52615. break;
  52616. case"disabled":
  52617. case'loadPanel':
  52618. that._tableElement = null;
  52619. that.render();
  52620. that.component.resize();
  52621. args.handled = true;
  52622. break;
  52623. case'noDataText':
  52624. that._updateNoDataText();
  52625. args.handled = true;
  52626. break
  52627. }
  52628. },
  52629. dispose: function() {
  52630. clearTimeout(this._hideLoadingTimeoutID)
  52631. },
  52632. setScrollerSpacing: function(){}
  52633. });
  52634. $.extend(dataGrid.__internals, {
  52635. DATAGRID_CELL_CONTENT_CLASS: DATAGRID_CELL_CONTENT_CLASS,
  52636. DATAGRID_GROUP_ROW_CLASS: DATAGRID_GROUP_ROW_CLASS,
  52637. DATAGRID_ROWS_VIEW_CLASS: DATAGRID_ROWS_VIEW_CLASS,
  52638. DATAGRID_TABLE_CLASS: DATAGRID_TABLE_CLASS,
  52639. DATAGRID_FREESPACE_CLASS: DATAGRID_FREESPACE_CLASS,
  52640. DATAGRID_NODATA_TEXT_CLASS: DATAGRID_NODATA_TEXT_CLASS,
  52641. DATAGRID_NOWRAP_CLASS: DATAGRID_NOWRAP_CLASS,
  52642. DATAGRID_ROW_LINES_CLASS: DATAGRID_ROW_LINES_CLASS,
  52643. DATAGRID_COLUMN_LINES_CLASS: DATAGRID_COLUMN_LINES_CLASS,
  52644. DATAGRID_ROW_ALTERNATION_CLASS: DATAGRID_ROW_ALTERNATION_CLASS
  52645. });
  52646. dataGrid.registerModule('rows', {
  52647. defaultOptions: function() {
  52648. return {
  52649. hoverStateEnabled: false,
  52650. loadPanel: {
  52651. enabled: true,
  52652. text: Globalize.localize("Loading"),
  52653. width: 200,
  52654. height: 70,
  52655. showIndicator: true,
  52656. indicatorSrc: "",
  52657. showPane: true
  52658. },
  52659. rowTemplate: null,
  52660. columnAutoWidth: false,
  52661. noDataText: Globalize.localize("dxDataGrid-noDataText"),
  52662. wordWrapEnabled: false,
  52663. showColumnLines: true,
  52664. showRowLines: false,
  52665. rowAlternationEnabled: false,
  52666. activeStateEnabled: false
  52667. }
  52668. },
  52669. views: {rowsView: dataGrid.RowsView}
  52670. })
  52671. })(jQuery, DevExpress);
  52672. /*! Module widgets-web, file ui.dataGrid.pager.js */
  52673. (function($, DX) {
  52674. var ui = DX.ui,
  52675. utils = DX.utils,
  52676. dataGrid = ui.dxDataGrid;
  52677. var DATAGRID_PAGER_CLASS = "dx-datagrid-pager";
  52678. var MAX_PAGES_COUNT = 10;
  52679. dataGrid.PagerView = dataGrid.View.inherit({
  52680. init: function() {
  52681. var that = this,
  52682. dataController = that.getController('data');
  52683. that._isVisible = false;
  52684. dataController.changed.add(function() {
  52685. that.render()
  52686. })
  52687. },
  52688. _getPager: function() {
  52689. var $element = this.element();
  52690. return $element && $element.data('dxPager')
  52691. },
  52692. _renderCore: function() {
  52693. var that = this,
  52694. $element = that.element().addClass(DATAGRID_PAGER_CLASS),
  52695. pagerOptions = that.option('pager') || {},
  52696. dataController = that.getController('data'),
  52697. options = {
  52698. maxPagesCount: MAX_PAGES_COUNT,
  52699. pageIndex: dataController.pageIndex() + 1,
  52700. pageCount: dataController.pageCount(),
  52701. pageSize: dataController.pageSize(),
  52702. showPageSizes: pagerOptions.showPageSizeSelector,
  52703. showInfo: pagerOptions.showInfo,
  52704. showNavigationButtons: pagerOptions.showNavigationButtons,
  52705. pageSizes: that.getPageSizes(),
  52706. hasKnownLastPage: dataController.hasKnownLastPage(),
  52707. pageIndexChanged: function(pageIndex) {
  52708. if (dataController.pageIndex() !== pageIndex - 1)
  52709. setTimeout(function() {
  52710. dataController.pageIndex(pageIndex - 1)
  52711. })
  52712. },
  52713. pageSizeChanged: function(pageSize) {
  52714. setTimeout(function() {
  52715. dataController.pageSize(pageSize)
  52716. })
  52717. }
  52718. };
  52719. if (utils.isDefined(pagerOptions.infoText))
  52720. options.infoText = pagerOptions.infoText;
  52721. that._createComponent($element, "dxPager", options)
  52722. },
  52723. getPageSizes: function() {
  52724. var that = this,
  52725. dataController = that.getController('data'),
  52726. pagerOptions = that.option('pager'),
  52727. allowedPageSizes = pagerOptions && pagerOptions.allowedPageSizes,
  52728. pageSize = dataController.pageSize();
  52729. if (!utils.isDefined(that._pageSizes) || $.inArray(pageSize, that._pageSizes) === -1) {
  52730. that._pageSizes = [];
  52731. if (pagerOptions)
  52732. if ($.isArray(allowedPageSizes))
  52733. that._pageSizes = allowedPageSizes;
  52734. else if (allowedPageSizes && pageSize > 1)
  52735. that._pageSizes = [Math.floor(pageSize / 2), pageSize, pageSize * 2]
  52736. }
  52737. return that._pageSizes
  52738. },
  52739. isVisible: function() {
  52740. var that = this,
  52741. dataController = that.getController('data'),
  52742. pagerOptions = that.option('pager'),
  52743. pagerVisible = pagerOptions && pagerOptions.visible,
  52744. scrolling = that.option('scrolling');
  52745. if (that._isVisible)
  52746. return true;
  52747. if (pagerVisible === 'auto')
  52748. if (scrolling && (scrolling.mode === 'virtual' || scrolling.mode === 'infinite'))
  52749. pagerVisible = false;
  52750. else
  52751. pagerVisible = dataController.pageCount() > 1 || dataController.isLoaded() && !dataController.hasKnownLastPage();
  52752. that._isVisible = pagerVisible;
  52753. return pagerVisible
  52754. },
  52755. getHeight: function() {
  52756. var pager = this._getPager();
  52757. return pager && this.isVisible() ? pager.getHeight() : 0
  52758. },
  52759. optionChanged: function(args) {
  52760. var that = this,
  52761. name = args.name,
  52762. isPager = name === "pager",
  52763. isPaging = name === "paging",
  52764. isScrolling = name === "scrolling";
  52765. if (isPager || isPaging || isScrolling) {
  52766. if (isPager || isPaging)
  52767. that._pageSizes = null;
  52768. that._isVisible = false;
  52769. that.render();
  52770. if (isPager && that.component)
  52771. that.component.resize();
  52772. args.handled = true
  52773. }
  52774. }
  52775. });
  52776. dataGrid.registerModule('pager', {
  52777. defaultOptions: function() {
  52778. return {pager: {
  52779. visible: 'auto',
  52780. showPageSizeSelector: false,
  52781. allowedPageSizes: 'auto'
  52782. }}
  52783. },
  52784. views: {pagerView: dataGrid.PagerView}
  52785. })
  52786. })(jQuery, DevExpress);
  52787. /*! Module widgets-web, file ui.dataGrid.gridView.js */
  52788. (function($, DX) {
  52789. var dataGrid = DX.ui.dxDataGrid,
  52790. utils = DX.utils;
  52791. var DATAGRID_CLASS = "dx-datagrid",
  52792. DATAGRID_HIDDEN_CLASS = "dx-hidden",
  52793. DATAGRID_TABLE_CLASS = "dx-datagrid-table",
  52794. DATAGRID_BORDERS_CLASS = "dx-datagrid-borders",
  52795. DATAGRID_TABLE_FIXED_CLASS = "dx-datagrid-table-fixed",
  52796. DATAGRID_COLUMN_HEADERS_HIDDEN = "dx-datagrid-headers-hidden",
  52797. DATAGRID_IMPORTANT_MARGIN_CLASS = "dx-datagrid-important-margin",
  52798. EMPTY_GRID_ROWS_HEIGHT = 100,
  52799. LOADPANEL_MARGIN = 50,
  52800. VIEW_NAMES = ['columnsSeparatorView', 'blockSeparatorView', 'trackerView', 'headerPanel', 'columnHeadersView', 'rowsView', 'footerView', 'columnChooserView', 'pagerView', 'draggingHeaderView', 'contextMenuView', 'errorView', 'headerFilterView'];
  52801. var isPercentWidth = function(width) {
  52802. return utils.isString(width) && width.slice(-1) === '%'
  52803. };
  52804. var mergeArraysByMaxValue = function(values1, values2) {
  52805. var result = [],
  52806. i;
  52807. if (values1 && values2 && values1.length && values1.length === values2.length)
  52808. for (i = 0; i < values1.length; i++)
  52809. result.push(values1[i] > values2[i] ? values1[i] : values2[i]);
  52810. else if (values1)
  52811. result = values1;
  52812. return result
  52813. };
  52814. dataGrid.ResizingController = dataGrid.ViewController.inherit({
  52815. _initPostRenderHandlers: function() {
  52816. var that = this;
  52817. if (!that._refreshSizesHandler) {
  52818. that._refreshSizesHandler = function(e) {
  52819. that._dataController.changed.remove(that._refreshSizesHandler);
  52820. var changeType = e && e.changeType;
  52821. if (!e || changeType === 'refresh' || changeType === 'prepend' || changeType === 'append' || changeType === 'update')
  52822. that.resize();
  52823. if (changeType) {
  52824. utils.triggerShownEvent(that.getView("rowsView").element());
  52825. that.component._fireContentReadyAction()
  52826. }
  52827. };
  52828. that._dataController.changed.add(function() {
  52829. that._dataController.changed.add(that._refreshSizesHandler)
  52830. });
  52831. that._columnHeadersView.sizeChanged.add(that._refreshSizesHandler)
  52832. }
  52833. },
  52834. _getBestFitWidths: function() {
  52835. var that = this,
  52836. rowsColumnWidths = that._rowsView.getColumnWidths(),
  52837. headerColumnWidths = that._columnHeadersView && that._columnHeadersView.getColumnWidths(),
  52838. footerColumnWidths = that._footerView && that._footerView.getColumnWidths(),
  52839. resultWidths;
  52840. resultWidths = mergeArraysByMaxValue(rowsColumnWidths, headerColumnWidths);
  52841. resultWidths = mergeArraysByMaxValue(resultWidths, footerColumnWidths);
  52842. return resultWidths
  52843. },
  52844. _setVisibleWidths: function(visibleColumns, widths) {
  52845. var columnsController = this._columnsController;
  52846. columnsController.beginUpdate();
  52847. $.each(visibleColumns, function(index, column) {
  52848. var columnId = column.command ? "command:" + column.command : column.index;
  52849. columnsController.columnOption(columnId, 'visibleWidth', widths[index])
  52850. });
  52851. columnsController.endUpdate()
  52852. },
  52853. _toggleBestFitMode: function(isBestFit) {
  52854. var $element = this.component.element();
  52855. $element.find('.' + DATAGRID_TABLE_CLASS).toggleClass(DATAGRID_TABLE_FIXED_CLASS, !isBestFit);
  52856. $element.find('input').toggleClass(DATAGRID_HIDDEN_CLASS, isBestFit)
  52857. },
  52858. _synchronizeColumns: function() {
  52859. var that = this,
  52860. columnsController = that._columnsController,
  52861. visibleColumns = columnsController.getVisibleColumns(),
  52862. columnAutoWidth = that.option("columnAutoWidth"),
  52863. needBestFit = columnAutoWidth,
  52864. lastWidthReseted = false,
  52865. resultWidths = [],
  52866. normalizeWidthsByExpandColumns = function() {
  52867. var expandColumnWidth;
  52868. $.each(visibleColumns, function(index, column) {
  52869. if (column.command === "expand")
  52870. expandColumnWidth = resultWidths[index]
  52871. });
  52872. $.each(visibleColumns, function(index, column) {
  52873. if (column.command === "expand" && expandColumnWidth)
  52874. resultWidths[index] = expandColumnWidth
  52875. })
  52876. };
  52877. !needBestFit && $.each(visibleColumns, function(index, column) {
  52878. if (column.width === "auto") {
  52879. needBestFit = true;
  52880. return false
  52881. }
  52882. });
  52883. that._setVisibleWidths(visibleColumns, []);
  52884. if (needBestFit) {
  52885. that._toggleBestFitMode(true);
  52886. resultWidths = that._getBestFitWidths();
  52887. $.each(visibleColumns, function(index, column) {
  52888. var columnId = column.command ? "command:" + column.command : column.index;
  52889. columnsController.columnOption(columnId, 'bestFitWidth', resultWidths[index], true)
  52890. })
  52891. }
  52892. $.each(visibleColumns, function(index) {
  52893. if (this.width !== 'auto')
  52894. if (this.width)
  52895. resultWidths[index] = this.width;
  52896. else if (!columnAutoWidth)
  52897. resultWidths[index] = undefined
  52898. });
  52899. lastWidthReseted = that._correctColumnWidths(resultWidths, visibleColumns);
  52900. if (columnAutoWidth) {
  52901. normalizeWidthsByExpandColumns();
  52902. that._processStretch(resultWidths, visibleColumns)
  52903. }
  52904. if (needBestFit)
  52905. that._toggleBestFitMode(false);
  52906. if (needBestFit || lastWidthReseted)
  52907. that._setVisibleWidths(visibleColumns, resultWidths)
  52908. },
  52909. _correctColumnWidths: function(resultWidths, visibleColumns) {
  52910. var that = this,
  52911. hasPercentWidth = false,
  52912. hasAutoWidth = false,
  52913. lastWidthReseted = false,
  52914. $element = that.component.element(),
  52915. hasWidth = that._hasWidth,
  52916. lastColumnIndex;
  52917. $.each(visibleColumns, function(index) {
  52918. if (this.width !== 'auto')
  52919. if (this.width)
  52920. resultWidths[index] = this.width;
  52921. else
  52922. hasAutoWidth = true;
  52923. if (isPercentWidth(this.width))
  52924. hasPercentWidth = true
  52925. });
  52926. if ($element && that._maxWidth) {
  52927. delete that._maxWidth;
  52928. $element.css('max-width', '')
  52929. }
  52930. if (!hasAutoWidth && resultWidths.length) {
  52931. var contentWidth = that._rowsView.contentWidth();
  52932. var totalWidth = that._getTotalWidth(resultWidths, contentWidth);
  52933. if (totalWidth <= contentWidth) {
  52934. lastColumnIndex = resultWidths.length - 1;
  52935. while (lastColumnIndex >= 0 && visibleColumns[lastColumnIndex] && visibleColumns[lastColumnIndex].command)
  52936. lastColumnIndex--;
  52937. if (lastColumnIndex >= 0) {
  52938. resultWidths[lastColumnIndex] = 'auto';
  52939. lastWidthReseted = true;
  52940. if (!hasWidth && !hasPercentWidth) {
  52941. that._maxWidth = totalWidth;
  52942. $element.css('max-width', that._maxWidth)
  52943. }
  52944. }
  52945. }
  52946. }
  52947. return lastWidthReseted
  52948. },
  52949. _processStretch: function(resultSizes, visibleColumns) {
  52950. var groupSize = this._rowsView.contentWidth(),
  52951. tableSize = this._getTotalWidth(resultSizes, groupSize),
  52952. unusedIndexes = {length: 0},
  52953. diff,
  52954. diffElement,
  52955. onePixelElementsCount,
  52956. i;
  52957. if (!resultSizes.length)
  52958. return;
  52959. $.each(visibleColumns, function(index) {
  52960. if (this.width) {
  52961. unusedIndexes[index] = true;
  52962. unusedIndexes.length++
  52963. }
  52964. });
  52965. diff = groupSize - tableSize;
  52966. diffElement = Math.floor(diff / (resultSizes.length - unusedIndexes.length));
  52967. onePixelElementsCount = diff - diffElement * (resultSizes.length - unusedIndexes.length);
  52968. if (diff >= 0)
  52969. for (i = 0; i < resultSizes.length; i++) {
  52970. if (unusedIndexes[i])
  52971. continue;
  52972. resultSizes[i] += diffElement;
  52973. if (onePixelElementsCount) {
  52974. resultSizes[i]++;
  52975. onePixelElementsCount--
  52976. }
  52977. }
  52978. },
  52979. _getTotalWidth: function(widths, groupWidth) {
  52980. var result = 0,
  52981. width,
  52982. i;
  52983. for (i = 0; i < widths.length; i++) {
  52984. width = widths[i];
  52985. if (width)
  52986. result += isPercentWidth(width) ? parseInt(width) * groupWidth / 100 : parseInt(width)
  52987. }
  52988. return Math.round(result)
  52989. },
  52990. updateSize: function($rootElement) {
  52991. var that = this,
  52992. $groupElement,
  52993. width;
  52994. if (that._hasHeight === undefined && $rootElement && $rootElement.closest(document).length) {
  52995. $groupElement = $rootElement.children('.' + DATAGRID_CLASS);
  52996. if ($groupElement.length)
  52997. $groupElement.detach();
  52998. that._hasHeight = !!$rootElement.height();
  52999. width = $rootElement.width();
  53000. $rootElement.addClass(DATAGRID_IMPORTANT_MARGIN_CLASS);
  53001. that._hasWidth = $rootElement.width() === width;
  53002. $rootElement.removeClass(DATAGRID_IMPORTANT_MARGIN_CLASS);
  53003. if ($groupElement.length)
  53004. $groupElement.appendTo($rootElement)
  53005. }
  53006. },
  53007. publicMethods: function() {
  53008. return ["resize", "updateDimensions"]
  53009. },
  53010. resize: function() {
  53011. this.updateDimensions()
  53012. },
  53013. updateDimensions: function() {
  53014. var that = this,
  53015. dataController = that._dataController,
  53016. $rootElement = that.component.element(),
  53017. rootElementHeight = $rootElement && ($rootElement.get(0).clientHeight || $rootElement.height()),
  53018. loadPanelOptions = that.option('loadPanel'),
  53019. height = that.option('height'),
  53020. rowsViewHeight,
  53021. editorFactory = that.getController('editorFactory'),
  53022. $testDiv;
  53023. that._initPostRenderHandlers();
  53024. that.updateSize($rootElement);
  53025. if (height && that._hasHeight ^ height !== 'auto') {
  53026. $testDiv = $('<div>').height(height).appendTo($rootElement);
  53027. that._hasHeight = !!$testDiv.height();
  53028. $testDiv.remove()
  53029. }
  53030. if (that._hasHeight && rootElementHeight > 0 && that.option('scrolling')) {
  53031. rowsViewHeight = rootElementHeight;
  53032. $.each(that.getViews(), function() {
  53033. if (this.isVisible() && this.getHeight)
  53034. rowsViewHeight -= this.getHeight()
  53035. })
  53036. }
  53037. else if (!that._hasHeight && dataController.items().length === 0)
  53038. rowsViewHeight = loadPanelOptions && loadPanelOptions.visible ? loadPanelOptions.height + LOADPANEL_MARGIN : EMPTY_GRID_ROWS_HEIGHT;
  53039. else
  53040. rowsViewHeight = 'auto';
  53041. that._rowsView.height(rowsViewHeight);
  53042. that._columnHeadersView.setScrollerSpacing(that._rowsView.getScrollbarWidth());
  53043. that._rowsView.setScrollerSpacing();
  53044. that._synchronizeColumns();
  53045. $.each(VIEW_NAMES, function(index, viewName) {
  53046. var view = that.getView(viewName);
  53047. if (view)
  53048. view.resize()
  53049. });
  53050. editorFactory && editorFactory.resize()
  53051. },
  53052. optionChanged: function(args) {
  53053. switch (args.name) {
  53054. case"width":
  53055. case"height":
  53056. this.component._renderDimensions();
  53057. this.resize();
  53058. default:
  53059. this.callBase(args)
  53060. }
  53061. },
  53062. init: function() {
  53063. var that = this;
  53064. that._dataController = that.getController('data');
  53065. that._columnsController = that.getController('columns');
  53066. that._columnHeadersView = that.getView('columnHeadersView');
  53067. that._footerView = that.getView("footerView");
  53068. that._rowsView = that.getView('rowsView');
  53069. that._footerView = that.getView('footerView');
  53070. that._rowsView.scrollOffsetChanged.add(function(e) {
  53071. that._columnHeadersView.scrollOffset(e.left);
  53072. that._footerView.scrollOffset(e.left)
  53073. })
  53074. }
  53075. });
  53076. dataGrid.GridView = dataGrid.View.inherit({
  53077. init: function() {
  53078. var that = this;
  53079. that._dataController = that.getController('data');
  53080. that._rowsView = that.getView('rowsView')
  53081. },
  53082. getView: function(name) {
  53083. return this.component._views[name]
  53084. },
  53085. element: function() {
  53086. return this._groupElement
  53087. },
  53088. optionChanged: function(args) {
  53089. var that = this;
  53090. if (utils.isDefined(that._groupElement) && args.name === "showBorders") {
  53091. that._groupElement.toggleClass(DATAGRID_BORDERS_CLASS, !!args.value);
  53092. args.handled = true
  53093. }
  53094. else
  53095. that.callBase(args)
  53096. },
  53097. render: function($rootElement) {
  53098. var that = this,
  53099. groupElement = that._groupElement || $('<div />').addClass(DATAGRID_CLASS).toggleClass(DATAGRID_BORDERS_CLASS, !!that.option("showBorders"));
  53100. that.component.setAria({
  53101. role: "application",
  53102. label: Globalize.localize("dxDataGrid-ariaDataGrid")
  53103. }, $rootElement);
  53104. that._rootElement = $rootElement || that._rootElement;
  53105. that._groupElement = groupElement;
  53106. $.each(VIEW_NAMES, function(index, viewName) {
  53107. var view = that.getView(viewName);
  53108. if (view)
  53109. view.render(groupElement)
  53110. });
  53111. that.update()
  53112. },
  53113. update: function() {
  53114. var that = this,
  53115. $rootElement = that._rootElement,
  53116. $groupElement = that._groupElement,
  53117. resizingController = that.getController('resizing');
  53118. if ($rootElement && $groupElement) {
  53119. if (!$groupElement.parent().length) {
  53120. resizingController.updateSize($rootElement);
  53121. $groupElement.appendTo($rootElement);
  53122. that._rowsView.renderDelayedTemplates()
  53123. }
  53124. resizingController.resize();
  53125. if (that._dataController.isLoaded())
  53126. that.component._fireContentReadyAction()
  53127. }
  53128. }
  53129. });
  53130. dataGrid.registerModule("gridView", {
  53131. defaultOptions: function() {
  53132. return {showBorders: false}
  53133. },
  53134. controllers: {resizing: dataGrid.ResizingController},
  53135. views: {gridView: dataGrid.GridView}
  53136. });
  53137. $.extend(dataGrid.__internals, {
  53138. viewNames: VIEW_NAMES,
  53139. DATAGRID_CLASS: DATAGRID_CLASS,
  53140. DATAGRID_COLUMN_HEADERS_HIDDEN: DATAGRID_COLUMN_HEADERS_HIDDEN,
  53141. DATAGRID_BORDERS_CLASS: DATAGRID_BORDERS_CLASS
  53142. })
  53143. })(jQuery, DevExpress);
  53144. /*! Module widgets-web, file ui.dataGrid.columnsResizingReorderingModule.js */
  53145. (function($, DX) {
  53146. var ui = DX.ui,
  53147. events = ui.events,
  53148. addNamespace = events.addNamespace,
  53149. utils = DX.utils,
  53150. dataGrid = ui.dxDataGrid,
  53151. fx = DX.fx;
  53152. var DATAGRID_COLUMNS_SEPARATOR_CLASS = "dx-datagrid-columns-separator",
  53153. DATAGRID_COLUMNS_SEPARATOR_TRANSPARENT = "dx-datagrid-columns-separator-transparent",
  53154. DATAGRID_DRAGGING_HEADER_CLASS = "dx-datagrid-drag-header",
  53155. DATAGRID_CELL_CONTENT_CLASS = "dx-datagrid-text-content",
  53156. DATAGRID_HEADERS_DRAG_ACTION_CLASS = "dx-datagrid-drag-action",
  53157. DATAGRID_TRACKER_CLASS = "dx-datagrid-tracker",
  53158. DATAGRID_BLOCK_SEPARATOR_CLASS = "dx-block-separator",
  53159. DATAGRID_HEADERS_DROP_HIGHLIGHT_CLASS = 'dx-datagrid-drop-highlight',
  53160. DATAGRID_HEADER_ROW_CLASS = "dx-header-row",
  53161. WIDGET_CLASS = "dx-widget",
  53162. DATAGRID_MODULE_NAMESPACE = "dxDataGridResizingReordering",
  53163. COLUMNS_SEPARATOR_TOUCH_TRACKER_WIDTH = 10,
  53164. DRAGGING_DELTA = 5;
  53165. var allowResizing = function(that) {
  53166. return that.option("allowColumnResizing") || that.getController("columns").isColumnOptionUsed("allowResizing")
  53167. };
  53168. var allowReordering = function(that) {
  53169. return that.option("allowColumnReordering") || that.getController("columns").isColumnOptionUsed("allowReordering")
  53170. };
  53171. dataGrid.getPointsByColumns = function(items, pointCreated, isVertical) {
  53172. var cellsLength = items.length,
  53173. cancel = false,
  53174. i,
  53175. point,
  53176. item,
  53177. offset,
  53178. result = [],
  53179. rtlEnabled,
  53180. columnIndex = 0;
  53181. for (i = 0; i <= cellsLength; i++) {
  53182. if (i < cellsLength) {
  53183. item = items.eq(columnIndex);
  53184. offset = item.offset();
  53185. rtlEnabled = item.css('direction') === 'rtl'
  53186. }
  53187. point = {
  53188. index: i,
  53189. x: offset ? offset.left + (!isVertical && rtlEnabled ^ i === cellsLength ? item.outerWidth() : 0) : 0,
  53190. y: offset ? offset.top + (isVertical && i === cellsLength ? item.outerHeight() : 0) : 0,
  53191. columnIndex: columnIndex
  53192. };
  53193. if (pointCreated)
  53194. cancel = pointCreated(point);
  53195. if (!cancel)
  53196. result.push(point);
  53197. columnIndex++
  53198. }
  53199. return result
  53200. };
  53201. dataGrid.TrackerView = dataGrid.View.inherit({
  53202. _renderCore: function(options) {
  53203. this.callBase();
  53204. this.element().addClass(DATAGRID_TRACKER_CLASS);
  53205. this.hide()
  53206. },
  53207. init: function() {
  53208. var that = this,
  53209. $element;
  53210. that.callBase();
  53211. that.getController("tablePosition").positionChanged.add(function(position) {
  53212. $element = that.element();
  53213. if ($element && $element.hasClass(DATAGRID_TRACKER_CLASS)) {
  53214. $element.css({top: position.top});
  53215. $element.height(position.height)
  53216. }
  53217. })
  53218. },
  53219. isVisible: function() {
  53220. return allowResizing(this)
  53221. },
  53222. show: function() {
  53223. this.element().show()
  53224. },
  53225. hide: function() {
  53226. this.element().hide()
  53227. },
  53228. setHeight: function(value) {
  53229. this.element().height(value)
  53230. }
  53231. });
  53232. dataGrid.SeparatorView = dataGrid.View.inherit({
  53233. _renderSeparator: function(){},
  53234. _renderCore: function(options) {
  53235. this.callBase(options);
  53236. this._isShown = true;
  53237. this._renderSeparator();
  53238. this.hide()
  53239. },
  53240. show: function() {
  53241. this._isShown = true
  53242. },
  53243. hide: function() {
  53244. this._isShown = false
  53245. },
  53246. height: function(value) {
  53247. var $element = this.element();
  53248. if ($element)
  53249. if (utils.isDefined(value))
  53250. $element.height(value);
  53251. else
  53252. return $element.height()
  53253. },
  53254. width: function(value) {
  53255. var $element = this.element();
  53256. if ($element)
  53257. if (utils.isDefined(value))
  53258. $element.width(value);
  53259. else
  53260. return $element.width()
  53261. }
  53262. });
  53263. dataGrid.ColumnsSeparatorView = dataGrid.SeparatorView.inherit({
  53264. _renderSeparator: function() {
  53265. this.callBase();
  53266. var $element = this.element();
  53267. $element.addClass(DATAGRID_COLUMNS_SEPARATOR_CLASS)
  53268. },
  53269. _subscribeToEvent: function() {
  53270. var that = this,
  53271. $element;
  53272. that.getController("tablePosition").positionChanged.add(function(position) {
  53273. $element = that.element();
  53274. if ($element) {
  53275. $element.css({top: position.top});
  53276. $element.height(position.height)
  53277. }
  53278. })
  53279. },
  53280. isVisible: function() {
  53281. return this.option('showColumnHeaders') && (allowReordering(this) || allowResizing(this))
  53282. },
  53283. init: function() {
  53284. this.callBase();
  53285. this._isTransparent = allowResizing(this);
  53286. if (this.isVisible())
  53287. this._subscribeToEvent()
  53288. },
  53289. show: function() {
  53290. var that = this,
  53291. $element = this.element();
  53292. if ($element && !that._isShown)
  53293. if (that._isTransparent)
  53294. $element.removeClass(DATAGRID_COLUMNS_SEPARATOR_TRANSPARENT);
  53295. else
  53296. $element.show();
  53297. this.callBase()
  53298. },
  53299. hide: function() {
  53300. var $element = this.element();
  53301. if ($element && this._isShown)
  53302. if (this._isTransparent)
  53303. $element.addClass(DATAGRID_COLUMNS_SEPARATOR_TRANSPARENT);
  53304. else
  53305. $element.hide();
  53306. this.callBase()
  53307. },
  53308. moveByX: function(outerX) {
  53309. var $element = this.element();
  53310. if ($element) {
  53311. $element.css("left", outerX - this._parentElement().offset().left);
  53312. this._testPosx = outerX
  53313. }
  53314. },
  53315. changeCursor: function(cursorName) {
  53316. cursorName = utils.isDefined(cursorName) ? cursorName : "";
  53317. var $element = this.element();
  53318. if ($element) {
  53319. $element.css('cursor', cursorName);
  53320. this._testCursorName = cursorName
  53321. }
  53322. }
  53323. });
  53324. dataGrid.BlockSeparatorView = dataGrid.SeparatorView.inherit({
  53325. _renderSeparator: function() {
  53326. this.callBase();
  53327. this.element().addClass(DATAGRID_BLOCK_SEPARATOR_CLASS).html('&nbsp;')
  53328. },
  53329. hide: function() {
  53330. var that = this,
  53331. $parent = this._parentElement(),
  53332. $element = this.element();
  53333. if ($element && this._isShown)
  53334. $element.hide();
  53335. if ($parent && !$parent.children('.' + DATAGRID_BLOCK_SEPARATOR_CLASS).length)
  53336. $parent.prepend(that.element());
  53337. that.callBase()
  53338. },
  53339. isVisible: function() {
  53340. var groupPanelOptions = this.option("groupPanel"),
  53341. columnChooserOptions = this.option('columnChooser');
  53342. return groupPanelOptions && groupPanelOptions.visible || columnChooserOptions && columnChooserOptions.enabled
  53343. },
  53344. show: function(targetLocation) {
  53345. var that = this,
  53346. $element = this.element(),
  53347. startAnimate = function(toOptions) {
  53348. fx.stop($element, true);
  53349. fx.animate($element, {
  53350. type: "slide",
  53351. from: {
  53352. width: 0,
  53353. display: toOptions.display
  53354. },
  53355. to: toOptions,
  53356. duration: 300,
  53357. easing: "swing"
  53358. })
  53359. };
  53360. if ($element && !that._isShown)
  53361. switch (targetLocation) {
  53362. case"group":
  53363. startAnimate({
  53364. width: "50px",
  53365. display: "inline-block"
  53366. });
  53367. break;
  53368. case"columnChooser":
  53369. startAnimate({
  53370. width: "100%",
  53371. display: "block"
  53372. });
  53373. break;
  53374. default:
  53375. $element.show()
  53376. }
  53377. that.callBase()
  53378. }
  53379. });
  53380. dataGrid.DraggingHeaderView = dataGrid.View.inherit({
  53381. _isDragging: false,
  53382. _getDropOptions: function() {
  53383. var that = this;
  53384. if (that._dragOptions)
  53385. return {
  53386. sourceColumnIndex: that._dragOptions.columnIndex,
  53387. sourceColumnElement: that._dragOptions.columnElement,
  53388. sourceLocation: that._dragOptions.sourceLocation,
  53389. targetColumnIndex: that._dropColumnIndex,
  53390. targetLocation: that._dropLocation
  53391. }
  53392. },
  53393. _dropHeader: function(args) {
  53394. var e = args.jQueryEvent,
  53395. that = e.data.that,
  53396. controller = that._controller;
  53397. that.element().hide();
  53398. if (controller && that._isDragging)
  53399. controller.drop(that._getDropOptions());
  53400. that.element().appendTo(that._parentElement());
  53401. that._dragOptions = null;
  53402. that._isDragging = false;
  53403. document.onselectstart = that._onSelectStart || null
  53404. },
  53405. _getDraggingPanelByPos: function(pos) {
  53406. var that = this,
  53407. result;
  53408. $.each(that._dragOptions.draggingPanels, function(index, draggingPanel) {
  53409. if (draggingPanel) {
  53410. var boundingRect = draggingPanel.getBoundingRect();
  53411. if (boundingRect && (boundingRect.bottom === undefined || pos.y < boundingRect.bottom) && (boundingRect.top === undefined || pos.y > boundingRect.top) && (boundingRect.left === undefined || pos.x > boundingRect.left) && (boundingRect.right === undefined || pos.x < boundingRect.right)) {
  53412. result = draggingPanel;
  53413. return false
  53414. }
  53415. }
  53416. });
  53417. return result
  53418. },
  53419. _pointCreated: function(point, columns, location, sourceColumn) {
  53420. var targetColumn = columns[point.columnIndex],
  53421. prevColumn = columns[point.columnIndex - 1];
  53422. switch (location) {
  53423. case"columnChooser":
  53424. return true;
  53425. case"headers":
  53426. return sourceColumn && !sourceColumn.allowReordering || (!targetColumn || !targetColumn.allowReordering) && (!prevColumn || !prevColumn.allowReordering);
  53427. default:
  53428. return columns.length === 0
  53429. }
  53430. },
  53431. _moveHeader: function(args) {
  53432. var e = args.jQueryEvent,
  53433. that = e.data.that,
  53434. columnElements,
  53435. pointsByColumns,
  53436. newLeft,
  53437. newTop,
  53438. moveDeltaX,
  53439. moveDeltaY,
  53440. eventData = events.eventData(e),
  53441. targetDraggingPanel,
  53442. controller = that._controller,
  53443. isResizing = that._columnsResizerViewController ? that._columnsResizerViewController.isResizing() : false,
  53444. i,
  53445. params,
  53446. dragOptions = that._dragOptions,
  53447. isVerticalOrientation,
  53448. centerPosition,
  53449. axisName,
  53450. rtlEnabled;
  53451. if (that._isDragging && !isResizing) {
  53452. moveDeltaX = Math.abs(eventData.x - dragOptions.columnElement.offset().left - dragOptions.deltaX);
  53453. moveDeltaY = Math.abs(eventData.y - dragOptions.columnElement.offset().top - dragOptions.deltaY);
  53454. if (that.element().is(':visible') || moveDeltaX > DRAGGING_DELTA || moveDeltaY > DRAGGING_DELTA) {
  53455. that.element().show();
  53456. newLeft = eventData.x - dragOptions.deltaX;
  53457. newTop = eventData.y - dragOptions.deltaY;
  53458. that.element().offset({
  53459. left: newLeft,
  53460. top: newTop
  53461. });
  53462. targetDraggingPanel = that._getDraggingPanelByPos(eventData);
  53463. if (targetDraggingPanel) {
  53464. rtlEnabled = that.option('rtlEnabled');
  53465. isVerticalOrientation = targetDraggingPanel.getName() === 'columnChooser';
  53466. axisName = isVerticalOrientation ? 'y' : 'x';
  53467. columnElements = targetDraggingPanel.getColumnElements() || [];
  53468. pointsByColumns = dataGrid.getPointsByColumns(columnElements, function(point) {
  53469. return that._pointCreated(point, targetDraggingPanel.getColumns(), targetDraggingPanel.getName(), dragOptions.sourceColumn)
  53470. }, axisName === 'y');
  53471. that._dropLocation = targetDraggingPanel.getName();
  53472. if (pointsByColumns.length > 0)
  53473. for (i = 0; i < pointsByColumns.length; i++) {
  53474. centerPosition = pointsByColumns[i + 1] && (pointsByColumns[i][axisName] + pointsByColumns[i + 1][axisName]) / 2;
  53475. if (centerPosition === undefined || (rtlEnabled && axisName === 'x' ? eventData[axisName] > centerPosition : eventData[axisName] < centerPosition)) {
  53476. that._dropColumnIndex = pointsByColumns[i].columnIndex;
  53477. params = that._getDropOptions();
  53478. if (columnElements[i])
  53479. params.targetColumnElement = columnElements.eq(i);
  53480. else {
  53481. params.targetColumnElement = columnElements.last();
  53482. params.isLast = true
  53483. }
  53484. params.posX = pointsByColumns[i].x;
  53485. controller.dock(params);
  53486. break
  53487. }
  53488. }
  53489. else {
  53490. that._dropColumnIndex = -1;
  53491. params = that._getDropOptions();
  53492. controller.dock(params)
  53493. }
  53494. }
  53495. }
  53496. e.preventDefault()
  53497. }
  53498. },
  53499. _subscribeToEvents: function(rootElement) {
  53500. var that = this;
  53501. that._moveHeaderAction = this.createAction(this._moveHeader);
  53502. that._dropHeaderAction = this.createAction(this._dropHeader);
  53503. $(document).on(addNamespace('dxpointermove', DATAGRID_MODULE_NAMESPACE), {
  53504. that: that,
  53505. rootElement: rootElement
  53506. }, that._moveHeaderAction);
  53507. that.element().on(addNamespace('dxpointerup', DATAGRID_MODULE_NAMESPACE), {that: that}, that._dropHeaderAction);
  53508. $(document).on(addNamespace('dxpointerup', DATAGRID_MODULE_NAMESPACE), {that: that}, that._dropHeaderAction)
  53509. },
  53510. _renderCore: function() {
  53511. this.element().addClass(DATAGRID_DRAGGING_HEADER_CLASS + ' ' + DATAGRID_CELL_CONTENT_CLASS + ' ' + WIDGET_CLASS).css('display', 'none')
  53512. },
  53513. _afterRender: function($parent) {
  53514. this._unsubscribeFromEvents();
  53515. this._subscribeToEvents($parent)
  53516. },
  53517. _unsubscribeFromEvents: function() {
  53518. if (this._dropHeaderAction) {
  53519. this.element().off(addNamespace('dxpointerup', DATAGRID_MODULE_NAMESPACE), this._dropHeaderAction);
  53520. $(document).off(addNamespace('dxpointerup', DATAGRID_MODULE_NAMESPACE), this._dropHeaderAction)
  53521. }
  53522. if (this._moveHeaderAction)
  53523. $(document).off(addNamespace('dxpointermove', DATAGRID_MODULE_NAMESPACE), this._moveHeaderAction)
  53524. },
  53525. dispose: function() {
  53526. var element = this.element();
  53527. this._dragOptions = null;
  53528. this._unsubscribeFromEvents();
  53529. element && element.parent().find('.' + DATAGRID_DRAGGING_HEADER_CLASS).remove()
  53530. },
  53531. isVisible: function() {
  53532. var columnsController = this.getController("columns"),
  53533. commonColumnSettings = columnsController.getCommonSettings();
  53534. return this.option('showColumnHeaders') && (allowReordering(this) || commonColumnSettings.allowGrouping || commonColumnSettings.allowHiding)
  53535. },
  53536. init: function() {
  53537. this.callBase();
  53538. this._controller = this.getController("draggingHeader");
  53539. this._columnsResizerViewController = this.getController("columnsResizer")
  53540. },
  53541. drag: function(options) {
  53542. var that = this,
  53543. columnElement = options.columnElement;
  53544. that._dragOptions = options;
  53545. that._isDragging = true;
  53546. that._dropColumnIndex = options.columnIndex;
  53547. that._dropLocation = options.sourceLocation;
  53548. that._onSelectStart = document.onselectstart;
  53549. document.onselectstart = function() {
  53550. return false
  53551. };
  53552. that.element().css({
  53553. textAlign: columnElement && columnElement.css('text-align'),
  53554. height: columnElement && columnElement.height(),
  53555. width: columnElement && columnElement.width(),
  53556. whiteSpace: columnElement && columnElement.css('white-space')
  53557. }).addClass(DATAGRID_HEADERS_DRAG_ACTION_CLASS).text(options.sourceColumn.caption);
  53558. that.element().appendTo($(document.body))
  53559. }
  53560. });
  53561. dataGrid.ColumnsResizerViewController = dataGrid.ViewController.inherit({
  53562. _isHeadersRowArea: function(posY) {
  53563. if (this._columnHeadersView) {
  53564. var element = this._columnHeadersView.element(),
  53565. headersRowHeight,
  53566. offsetTop;
  53567. if (element) {
  53568. offsetTop = element.offset().top;
  53569. headersRowHeight = this._columnHeadersView.getHeadersRowHeight();
  53570. return posY >= offsetTop && posY <= offsetTop + headersRowHeight
  53571. }
  53572. }
  53573. return false
  53574. },
  53575. _pointCreated: function(point, cellsLength, columns) {
  53576. var currentColumn,
  53577. nextColumn;
  53578. if (point.index > 0 && point.index < cellsLength) {
  53579. point.columnIndex -= 1;
  53580. currentColumn = columns[point.columnIndex] || {};
  53581. nextColumn = columns[point.columnIndex + 1] || {};
  53582. return !(currentColumn.allowResizing && nextColumn.allowResizing)
  53583. }
  53584. return true
  53585. },
  53586. _getTargetPoint: function(pointsByColumns, currentX, deltaX) {
  53587. if (pointsByColumns)
  53588. for (var i = 0; i < pointsByColumns.length; i++)
  53589. if (pointsByColumns[i].x - deltaX <= currentX && currentX <= pointsByColumns[i].x + deltaX)
  53590. return pointsByColumns[i];
  53591. return null
  53592. },
  53593. _moveSeparator: function(args) {
  53594. var e = args.jQueryEvent,
  53595. that = e.data,
  53596. pointsByColumns = that._pointsByColumns,
  53597. columnsSeparatorWidth = that._columnsSeparatorView.width(),
  53598. columnsSeparatorOffset = that._columnsSeparatorView.element().offset(),
  53599. deltaX = columnsSeparatorWidth / 2,
  53600. parentOffsetLeft = that._$parentContainer.offset().left,
  53601. eventData = events.eventData(e);
  53602. if (that._isResizing) {
  53603. if (parentOffsetLeft <= eventData.x && eventData.x <= parentOffsetLeft + that._$parentContainer.width())
  53604. if (that._updateColumnsWidthIfNeeded(that._targetPoint.columnIndex, eventData.x)) {
  53605. that._columnsSeparatorView.moveByX(that._targetPoint.x + (eventData.x - that._resizingInfo.startPosX));
  53606. that._tablePositionController.update();
  53607. e.preventDefault()
  53608. }
  53609. }
  53610. else if (that._isHeadersRowArea(eventData.y)) {
  53611. that._targetPoint = that._getTargetPoint(pointsByColumns, eventData.x, columnsSeparatorWidth);
  53612. that._isReadyResizing = false;
  53613. that._columnsSeparatorView.changeCursor();
  53614. if (that._targetPoint && columnsSeparatorOffset.top <= eventData.y && columnsSeparatorOffset.top + that._columnsSeparatorView.height() >= eventData.y) {
  53615. that._columnsSeparatorView.changeCursor('col-resize');
  53616. that._columnsSeparatorView.moveByX(that._targetPoint.x - deltaX);
  53617. that._isReadyResizing = true;
  53618. e.preventDefault()
  53619. }
  53620. }
  53621. else {
  53622. that._isReadyResizing = false;
  53623. that._columnsSeparatorView.changeCursor()
  53624. }
  53625. },
  53626. _endResizing: function(args) {
  53627. var e = args.jQueryEvent,
  53628. that = e.data;
  53629. if (that._isResizing) {
  53630. that._updatePointsByColumns();
  53631. that._resizingInfo = null;
  53632. that._columnsSeparatorView.hide();
  53633. that._columnsSeparatorView.changeCursor();
  53634. that._trackerView.hide();
  53635. that._isReadyResizing = false;
  53636. that._isResizing = false
  53637. }
  53638. },
  53639. _setupResizingInfo: function(posX) {
  53640. var that = this,
  53641. currentHeader = that._columnHeadersView.getHeaderElement(that._targetPoint.columnIndex),
  53642. nextHeader = that._columnHeadersView.getHeaderElement(that._targetPoint.columnIndex + 1);
  53643. that._resizingInfo = {
  53644. startPosX: posX,
  53645. currentColumnWidth: currentHeader && currentHeader.length > 0 ? currentHeader.outerWidth() : 0,
  53646. nextColumnWidth: nextHeader && nextHeader.length > 0 ? nextHeader.outerWidth() : 0
  53647. }
  53648. },
  53649. _startResizing: function(args) {
  53650. var e = args.jQueryEvent,
  53651. that = e.data,
  53652. eventData = events.eventData(e);
  53653. if (events.isTouchEvent(e))
  53654. if (that._isHeadersRowArea(eventData.y)) {
  53655. that._targetPoint = that._getTargetPoint(that._pointsByColumns, eventData.x, COLUMNS_SEPARATOR_TOUCH_TRACKER_WIDTH);
  53656. if (that._targetPoint) {
  53657. that._columnsSeparatorView.moveByX(that._targetPoint.x - that._columnsSeparatorView.width() / 2);
  53658. that._isReadyResizing = true
  53659. }
  53660. }
  53661. else
  53662. that._isReadyResizing = false;
  53663. if (that._isReadyResizing) {
  53664. if (that._targetPoint)
  53665. that._testColumnIndex = that._targetPoint.columnIndex;
  53666. that._setupResizingInfo(eventData.x);
  53667. that._columnsSeparatorView.show();
  53668. that._trackerView.show();
  53669. that._isResizing = true;
  53670. e.preventDefault()
  53671. }
  53672. },
  53673. _generatePointsByColumns: function() {
  53674. var that = this,
  53675. columns = that._columnsController ? that._columnsController.getVisibleColumns() : [],
  53676. cells = that._columnHeadersView.getColumnElements(),
  53677. pointsByColumns = [];
  53678. if (cells && cells.length > 0)
  53679. pointsByColumns = dataGrid.getPointsByColumns(cells, function(point) {
  53680. return that._pointCreated(point, cells.length, columns)
  53681. });
  53682. that._pointsByColumns = pointsByColumns
  53683. },
  53684. _unsubscribeFromEvents: function() {
  53685. this._moveSeparatorHandler && this._$parentContainer.off(addNamespace('dxpointermove', DATAGRID_MODULE_NAMESPACE), this._moveSeparatorHandler);
  53686. this._startResizingHandler && this._$parentContainer.off(addNamespace('dxpointerdown', DATAGRID_MODULE_NAMESPACE), this._startResizingHandler);
  53687. if (this._endResizingHandler) {
  53688. this._columnsSeparatorView.element().off(addNamespace('dxpointerup', DATAGRID_MODULE_NAMESPACE), this._endResizingHandler);
  53689. $(document).off(addNamespace('dxpointerup', DATAGRID_MODULE_NAMESPACE), this._endResizingHandler)
  53690. }
  53691. },
  53692. _subscribeToEvents: function() {
  53693. this._moveSeparatorHandler = this.createAction(this._moveSeparator);
  53694. this._startResizingHandler = this.createAction(this._startResizing);
  53695. this._endResizingHandler = this.createAction(this._endResizing);
  53696. this._$parentContainer.on(addNamespace('dxpointermove', DATAGRID_MODULE_NAMESPACE), this, this._moveSeparatorHandler);
  53697. this._$parentContainer.on(addNamespace('dxpointerdown', DATAGRID_MODULE_NAMESPACE), this, this._startResizingHandler);
  53698. this._columnsSeparatorView.element().on(addNamespace('dxpointerup', DATAGRID_MODULE_NAMESPACE), this, this._endResizingHandler);
  53699. $(document).on(addNamespace('dxpointerup', DATAGRID_MODULE_NAMESPACE), this, this._endResizingHandler)
  53700. },
  53701. _updateColumnsWidthIfNeeded: function(columnIndex, posX) {
  53702. var deltaX,
  53703. isUpdated = false,
  53704. nextCellWidth,
  53705. columnsController = this._columnsController,
  53706. visibleColumns = columnsController.getVisibleColumns(),
  53707. columnsSeparatorWidth = this._columnsSeparatorView.width(),
  53708. column,
  53709. nextColumn,
  53710. cellWidth;
  53711. deltaX = posX - this._resizingInfo.startPosX;
  53712. if (this.option("rtlEnabled"))
  53713. deltaX = -deltaX;
  53714. cellWidth = this._resizingInfo.currentColumnWidth + deltaX;
  53715. nextCellWidth = this._resizingInfo.nextColumnWidth - deltaX;
  53716. isUpdated = !(cellWidth <= columnsSeparatorWidth || nextCellWidth <= columnsSeparatorWidth);
  53717. if (isUpdated) {
  53718. column = visibleColumns[columnIndex];
  53719. nextColumn = visibleColumns[columnIndex + 1];
  53720. columnsController.beginUpdate();
  53721. column && columnsController.columnOption(column.index, 'visibleWidth', undefined);
  53722. nextColumn && columnsController.columnOption(nextColumn.index, 'visibleWidth', undefined);
  53723. column && columnsController.columnOption(column.index, 'width', Math.floor(cellWidth));
  53724. nextColumn && columnsController.columnOption(nextColumn.index, 'width', Math.floor(nextCellWidth));
  53725. columnsController.endUpdate()
  53726. }
  53727. return isUpdated
  53728. },
  53729. _updatePointsByColumns: function() {
  53730. var i,
  53731. point,
  53732. rtlEnabled = this.option("rtlEnabled"),
  53733. headerElement;
  53734. for (i = 0; i < this._pointsByColumns.length; i++) {
  53735. point = this._pointsByColumns[i];
  53736. headerElement = this._columnHeadersView.getHeaderElement(point.columnIndex + 1);
  53737. if (headerElement && headerElement.length > 0)
  53738. point.x = headerElement.offset().left + (rtlEnabled ? headerElement.outerWidth() : 0)
  53739. }
  53740. },
  53741. isResizing: function() {
  53742. return this._isResizing
  53743. },
  53744. init: function() {
  53745. var that = this,
  53746. gridView,
  53747. previousScrollbarVisibility,
  53748. generatePointsByColumnsScrollHandler = function(offset) {
  53749. if (that._scrollLeft !== offset.left) {
  53750. that._scrollLeft = offset.left;
  53751. that._generatePointsByColumns()
  53752. }
  53753. },
  53754. generatePointsByColumnsHandler = function() {
  53755. that._generatePointsByColumns()
  53756. };
  53757. that.callBase();
  53758. if (allowResizing(that)) {
  53759. that._columnsSeparatorView = that.getView("columnsSeparatorView");
  53760. that._columnHeadersView = that.getView("columnHeadersView");
  53761. that._trackerView = that.getView("trackerView");
  53762. that._rowsView = that.getView("rowsView");
  53763. that._columnsController = that.getController("columns");
  53764. that._tablePositionController = that.getController("tablePosition");
  53765. that._$parentContainer = that._columnsSeparatorView.component.element();
  53766. that._columnHeadersView.renderCompleted.add(generatePointsByColumnsHandler);
  53767. that._columnHeadersView.resizeCompleted.add(generatePointsByColumnsHandler);
  53768. that._columnsSeparatorView.renderCompleted.add(function() {
  53769. that._unsubscribeFromEvents();
  53770. that._subscribeToEvents()
  53771. });
  53772. that._rowsView.renderCompleted.add(function() {
  53773. that._rowsView.scrollOffsetChanged.remove(generatePointsByColumnsScrollHandler);
  53774. that._rowsView.scrollOffsetChanged.add(generatePointsByColumnsScrollHandler)
  53775. });
  53776. gridView = that.getView("gridView");
  53777. previousScrollbarVisibility = that._rowsView.getScrollbarWidth() !== 0;
  53778. that.getController("tablePosition").positionChanged.add(function() {
  53779. if (that._isResizing && !that._rowsView.isResizing) {
  53780. var scrollbarVisibility = that._rowsView.getScrollbarWidth() !== 0;
  53781. if (previousScrollbarVisibility !== scrollbarVisibility) {
  53782. previousScrollbarVisibility = scrollbarVisibility;
  53783. gridView.resize()
  53784. }
  53785. else {
  53786. that._rowsView.updateFreeSpaceRowHeight();
  53787. that._columnHeadersView.processSizeChanged()
  53788. }
  53789. }
  53790. })
  53791. }
  53792. },
  53793. dispose: function() {
  53794. this._unsubscribeFromEvents()
  53795. }
  53796. });
  53797. dataGrid.TablePositionViewController = dataGrid.ViewController.inherit({
  53798. update: function() {
  53799. var $element = this._columnHeadersView.element(),
  53800. columnsHeadersHeight = this._columnHeadersView ? this._columnHeadersView.getHeight() : 0,
  53801. rowsHeight = this._rowsView ? this._rowsView.height() - this._rowsView.getScrollbarWidth(true) : 0;
  53802. this.positionChanged.fire({
  53803. height: columnsHeadersHeight + rowsHeight,
  53804. top: $element && $element.length > 0 ? Math.floor($element[0].offsetTop) : 0
  53805. })
  53806. },
  53807. init: function() {
  53808. var that = this;
  53809. that.callBase();
  53810. that._columnHeadersView = this.getView("columnHeadersView");
  53811. that._rowsView = this.getView("rowsView");
  53812. that._pagerView = this.getView("pagerView");
  53813. that._rowsView.resizeCompleted.add(function() {
  53814. that.update()
  53815. })
  53816. },
  53817. ctor: function(component) {
  53818. this.callBase(component);
  53819. this.positionChanged = $.Callbacks()
  53820. }
  53821. });
  53822. dataGrid.DraggingHeaderViewController = dataGrid.ViewController.inherit({
  53823. _subscribeToEvent: function(draggingHeader, draggingPanels) {
  53824. var that = this;
  53825. $.each(draggingPanels, function(_, draggingPanel) {
  53826. if (draggingPanel) {
  53827. var columnElements = draggingPanel.getColumnElements() || [],
  53828. nameDraggingPanel = draggingPanel.getName(),
  53829. columns = draggingPanel.getColumns() || [];
  53830. $.each(columnElements, function(index, columnElement) {
  53831. var $columnElement = $(columnElement);
  53832. $columnElement.off(addNamespace('dxpointerdown', DATAGRID_MODULE_NAMESPACE));
  53833. $columnElement.removeClass(DATAGRID_HEADERS_DRAG_ACTION_CLASS);
  53834. if (draggingPanel.allowDragging(columns[index], draggingPanels)) {
  53835. $columnElement.addClass(DATAGRID_HEADERS_DRAG_ACTION_CLASS);
  53836. $columnElement.on(addNamespace('dxpointerdown', DATAGRID_MODULE_NAMESPACE), that.createAction(function(args) {
  53837. var e = args.jQueryEvent,
  53838. eventData = events.eventData(e);
  53839. e.preventDefault();
  53840. e.stopPropagation();
  53841. draggingHeader.drag({
  53842. deltaX: eventData.x - $(e.currentTarget).offset().left,
  53843. deltaY: eventData.y - $(e.currentTarget).offset().top,
  53844. sourceColumn: columns[index],
  53845. columnIndex: index,
  53846. columnElement: $columnElement,
  53847. sourceLocation: nameDraggingPanel,
  53848. draggingPanels: draggingPanels
  53849. })
  53850. }))
  53851. }
  53852. })
  53853. }
  53854. })
  53855. },
  53856. _getSeparator: function(targetLocation) {
  53857. return targetLocation === "headers" ? this._columnsSeparatorView : this._blockSeparatorView
  53858. },
  53859. hideSeparators: function() {
  53860. var blockSeparator = this._blockSeparatorView,
  53861. columnsSeparator = this._columnsSeparatorView;
  53862. this._animationColumnIndex = null;
  53863. blockSeparator && blockSeparator.hide();
  53864. columnsSeparator && columnsSeparator.hide()
  53865. },
  53866. init: function() {
  53867. var that = this,
  53868. subscribeToEvent;
  53869. that.callBase();
  53870. that._columnsController = that.getController("columns");
  53871. that._columnHeadersView = that.getView("columnHeadersView");
  53872. that._columnsSeparatorView = that.getView("columnsSeparatorView");
  53873. that._draggingHeaderView = that.getView("draggingHeaderView");
  53874. that._rowsView = that.getView('rowsView');
  53875. that._blockSeparatorView = that.getView("blockSeparatorView");
  53876. that._headerPanelView = that.getView("headerPanel");
  53877. that._columnChooserView = that.getView("columnChooserView");
  53878. subscribeToEvent = function() {
  53879. if (that._draggingHeaderView)
  53880. that._subscribeToEvent(that._draggingHeaderView, [that._columnChooserView, that._columnHeadersView, that._headerPanelView])
  53881. };
  53882. that._columnHeadersView.renderCompleted.add(subscribeToEvent);
  53883. that._headerPanelView && that._headerPanelView.renderCompleted.add(subscribeToEvent);
  53884. that._columnChooserView && that._columnChooserView.renderCompleted.add(subscribeToEvent)
  53885. },
  53886. allowDrop: function(parameters) {
  53887. return this._columnsController.allowMoveColumn(parameters.sourceColumnIndex, parameters.targetColumnIndex, parameters.sourceLocation, parameters.targetLocation)
  53888. },
  53889. dock: function(parameters) {
  53890. var that = this,
  53891. targetColumnIndex = parameters.targetColumnIndex,
  53892. sourceLocation = parameters.sourceLocation,
  53893. sourceColumnIndex = parameters.sourceColumnIndex,
  53894. sourceColumnElement = parameters.sourceColumnElement,
  53895. targetLocation = parameters.targetLocation,
  53896. separator = that._getSeparator(targetLocation),
  53897. hasTargetColumnIndex = targetColumnIndex >= 0;
  53898. var showSeparator = function() {
  53899. if (that._animationColumnIndex !== targetColumnIndex) {
  53900. that.hideSeparators();
  53901. separator.element()[parameters.isLast ? 'insertAfter' : 'insertBefore'](parameters.targetColumnElement);
  53902. that._animationColumnIndex = targetColumnIndex;
  53903. separator.show(targetLocation)
  53904. }
  53905. };
  53906. that._columnHeadersView.element().find('.' + DATAGRID_HEADER_ROW_CLASS).toggleClass(DATAGRID_HEADERS_DROP_HIGHLIGHT_CLASS, sourceLocation !== 'headers' && targetLocation === 'headers' && !hasTargetColumnIndex);
  53907. if (separator) {
  53908. if (sourceColumnElement) {
  53909. sourceColumnElement.css({opacity: 0.5});
  53910. if (sourceLocation === 'headers')
  53911. that._rowsView.setRowsOpacity(sourceColumnIndex, 0.5)
  53912. }
  53913. if (that.allowDrop(parameters) && hasTargetColumnIndex)
  53914. if (targetLocation === 'group' || targetLocation === 'columnChooser')
  53915. showSeparator();
  53916. else {
  53917. that.hideSeparators();
  53918. separator.moveByX(parameters.posX - separator.width());
  53919. separator.show()
  53920. }
  53921. else
  53922. that.hideSeparators()
  53923. }
  53924. },
  53925. drop: function(parameters) {
  53926. var sourceColumnElement = parameters.sourceColumnElement;
  53927. if (sourceColumnElement) {
  53928. sourceColumnElement.css({opacity: ''});
  53929. this._rowsView.setRowsOpacity(parameters.sourceColumnIndex, '');
  53930. this._columnHeadersView.element().find('.' + DATAGRID_HEADER_ROW_CLASS).removeClass(DATAGRID_HEADERS_DROP_HIGHLIGHT_CLASS)
  53931. }
  53932. if (this.allowDrop(parameters)) {
  53933. var separator = this._getSeparator(parameters.targetLocation);
  53934. if (separator)
  53935. separator.hide();
  53936. this._columnsController.moveColumn(parameters.sourceColumnIndex, parameters.targetColumnIndex, parameters.sourceLocation, parameters.targetLocation)
  53937. }
  53938. }
  53939. });
  53940. dataGrid.__internals = $.extend({}, dataGrid.__internals, {
  53941. DATAGRID_COLUMNS_SEPARATOR_CLASS: DATAGRID_COLUMNS_SEPARATOR_CLASS,
  53942. DATAGRID_COLUMNS_SEPARATOR_TRANSPARENT: DATAGRID_COLUMNS_SEPARATOR_TRANSPARENT,
  53943. DATAGRID_DRAGGING_HEADER_CLASS: DATAGRID_DRAGGING_HEADER_CLASS,
  53944. DATAGRID_HEADERS_DRAG_ACTION_CLASS: DATAGRID_HEADERS_DRAG_ACTION_CLASS,
  53945. DATAGRID_CELL_CONTENT_CLASS: DATAGRID_CELL_CONTENT_CLASS,
  53946. DATAGRID_TRACKER_CLASS: DATAGRID_TRACKER_CLASS,
  53947. DATAGRID_MODULE_NAMESPACE: DATAGRID_MODULE_NAMESPACE,
  53948. DATAGRID_HEADERS_DROP_HIGHLIGHT_CLASS: DATAGRID_HEADERS_DROP_HIGHLIGHT_CLASS,
  53949. WIDGET_CLASS: WIDGET_CLASS
  53950. });
  53951. dataGrid.registerModule("columnsResizingReordering", {
  53952. views: {
  53953. columnsSeparatorView: dataGrid.ColumnsSeparatorView,
  53954. blockSeparatorView: dataGrid.BlockSeparatorView,
  53955. draggingHeaderView: dataGrid.DraggingHeaderView,
  53956. trackerView: dataGrid.TrackerView
  53957. },
  53958. controllers: {
  53959. draggingHeader: dataGrid.DraggingHeaderViewController,
  53960. tablePosition: dataGrid.TablePositionViewController,
  53961. columnsResizer: dataGrid.ColumnsResizerViewController
  53962. }
  53963. })
  53964. })(jQuery, DevExpress);
  53965. /*! Module widgets-web, file ui.dataGrid.contextMenuView.js */
  53966. (function($, DX) {
  53967. var ui = DX.ui,
  53968. dataGrid = ui.dxDataGrid;
  53969. var DATAGRID_CLASS = "dx-datagrid",
  53970. DATAGRID_CONTEXT_MENU = "dx-context-menu",
  53971. viewName = {
  53972. columnHeadersView: "header",
  53973. rowsView: "content",
  53974. footerView: "footer"
  53975. },
  53976. VIEW_NAMES = ["columnHeadersView", "rowsView", "footerView"];
  53977. dataGrid.ContextMenuController = dataGrid.ViewController.inherit({
  53978. init: function() {
  53979. this.createAction("onContextMenuPreparing")
  53980. },
  53981. getContextMenuItems: function($targetElement) {
  53982. var that = this,
  53983. view,
  53984. options,
  53985. rowIndex,
  53986. columnIndex,
  53987. $targetRowElement,
  53988. $targetCellElement,
  53989. menuItems;
  53990. $.each(VIEW_NAMES, function() {
  53991. view = that.getView(this);
  53992. if (view && view.element().find($targetElement).length) {
  53993. $targetCellElement = $targetElement.closest("td");
  53994. $targetRowElement = $targetCellElement.closest(".dx-row");
  53995. rowIndex = view.getRowIndex($targetRowElement);
  53996. columnIndex = $targetCellElement[0] && $targetCellElement[0].cellIndex;
  53997. options = {
  53998. targetElement: $targetElement,
  53999. target: viewName[this],
  54000. rowIndex: rowIndex,
  54001. row: view._getRows()[rowIndex],
  54002. columnIndex: columnIndex,
  54003. column: view.getColumns()[columnIndex],
  54004. items: view.getContextMenuItems && view.getContextMenuItems($targetElement)
  54005. };
  54006. that.executeAction("onContextMenuPreparing", options);
  54007. menuItems = options.items;
  54008. if (menuItems)
  54009. return false
  54010. }
  54011. });
  54012. return menuItems
  54013. }
  54014. });
  54015. dataGrid.ContextMenuView = dataGrid.View.inherit({_renderCore: function() {
  54016. var that = this;
  54017. this._createComponent(that.element().addClass(DATAGRID_CONTEXT_MENU), "dxContextMenu", {
  54018. onPositioning: function(actionArgs) {
  54019. var event = actionArgs.jQueryEvent,
  54020. $targetElement = $(event.target),
  54021. contextMenuInstance = actionArgs.component,
  54022. items = that.getController('contextMenu').getContextMenuItems($targetElement);
  54023. if (items) {
  54024. contextMenuInstance.option('items', items);
  54025. event.stopPropagation()
  54026. }
  54027. else
  54028. actionArgs.canceled = true
  54029. },
  54030. onItemClick: function(params) {
  54031. params.itemData.onItemClick && params.itemData.onItemClick(params)
  54032. },
  54033. cssClass: DATAGRID_CLASS,
  54034. target: that.component.element()
  54035. })
  54036. }});
  54037. dataGrid.registerModule("contextMenu", {
  54038. defaultOptions: function() {
  54039. return {onContextMenuPreparing: null}
  54040. },
  54041. controllers: {contextMenu: dataGrid.ContextMenuController},
  54042. views: {contextMenuView: dataGrid.ContextMenuView}
  54043. })
  54044. })(jQuery, DevExpress);
  54045. /*! Module widgets-web, file ui.dataGrid.keyboardNavigation.js */
  54046. (function($, DX) {
  54047. var ui = DX.ui,
  54048. utils = DX.utils,
  54049. events = ui.events,
  54050. dataGrid = ui.dxDataGrid;
  54051. var DATAGRID_ROW_CLASS = "dx-row",
  54052. DATAGRID_GROUP_ROW_CLASS = "dx-group-row",
  54053. DATAGRID_ROWS_VIEW_CLASS = "dx-datagrid-rowsview",
  54054. DATAGRID_MASTER_DETAIL_ROW_CLASS = "dx-master-detail-row",
  54055. DATAGRID_GROUP_FOOTER_CLASS = "dx-datagrid-group-footer",
  54056. DATAGRID_COMMAND_EXPAND_CLASS = "dx-command-expand",
  54057. DATAGRID_INTERACTIVE_ELEMENTS_SELECTOR = ".dx-checkbox, .dx-menu, input",
  54058. DATAGRID_VIEWS = ["rowsView", "columnHeadersView"],
  54059. DATAGRID_EDIT_MODE_ROW = "row";
  54060. dataGrid.KeyboardNavigationController = dataGrid.ViewController.inherit({
  54061. _focusView: function(view, viewIndex) {
  54062. this._focusedViews.viewIndex = viewIndex;
  54063. this._focusedView = view
  54064. },
  54065. _focusInteractiveElement: function($cell) {
  54066. var $focusedElement = $cell.find(DATAGRID_INTERACTIVE_ELEMENTS_SELECTOR).first();
  54067. this._testInteractiveElement = $focusedElement;
  54068. $focusedElement.focus()
  54069. },
  54070. _updateFocus: function() {
  54071. var that = this,
  54072. $cell = that._getFocusedCell();
  54073. if ($cell) {
  54074. if (that._hasSkipRow($cell.parent()))
  54075. $cell = that._getNextCell("upArrow");
  54076. if ($cell && $cell.length > 0)
  54077. setTimeout(function() {
  54078. if (that.getController('editorFactory').focus())
  54079. that._focus($cell);
  54080. that._editingController.isEditing() && $.proxy(that._focusInteractiveElement, that)($cell)
  54081. })
  54082. }
  54083. },
  54084. _clickHandler: function(e) {
  54085. var event = e.jQueryEvent,
  54086. $cell = $(event.currentTarget);
  54087. if (this._isCellValid($cell, true)) {
  54088. this._focusView(event.data.view, event.data.viewIndex);
  54089. this._updateFocusedCellPosition($cell);
  54090. if (!this._editingController.isEditing()) {
  54091. $cell.focus();
  54092. this._testCellIsFocused = true
  54093. }
  54094. }
  54095. else
  54096. this._resetFocusedCell(this)
  54097. },
  54098. _initFocusedViews: function() {
  54099. var that = this,
  54100. clickAction = that.createAction(that._clickHandler);
  54101. that._focusedViews = [];
  54102. $.each(DATAGRID_VIEWS, function(key, viewName) {
  54103. var view = that.getView(viewName);
  54104. if (view && view.isVisible())
  54105. that._focusedViews.push(view)
  54106. });
  54107. $.each(that._focusedViews, function(index, view) {
  54108. if (view)
  54109. view.renderCompleted.add(function() {
  54110. var $element = view.element();
  54111. $element.off(events.addNamespace("dxpointerdown", "dxDataGridKeyboardNavigation"), clickAction);
  54112. $element.on(events.addNamespace("dxpointerdown", "dxDataGridKeyboardNavigation"), "." + DATAGRID_ROW_CLASS + " td", {
  54113. viewIndex: index,
  54114. view: view
  54115. }, clickAction);
  54116. that._initKeyDownProcessor(that, $element, that._keyDownHandler);
  54117. if (that._focusedView && that._focusedView.name === view.name && that._isNeedFocus)
  54118. that._updateFocus()
  54119. })
  54120. })
  54121. },
  54122. _initKeyDownProcessor: function(context, element, handler) {
  54123. if (this._keyDownProcessor) {
  54124. this._keyDownProcessor.dispose();
  54125. this._keyDownProcessor = null
  54126. }
  54127. this._keyDownProcessor = new ui.KeyboardProcessor({
  54128. element: element,
  54129. context: context,
  54130. handler: handler
  54131. })
  54132. },
  54133. _getFocusedCell: function() {
  54134. if (this._focusedView && this._focusedCellPosition)
  54135. return this._focusedView.getCell(this._focusedCellPosition)
  54136. },
  54137. _updateFocusedCellPosition: function($cell) {
  54138. var that = this,
  54139. rowsView = that.getView("rowsView");
  54140. if ($cell.length > 0)
  54141. this._focusedCellPosition = {
  54142. columnIndex: rowsView.getCellIndex($cell),
  54143. rowIndex: $cell.parent().length > 0 && that._focusedView ? that._focusedView.getRowIndex($cell.parent()) : null
  54144. }
  54145. },
  54146. _isCellValid: function($cell, allCommandColumns) {
  54147. if (utils.isDefined($cell)) {
  54148. var visibleColumns = this._columnsController.getVisibleColumns(),
  54149. columnIndex = $cell[0].cellIndex,
  54150. isExpandColumn = !allCommandColumns ? visibleColumns[columnIndex].command === "expand" : false,
  54151. isValidGroupSpaceColumn = !utils.isDefined(visibleColumns[columnIndex].groupIndex) || parseInt($cell.attr("colspan")) > 1;
  54152. if (visibleColumns.length > columnIndex && isValidGroupSpaceColumn)
  54153. return !utils.isDefined(visibleColumns[columnIndex].command) || isExpandColumn
  54154. }
  54155. },
  54156. _isCellByPositionValid: function(cellPosition, allCommandColumns) {
  54157. var $cell = this._focusedView && this._focusedView.getCell(cellPosition);
  54158. return this._isCellValid($cell, allCommandColumns)
  54159. },
  54160. _isGroupRow: function($row) {
  54161. return $row && $row.hasClass(DATAGRID_GROUP_ROW_CLASS)
  54162. },
  54163. _focus: function($cell) {
  54164. var $row = $cell.parent(),
  54165. $focusedCell = this._getFocusedCell(),
  54166. $focusElement;
  54167. $focusedCell && $focusedCell.attr("tabindex", null);
  54168. if (this._isGroupRow($row)) {
  54169. $focusElement = $row;
  54170. this._focusedCellPosition.rowIndex = this._focusedView.getRowIndex($row)
  54171. }
  54172. else {
  54173. $focusElement = $cell;
  54174. this._updateFocusedCellPosition($cell)
  54175. }
  54176. $focusElement.attr("tabindex", 0);
  54177. $focusElement.focus();
  54178. this.getController('editorFactory').focus($focusElement)
  54179. },
  54180. _hasSkipRow: function($row) {
  54181. return $row && ($row.hasClass(DATAGRID_MASTER_DETAIL_ROW_CLASS) || $row.hasClass(DATAGRID_GROUP_FOOTER_CLASS))
  54182. },
  54183. _enterKeyHandler: function(eventArgs, isEditing) {
  54184. var $cell = this._getFocusedCell(),
  54185. editingOptions = this.option("editing"),
  54186. rowIndex = this._focusedCellPosition ? this._focusedCellPosition.rowIndex : null,
  54187. $row = this._focusedView && this._focusedView.getRow(rowIndex);
  54188. if (this.option("grouping.allowCollapsing") && this._isGroupRow($row) || this.option("masterDetail.enabled") && $cell.hasClass(DATAGRID_COMMAND_EXPAND_CLASS)) {
  54189. var key = this._dataController.getKeyByRowIndex(rowIndex),
  54190. item = this._dataController.items()[rowIndex];
  54191. if (key !== undefined && item && item.data && !item.data.isContinuation)
  54192. this._dataController.changeRowExpand(key)
  54193. }
  54194. else {
  54195. var isRowEditMode = this._editingController.getEditMode() === DATAGRID_EDIT_MODE_ROW;
  54196. if (isEditing) {
  54197. this._updateFocusedCellPosition($(eventArgs.originalEvent.target).closest('td'));
  54198. if (isRowEditMode)
  54199. setTimeout($.proxy(this._editingController.saveEditData, this._editingController));
  54200. else
  54201. this._editingController.closeEditCell()
  54202. }
  54203. else if (editingOptions.editEnabled)
  54204. if (isRowEditMode)
  54205. this._editingController.editRow(rowIndex);
  54206. else
  54207. this._focusedCellPosition && this._editingController.editCell(rowIndex, this._focusedCellPosition.columnIndex)
  54208. }
  54209. },
  54210. _leftRightKeysHandler: function(eventArgs, isEditing) {
  54211. var rowIndex = this._focusedCellPosition ? this._focusedCellPosition.rowIndex : null,
  54212. $row = this._focusedView && this._focusedView.getRow(rowIndex),
  54213. directionCode,
  54214. $cell;
  54215. if (!isEditing && !this._isGroupRow($row)) {
  54216. directionCode = this._getDirectionCodeByKey(eventArgs.key);
  54217. $cell = this._getNextCell(directionCode);
  54218. if ($cell && this._isCellValid($cell))
  54219. this._focus($cell);
  54220. eventArgs.originalEvent.preventDefault()
  54221. }
  54222. },
  54223. _getDirectionCodeByKey: function(key) {
  54224. var directionCode;
  54225. if (this.option("rtlEnabled"))
  54226. directionCode = key === "leftArrow" ? "nextInRow" : "previousInRow";
  54227. else
  54228. directionCode = key === "leftArrow" ? "previousInRow" : "nextInRow";
  54229. return directionCode
  54230. },
  54231. _upDownKeysHandler: function(eventArgs, isEditing) {
  54232. var rowIndex = this._focusedCellPosition ? this._focusedCellPosition.rowIndex : null,
  54233. $cell;
  54234. if (!isEditing) {
  54235. if (rowIndex === 0 || this._focusedView && rowIndex === this._focusedView.getRowsCount() - 1);
  54236. $cell = this._getNextCell(eventArgs.key);
  54237. if ($cell && this._isCellValid($cell))
  54238. this._focus($cell);
  54239. eventArgs.originalEvent.preventDefault()
  54240. }
  54241. },
  54242. _pageUpKeyHandler: function(eventArgs) {
  54243. var scrollingMode = this.option("scrolling.mode"),
  54244. pageIndex = this._dataController.pageIndex(),
  54245. isVirtualScrolling = scrollingMode === "virtual" || scrollingMode === "infinite";
  54246. if (pageIndex > 0 && !isVirtualScrolling) {
  54247. this._dataController.pageIndex(pageIndex - 1);
  54248. eventArgs.originalEvent.preventDefault()
  54249. }
  54250. },
  54251. _pageDownKeyHandler: function(eventArgs) {
  54252. var scrollingMode = this.option("scrolling.mode"),
  54253. isVirtualScrolling = scrollingMode === "virtual" || scrollingMode === "infinite",
  54254. pageIndex = this._dataController.pageIndex(),
  54255. pageCount = this._dataController.pageCount();
  54256. if (pageIndex < pageCount - 1 && !isVirtualScrolling) {
  54257. this._dataController.pageIndex(pageIndex + 1);
  54258. eventArgs.originalEvent.preventDefault()
  54259. }
  54260. },
  54261. _spaceKeyHandler: function(eventArgs, isEditing) {
  54262. var rowIndex = this._focusedCellPosition ? this._focusedCellPosition.rowIndex : null;
  54263. if (this.option("selection") && this.option("selection").mode !== "none" && !isEditing) {
  54264. this._selectionController.changeItemSelection(rowIndex, {
  54265. shift: eventArgs.shift,
  54266. control: eventArgs.ctrl
  54267. });
  54268. eventArgs.originalEvent.preventDefault()
  54269. }
  54270. },
  54271. _crtlAKeyHandler: function(eventArgs) {
  54272. if (eventArgs.ctrl && this.option("selection.mode") === "multiple" && this.option("selection.allowSelectAll")) {
  54273. this._selectionController.selectAll();
  54274. eventArgs.originalEvent.preventDefault()
  54275. }
  54276. },
  54277. _tabKeyHandler: function(eventArgs, isEditing) {
  54278. var editingOptions = this.option('editing'),
  54279. direction = eventArgs.shift ? "previous" : "next",
  54280. $cell;
  54281. if (editingOptions && eventArgs.originalEvent.target)
  54282. if (isEditing) {
  54283. if (!editingOptions.editEnabled)
  54284. this._editingController.closeEditCell();
  54285. this._updateFocusedCellPosition($(eventArgs.originalEvent.target).closest('td'));
  54286. $cell = this._getNextCell(direction);
  54287. if (this._focusCell($cell))
  54288. if (this._editingController.getEditMode() !== DATAGRID_EDIT_MODE_ROW && editingOptions.editEnabled)
  54289. this._editingController.editCell(this._focusedCellPosition.rowIndex, this._focusedCellPosition.columnIndex);
  54290. else
  54291. this._focusInteractiveElement($cell)
  54292. }
  54293. else {
  54294. $cell = this._getNextCell(direction, this._getElementType(eventArgs.originalEvent.target));
  54295. this._focusCell($cell)
  54296. }
  54297. eventArgs.originalEvent.preventDefault()
  54298. },
  54299. _focusCell: function($cell) {
  54300. if (this._isCellValid($cell)) {
  54301. this._focus($cell);
  54302. return true
  54303. }
  54304. },
  54305. _getElementType: function(target) {
  54306. return $(target).is("tr") ? "row" : "cell"
  54307. },
  54308. _escapeKeyHandler: function(eventArgs, isEditing) {
  54309. if (isEditing) {
  54310. this._updateFocusedCellPosition($(eventArgs.originalEvent.target).closest('td'));
  54311. if (this._editingController.getEditMode() !== DATAGRID_EDIT_MODE_ROW)
  54312. this._editingController.closeEditCell();
  54313. else
  54314. this._editingController.cancelEditData();
  54315. eventArgs.originalEvent.preventDefault()
  54316. }
  54317. },
  54318. _ctrlFKeyHandler: function(eventArgs) {
  54319. if (eventArgs.ctrl && this.option("searchPanel") && this.option("searchPanel").visible) {
  54320. this._testHeaderPanelFocused = true;
  54321. this._headerPanel.focus();
  54322. eventArgs.originalEvent.preventDefault()
  54323. }
  54324. },
  54325. _keyDownHandler: function(e) {
  54326. var isEditing = this._editingController.isEditing();
  54327. if (e.originalEvent.isDefaultPrevented())
  54328. return;
  54329. this._isNeedFocus = true;
  54330. switch (e.key) {
  54331. case"leftArrow":
  54332. case"rightArrow":
  54333. this._leftRightKeysHandler(e, isEditing);
  54334. break;
  54335. case"upArrow":
  54336. case"downArrow":
  54337. this._upDownKeysHandler(e, isEditing);
  54338. break;
  54339. case"pageUp":
  54340. this._pageUpKeyHandler(e);
  54341. break;
  54342. case"pageDown":
  54343. this._pageDownKeyHandler(e);
  54344. break;
  54345. case"space":
  54346. this._spaceKeyHandler(e, isEditing);
  54347. break;
  54348. case"A":
  54349. this._crtlAKeyHandler(e);
  54350. break;
  54351. case"tab":
  54352. this._tabKeyHandler(e, isEditing);
  54353. break;
  54354. case"enter":
  54355. this._enterKeyHandler(e, isEditing);
  54356. break;
  54357. case"escape":
  54358. this._escapeKeyHandler(e, isEditing);
  54359. break;
  54360. case"F":
  54361. this._ctrlFKeyHandler(e);
  54362. break
  54363. }
  54364. e.originalEvent.stopPropagation()
  54365. },
  54366. _isLastRow: function(rowIndex) {
  54367. return rowIndex === this.getController("data").items().length - 1
  54368. },
  54369. _getNextCell: function(keyCode, elementType, cellPosition) {
  54370. var focusedCellPosition = cellPosition || this._focusedCellPosition,
  54371. includeCommandCells = $.inArray(keyCode, ["next", "previous"]) > -1,
  54372. rowIndex,
  54373. newFocusedCellPosition,
  54374. $cell,
  54375. $row;
  54376. if (this._focusedView && focusedCellPosition) {
  54377. newFocusedCellPosition = this._getNewPositionByCode({
  54378. columnIndex: focusedCellPosition.columnIndex,
  54379. rowIndex: focusedCellPosition.rowIndex
  54380. }, elementType, keyCode);
  54381. $cell = this._focusedView.getCell(newFocusedCellPosition);
  54382. if (!this._isCellValid($cell) && this._isCellInRow(newFocusedCellPosition.columnIndex, includeCommandCells))
  54383. $cell = this._getNextCell(keyCode, "cell", newFocusedCellPosition);
  54384. $row = $cell && $cell.parent();
  54385. if (this._hasSkipRow($row)) {
  54386. rowIndex = this._focusedView.getRowIndex($row);
  54387. if (!this._isLastRow(rowIndex))
  54388. $cell = this._getNextCell(keyCode, "row", $.extend({}, focusedCellPosition, {rowIndex: rowIndex}));
  54389. else
  54390. return null
  54391. }
  54392. return $cell
  54393. }
  54394. return null
  54395. },
  54396. _getNewPositionByCode: function(cellPosition, elementType, code) {
  54397. var columnIndex = cellPosition.columnIndex,
  54398. rowIndex = cellPosition.rowIndex,
  54399. visibleColumnsCount = this.getController("columns").getVisibleColumns().length;
  54400. switch (code) {
  54401. case"nextInRow":
  54402. case"next":
  54403. if (columnIndex < visibleColumnsCount - 1 && !this._isLastValidCell({
  54404. columnIndex: columnIndex,
  54405. rowIndex: rowIndex
  54406. }) && elementType !== "row")
  54407. columnIndex++;
  54408. else if (!this._isLastRow(rowIndex) && code === "next") {
  54409. columnIndex = 0;
  54410. rowIndex++
  54411. }
  54412. break;
  54413. case"previousInRow":
  54414. case"previous":
  54415. if (columnIndex > 0 && !this._isFirstValidCell({
  54416. columnIndex: columnIndex,
  54417. rowIndex: rowIndex
  54418. }) && elementType !== "row")
  54419. columnIndex--;
  54420. else if (rowIndex > 0 && code === "previous") {
  54421. columnIndex = visibleColumnsCount - 1;
  54422. rowIndex--
  54423. }
  54424. break;
  54425. case"upArrow":
  54426. rowIndex = rowIndex > 0 ? rowIndex - 1 : rowIndex;
  54427. break;
  54428. case"downArrow":
  54429. rowIndex = !this._isLastRow(rowIndex) ? rowIndex + 1 : rowIndex;
  54430. break
  54431. }
  54432. return {
  54433. columnIndex: columnIndex,
  54434. rowIndex: rowIndex
  54435. }
  54436. },
  54437. _isFirstValidCell: function(cellPosition) {
  54438. var isFirstValidCell = false;
  54439. if (cellPosition.rowIndex === 0 && cellPosition.columnIndex > 0)
  54440. isFirstValidCell = isFirstValidCell || !this._haveValidCellBeforePosition(cellPosition);
  54441. return isFirstValidCell
  54442. },
  54443. _haveValidCellBeforePosition: function(cellPosition) {
  54444. var columnIndex = cellPosition.columnIndex,
  54445. hasValidCells = false;
  54446. while (columnIndex > 0 && !hasValidCells) {
  54447. var checkingPosition = {
  54448. columnIndex: --columnIndex,
  54449. rowIndex: cellPosition.rowIndex
  54450. };
  54451. hasValidCells = this._isCellByPositionValid(checkingPosition)
  54452. }
  54453. return hasValidCells
  54454. },
  54455. _isLastValidCell: function(cellPosition) {
  54456. var checkingPosition = {
  54457. columnIndex: cellPosition.columnIndex + 1,
  54458. rowIndex: cellPosition.rowIndex
  54459. },
  54460. visibleColumnsCount = this.getController("columns").getVisibleColumns().length,
  54461. isCheckingCellValid = this._isCellByPositionValid(checkingPosition);
  54462. if (!this._isLastRow(cellPosition.rowIndex) || isCheckingCellValid)
  54463. return false;
  54464. else if (cellPosition.columnIndex === visibleColumnsCount - 1)
  54465. return true;
  54466. return this._isLastValidCell(checkingPosition)
  54467. },
  54468. _isCellInRow: function(columnIndex, includeCommandCells) {
  54469. var visibleColumnsCount = this.getController("columns").getVisibleColumns().length;
  54470. return includeCommandCells ? columnIndex >= 0 && columnIndex <= visibleColumnsCount - 1 : columnIndex > 0 && columnIndex < visibleColumnsCount - 1
  54471. },
  54472. _resetFocusedCell: function(that) {
  54473. var $cell = that._getFocusedCell();
  54474. $cell && $cell.attr("tabindex", null);
  54475. that._isNeedFocus = false
  54476. },
  54477. init: function() {
  54478. var that = this;
  54479. if (that.option("useKeyboard")) {
  54480. that._dataController = that.getController("data");
  54481. that._selectionController = that.getController("selection");
  54482. that._editingController = that.getController("editing");
  54483. that._headerPanel = that.getView("headerPanel");
  54484. that._columnsController = that.getController("columns");
  54485. that.getController("editorFactory").focused.add(function($element) {
  54486. that.setupFocusedView();
  54487. if (that._isNeedFocus)
  54488. if (that._focusedView && that._focusedView.getScrollable) {
  54489. that._focusedView.getScrollable().scrollToElement($element);
  54490. that._isNeedFocus = false
  54491. }
  54492. });
  54493. that._focusedCellPosition = {
  54494. columnIndex: 0,
  54495. rowIndex: 0
  54496. };
  54497. that._dataController.changed.add(function(change) {
  54498. if (that._focusedCellPosition && change && change.changeType === 'prepend')
  54499. that._focusedCellPosition.rowIndex += change.items.length
  54500. });
  54501. that._initFocusedViews();
  54502. that._documentClickHandler = that.createAction(function(e) {
  54503. if (!$(e.jQueryEvent.target).closest("." + DATAGRID_ROWS_VIEW_CLASS).length)
  54504. that._resetFocusedCell(that)
  54505. });
  54506. $(document).on(events.addNamespace("dxpointerdown", "dxDataGridKeyboardNavigation"), that._documentClickHandler)
  54507. }
  54508. },
  54509. focus: function($element) {
  54510. var focusView = this._getFocusedViewByElement($element);
  54511. if (focusView) {
  54512. this._focusView(focusView.view, focusView.viewIndex);
  54513. this._isNeedFocus = true;
  54514. this._focus($element);
  54515. this._isHeaderView(focusView.view.name) && this._focusInteractiveElement($element)
  54516. }
  54517. },
  54518. _getFocusedViewByElement: function($element) {
  54519. var condition = function(view) {
  54520. return $element.closest(view._$element).length
  54521. };
  54522. return this._getFocusedViewByCondition(condition)
  54523. },
  54524. _getFocusedViewByCondition: function(conditionFunction) {
  54525. var focusView;
  54526. $.each(this._focusedViews, function(index, view) {
  54527. if (conditionFunction(view)) {
  54528. focusView = {
  54529. viewIndex: index,
  54530. view: view
  54531. };
  54532. return false
  54533. }
  54534. });
  54535. return focusView
  54536. },
  54537. _isHeaderView: function(viewName) {
  54538. return viewName === "columnHeadersView"
  54539. },
  54540. focusViewByName: function(viewName) {
  54541. var view = this._getFocusedViewByName(viewName);
  54542. this._focusView(view.view, view.viewIndex)
  54543. },
  54544. setupFocusedView: function() {
  54545. if (!utils.isDefined(this._focusedView))
  54546. this.focusViewByName("rowsView")
  54547. },
  54548. _getFocusedViewByName: function(viewName) {
  54549. var condition = function(view) {
  54550. return view.name === viewName
  54551. };
  54552. return this._getFocusedViewByCondition(condition)
  54553. },
  54554. optionChanged: function(args) {
  54555. var that = this;
  54556. switch (args.name) {
  54557. case'useKeyboard':
  54558. args.handled = true;
  54559. break;
  54560. default:
  54561. that.callBase(args)
  54562. }
  54563. },
  54564. dispose: function() {
  54565. this.callBase();
  54566. this._focusedView = null;
  54567. this._focusedViews = null;
  54568. this._keyDownProcessor && this._keyDownProcessor.dispose();
  54569. $(document).off(events.addNamespace("dxpointerdown", "dxDataGridKeyboardNavigation"), this._documentClickHandler)
  54570. }
  54571. });
  54572. $.extend(dataGrid.__internals, {
  54573. DATAGRID_GROUP_ROW_CLASS: DATAGRID_GROUP_ROW_CLASS,
  54574. DATAGRID_ROW_CLASS: DATAGRID_ROW_CLASS
  54575. });
  54576. dataGrid.registerModule("keyboardNavigation", {
  54577. defaultOptions: function() {
  54578. return {useKeyboard: true}
  54579. },
  54580. controllers: {keyboardNavigation: dataGrid.KeyboardNavigationController},
  54581. extenders: {
  54582. views: {rowsView: {_renderCore: function(change) {
  54583. this.callBase(change);
  54584. this.element().attr("tabindex", this.option("useKeyboard") ? 0 : null)
  54585. }}},
  54586. controllers: {editing: {editCell: function(rowIndex, columnIndex) {
  54587. var isCellEditing = this.callBase(rowIndex, columnIndex),
  54588. keyboardNavigationController = this.getController("keyboardNavigation");
  54589. if (isCellEditing)
  54590. keyboardNavigationController.setupFocusedView();
  54591. return isCellEditing
  54592. }}}
  54593. }
  54594. })
  54595. })(jQuery, DevExpress);
  54596. /*! Module widgets-web, file ui.dataGrid.errorHandling.js */
  54597. (function($, DX) {
  54598. var ui = DX.ui,
  54599. dataGrid = ui.dxDataGrid;
  54600. var DATAGRID_ERROR_ROW_CLASS = "dx-error-row",
  54601. DATAGRID_DATA_ROW_CLASS = "dx-data-row",
  54602. DATAGRID_ERROR_MESSAGE_CLASS = "dx-error-message",
  54603. DATAGRID_ERROR_CLOSEBUTTON_CLASS = "dx-closebutton",
  54604. DATAGRID_ACTION_CLASS = "dx-datagrid-action";
  54605. dataGrid.ErrorHandlingController = dataGrid.ViewController.inherit({
  54606. init: function() {
  54607. var that = this;
  54608. that._columnHeadersView = that.getView("columnHeadersView");
  54609. that._rowsView = that.getView("rowsView")
  54610. },
  54611. renderErrorRow: function(message, rowIndex) {
  54612. var that = this,
  54613. viewElement = rowIndex >= 0 ? that._rowsView : that._columnHeadersView,
  54614. $tableElement = viewElement._getTableElement(),
  54615. $errorRow = $("<tr />").addClass(DATAGRID_ERROR_ROW_CLASS),
  54616. $row = $tableElement.find("." + DATAGRID_DATA_ROW_CLASS).eq(rowIndex),
  54617. $errorMessage = $("<div/>").addClass(DATAGRID_ERROR_MESSAGE_CLASS).text(message),
  54618. $closeButton = $("<div/>").addClass(DATAGRID_ERROR_CLOSEBUTTON_CLASS).addClass(DATAGRID_ACTION_CLASS);
  54619. if (rowIndex >= 0) {
  54620. that.removeErrorRow($tableElement.find("tr").eq($row.index() + 1));
  54621. $errorRow.insertAfter($row)
  54622. }
  54623. else {
  54624. that.removeErrorRow($tableElement.find("tr").last());
  54625. $tableElement.append($errorRow)
  54626. }
  54627. $closeButton.on("dxclick", that.createAction(function(args) {
  54628. var e = args.jQueryEvent,
  54629. $currentErrorRow = $(e.currentTarget).closest("." + DATAGRID_ERROR_ROW_CLASS);
  54630. e.stopPropagation();
  54631. that.removeErrorRow($currentErrorRow)
  54632. }));
  54633. $("<td/>").attr({
  54634. colspan: that._columnHeadersView.getColumnCount(),
  54635. role: "presentation"
  54636. }).prepend($closeButton).append($errorMessage).appendTo($errorRow)
  54637. },
  54638. removeErrorRow: function($row) {
  54639. $row.hasClass(DATAGRID_ERROR_ROW_CLASS) && $row.remove()
  54640. },
  54641. optionChanged: function(args) {
  54642. var that = this;
  54643. switch (args.name) {
  54644. case'errorRowEnabled':
  54645. args.handled = true;
  54646. break;
  54647. default:
  54648. that.callBase(args)
  54649. }
  54650. }
  54651. });
  54652. dataGrid.registerModule('errorHandling', {
  54653. defaultOptions: function() {
  54654. return {errorRowEnabled: true}
  54655. },
  54656. controllers: {errorHandling: dataGrid.ErrorHandlingController},
  54657. extenders: {controllers: {data: {init: function() {
  54658. var that = this,
  54659. errorHandlingController = that.getController('errorHandling');
  54660. that.callBase();
  54661. that.dataErrorOccurred.add(function(error) {
  54662. var message = error && error.message || error;
  54663. if (that.option("errorRowEnabled"))
  54664. errorHandlingController.renderErrorRow(message)
  54665. })
  54666. }}}}
  54667. })
  54668. })(jQuery, DevExpress);
  54669. /*! Module widgets-web, file ui.dataGrid.summaryModule.js */
  54670. (function($, DX) {
  54671. var ui = DX.ui,
  54672. utils = DX.utils,
  54673. dataGrid = ui.dxDataGrid,
  54674. normalizeSortingInfo = DX.data.utils.normalizeSortingInfo;
  54675. var DATAGRID_TOTAL_FOOTER_CLASS = "dx-datagrid-total-footer",
  54676. DATAGRID_SUMMARY_ITEM_CLASS = "dx-datagrid-summary-item",
  54677. DATAGRID_TEXT_CONTENT_CLASS = "dx-datagrid-text-content",
  54678. DATAGRID_GROUP_FOOTER_CLASS = "dx-datagrid-group-footer",
  54679. DATAGRID_GROUP_TEXT_CONTENT_CLASS = "dx-datagrid-group-text-content",
  54680. DATAGRID_GROUP_FOOTER_ROW_TYPE = "groupFooter";
  54681. var renderSummaryCell = function($cell, options) {
  54682. var i,
  54683. column = options.column,
  54684. summaryItems = options.summaryItems,
  54685. summaryItem,
  54686. $summaryItems = [];
  54687. if (!column.command && summaryItems) {
  54688. for (i = 0; i < summaryItems.length; i++) {
  54689. summaryItem = summaryItems[i];
  54690. $summaryItems.push($("<div>").css('text-align', summaryItem.alignment || column.alignment).addClass(DATAGRID_SUMMARY_ITEM_CLASS).addClass(DATAGRID_TEXT_CONTENT_CLASS).addClass(summaryItem.cssClass).toggleClass(DATAGRID_GROUP_TEXT_CONTENT_CLASS, options.rowType === "group").text(dataGrid.getSummaryText(summaryItem, options.summaryTexts)))
  54691. }
  54692. $cell.append($summaryItems)
  54693. }
  54694. },
  54695. getSummaryCellOptions = function(that, options) {
  54696. var summaryTexts = that.option("summary.texts");
  54697. return {
  54698. totalItem: options.row,
  54699. summaryItems: options.row.summaryCells[options.columnIndex],
  54700. summaryTexts: summaryTexts
  54701. }
  54702. };
  54703. dataGrid.FooterView = dataGrid.ColumnsView.inherit(function() {
  54704. return {
  54705. _getRows: function() {
  54706. return this._dataController.footerItems()
  54707. },
  54708. _getCellOptions: function(options) {
  54709. return $.extend(this.callBase(options), getSummaryCellOptions(this, options))
  54710. },
  54711. _renderCellContent: function($cell, options) {
  54712. renderSummaryCell($cell, options);
  54713. this.callBase($cell, options)
  54714. },
  54715. _renderCore: function() {
  54716. var totalItem = this._dataController.footerItems()[0];
  54717. this.element().empty().addClass(DATAGRID_TOTAL_FOOTER_CLASS);
  54718. if (totalItem && totalItem.summaryCells && totalItem.summaryCells.length)
  54719. this._setTableElement(this._renderTable())
  54720. },
  54721. _renderTable: function() {
  54722. var $table = this.callBase.apply(this, arguments),
  54723. $content = this.element();
  54724. this.wrapTableInScrollContainer($table).appendTo($content);
  54725. return $table
  54726. },
  54727. _columnOptionChanged: function(e) {
  54728. var optionNames = e.optionNames;
  54729. if (e.changeTypes.grouping)
  54730. return;
  54731. if (optionNames.width || optionNames.visibleWidth)
  54732. this.callBase(e)
  54733. },
  54734. _handleDataChanged: function(e) {
  54735. if (e.changeType === "refresh")
  54736. this.render()
  54737. },
  54738. getHeight: function() {
  54739. var $element = this.element();
  54740. return $element ? $element.outerHeight() : 0
  54741. },
  54742. isVisible: function() {
  54743. return !!this._dataController.footerItems().length
  54744. }
  54745. }
  54746. }());
  54747. var SummaryDataSourceAdapterExtender = function() {
  54748. return {
  54749. init: function() {
  54750. this.callBase.apply(this, arguments);
  54751. this._totalAggregates = []
  54752. },
  54753. summary: function(summary) {
  54754. if (!arguments.length)
  54755. return this._summary;
  54756. this._summary = summary
  54757. },
  54758. totalAggregates: function() {
  54759. return this._totalAggregates
  54760. }
  54761. }
  54762. }();
  54763. var SummaryDataSourceAdapterClientExtender = function() {
  54764. var calculateAggregates = function(that, summary, data, groupLevel) {
  54765. var calculator;
  54766. if (summary) {
  54767. calculator = new DX.data.AggregateCalculator({
  54768. totalAggregates: summary.totalAggregates,
  54769. groupAggregates: summary.groupAggregates,
  54770. data: data,
  54771. groupLevel: groupLevel
  54772. });
  54773. calculator.calculate()
  54774. }
  54775. that._totalAggregates = calculator ? calculator.totalAggregates() : []
  54776. };
  54777. var sortGroupsBySummaryCore = function(items, groups, sortByGroups) {
  54778. if (!items || !groups.length)
  54779. return items;
  54780. var group = groups[0],
  54781. sorts = sortByGroups[0],
  54782. query;
  54783. if (group && sorts && sorts.length) {
  54784. query = DX.data.query(items);
  54785. $.each(sorts, function(index) {
  54786. if (index === 0)
  54787. query = query.sortBy(this.selector, this.desc);
  54788. else
  54789. query = query.thenBy(this.selector, this.desc)
  54790. });
  54791. query.enumerate().done(function(sortedItems) {
  54792. items = sortedItems
  54793. })
  54794. }
  54795. groups = groups.slice(1);
  54796. sortByGroups = sortByGroups.slice(1);
  54797. if (groups.length && sortByGroups.length)
  54798. $.each(items, function() {
  54799. this.items = sortGroupsBySummaryCore(this.items, groups, sortByGroups)
  54800. });
  54801. return items
  54802. };
  54803. var sortGroupsBySummary = function(data, group, summary) {
  54804. var sortByGroups = summary && summary.sortByGroups && summary.sortByGroups();
  54805. if (sortByGroups && sortByGroups.length)
  54806. return sortGroupsBySummaryCore(data, group, sortByGroups);
  54807. return data
  54808. };
  54809. return {_handleDataLoadedCore: function(options) {
  54810. var that = this,
  54811. groups = normalizeSortingInfo(options.loadOptions.group || []),
  54812. summary = that.summary();
  54813. calculateAggregates(that, summary, options.data, groups.length);
  54814. options.data = sortGroupsBySummary(options.data, groups, summary);
  54815. options.totalAggregates = that._totalAggregates;
  54816. that.callBase(options)
  54817. }}
  54818. }();
  54819. dataGrid.DataSourceAdapterServer = dataGrid.DataSourceAdapterServer.inherit(SummaryDataSourceAdapterExtender);
  54820. dataGrid.DataSourceAdapterClient = dataGrid.DataSourceAdapterClient.inherit(SummaryDataSourceAdapterExtender).inherit(SummaryDataSourceAdapterClientExtender);
  54821. dataGrid.renderSummaryCell = renderSummaryCell;
  54822. $.extend(dataGrid.__internals, {
  54823. DATAGRID_TOTAL_FOOTER_CLASS: DATAGRID_TOTAL_FOOTER_CLASS,
  54824. DATAGRID_SUMMARY_ITEM_CLASS: DATAGRID_SUMMARY_ITEM_CLASS,
  54825. DATAGRID_GROUP_FOOTER_CLASS: DATAGRID_GROUP_FOOTER_CLASS
  54826. });
  54827. dataGrid.registerModule('summary', {
  54828. defaultOptions: function() {
  54829. return {
  54830. summary: {
  54831. groupItems: undefined,
  54832. totalItems: undefined,
  54833. calculateCustomSummary: undefined,
  54834. texts: {
  54835. sum: Globalize.localize("dxDataGrid-summarySum"),
  54836. sumOtherColumn: Globalize.localize("dxDataGrid-summarySumOtherColumn"),
  54837. min: Globalize.localize("dxDataGrid-summaryMin"),
  54838. minOtherColumn: Globalize.localize("dxDataGrid-summaryMinOtherColumn"),
  54839. max: Globalize.localize("dxDataGrid-summaryMax"),
  54840. maxOtherColumn: Globalize.localize("dxDataGrid-summaryMaxOtherColumn"),
  54841. avg: Globalize.localize("dxDataGrid-summaryAvg"),
  54842. avgOtherColumn: Globalize.localize("dxDataGrid-summaryAvgOtherColumn"),
  54843. count: Globalize.localize("dxDataGrid-summaryCount")
  54844. }
  54845. },
  54846. sortByGroupSummaryInfo: undefined
  54847. }
  54848. },
  54849. views: {footerView: dataGrid.FooterView},
  54850. extenders: {
  54851. controllers: {data: function() {
  54852. return {
  54853. _isDataColumn: function(column) {
  54854. return column && (!utils.isDefined(column.groupIndex) || column.showWhenGrouped)
  54855. },
  54856. _isGroupFooterVisible: function() {
  54857. var groupItems = this.option("summary.groupItems") || [],
  54858. groupItem,
  54859. column,
  54860. i;
  54861. for (i = 0; i < groupItems.length; i++) {
  54862. groupItem = groupItems[i];
  54863. column = this._columnsController.columnOption(groupItem.column);
  54864. if (groupItem.showInGroupFooter && this._isDataColumn(column))
  54865. return true
  54866. }
  54867. return false
  54868. },
  54869. _processGroupItems: function(items, groupCount, options) {
  54870. var result = this.callBase.apply(this, arguments);
  54871. if (options) {
  54872. if (options.isGroupFooterVisible === undefined)
  54873. options.isGroupFooterVisible = this._isGroupFooterVisible();
  54874. if (options.data && options.data.items && options.isGroupFooterVisible)
  54875. result.push({
  54876. rowType: DATAGRID_GROUP_FOOTER_ROW_TYPE,
  54877. data: options.data,
  54878. groupIndex: options.path.length - 1,
  54879. values: []
  54880. })
  54881. }
  54882. return result
  54883. },
  54884. _processGroupItem: function(groupItem, options) {
  54885. var that = this;
  54886. if (!options.summaryGroupItems)
  54887. options.summaryGroupItems = that.option("summary.groupItems") || [];
  54888. if (groupItem.rowType === "group") {
  54889. var groupColumnIndex = -1;
  54890. $.each(options.visibleColumns, function() {
  54891. if (groupItem.groupIndex === this.groupIndex) {
  54892. groupColumnIndex = this.index;
  54893. return false
  54894. }
  54895. });
  54896. groupItem.summaryCells = this._calculateSummaryCells(options.summaryGroupItems, groupItem.data.aggregates || [], options.visibleColumns, function(summaryItem, column) {
  54897. if (summaryItem.showInGroupFooter)
  54898. return -1;
  54899. if (summaryItem.alignByColumn && column && !utils.isDefined(column.groupIndex))
  54900. return column.index;
  54901. else
  54902. return groupColumnIndex
  54903. })
  54904. }
  54905. if (groupItem.rowType === DATAGRID_GROUP_FOOTER_ROW_TYPE)
  54906. groupItem.summaryCells = this._calculateSummaryCells(options.summaryGroupItems, groupItem.data.aggregates || [], options.visibleColumns, function(summaryItem, column) {
  54907. return summaryItem.showInGroupFooter && that._isDataColumn(column) ? column.index : -1
  54908. });
  54909. return groupItem
  54910. },
  54911. _calculateSummaryCells: function(summaryItems, aggregates, visibleColumns, calculateTargetColumnIndex) {
  54912. var that = this,
  54913. summaryCells = [],
  54914. summaryCellsByColumns = {};
  54915. $.each(summaryItems, function(summaryIndex, summaryItem) {
  54916. var column = that._columnsController.columnOption(summaryItem.column),
  54917. showInColumn = summaryItem.showInColumn && that._columnsController.columnOption(summaryItem.showInColumn) || column,
  54918. columnIndex = calculateTargetColumnIndex(summaryItem, showInColumn),
  54919. aggregate;
  54920. if (columnIndex >= 0) {
  54921. if (!summaryCellsByColumns[columnIndex])
  54922. summaryCellsByColumns[columnIndex] = [];
  54923. aggregate = aggregates[summaryIndex];
  54924. if (utils.isDefined(aggregate) && !isNaN(aggregate))
  54925. summaryCellsByColumns[columnIndex].push($.extend({}, summaryItem, {
  54926. value: aggregate,
  54927. columnCaption: column && column.index !== columnIndex ? column.caption : undefined
  54928. }))
  54929. }
  54930. });
  54931. if (!$.isEmptyObject(summaryCellsByColumns))
  54932. $.each(visibleColumns, function() {
  54933. summaryCells.push(summaryCellsByColumns[this.index] || [])
  54934. });
  54935. return summaryCells
  54936. },
  54937. _getSummaryCells: function(summaryTotalItems, totalAggregates) {
  54938. var that = this,
  54939. columnsController = that._columnsController;
  54940. return that._calculateSummaryCells(summaryTotalItems, totalAggregates, columnsController.getVisibleColumns(), function(summaryItem, column) {
  54941. return that._isDataColumn(column) ? column.index : -1
  54942. })
  54943. },
  54944. _updateItemsCore: function(change) {
  54945. var that = this,
  54946. summaryCells,
  54947. totalAggregates,
  54948. dataSource = that._dataSource,
  54949. summaryTotalItems = that.option("summary.totalItems");
  54950. that.callBase(change);
  54951. that._footerItems = [];
  54952. if (dataSource && summaryTotalItems && summaryTotalItems.length) {
  54953. totalAggregates = dataSource.totalAggregates();
  54954. summaryCells = this._getSummaryCells(summaryTotalItems, totalAggregates);
  54955. if (summaryCells.length)
  54956. that._footerItems.push({
  54957. rowType: 'totalFooter',
  54958. summaryCells: summaryCells
  54959. })
  54960. }
  54961. },
  54962. _getAggregates: function(summaryItems) {
  54963. var that = this,
  54964. columnsController = that.getController("columns"),
  54965. calculateCustomSummary = that.option("summary.calculateCustomSummary");
  54966. return $.map(summaryItems || [], function(summaryItem) {
  54967. var column = columnsController.columnOption(summaryItem.column),
  54968. calculateCellValue = column && column.calculateCellValue ? $.proxy(column, "calculateCellValue") : DX.data.utils.compileGetter(column ? column.dataField : summaryItem.column),
  54969. aggregator = summaryItem.summaryType || "count",
  54970. selector = calculateCellValue,
  54971. options;
  54972. if (aggregator === 'avg' || aggregator === 'sum')
  54973. selector = function(data) {
  54974. return Number(calculateCellValue(data))
  54975. };
  54976. if (aggregator === "custom") {
  54977. if (!calculateCustomSummary) {
  54978. DX.log("E1026");
  54979. calculateCustomSummary = function(){}
  54980. }
  54981. options = {
  54982. component: that.component,
  54983. name: summaryItem.name,
  54984. summaryProcess: "start",
  54985. totalValue: undefined
  54986. };
  54987. calculateCustomSummary(options);
  54988. options.summaryProcess = "calculate";
  54989. aggregator = {
  54990. seed: options.totalValue,
  54991. step: function(totalValue, value) {
  54992. options.summaryProcess = "calculate";
  54993. options.totalValue = totalValue;
  54994. options.value = value;
  54995. calculateCustomSummary(options);
  54996. return options.totalValue
  54997. },
  54998. finalize: function(totalValue) {
  54999. options.summaryProcess = "finalize";
  55000. options.totalValue = totalValue;
  55001. delete options.value;
  55002. calculateCustomSummary(options);
  55003. return options.totalValue
  55004. }
  55005. }
  55006. }
  55007. return {
  55008. selector: selector,
  55009. aggregator: aggregator
  55010. }
  55011. })
  55012. },
  55013. _addSortInfo: function(sortByGroups, groupColumn, selector, sortOrder) {
  55014. var groupIndex;
  55015. if (groupColumn) {
  55016. groupIndex = groupColumn.groupIndex;
  55017. sortOrder = sortOrder || groupColumn.sortOrder;
  55018. if (utils.isDefined(groupIndex)) {
  55019. sortByGroups[groupIndex] = sortByGroups[groupIndex] || [];
  55020. sortByGroups[groupIndex].push({
  55021. selector: selector,
  55022. desc: sortOrder === "desc"
  55023. })
  55024. }
  55025. }
  55026. },
  55027. _findSummaryItem: function(summaryItems, name) {
  55028. var summaryItemIndex = -1;
  55029. var getFullName = function(summaryItem) {
  55030. var summaryType = summaryItem.summaryType,
  55031. column = summaryItem.column;
  55032. return summaryType && column && summaryType + "_" + column
  55033. };
  55034. if (utils.isDefined(name))
  55035. $.each(summaryItems || [], function(index) {
  55036. if (this.name === name || index === name || this.summaryType === name || this.column === name || getFullName(this) === name) {
  55037. summaryItemIndex = index;
  55038. return false
  55039. }
  55040. });
  55041. return summaryItemIndex
  55042. },
  55043. _getSummarySortByGroups: function(sortByGroupSummaryInfo, groupSummaryItems) {
  55044. var that = this,
  55045. columnsController = that._columnsController,
  55046. groupColumns = columnsController.getGroupColumns(),
  55047. sortByGroups = [];
  55048. if (!groupSummaryItems || !groupSummaryItems.length)
  55049. return;
  55050. $.each(sortByGroupSummaryInfo || [], function() {
  55051. var sortOrder = this.sortOrder,
  55052. groupColumn = this.groupColumn,
  55053. summaryItemIndex = that._findSummaryItem(groupSummaryItems, this.summaryItem);
  55054. if (summaryItemIndex < 0)
  55055. return;
  55056. var selector = function(data) {
  55057. return data.aggregates[summaryItemIndex]
  55058. };
  55059. if (utils.isDefined(groupColumn)) {
  55060. groupColumn = columnsController.columnOption(groupColumn);
  55061. that._addSortInfo(sortByGroups, groupColumn, selector, sortOrder)
  55062. }
  55063. else
  55064. $.each(groupColumns, function(groupIndex, groupColumn) {
  55065. that._addSortInfo(sortByGroups, groupColumn, selector, sortOrder)
  55066. })
  55067. });
  55068. return sortByGroups
  55069. },
  55070. _createDataSourceAdapterCore: function(dataSource, remoteOperations) {
  55071. var summary = this._getSummaryOptions(),
  55072. dataSourceAdapter;
  55073. if (remoteOperations === 'auto' && summary)
  55074. remoteOperations = {
  55075. filtering: true,
  55076. sorting: true,
  55077. paging: false
  55078. };
  55079. dataSourceAdapter = this.callBase(dataSource, remoteOperations);
  55080. dataSourceAdapter.summary(summary);
  55081. return dataSourceAdapter
  55082. },
  55083. _getSummaryOptions: function() {
  55084. var that = this,
  55085. groupSummaryItems = that.option("summary.groupItems"),
  55086. totalSummaryItems = that.option("summary.totalItems"),
  55087. sortByGroupSummaryInfo = that.option("sortByGroupSummaryInfo"),
  55088. groupAggregates = that._getAggregates(groupSummaryItems),
  55089. totalAggregates = that._getAggregates(totalSummaryItems),
  55090. sortByGroups = function() {
  55091. return that._getSummarySortByGroups(sortByGroupSummaryInfo, groupSummaryItems)
  55092. };
  55093. if (groupAggregates.length || totalAggregates.length)
  55094. return {
  55095. groupAggregates: groupAggregates,
  55096. totalAggregates: totalAggregates,
  55097. sortByGroups: sortByGroups
  55098. }
  55099. },
  55100. publicMethods: function() {
  55101. var methods = this.callBase();
  55102. methods.push("getTotalSummaryValue");
  55103. return methods
  55104. },
  55105. getTotalSummaryValue: function(summaryItemName) {
  55106. var summaryItemIndex = this._findSummaryItem(this.option("summary.totalItems"), summaryItemName),
  55107. aggregates = this._dataSource.totalAggregates();
  55108. if (aggregates.length && summaryItemIndex > -1)
  55109. return aggregates[summaryItemIndex]
  55110. },
  55111. optionChanged: function(args) {
  55112. if (args.name === "summary" || args.name === "sortByGroupSummaryInfo")
  55113. args.name = "dataSource";
  55114. this.callBase(args)
  55115. },
  55116. init: function() {
  55117. this._footerItems = [];
  55118. this.callBase()
  55119. },
  55120. footerItems: function() {
  55121. return this._footerItems
  55122. }
  55123. }
  55124. }()},
  55125. views: {rowsView: function() {
  55126. return {
  55127. _createRow: function(row) {
  55128. var $row = this.callBase(row);
  55129. row && $row.addClass(row.rowType === DATAGRID_GROUP_FOOTER_ROW_TYPE ? DATAGRID_GROUP_FOOTER_CLASS : "");
  55130. return $row
  55131. },
  55132. _renderCells: function($row, options) {
  55133. this.callBase.apply(this, arguments);
  55134. this._renderGroupSummaryCells($row, options)
  55135. },
  55136. _hasAlignByColumnSummaryItems: function(columnIndex, options) {
  55137. return options.row.summaryCells[options.row.summaryCells.length - columnIndex].length
  55138. },
  55139. _renderGroupSummaryCells: function($row, options) {
  55140. if (options.row.rowType === "group" && options.row.summaryCells && options.row.summaryCells.length) {
  55141. var $groupCell = $row.children().last(),
  55142. groupCellColSpan = Number($groupCell.attr("colspan")) || 1,
  55143. alignByColumnCellCount = 0;
  55144. for (var i = 1; i < groupCellColSpan; i++)
  55145. alignByColumnCellCount = this._hasAlignByColumnSummaryItems(i, options) ? i : alignByColumnCellCount;
  55146. if (alignByColumnCellCount > 0) {
  55147. $groupCell.attr("colspan", groupCellColSpan - alignByColumnCellCount);
  55148. for (i = 0; i < alignByColumnCellCount; i++) {
  55149. var columnIndex = options.columns.length - alignByColumnCellCount + i;
  55150. this._renderCell($row, $.extend({
  55151. column: options.columns[columnIndex],
  55152. columnIndex: columnIndex
  55153. }, options))
  55154. }
  55155. }
  55156. }
  55157. },
  55158. _getColumnTemplate: function(options) {
  55159. if (!options.column.command && !utils.isDefined(options.column.groupIndex) && options.summaryItems && options.summaryItems.length)
  55160. return renderSummaryCell;
  55161. else
  55162. return this.callBase(options)
  55163. },
  55164. _getCellOptions: function(options) {
  55165. var that = this,
  55166. parameters = that.callBase(options);
  55167. if (options.row.summaryCells)
  55168. return $.extend(parameters, getSummaryCellOptions(that, options));
  55169. else
  55170. return parameters
  55171. }
  55172. }
  55173. }()}
  55174. }
  55175. })
  55176. })(jQuery, DevExpress);
  55177. /*! Module widgets-web, file ui.dataGrid.masterDetailModule.js */
  55178. (function($, DX) {
  55179. var ui = DX.ui,
  55180. utils = DX.utils,
  55181. dataGrid = ui.dxDataGrid,
  55182. DATAGRID_MASTER_DETAIL_CELL_CLASS = "dx-master-detail-cell",
  55183. DATAGRID_MASTER_DETAIL_ROW_CLASS = "dx-master-detail-row",
  55184. DATAGRID_ROW_LINES_CLASS = "dx-row-lines";
  55185. $.extend(dataGrid.__internals, {
  55186. DATAGRID_MASTER_DETAIL_CELL_CLASS: DATAGRID_MASTER_DETAIL_CELL_CLASS,
  55187. DATAGRID_MASTER_DETAIL_ROW_CLASS: DATAGRID_MASTER_DETAIL_ROW_CLASS,
  55188. DATAGRID_ROW_LINES_CLASS: DATAGRID_ROW_LINES_CLASS
  55189. });
  55190. dataGrid.registerModule('masterDetail', {
  55191. defaultOptions: function() {
  55192. return {masterDetail: {
  55193. enabled: false,
  55194. autoExpandAll: false,
  55195. template: null
  55196. }}
  55197. },
  55198. extenders: {
  55199. controllers: {
  55200. editorFactory: {focus: function($element) {
  55201. if ($element && $element.hasClass(DATAGRID_MASTER_DETAIL_CELL_CLASS))
  55202. this.loseFocus();
  55203. else
  55204. return this.callBase($element)
  55205. }},
  55206. columns: {_getExpandColumnsCore: function() {
  55207. var expandColumns = this.callBase();
  55208. if (this.option('masterDetail.enabled'))
  55209. expandColumns.push({});
  55210. return expandColumns
  55211. }},
  55212. data: function() {
  55213. var initMasterDetail = function(that) {
  55214. that._expandedItems = [];
  55215. that._isExpandAll = that.option('masterDetail.autoExpandAll')
  55216. };
  55217. return {
  55218. init: function() {
  55219. var that = this;
  55220. initMasterDetail(that);
  55221. that.loadingChanged.add(function(isLoading) {
  55222. if (!isLoading)
  55223. that._expandedItems = $.grep(that._expandedItems, function(item) {
  55224. return item.visible
  55225. })
  55226. });
  55227. that.callBase()
  55228. },
  55229. expandAll: function(groupIndex) {
  55230. var that = this;
  55231. if (groupIndex < 0) {
  55232. that._isExpandAll = true;
  55233. that._expandedItems = [];
  55234. that.updateItems()
  55235. }
  55236. else
  55237. that.callBase.apply(that, arguments)
  55238. },
  55239. collapseAll: function(groupIndex) {
  55240. var that = this;
  55241. if (groupIndex < 0) {
  55242. that._isExpandAll = false;
  55243. that._expandedItems = [];
  55244. that.updateItems()
  55245. }
  55246. else
  55247. that.callBase.apply(that, arguments)
  55248. },
  55249. isRowExpanded: function(key) {
  55250. var that = this,
  55251. expandIndex = dataGrid.getIndexByKey(key, that._expandedItems);
  55252. if (utils.isArray(key))
  55253. return that.callBase.apply(that, arguments);
  55254. else
  55255. return !!(that._isExpandAll ^ (expandIndex >= 0 && that._expandedItems[expandIndex].visible))
  55256. },
  55257. _changeRowExpandCore: function(key) {
  55258. var that = this,
  55259. expandIndex,
  55260. rowIndex;
  55261. if (utils.isArray(key))
  55262. return that.callBase.apply(that, arguments);
  55263. else {
  55264. expandIndex = dataGrid.getIndexByKey(key, that._expandedItems);
  55265. if (expandIndex >= 0) {
  55266. var visible = that._expandedItems[expandIndex].visible;
  55267. that._expandedItems[expandIndex].visible = !visible
  55268. }
  55269. else
  55270. that._expandedItems.push({
  55271. key: key,
  55272. visible: true
  55273. });
  55274. rowIndex = that.getRowIndexByKey(key);
  55275. that.updateItems({
  55276. changeType: 'update',
  55277. rowIndices: [rowIndex, rowIndex + 1]
  55278. })
  55279. }
  55280. },
  55281. _processDataItem: function(data, options) {
  55282. var that = this,
  55283. dataItem = that.callBase.apply(that, arguments);
  55284. dataItem.isExpanded = that.isRowExpanded(dataItem.key);
  55285. if (options.detailColumnIndex === undefined) {
  55286. options.detailColumnIndex = -1;
  55287. $.each(options.visibleColumns, function(index, column) {
  55288. if (column.command === 'expand' && !utils.isDefined(column.groupIndex)) {
  55289. options.detailColumnIndex = index;
  55290. return false
  55291. }
  55292. })
  55293. }
  55294. if (options.detailColumnIndex >= 0)
  55295. dataItem.values[options.detailColumnIndex] = dataItem.isExpanded;
  55296. return dataItem
  55297. },
  55298. _processItems: function() {
  55299. var that = this,
  55300. items = that.callBase.apply(that, arguments),
  55301. expandIndex,
  55302. result = [];
  55303. if (this._isLoadingAll)
  55304. return items;
  55305. $.each(items, function(index, item) {
  55306. result.push(item);
  55307. expandIndex = dataGrid.getIndexByKey(item.key, that._expandedItems);
  55308. if (item.rowType === 'data' && (item.isExpanded || expandIndex >= 0) && !item.inserted)
  55309. result.push({
  55310. visible: item.isExpanded,
  55311. rowType: 'detail',
  55312. key: item.key,
  55313. data: item.data,
  55314. values: []
  55315. })
  55316. });
  55317. return result
  55318. },
  55319. optionChanged: function(args) {
  55320. var that = this,
  55321. value,
  55322. previousValue,
  55323. isEnabledChanged,
  55324. isAutoExpandAllChanged;
  55325. if (args.name === 'masterDetail') {
  55326. args.name = 'dataSource';
  55327. switch (args.fullName) {
  55328. case'masterDetail':
  55329. value = args.value || {};
  55330. previousValue = args.previousValue || {};
  55331. isEnabledChanged = value.enabled !== previousValue.enabled;
  55332. isAutoExpandAllChanged = value.autoExpandAll !== previousValue.autoExpandAll;
  55333. break;
  55334. case'masterDetail.enabled':
  55335. isEnabledChanged = true;
  55336. break;
  55337. case'masterDetail.autoExpandAll':
  55338. isAutoExpandAllChanged = true;
  55339. break
  55340. }
  55341. if (isEnabledChanged || isAutoExpandAllChanged)
  55342. initMasterDetail(that)
  55343. }
  55344. that.callBase(args)
  55345. },
  55346. refresh: function() {
  55347. var that = this;
  55348. initMasterDetail(that);
  55349. return that.callBase.apply(that, arguments)
  55350. }
  55351. }
  55352. }()
  55353. },
  55354. views: {rowsView: function() {
  55355. return {
  55356. _getColumnTemplate: function(options) {
  55357. var that = this,
  55358. column = options.column,
  55359. template;
  55360. if (column.command === 'detail') {
  55361. template = that.option('masterDetail.template') || that._getDefaultTemplate(column);
  55362. options.denyRenderToDetachedContainer = true
  55363. }
  55364. else
  55365. template = that.callBase.apply(that, arguments);
  55366. return template
  55367. },
  55368. _createRow: function(row) {
  55369. var $row = this.callBase(row);
  55370. if (row && row.rowType === "detail") {
  55371. this.option('showRowLines') && $row.addClass(DATAGRID_ROW_LINES_CLASS);
  55372. $row.addClass(DATAGRID_MASTER_DETAIL_ROW_CLASS).toggle(row.visible)
  55373. }
  55374. return $row
  55375. },
  55376. _getGroupCellOptions: function(options) {
  55377. var row = options.row,
  55378. groupColumns = this._columnsController.getGroupColumns(),
  55379. columnIndex = groupColumns.length + options.columnsCountBeforeGroups,
  55380. emptyCellsCount = columnIndex + Number(this.option("masterDetail.enabled"));
  55381. if (row && row.rowType === "detail")
  55382. return {
  55383. columnIndex: columnIndex,
  55384. emptyCellsCount: emptyCellsCount,
  55385. colspan: options.columns.length - emptyCellsCount
  55386. };
  55387. return this.callBase(options)
  55388. },
  55389. _renderCells: function($row, options) {
  55390. var row = options.row,
  55391. $detailCell,
  55392. groupCellOptions = this._getGroupCellOptions(options),
  55393. i;
  55394. if (row.rowType === 'detail') {
  55395. for (i = 0; i < groupCellOptions.emptyCellsCount; i++)
  55396. this._renderCell($row, {
  55397. value: null,
  55398. row: row,
  55399. rowIndex: row.rowIndex,
  55400. column: options.columns[i]
  55401. });
  55402. $detailCell = this._renderCell($row, {
  55403. value: null,
  55404. row: row,
  55405. rowIndex: row.rowIndex,
  55406. column: {command: 'detail'},
  55407. columnIndex: groupCellOptions.columnIndex
  55408. });
  55409. $detailCell.addClass(DATAGRID_MASTER_DETAIL_CELL_CLASS).attr('colspan', groupCellOptions.colspan)
  55410. }
  55411. else
  55412. this.callBase.apply(this, arguments)
  55413. }
  55414. }
  55415. }()}
  55416. }
  55417. })
  55418. })(jQuery, DevExpress);
  55419. /*! Module widgets-web, file ui.dataGrid.fixedColumns.js */
  55420. (function($, DX, undefined) {
  55421. var ui = DX.ui,
  55422. utils = DX.utils,
  55423. dataGrid = ui.dxDataGrid;
  55424. var DATAGRID_CONTENT_CLASS = "dx-datagrid-content",
  55425. DATAGRID_HOVER_STATE_CLASS = "dx-state-hover",
  55426. DATAGRID_HEADER_ROW_CLASS = "dx-header-row",
  55427. DATAGRID_CONTENT_FIXED_CLASS = "dx-datagrid-content-fixed",
  55428. DATAGRID_GROUP_TEXT_CONTENT_CLASS = "dx-datagrid-group-text-content",
  55429. DATAGRID_FIXED_COL_CLASS = "dx-col-fixed",
  55430. DATAGRID_POINTER_EVENTS_TARGET_CLASS = "dx-pointer-events-target",
  55431. DATAGRID_POINTER_EVENTS_NONE_CLASS = "dx-pointer-events-none";
  55432. var baseFixedColumns = {
  55433. init: function() {
  55434. this.callBase();
  55435. this._isFixedTableRendering = false;
  55436. this._isFixedColumns = false
  55437. },
  55438. _createCol: function(column) {
  55439. return this.callBase(column).toggleClass(DATAGRID_FIXED_COL_CLASS, this._isFixedTableRendering && (column.fixed || column.command && column.command !== "transparent"))
  55440. },
  55441. _createCell: function(column) {
  55442. return this.callBase(column).attr("colspan", column.colspan).toggleClass(DATAGRID_POINTER_EVENTS_NONE_CLASS, column.command === "transparent")
  55443. },
  55444. _createTable: function(columns) {
  55445. var that = this,
  55446. $table = that.callBase(columns),
  55447. hoverStateEnabled = that.option("hoverStateEnabled"),
  55448. toggleHoverState = function(rowIndex, isHover) {
  55449. that._fixedTableElement && that._getRowElements(that._fixedTableElement).eq(rowIndex).toggleClass(DATAGRID_HOVER_STATE_CLASS, isHover);
  55450. that._tableElement && that._getRowElements(that._tableElement).eq(rowIndex).toggleClass(DATAGRID_HOVER_STATE_CLASS, isHover)
  55451. };
  55452. if (hoverStateEnabled && that._isFixedColumns)
  55453. $table.on("mouseover mouseout", ".dx-data-row", that.createAction(function(args) {
  55454. var event = args.jQueryEvent;
  55455. toggleHoverState(that.getRowIndex($(event.target).closest(".dx-row")), event.type === "mouseover")
  55456. }));
  55457. return $table
  55458. },
  55459. _renderTable: function(options) {
  55460. var that = this,
  55461. $fixedTable,
  55462. $table,
  55463. fixedColumns = that._columnsController.getFixedColumns();
  55464. that._isFixedColumns = !!fixedColumns.length;
  55465. $table = that.callBase(options);
  55466. if (that._isFixedColumns) {
  55467. that._isFixedTableRendering = true;
  55468. that._fixedTableElement = $fixedTable = that._createTable(fixedColumns);
  55469. that._renderRows($fixedTable, $.extend({}, options, {columns: fixedColumns}));
  55470. that.wrapTableInScrollContainer(that._fixedTableElement).appendTo(that.element()).addClass(DATAGRID_CONTENT_FIXED_CLASS + " " + DATAGRID_POINTER_EVENTS_TARGET_CLASS);
  55471. that._isFixedTableRendering = false
  55472. }
  55473. else
  55474. that._fixedTableElement && that._fixedTableElement.remove();
  55475. return $table
  55476. },
  55477. _renderCellContent: function($cell, options) {
  55478. var that = this,
  55479. column = options.column;
  55480. if (!that._isFixedTableRendering && that._isFixedColumns && (column.fixed || column.command || utils.isDefined(column.groupIndex)))
  55481. $cell.html("&nbsp;").addClass(column.cssClass);
  55482. else if (column.command !== "transparent")
  55483. that.callBase($cell, options)
  55484. },
  55485. getCellElements: function(rowIndex) {
  55486. var that = this,
  55487. fixedColumns,
  55488. fixedColumnIndex = 0,
  55489. fixedCellElements,
  55490. cellElements = that.callBase(rowIndex);
  55491. if (that._fixedTableElement && cellElements) {
  55492. fixedColumns = that._columnsController.getFixedColumns(),
  55493. fixedCellElements = that._fixedTableElement.find(".dx-row").eq(rowIndex).children("td");
  55494. $.each(fixedColumns, function(index, column) {
  55495. if (column.command === "transparent")
  55496. fixedColumnIndex += column.colspan;
  55497. else {
  55498. cellElements[fixedColumnIndex] = fixedCellElements.get(index);
  55499. fixedColumnIndex++
  55500. }
  55501. })
  55502. }
  55503. return cellElements
  55504. },
  55505. getColumnWidths: function() {
  55506. var that = this,
  55507. i,
  55508. fixedColumnIndex = 0,
  55509. widths,
  55510. result = that.callBase(),
  55511. fixedColumns = that._columnsController.getFixedColumns();
  55512. if (that._fixedTableElement && result.length) {
  55513. widths = dataGrid.getWidths(that._fixedTableElement);
  55514. for (i = 0; i < fixedColumns.length; i++)
  55515. if (fixedColumns[i].command === "transparent")
  55516. fixedColumnIndex += fixedColumns[i].colspan;
  55517. else {
  55518. if (result[fixedColumnIndex] < widths[i])
  55519. result[fixedColumnIndex] = widths[i];
  55520. fixedColumnIndex++
  55521. }
  55522. }
  55523. return result
  55524. },
  55525. _getTableElement: function() {
  55526. var tableElement = this._isFixedTableRendering ? this._fixedTableElement : this.callBase();
  55527. return tableElement
  55528. },
  55529. _setTableElement: function(tableElement) {
  55530. if (this._isFixedTableRendering)
  55531. this._fixedTableElement = tableElement;
  55532. else
  55533. this.callBase(tableElement)
  55534. },
  55535. getColumns: function($tableElement) {
  55536. $tableElement = $tableElement || this._getTableElement();
  55537. if (this._isFixedTableRendering || $tableElement && $tableElement.closest("table").parent("." + DATAGRID_CONTENT_FIXED_CLASS).length)
  55538. return this._columnsController.getFixedColumns();
  55539. return this.callBase($tableElement)
  55540. },
  55541. getRowIndex: function($row) {
  55542. var $fixedTable = this._fixedTableElement;
  55543. if ($fixedTable && $fixedTable.find($row).length)
  55544. return this._getRowElements($fixedTable).index($row);
  55545. return this.callBase($row)
  55546. },
  55547. _getTableElements: function() {
  55548. var result = this.callBase.apply(this, arguments);
  55549. if (this._fixedTableElement)
  55550. result = result.add(this._fixedTableElement);
  55551. return result
  55552. },
  55553. _resizeCore: function() {
  55554. this.callBase();
  55555. this._synchronizeRows()
  55556. },
  55557. setColumnWidths: function(widths) {
  55558. this.callBase(widths);
  55559. this._synchronizeRows()
  55560. },
  55561. _getClientHeight: function(element) {
  55562. var boundingClientRectElement = element.getBoundingClientRect && element.getBoundingClientRect();
  55563. return boundingClientRectElement && boundingClientRectElement.height ? boundingClientRectElement.height : element.clientHeight
  55564. },
  55565. _synchronizeRows: function() {
  55566. var that = this,
  55567. rowHeight,
  55568. fixedRowHeight,
  55569. rowIndex,
  55570. heightTable,
  55571. heightFixedTable,
  55572. $rowElements,
  55573. $fixedRowElements;
  55574. if (that._isFixedColumns && that._tableElement && that._fixedTableElement) {
  55575. heightTable = that._getClientHeight(that._tableElement.get(0));
  55576. heightFixedTable = that._getClientHeight(that._fixedTableElement.get(0));
  55577. $rowElements = that._getRowElements(that._tableElement);
  55578. $fixedRowElements = that._getRowElements(that._fixedTableElement);
  55579. if (heightTable !== heightFixedTable) {
  55580. $rowElements.height("");
  55581. $fixedRowElements.height("");
  55582. for (rowIndex = 0; rowIndex < $rowElements.length; rowIndex++) {
  55583. rowHeight = that._getClientHeight($rowElements.get(rowIndex));
  55584. fixedRowHeight = that._getClientHeight($fixedRowElements.get(rowIndex));
  55585. if (rowHeight > fixedRowHeight)
  55586. $fixedRowElements.eq(rowIndex).css("height", rowHeight);
  55587. else if (rowHeight < fixedRowHeight)
  55588. $rowElements.eq(rowIndex).css("height", fixedRowHeight)
  55589. }
  55590. }
  55591. }
  55592. }
  55593. };
  55594. var ColumnHeadersViewFixedColumnsExtender = $.extend({}, baseFixedColumns, {
  55595. getContextMenuItems: function($targetElement) {
  55596. var that = this,
  55597. $cell,
  55598. column,
  55599. onItemClick,
  55600. columnFixingOptions = that.option("columnFixing"),
  55601. items = that.callBase($targetElement);
  55602. if ($targetElement.closest("." + DATAGRID_HEADER_ROW_CLASS).length) {
  55603. $cell = $targetElement.closest("td");
  55604. column = $cell.length && that.getColumns($targetElement)[$cell[0].cellIndex];
  55605. if (column.allowFixing) {
  55606. onItemClick = function(params) {
  55607. switch (params.itemData.value) {
  55608. case"none":
  55609. that._columnsController.columnOption(column.index, "fixed", false);
  55610. break;
  55611. case"left":
  55612. that._columnsController.columnOption(column.index, "fixed", true);
  55613. that._columnsController.columnOption(column.index, "fixedPosition", "left");
  55614. break;
  55615. case"right":
  55616. that._columnsController.columnOption(column.index, "fixed", true);
  55617. that._columnsController.columnOption(column.index, "fixedPosition", "right");
  55618. break
  55619. }
  55620. };
  55621. items.push({
  55622. text: columnFixingOptions.texts.fix,
  55623. beginGroup: true,
  55624. items: [{
  55625. text: columnFixingOptions.texts.leftPosition,
  55626. value: "left",
  55627. disabled: column.fixed && (!column.fixedPosition || column.fixedPosition === "left"),
  55628. onItemClick: onItemClick
  55629. }, {
  55630. text: columnFixingOptions.texts.rightPosition,
  55631. value: "right",
  55632. disabled: column.fixed && column.fixedPosition === "right",
  55633. onItemClick: onItemClick
  55634. }]
  55635. }, {
  55636. text: columnFixingOptions.texts.unfix,
  55637. value: "none",
  55638. disabled: !column.fixed,
  55639. onItemClick: onItemClick
  55640. })
  55641. }
  55642. }
  55643. return items
  55644. },
  55645. setScrollerSpacing: function(width) {
  55646. var that = this,
  55647. rtlEnabled = that.option("rtlEnabled");
  55648. that.callBase(width);
  55649. that.element().children("." + DATAGRID_CONTENT_FIXED_CLASS).css(rtlEnabled ? {paddingLeft: width} : {paddingRight: width})
  55650. }
  55651. });
  55652. var RowsViewFixedColumnsExtender = $.extend({}, baseFixedColumns, {
  55653. _renderTable: function(options) {
  55654. var that = this,
  55655. $content,
  55656. $table,
  55657. $fixedTable,
  55658. fixedColumns = that._columnsController.getFixedColumns();
  55659. that._isFixedColumns = !!fixedColumns.length;
  55660. $table = that.callBase(options);
  55661. if (that._isFixedColumns) {
  55662. that._isFixedTableRendering = true;
  55663. $fixedTable = that._createTable(fixedColumns);
  55664. that._fixedTableElement = that._fixedTableElement || $fixedTable;
  55665. that._renderRows($fixedTable, $.extend({}, options, {columns: fixedColumns}));
  55666. $content = that._findContentElement();
  55667. that._updateContent($content, options.change, $fixedTable);
  55668. that._isFixedTableRendering = false
  55669. }
  55670. else
  55671. that._fixedTableElement && that._fixedTableElement.remove();
  55672. return $table
  55673. },
  55674. _findContentElement: function() {
  55675. var that = this,
  55676. $content,
  55677. scrollable,
  55678. scrollTop,
  55679. element = that.element();
  55680. if (element && that._isFixedTableRendering) {
  55681. $content = element.children("." + DATAGRID_CONTENT_CLASS);
  55682. if (!$content.length) {
  55683. scrollable = that.getScrollable();
  55684. $content = $("<div/>").addClass(DATAGRID_CONTENT_CLASS).on("dxmousewheel", function(e) {
  55685. if (scrollable) {
  55686. scrollTop = scrollable.scrollTop();
  55687. scrollable.scrollTo({y: scrollTop - e.delta});
  55688. if (scrollable.scrollTop() > 0 && scrollable.scrollTop() + scrollable.clientHeight() < scrollable.scrollHeight() + that.getScrollbarWidth())
  55689. return false
  55690. }
  55691. }).appendTo(element)
  55692. }
  55693. return $content
  55694. }
  55695. return that.callBase()
  55696. },
  55697. _renderContent: function(contentElement, tableElement) {
  55698. if (this._isFixedTableRendering)
  55699. return contentElement.empty().addClass(DATAGRID_CONTENT_CLASS + " " + DATAGRID_CONTENT_FIXED_CLASS + " " + DATAGRID_POINTER_EVENTS_TARGET_CLASS).append(tableElement);
  55700. return this.callBase(contentElement, tableElement)
  55701. },
  55702. _getGroupCellOptions: function(options) {
  55703. if (this._isFixedTableRendering)
  55704. return this.callBase($.extend({}, options, {columns: this._columnsController.getVisibleColumns()}));
  55705. return this.callBase(options)
  55706. },
  55707. _renderGroupSummaryCells: function($row, options) {
  55708. if (this._isFixedTableRendering)
  55709. this.callBase($row, $.extend({}, options, {columns: this._columnsController.getVisibleColumns()}));
  55710. else
  55711. this.callBase($row, options)
  55712. },
  55713. _getColumnTemplate: function(options) {
  55714. var that = this,
  55715. column = options.column,
  55716. template = this.callBase(options);
  55717. if (that._isFixedTableRendering && options.rowType === 'group')
  55718. if (column.groupIndex !== undefined)
  55719. return function($container, params) {
  55720. var $groupContent = $("<div/>").addClass(DATAGRID_GROUP_TEXT_CONTENT_CLASS);
  55721. $container.append($groupContent);
  55722. template($groupContent, params)
  55723. };
  55724. return template
  55725. },
  55726. _hasAlignByColumnSummaryItems: function(columnIndex, options) {
  55727. if (!this._isFixedTableRendering || options.columns[options.row.summaryCells.length - columnIndex].fixed)
  55728. return this.callBase(columnIndex, options)
  55729. },
  55730. getCellIndex: function($cell) {
  55731. var $fixedTable = this._fixedTableElement,
  55732. columns,
  55733. cellIndex = 0;
  55734. if ($fixedTable && $fixedTable.find($cell).length) {
  55735. columns = this._columnsController.getFixedColumns();
  55736. $.each(columns, function(index, column) {
  55737. if (index === $cell[0].cellIndex)
  55738. return false;
  55739. if (column.colspan) {
  55740. cellIndex += column.colspan;
  55741. return
  55742. }
  55743. cellIndex++
  55744. });
  55745. return cellIndex
  55746. }
  55747. return this.callBase($cell)
  55748. },
  55749. _updateFixedTablePosition: function(scrollTop) {
  55750. if (this._fixedTableElement && this._tableElement)
  55751. this._fixedTableElement.css("top", scrollTop + this._tableElement.position().top)
  55752. },
  55753. setScrollerSpacing: function() {
  55754. var that = this,
  55755. vWidth = that.getScrollbarWidth(),
  55756. hWidth = that.getScrollbarWidth(true),
  55757. styles = that.option("rtlEnabled") ? {marginLeft: vWidth} : {marginRight: vWidth};
  55758. styles.marginBottom = hWidth;
  55759. that.element().children("." + DATAGRID_CONTENT_FIXED_CLASS).css(styles)
  55760. },
  55761. _handleScroll: function(e) {
  55762. this._updateFixedTablePosition(-e.scrollOffset.top);
  55763. this.callBase(e)
  55764. },
  55765. _updateContentPosition: function() {
  55766. var isUpdated = this.callBase();
  55767. if (isUpdated)
  55768. this._updateFixedTablePosition(-this._scrollTop);
  55769. return isUpdated
  55770. },
  55771. getCell: function(cellPosition) {
  55772. var that = this,
  55773. columns = that.getColumns(),
  55774. columnIndex = cellPosition.columnIndex,
  55775. $rows;
  55776. if (columns && columnIndex < columns.length && (columns[columnIndex].fixed || columns[columnIndex].command === "expand")) {
  55777. var $colspanElement;
  55778. $rows = that._getRowElements(that._fixedTableElement);
  55779. $colspanElement = $rows.first().find("[colspan]");
  55780. if ($colspanElement[0].cellIndex < columnIndex)
  55781. cellPosition.columnIndex = columnIndex - $colspanElement.attr("colspan") + 1
  55782. }
  55783. return that.callBase(cellPosition, $rows)
  55784. },
  55785. optionChanged: function(args) {
  55786. switch (args.name) {
  55787. case'scrolling':
  55788. case'rtlEnabled':
  55789. case"disabled":
  55790. case'loadPanel':
  55791. this._fixedTableElement = null
  55792. }
  55793. this.callBase(args)
  55794. }
  55795. });
  55796. var FooterViewFixedColumnsExtender = baseFixedColumns;
  55797. dataGrid.registerModule('fixedColumns', {
  55798. defaultOptions: function() {
  55799. return {columnFixing: {
  55800. enabled: false,
  55801. texts: {
  55802. fix: Globalize.localize("dxDataGrid-columnFixingFix"),
  55803. unfix: Globalize.localize("dxDataGrid-columnFixingUnfix"),
  55804. leftPosition: Globalize.localize("dxDataGrid-columnFixingLeftPosition"),
  55805. rightPosition: Globalize.localize("dxDataGrid-columnFixingRightPosition")
  55806. }
  55807. }}
  55808. },
  55809. extenders: {views: {
  55810. columnHeadersView: ColumnHeadersViewFixedColumnsExtender,
  55811. rowsView: RowsViewFixedColumnsExtender,
  55812. footerView: FooterViewFixedColumnsExtender,
  55813. draggingHeaderView: {_pointCreated: function(point, columns, location, sourceColumn) {
  55814. var result = this.callBase.apply(this, arguments),
  55815. targetColumn = columns[point.columnIndex],
  55816. prevColumn = columns[point.columnIndex - 1],
  55817. getFixedPosition = function(column) {
  55818. return column.fixedPosition === "right" ? "right" : "left"
  55819. };
  55820. if (!result && location === "headers")
  55821. if (sourceColumn && sourceColumn.fixed)
  55822. return !(targetColumn && targetColumn.fixed && getFixedPosition(targetColumn) === getFixedPosition(sourceColumn) || prevColumn && prevColumn.fixed && getFixedPosition(prevColumn) === getFixedPosition(sourceColumn));
  55823. else
  55824. return targetColumn && targetColumn.fixed && getFixedPosition(targetColumn) !== "right" || prevColumn && prevColumn.fixed && getFixedPosition(prevColumn) === "right";
  55825. return result
  55826. }}
  55827. }}
  55828. })
  55829. })(jQuery, DevExpress);
  55830. /*! Module widgets-web, file ui.dataGrid.exportController.js */
  55831. (function($, DX) {
  55832. var ui = DX.ui,
  55833. utils = DX.utils,
  55834. dataGrid = ui.dxDataGrid,
  55835. DATAGRID_CHECKBOX_SIZE = "dx-datagrid-checkbox-size",
  55836. DATAGRID_EXPORT_MENU_CLASS = "dx-datagrid-export-menu",
  55837. DATAGRID_EXPORT_BUTTON_CLASS = "dx-datagrid-export-button",
  55838. DATAGRID_EXPORT_ICON = "export-to",
  55839. DATAGRID_EXPORT_EXCEL_ICON = "exportxlsx",
  55840. DATAGRID_EXPORT_EXCEL_BUTTON_ICON = "export-excel-button";
  55841. dataGrid.DataProvider = DX.Class.inherit({
  55842. _getGroupValue: function(item) {
  55843. var groupColumn = this._options.groupColumns[item.groupIndex],
  55844. value = dataGrid.getDisplayValue(groupColumn, item.values[item.groupIndex]),
  55845. result = groupColumn.caption + ": " + dataGrid.formatValue(value, groupColumn),
  55846. visibleIndex;
  55847. visibleIndex = this._options.getVisibleIndex(groupColumn.index);
  55848. if (item.summaryCells && item.summaryCells.length && item.summaryCells[visibleIndex].length)
  55849. result += " " + dataGrid.getGroupRowSummaryText(item.summaryCells[visibleIndex], this._options.summaryTexts);
  55850. return result
  55851. },
  55852. _correctCellIndex: function(cellIndex) {
  55853. var startIndex = this._options.startValueIndex,
  55854. endIndex = this._options.endValueIndex;
  55855. return cellIndex <= endIndex ? startIndex + cellIndex : null
  55856. },
  55857. ctor: function(options) {
  55858. this._options = options
  55859. },
  55860. getColumns: function() {
  55861. return this._options.columns
  55862. },
  55863. getRowsCount: function() {
  55864. return this._options.items.length
  55865. },
  55866. isGroupRow: function(rowIndex) {
  55867. return rowIndex < this._options.items.length && this._options.items[rowIndex].rowType === "group"
  55868. },
  55869. getGroupLevel: function(rowIndex) {
  55870. var item = this._options.items[rowIndex],
  55871. groupIndex = item.groupIndex;
  55872. if (item.isTotalSummary)
  55873. return 0;
  55874. return utils.isDefined(groupIndex) ? groupIndex : this._options.groupColumns.length
  55875. },
  55876. getCellType: function(rowIndex, cellIndex) {
  55877. if (cellIndex < this._options.columns.length) {
  55878. var item = this._options.items.length && this._options.items[rowIndex],
  55879. column = this._options.columns[cellIndex];
  55880. if (item && item.rowType === "data")
  55881. if (isFinite(item.values[this._correctCellIndex(cellIndex)]) && !utils.isDefined(column.customizeText))
  55882. return utils.isDefined(column.lookup) ? column.lookup.dataType : column.dataType;
  55883. return "string"
  55884. }
  55885. },
  55886. ready: function() {
  55887. var options = this._options;
  55888. return $.when(options.items).done(function(items) {
  55889. options.items = items
  55890. })
  55891. },
  55892. getCellValue: function(rowIndex, cellIndex) {
  55893. var column,
  55894. value,
  55895. correctedCellIndex = this._correctCellIndex(cellIndex),
  55896. itemValues,
  55897. item = this._options.items.length && this._options.items[rowIndex];
  55898. if (item) {
  55899. itemValues = item.values;
  55900. switch (item.rowType) {
  55901. case"summaryFooter":
  55902. if (correctedCellIndex < itemValues.length) {
  55903. value = itemValues[correctedCellIndex];
  55904. if (utils.isDefined(value))
  55905. return dataGrid.getSummaryText(value, this._options.summaryTexts)
  55906. }
  55907. break;
  55908. case"group":
  55909. if (cellIndex < 1)
  55910. return this._getGroupValue(item);
  55911. break;
  55912. default:
  55913. column = this._options.columns[cellIndex];
  55914. if (column) {
  55915. value = dataGrid.getDisplayValue(column, itemValues[correctedCellIndex]);
  55916. return !isFinite(value) || column.customizeText ? dataGrid.formatValue(value, column) : value
  55917. }
  55918. }
  55919. }
  55920. },
  55921. isHeadersVisible: function() {
  55922. return this._options.isHeadersVisible
  55923. },
  55924. isTotalRow: function(rowIndex) {
  55925. var items = this._options.items,
  55926. item = items[rowIndex];
  55927. return item && item.rowType === "summaryFooter"
  55928. }
  55929. });
  55930. dataGrid.ExportController = dataGrid.ViewController.inherit({
  55931. _getColumns: function() {
  55932. var result = [],
  55933. visibleColumns = this._columnsController.getVisibleColumns(),
  55934. columnWidths = this._rowsView.getColumnWidths(),
  55935. column,
  55936. i;
  55937. for (i = 0; i < visibleColumns.length; i++) {
  55938. column = visibleColumns[i];
  55939. if (!utils.isDefined(column.command))
  55940. result.push($.extend({}, column, {width: columnWidths[i]}))
  55941. }
  55942. return result
  55943. },
  55944. _getFooterSummaryItems: function(summaryCells, isTotal) {
  55945. var result = [],
  55946. estimatedItemsCount = 1,
  55947. values,
  55948. itemslength,
  55949. summaryCell,
  55950. j,
  55951. i = 0;
  55952. do {
  55953. values = [];
  55954. for (j = 0; j < summaryCells.length; j++) {
  55955. summaryCell = summaryCells[j];
  55956. itemslength = summaryCell.length;
  55957. if (estimatedItemsCount < itemslength)
  55958. estimatedItemsCount = itemslength;
  55959. values.push(summaryCell[i])
  55960. }
  55961. result.push({
  55962. values: values,
  55963. rowType: "summaryFooter",
  55964. isTotalSummary: isTotal
  55965. })
  55966. } while (i++ < estimatedItemsCount - 1);
  55967. return result
  55968. },
  55969. _hasSummaryGroupFooters: function() {
  55970. var i,
  55971. groupItems = this.option("summary.groupItems");
  55972. if (utils.isDefined(groupItems))
  55973. for (i = 0; i < groupItems.length; i++)
  55974. if (groupItems[i].showInGroupFooter)
  55975. return true;
  55976. return false
  55977. },
  55978. _getItemsWithSummaryGroupFooters: function(sourceItems) {
  55979. var item,
  55980. result = [],
  55981. beforeGroupFooterItems = [],
  55982. groupFooterItems = [],
  55983. i;
  55984. for (i = 0; i < sourceItems.length; i++) {
  55985. item = sourceItems[i];
  55986. if (item.rowType === "groupFooter") {
  55987. groupFooterItems = this._getFooterSummaryItems(item.summaryCells);
  55988. result = result.concat(beforeGroupFooterItems, groupFooterItems);
  55989. beforeGroupFooterItems = []
  55990. }
  55991. else
  55992. beforeGroupFooterItems.push(item)
  55993. }
  55994. return result.length ? result : beforeGroupFooterItems
  55995. },
  55996. _getAllItems: function(data) {
  55997. var that = this,
  55998. d = $.Deferred(),
  55999. dataController = this.getController("data"),
  56000. footerItems = dataController.footerItems(),
  56001. totalItem = footerItems.length && footerItems[0],
  56002. summaryTotalItems = that.option("summary.totalItems"),
  56003. summaryCells,
  56004. summaryItems;
  56005. dataController.loadAll(data).done(function(sourceItems, totalAggregates) {
  56006. if (that._hasSummaryGroupFooters())
  56007. sourceItems = that._getItemsWithSummaryGroupFooters(sourceItems);
  56008. summaryCells = totalItem && totalItem.summaryCells;
  56009. if (utils.isDefined(totalAggregates) && summaryTotalItems)
  56010. summaryCells = dataController._getSummaryCells(summaryTotalItems, totalAggregates);
  56011. summaryItems = totalItem && that._getFooterSummaryItems(summaryCells, true);
  56012. if (summaryItems)
  56013. sourceItems = sourceItems.concat(summaryItems);
  56014. d.resolve(sourceItems)
  56015. }).fail(d.reject);
  56016. return d
  56017. },
  56018. _getSelectedItems: function() {
  56019. var selectionController = this.getController("selection"),
  56020. selectedRowData = selectionController.getSelectedRowsData();
  56021. return this._getAllItems(selectedRowData)
  56022. },
  56023. _getStartEndValueIndexces: function(visibleColumns) {
  56024. var i,
  56025. startIndex,
  56026. endIndex,
  56027. visibleColumnslength = visibleColumns.length;
  56028. for (i = 0; i < visibleColumnslength; i++)
  56029. if (!utils.isDefined(visibleColumns[i].command)) {
  56030. startIndex = i;
  56031. break
  56032. }
  56033. for (i = visibleColumnslength - 1; i >= 0; i--)
  56034. if (!utils.isDefined(visibleColumns[i].command)) {
  56035. endIndex = i;
  56036. break
  56037. }
  56038. return {
  56039. startIndex: startIndex,
  56040. endIndex: endIndex
  56041. }
  56042. },
  56043. init: function() {
  56044. this._columnsController = this.getController("columns");
  56045. this._rowsView = this.getView("rowsView");
  56046. this.createAction("onExporting", {excludeValidators: ["disabled", "readOnly"]});
  56047. this.createAction("onExported", {excludeValidators: ["disabled", "readOnly"]});
  56048. this._clientExporter = new DX.dxClientExporter({
  56049. exportingAction: this.getAction("onExporting"),
  56050. exportedAction: this.getAction("onExported")
  56051. })
  56052. },
  56053. optionChanged: function(args) {
  56054. this.callBase(args);
  56055. if (args.name === "onExporting")
  56056. this._clientExporter.option("exportingAction", this.getAction(args.name));
  56057. if (args.name === "onExported")
  56058. this._clientExporter.option("exportedAction", this.getAction(args.name))
  56059. },
  56060. callbackNames: function() {
  56061. return ['selectionOnlyChanged']
  56062. },
  56063. getExportFormat: function() {
  56064. return ["EXCEL"]
  56065. },
  56066. getDataProvider: function() {
  56067. var groupColumns = this._columnsController.getGroupColumns(),
  56068. startEndIndexces = this._getStartEndValueIndexces(this._columnsController.getVisibleColumns());
  56069. return new dataGrid.DataProvider({
  56070. columns: this._getColumns(),
  56071. groupColumns: groupColumns,
  56072. items: !!this._selectionOnly ? this._getSelectedItems() : this._getAllItems(),
  56073. getVisibleIndex: $.proxy(this._columnsController.getVisibleIndex, this._columnsController),
  56074. startValueIndex: startEndIndexces.startIndex,
  56075. endValueIndex: startEndIndexces.endIndex,
  56076. isHeadersVisible: this.option("showColumnHeaders"),
  56077. summaryTexts: this.option("summary.texts")
  56078. })
  56079. },
  56080. exportToExcel: function(selectionOnly) {
  56081. this._selectionOnly = selectionOnly;
  56082. var excelWrapTextEnabled = this.option("export.excelWrapTextEnabled");
  56083. utils.isDefined(this._clientExporter) && this._clientExporter.exportTo({
  56084. fileName: this.option("export.fileName"),
  56085. proxyUrl: this.option("export.proxyUrl"),
  56086. format: "EXCEL",
  56087. wrapTextEnabled: utils.isDefined(excelWrapTextEnabled) ? excelWrapTextEnabled : !!this.option("wordWrapEnabled"),
  56088. autoFilterEnabled: !!this.option("export.excelFilterEnabled"),
  56089. component: this.component
  56090. })
  56091. },
  56092. publicMethods: function() {
  56093. return ["getDataProvider", "getExportFormat", "exportToExcel"]
  56094. },
  56095. selectionOnly: function(value) {
  56096. if (utils.isDefined(value)) {
  56097. this._isSelectedRows = value;
  56098. this.selectionOnlyChanged.fire()
  56099. }
  56100. else
  56101. return this._isSelectedRows
  56102. }
  56103. });
  56104. dataGrid.registerModule("export", {
  56105. defaultOptions: function() {
  56106. return {"export": {
  56107. enabled: false,
  56108. fileName: "DataGrid",
  56109. excelFilterEnabled: false,
  56110. excelWrapTextEnabled: undefined,
  56111. proxyUrl: undefined,
  56112. allowExportSelectedData: false,
  56113. texts: {
  56114. exportTo: Globalize.localize("dxDataGrid-exportTo"),
  56115. exportToExcel: Globalize.localize("dxDataGrid-exportToExcel"),
  56116. excelFormat: Globalize.localize("dxDataGrid-excelFormat"),
  56117. selectedRows: Globalize.localize("dxDataGrid-selectedRows")
  56118. }
  56119. }}
  56120. },
  56121. controllers: {"export": dataGrid.ExportController},
  56122. extenders: {views: {headerPanel: {
  56123. _isExportButtonVisible: function() {
  56124. return this.option("export.enabled")
  56125. },
  56126. _getButtonOptions: function() {
  56127. var that = this,
  56128. texts = that.option("export.texts");
  56129. return that.option("export.allowExportSelectedData") ? {
  56130. hint: texts.exportTo,
  56131. icon: DATAGRID_EXPORT_ICON
  56132. } : {
  56133. hint: texts.exportToExcel,
  56134. icon: DATAGRID_EXPORT_EXCEL_BUTTON_ICON,
  56135. onClick: function() {
  56136. that._exportController.exportToExcel()
  56137. }
  56138. }
  56139. },
  56140. _renderExportButton: function() {
  56141. var that = this;
  56142. utils.isDefined(that._$exportButton) && that._$exportButton.remove();
  56143. if (that.option("export.enabled")) {
  56144. that._$exportButton = $("<div>").addClass(DATAGRID_EXPORT_BUTTON_CLASS).dxButton(that._getButtonOptions());
  56145. that.element().append(that._$exportButton)
  56146. }
  56147. },
  56148. _renderExportMenu: function() {
  56149. var that = this,
  56150. texts = that.option("export.texts"),
  56151. menuItems = [{
  56152. text: texts.excelFormat,
  56153. icon: DATAGRID_EXPORT_EXCEL_ICON
  56154. }];
  56155. utils.isDefined(that._exportContextMenu) && that._exportContextMenu.element().remove();
  56156. if (that.option("export.enabled") && that.option("export.allowExportSelectedData")) {
  56157. menuItems.push({
  56158. value: "selectionOnly",
  56159. template: function() {
  56160. var $selectionOnlyEditor = $("<div>").addClass(DATAGRID_CHECKBOX_SIZE).dxCheckBox({
  56161. text: texts.selectedRows,
  56162. value: !!that._exportController.selectionOnly(),
  56163. onValueChanged: function(e) {
  56164. that._exportController.selectionOnly(e.value)
  56165. }
  56166. });
  56167. return $selectionOnlyEditor
  56168. },
  56169. beginGroup: true,
  56170. closeMenuOnClick: false
  56171. });
  56172. that._exportContextMenu = $("<div>").dxContextMenu({
  56173. alternativeInvocationMode: {
  56174. enabled: true,
  56175. invokingElement: that._$exportButton
  56176. },
  56177. items: menuItems,
  56178. cssClass: DATAGRID_EXPORT_MENU_CLASS,
  56179. onItemClick: function(e) {
  56180. if (e.itemData.text && e.itemData.text.indexOf("Excel") > -1)
  56181. that._exportController.exportToExcel(that._exportController.selectionOnly())
  56182. },
  56183. target: this._$exportButton,
  56184. position: {
  56185. at: "left bottom",
  56186. my: "left top",
  56187. offset: "0 3"
  56188. }
  56189. }).appendTo(that.component.element()).dxContextMenu("instance")
  56190. }
  56191. },
  56192. _renderCore: function() {
  56193. this.callBase();
  56194. this._renderExportButton();
  56195. this._renderExportMenu()
  56196. },
  56197. optionChanged: function(args) {
  56198. this.callBase(args);
  56199. if (args.name === "export") {
  56200. args.handled = true;
  56201. this.render()
  56202. }
  56203. },
  56204. init: function() {
  56205. this.callBase();
  56206. this._exportController = this.getController("export")
  56207. },
  56208. isVisible: function() {
  56209. return this.callBase() || this._isExportButtonVisible()
  56210. }
  56211. }}}
  56212. });
  56213. $.extend(dataGrid.__internals, {
  56214. DATAGRID_EXPORT_MENU_CLASS: DATAGRID_EXPORT_MENU_CLASS,
  56215. DATAGRID_EXPORT_BUTTON_CLASS: DATAGRID_EXPORT_BUTTON_CLASS
  56216. })
  56217. })(jQuery, DevExpress);
  56218. /*! Module widgets-web, file ui.pivotGrid.js */
  56219. (function($, DX) {
  56220. var ui = DX.ui,
  56221. events = ui.events,
  56222. utils = DX.utils;
  56223. function mergeArraysByMaxValue(values1, values2) {
  56224. var result = [],
  56225. i;
  56226. for (i = 0; i < values1.length; i++)
  56227. result.push(Math.max(values1[i] || 0, values2[i] || 0));
  56228. return result
  56229. }
  56230. var getScrollBarInfo = function(rootElement, useNativeScrolling) {
  56231. var scrollBarWidth = 0,
  56232. scrollBarUseNative,
  56233. options = {};
  56234. var container = $('<div>').css({
  56235. position: 'absolute',
  56236. visibility: 'hidden',
  56237. width: 100,
  56238. height: 100
  56239. }).appendTo(rootElement);
  56240. var content = $('<p>').css({
  56241. width: '100%',
  56242. height: 200
  56243. }).appendTo(container);
  56244. if (useNativeScrolling !== 'auto') {
  56245. options.useNative = !!useNativeScrolling;
  56246. options.useSimulatedScrollbar = !useNativeScrolling
  56247. }
  56248. container.dxScrollable(options);
  56249. scrollBarUseNative = container.dxScrollable('instance').option('useNative');
  56250. scrollBarWidth = scrollBarUseNative ? container.width() - content.width() : 0;
  56251. container.remove();
  56252. return {
  56253. scrollBarWidth: scrollBarWidth,
  56254. scrollBarUseNative: scrollBarUseNative
  56255. }
  56256. };
  56257. DX.registerComponent("dxPivotGrid", ui, ui.Widget.inherit({
  56258. _setDefaultOptions: function() {
  56259. this.callBase();
  56260. this.option({
  56261. useNativeScrolling: "auto",
  56262. encodeHtml: true,
  56263. descriptions: null,
  56264. dataSource: null,
  56265. activeStateEnabled: false,
  56266. fieldChooser: {
  56267. enabled: true,
  56268. layout: 0,
  56269. title: Globalize.localize("dxPivotGrid-fieldChooserTitle"),
  56270. width: 600,
  56271. height: 600
  56272. },
  56273. onContextMenuPreparing: null,
  56274. allowSorting: false,
  56275. allowSortingBySummary: false,
  56276. allowFiltering: false,
  56277. allowExpandAll: false,
  56278. showRowTotals: true,
  56279. showRowGrandTotals: true,
  56280. showColumnTotals: true,
  56281. showColumnGrandTotals: true,
  56282. loadPanel: {
  56283. enabled: true,
  56284. text: Globalize.localize("Loading"),
  56285. width: 200,
  56286. height: 70,
  56287. showIndicator: true,
  56288. indicatorSrc: "",
  56289. showPane: true
  56290. },
  56291. texts: {
  56292. grandTotal: Globalize.localize("dxPivotGrid-grandTotal"),
  56293. total: Globalize.localize("dxPivotGrid-total"),
  56294. noData: Globalize.localize("dxDataGrid-noDataText"),
  56295. showFieldChooser: Globalize.localize("dxPivotGrid-showFieldChooser"),
  56296. expandAll: Globalize.localize("dxPivotGrid-expandAll"),
  56297. collapseAll: Globalize.localize("dxPivotGrid-collapseAll"),
  56298. sortColumnBySummary: Globalize.localize("dxPivotGrid-sortColumnBySummary"),
  56299. sortRowBySummary: Globalize.localize("dxPivotGrid-sortRowBySummary"),
  56300. removeAllSorting: Globalize.localize("dxPivotGrid-removeAllSorting")
  56301. },
  56302. onCellClick: null,
  56303. onCellPrepared: null,
  56304. onExpandValueChanging: null,
  56305. renderCellCountLimit: 20000
  56306. })
  56307. },
  56308. _initDataController: function() {
  56309. var that = this;
  56310. if (that._dataController)
  56311. that._dataController.dispose();
  56312. that._dataController = new pivotGrid.DataController({
  56313. descriptions: that.option('descriptions'),
  56314. dataSource: that.option('dataSource'),
  56315. texts: that.option('texts'),
  56316. showRowTotals: that.option('showRowTotals'),
  56317. showRowGrandTotals: that.option('showRowGrandTotals'),
  56318. showColumnTotals: that.option('showColumnTotals'),
  56319. showColumnGrandTotals: that.option('showColumnGrandTotals'),
  56320. onFieldsPrepared: function(fields) {
  56321. $.each(fields, function(index, field) {
  56322. $.each(["allowSorting", "allowSortingBySummary", "allowFiltering", "allowExpandAll"], function(_, optionName) {
  56323. if (field[optionName] === undefined)
  56324. field[optionName] = that.option(optionName)
  56325. })
  56326. })
  56327. }
  56328. });
  56329. that._dataController.changed.add(function() {
  56330. that._render()
  56331. });
  56332. that._dataController.loadingChanged.add(function() {
  56333. that._updateLoading()
  56334. });
  56335. var expandValueChanging = that.option('onExpandValueChanging');
  56336. if (expandValueChanging)
  56337. that._dataController.expandValueChanging.add(function(e) {
  56338. expandValueChanging(e)
  56339. })
  56340. },
  56341. _init: function() {
  56342. var that = this;
  56343. that.callBase();
  56344. that._initDataController();
  56345. that._scrollLeft = 0;
  56346. that._scrollTop = 0
  56347. },
  56348. _optionChanged: function(args) {
  56349. var that = this;
  56350. switch (args.name) {
  56351. case"dataSource":
  56352. case"descriptions":
  56353. case"texts":
  56354. case"showRowTotals":
  56355. case"showRowGrandTotals":
  56356. case"showColumnTotals":
  56357. case"showColumnGrandTotals":
  56358. case"showColumnGrandTotals":
  56359. case"allowSorting":
  56360. case"allowFiltering":
  56361. that._initDataController();
  56362. that._invalidate();
  56363. break;
  56364. case"useNativeScrolling":
  56365. case"encodeHtml":
  56366. case"renderCellCountLimit":
  56367. that._invalidate();
  56368. break;
  56369. case"rtlEnabled":
  56370. that.callBase(args);
  56371. that._renderFieldChooser();
  56372. that._renderContextMenu();
  56373. that._renderLoadPanel(that._dataArea.groupElement());
  56374. that._invalidate();
  56375. break;
  56376. case"onCellClick":
  56377. case"onExpandValueChanging":
  56378. case"onCellPrepared":
  56379. case"onContextMenuPreparing":
  56380. case"allowSortingBySummary":
  56381. case"allowExpandAll":
  56382. break;
  56383. case"fieldChooser":
  56384. that._renderFieldChooser();
  56385. break;
  56386. case"loadPanel":
  56387. that._renderLoadPanel(that._dataArea.groupElement());
  56388. that._invalidate();
  56389. break;
  56390. default:
  56391. that.callBase(args)
  56392. }
  56393. },
  56394. _updateScrollPosition: function(columnsArea, rowsArea, dataArea) {
  56395. var that = this,
  56396. setScrollPos = function(area, pos) {
  56397. var scrollable;
  56398. if (area) {
  56399. scrollable = area.groupElement().data('dxScrollable');
  56400. if (scrollable) {
  56401. scrollable.scrollTo(pos);
  56402. scrollable.update()
  56403. }
  56404. }
  56405. };
  56406. if (rowsArea && !rowsArea.hasScroll())
  56407. that._scrollTop = 0;
  56408. if (columnsArea && !columnsArea.hasScroll())
  56409. that._scrollLeft = 0;
  56410. setScrollPos(dataArea, {
  56411. x: that._scrollLeft,
  56412. y: that._scrollTop
  56413. });
  56414. setScrollPos(columnsArea, that._scrollLeft);
  56415. setScrollPos(rowsArea, that._scrollTop)
  56416. },
  56417. _subscribeToEvents: function(columnsArea, rowsArea, dataArea) {
  56418. var that = this,
  56419. subscribeToScrollEvent = function(area, handler) {
  56420. var scrollable = area.groupElement().data('dxScrollable');
  56421. if (scrollable) {
  56422. scrollable.option('onScroll', handler);
  56423. scrollable.option('onStop', handler)
  56424. }
  56425. };
  56426. subscribeToScrollEvent(dataArea, function(e) {
  56427. var scrollOffset = e.scrollOffset;
  56428. if (that._scrollLeft !== scrollOffset.left || that._scrollTop !== scrollOffset.top) {
  56429. that._scrollLeft = Math.floor(e.scrollOffset.left);
  56430. that._scrollTop = Math.floor(e.scrollOffset.top);
  56431. that._updateScrollPosition(columnsArea, rowsArea, null)
  56432. }
  56433. })
  56434. },
  56435. _clean: $.noop,
  56436. _needDelayResizing: function() {
  56437. var cells = this._dataController.getCellsInfo(),
  56438. cellsCount = cells.length * (cells.length ? cells[0].length : 0);
  56439. return cellsCount > this.option("renderCellCountLimit")
  56440. },
  56441. _renderFieldChooser: function() {
  56442. var that = this,
  56443. container = that._pivotGridContainer,
  56444. fieldChooserOptions = that.option("fieldChooser") || {};
  56445. var popupOptions = {
  56446. visible: false,
  56447. shading: false,
  56448. title: fieldChooserOptions.title,
  56449. width: fieldChooserOptions.width,
  56450. height: fieldChooserOptions.height,
  56451. showCloseButton: true,
  56452. rtlEnabled: that.option('rtlEnabled'),
  56453. onShown: function(e) {
  56454. var popup = e.component,
  56455. $content = e.component.content();
  56456. that._createComponent($content, "dxPivotGridFieldChooser", {
  56457. layout: fieldChooserOptions.layout,
  56458. texts: fieldChooserOptions.texts || {},
  56459. dataSource: that.getDataSource(),
  56460. width: undefined,
  56461. height: undefined
  56462. });
  56463. that._createComponent($content.parent(), "dxResizable", {
  56464. handles: that.option('rtlEnabled') ? "left bottom" : "right bottom",
  56465. onResize: function(e) {
  56466. popup._setContentHeight();
  56467. $content.dxPivotGridFieldChooser("updateDimensions")
  56468. }
  56469. })
  56470. }
  56471. };
  56472. if (that._fieldChooserPopup)
  56473. that._fieldChooserPopup.option(popupOptions);
  56474. else
  56475. that._fieldChooserPopup = that._createComponent($('<div>').addClass('dx-fieldchooser-popup').appendTo(container), "dxPopup", popupOptions)
  56476. },
  56477. _renderContextMenu: function() {
  56478. var that = this,
  56479. $container = that._pivotGridContainer;
  56480. if (that._contextMenu)
  56481. that._contextMenu.element().remove();
  56482. that._contextMenu = that._createComponent($("<div>").appendTo($container), "dxContextMenu", {
  56483. onPositioning: function(actionArgs) {
  56484. var event = actionArgs.jQueryEvent,
  56485. cellElement = event.target.cellIndex >= 0 ? event.target : $(event.target).closest('td').get(0),
  56486. cellArgs = that._createCellArgs(cellElement),
  56487. items = that._getContextMenuItems(cellArgs);
  56488. if (items)
  56489. actionArgs.component.option('items', items);
  56490. else
  56491. actionArgs.canceled = true
  56492. },
  56493. onItemClick: function(params) {
  56494. params.itemData.onItemClick && params.itemData.onItemClick(params)
  56495. },
  56496. cssClass: pivotGrid.cssClassNames.pivotGrid,
  56497. target: that.element()
  56498. })
  56499. },
  56500. _getContextMenuItems: function(e) {
  56501. var that = this,
  56502. onContextMenuPreparing = that.option("onContextMenuPreparing"),
  56503. items = [];
  56504. if (e.area === "row" || e.area === "column") {
  56505. var areaFields = e[e.area + "Fields"],
  56506. oppositeAreaFields = e[e.area === "column" ? "rowFields" : "columnFields"],
  56507. field = e.cell.path && areaFields[e.cell.path.length - 1],
  56508. dataSource = that.getDataSource();
  56509. if (field && field.allowExpandAll && e.cell.path.length < e[e.area + "Fields"].length && e.cell.type === "D") {
  56510. items.push({
  56511. beginGroup: true,
  56512. icon: "none",
  56513. text: that.option("texts.expandAll"),
  56514. onItemClick: function() {
  56515. dataSource.expandAll(field.index)
  56516. }
  56517. });
  56518. items.push({
  56519. text: that.option("texts.collapseAll"),
  56520. icon: "none",
  56521. onItemClick: function() {
  56522. dataSource.collapseAll(field.index)
  56523. }
  56524. })
  56525. }
  56526. if (e.cell.isLast) {
  56527. var sortingBySummaryItemCount = 0;
  56528. $.each(oppositeAreaFields, function(index, field) {
  56529. if (field.allowSortingBySummary)
  56530. $.each(e.dataFields, function(dataIndex, dataField) {
  56531. if (utils.isDefined(e.cell.dataIndex) && e.cell.dataIndex !== dataIndex)
  56532. return;
  56533. var showDataFieldCaption = !utils.isDefined(e.cell.dataIndex) && e.dataFields.length > 1,
  56534. textFormat = that.option(e.area === "column" ? "texts.sortColumnBySummary" : "texts.sortRowBySummary"),
  56535. checked = pivotGrid.findField(e.dataFields, field.sortBySummaryField) === dataIndex && (e.cell.path || []).join("/") === (field.sortBySummaryPath || []).join("/"),
  56536. text = utils.stringFormat(textFormat, showDataFieldCaption ? field.caption + " - " + dataField.caption : field.caption);
  56537. items.push({
  56538. beginGroup: sortingBySummaryItemCount === 0,
  56539. icon: checked ? field.sortOrder === "desc" ? "desc" : "asc" : "none",
  56540. text: text,
  56541. onItemClick: function() {
  56542. dataSource.field(field.index, {
  56543. sortBySummaryField: dataField.caption || dataField.dataField,
  56544. sortBySummaryPath: e.cell.path,
  56545. sortOrder: field.sortOrder === "desc" ? "asc" : "desc"
  56546. });
  56547. dataSource.load()
  56548. }
  56549. });
  56550. sortingBySummaryItemCount++
  56551. })
  56552. });
  56553. $.each(oppositeAreaFields, function(index, field) {
  56554. if (field.allowSortingBySummary && utils.isDefined(field.sortBySummaryField)) {
  56555. items.push({
  56556. beginGroup: sortingBySummaryItemCount === 0,
  56557. icon: "none",
  56558. text: that.option("texts.removeAllSorting"),
  56559. onItemClick: function() {
  56560. $.each(oppositeAreaFields, function(index, field) {
  56561. dataSource.field(field.index, {
  56562. sortBySummaryField: undefined,
  56563. sortBySummaryPath: undefined,
  56564. sortOrder: undefined
  56565. })
  56566. });
  56567. dataSource.load()
  56568. }
  56569. });
  56570. return false
  56571. }
  56572. })
  56573. }
  56574. }
  56575. if (that.option("fieldChooser.enabled"))
  56576. items.push({
  56577. beginGroup: true,
  56578. icon: "field-chooser",
  56579. text: that.option("texts.showFieldChooser"),
  56580. onItemClick: function() {
  56581. that._fieldChooserPopup.show()
  56582. }
  56583. });
  56584. if (onContextMenuPreparing) {
  56585. e.items = items;
  56586. onContextMenuPreparing(e);
  56587. items = e.items
  56588. }
  56589. if (items && items.length)
  56590. return items
  56591. },
  56592. _createCellArgs: function(cellElement) {
  56593. var that = this,
  56594. $cellElement = $(cellElement),
  56595. columnIndex = cellElement.cellIndex,
  56596. rowIndex = cellElement.parentElement.rowIndex,
  56597. $table = $cellElement.closest('table'),
  56598. area = $table.data("area"),
  56599. data = $table.data("data"),
  56600. cell = data && data[rowIndex] && data[rowIndex][columnIndex],
  56601. args = {
  56602. area: area,
  56603. rowFields: that.getDataSource().getAreaFields("row"),
  56604. columnFields: that.getDataSource().getAreaFields("column"),
  56605. dataFields: that.getDataSource().getAreaFields("data"),
  56606. rowIndex: rowIndex,
  56607. columnIndex: columnIndex,
  56608. cellElement: $cellElement,
  56609. cell: cell
  56610. };
  56611. return args
  56612. },
  56613. _handleCellClick: function(e) {
  56614. var that = this,
  56615. onCellClick = that.option('onCellClick'),
  56616. args = that._createCellArgs(e.currentTarget);
  56617. if (!args.area && (args.rowIndex || args.columnIndex))
  56618. return;
  56619. if (onCellClick)
  56620. onCellClick(args);
  56621. if (!args.handled)
  56622. if (!args.area && that.option("fieldChooser.enabled"))
  56623. that._fieldChooserPopup.show()
  56624. },
  56625. _getNoDataText: function() {
  56626. return this.option("texts.noData")
  56627. },
  56628. _updateNoDataText: DX.ui.dxDataGrid.RowsView.prototype._updateNoDataText,
  56629. _renderLoadPanel: DX.ui.dxDataGrid.RowsView.prototype._renderLoadPanel,
  56630. _updateLoading: function() {
  56631. var that = this;
  56632. that._loadPanel && that._loadPanel.option("visible", that._dataController.isLoading())
  56633. },
  56634. _renderContentImpl: function() {
  56635. var that = this,
  56636. columnsAreaElement = $('<td>'),
  56637. rowsAreaElement = $('<td>'),
  56638. dataAreaElement = $('<td>'),
  56639. tableElement = $('<table>'),
  56640. dataArea = that._dataArea || new pivotGrid.DataArea(that),
  56641. rowsArea = (that._rowsArea || new pivotGrid.VerticalHeadersArea(that)).setDataController(that._dataController),
  56642. columnsArea = (that._columnsArea || new pivotGrid.HorizontalHeadersArea(that)).setDataController(that._dataController),
  56643. scrollBarInfo = getScrollBarInfo(that.element(), that.option("useNativeScrolling"));
  56644. that._scrollBarWidth = scrollBarInfo.scrollBarWidth;
  56645. that._scrollBarUseNative = scrollBarInfo.scrollBarUseNative;
  56646. if (!utils.isDefined(that._pivotGridContainer)) {
  56647. that._pivotGridContainer = $('<div>');
  56648. that._renderFieldChooser();
  56649. that._renderContextMenu();
  56650. $('<tr>').append($('<td>').addClass(pivotGrid.cssClassNames.areaDescription)).append(columnsAreaElement).appendTo(tableElement);
  56651. $('<tr>').addClass(pivotGrid.cssClassNames.bottomAraesRow).append(rowsAreaElement).append(dataAreaElement).appendTo(tableElement);
  56652. tableElement.appendTo(that._pivotGridContainer);
  56653. tableElement.on(events.addNamespace("dxclick", "dxPivotGrid"), 'td', $.proxy(that, "_handleCellClick"))
  56654. }
  56655. else
  56656. tableElement = that._pivotGridContainer.children().first();
  56657. that._rowsArea = rowsArea;
  56658. that._columnsArea = columnsArea;
  56659. that._dataArea = dataArea;
  56660. columnsArea.render(columnsAreaElement, that._dataController.getColumnsInfo());
  56661. rowsArea.render(rowsAreaElement, that._dataController.getRowsInfo());
  56662. dataArea.render(dataAreaElement, that._dataController.getCellsInfo());
  56663. dataArea.tableElement().prepend(columnsArea.headElement());
  56664. var updateHandler = function() {
  56665. that.updateDimensions();
  56666. that._subscribeToEvents(columnsArea, rowsArea, dataArea)
  56667. };
  56668. if (!utils.isDefined(that._pivotGridContainer[0].parentElement)) {
  56669. that._hasHeight = that.element().height() > 0;
  56670. that._pivotGridContainer.appendTo(that.element());
  56671. that.element().addClass(pivotGrid.cssClassNames.pivotGrid).addClass(pivotGrid.cssClassNames.rowLines);
  56672. that._renderLoadPanel(dataArea.groupElement());
  56673. rowsArea.processScroll();
  56674. columnsArea.processScroll();
  56675. if (that._needDelayResizing())
  56676. setTimeout(updateHandler);
  56677. else
  56678. updateHandler()
  56679. }
  56680. else
  56681. updateHandler()
  56682. },
  56683. _fireContentReadyAction: function() {
  56684. if (!this._dataController.isLoading())
  56685. this.callBase()
  56686. },
  56687. getScrollPath: function(area) {
  56688. var that = this,
  56689. i,
  56690. currentScrollPosition = 0,
  56691. scrollPosition,
  56692. columnSizes;
  56693. if (area === 'column') {
  56694. scrollPosition = that._scrollLeft;
  56695. columnSizes = that._columnsArea.getColumnsWidth()
  56696. }
  56697. else {
  56698. scrollPosition = that._scrollTop;
  56699. columnSizes = that._rowsArea.getRowsHeight()
  56700. }
  56701. for (i = 0; i < columnSizes.length; i++) {
  56702. if (scrollPosition < currentScrollPosition + columnSizes[i] / 2)
  56703. return that._dataController.getHeaderItemPath(area, i);
  56704. currentScrollPosition += columnSizes[i]
  56705. }
  56706. },
  56707. getDataSource: function() {
  56708. return this._dataController.getDataSource()
  56709. },
  56710. hasScroll: function(area) {
  56711. var that = this;
  56712. if (area === 'column')
  56713. return that._columnsArea.hasScroll();
  56714. else
  56715. return that._rowsArea.hasScroll()
  56716. },
  56717. _dimensionChanged: function() {
  56718. this.updateDimensions()
  56719. },
  56720. _visibilityChanged: function(visible) {
  56721. if (visible)
  56722. this.updateDimensions()
  56723. },
  56724. _dispose: function() {
  56725. var that = this;
  56726. that.callBase.apply(that, arguments);
  56727. if (that._dataController)
  56728. that._dataController.dispose()
  56729. },
  56730. resize: function() {
  56731. this.updateDimensions()
  56732. },
  56733. updateDimensions: function() {
  56734. var that = this,
  56735. diff,
  56736. groupWidth,
  56737. groupHeight,
  56738. tableElement = that.element().find('table').first(),
  56739. bottomAraesRowElement,
  56740. rowsArea = that._rowsArea,
  56741. columnsArea = that._columnsArea,
  56742. dataArea = that._dataArea,
  56743. dataAreaHeights,
  56744. rowsAreaHeights,
  56745. resultHeights,
  56746. resultWidths,
  56747. rowsAreaColumnWidths,
  56748. totalWidth = 0,
  56749. totalHeight = 0,
  56750. hasRowsScroll,
  56751. hasColumnsScroll,
  56752. dataFields = that.getDataSource().getAreaFields("data"),
  56753. loadPanelOptions = that.option("loadPanel") || {},
  56754. minHeight,
  56755. scrollBarWidth = that._scrollBarWidth || 0;
  56756. if (!dataArea.headElement().length) {
  56757. dataArea.tableElement().prepend(columnsArea.headElement());
  56758. dataArea.resetColumnsWidth()
  56759. }
  56760. resultWidths = dataArea.getColumnsWidth();
  56761. rowsAreaHeights = rowsArea.getRowsHeight();
  56762. dataAreaHeights = dataArea.getRowsHeight();
  56763. resultHeights = mergeArraysByMaxValue(rowsAreaHeights, dataAreaHeights.slice(dataAreaHeights.length - rowsAreaHeights.length));
  56764. rowsAreaColumnWidths = rowsArea.getColumnsWidth();
  56765. diff = that.element().width() - tableElement.width();
  56766. groupWidth = Math.floor(dataArea.groupWidth() + diff);
  56767. if (that._hasHeight) {
  56768. diff = that.element().height() - tableElement.height() - dataArea.headElement().height();
  56769. bottomAraesRowElement = tableElement.find('.' + pivotGrid.cssClassNames.bottomAraesRow),
  56770. groupHeight = Math.floor(bottomAraesRowElement.height() + diff)
  56771. }
  56772. totalWidth = dataArea.tableElement().width();
  56773. $.each(resultHeights, function(index, height) {
  56774. totalHeight += height || 0
  56775. });
  56776. hasRowsScroll = groupHeight < totalHeight;
  56777. hasColumnsScroll = groupWidth < totalWidth;
  56778. if (!hasRowsScroll)
  56779. groupHeight = totalHeight + (hasColumnsScroll ? scrollBarWidth : 0);
  56780. columnsArea.tableElement().append(dataArea.headElement());
  56781. if (resultHeights.length === 1 && loadPanelOptions.enabled && loadPanelOptions.height) {
  56782. minHeight = loadPanelOptions.height + 50;
  56783. if (resultHeights[0] < minHeight) {
  56784. resultHeights[0] = minHeight;
  56785. if (groupHeight < minHeight)
  56786. groupHeight = minHeight
  56787. }
  56788. }
  56789. columnsArea.groupWidth(groupWidth);
  56790. columnsArea.processScrollBarSpacing(hasRowsScroll ? scrollBarWidth : 0);
  56791. columnsArea.processStretch(resultWidths, hasColumnsScroll, dataFields);
  56792. columnsArea.setColumnsWidth(resultWidths);
  56793. rowsArea.groupHeight(groupHeight);
  56794. rowsArea.processScrollBarSpacing(hasColumnsScroll ? scrollBarWidth : 0);
  56795. rowsArea.setColumnsWidth(rowsAreaColumnWidths);
  56796. rowsArea.setRowsHeight(resultHeights);
  56797. dataArea.setColumnsWidth(resultWidths);
  56798. dataArea.setRowsHeight(resultHeights);
  56799. dataArea.groupWidth(groupWidth);
  56800. dataArea.groupHeight(groupHeight);
  56801. dataArea.groupElement().css('border-bottom-width', hasRowsScroll || scrollBarWidth ? '0px' : '');
  56802. rowsArea.groupElement().css('border-bottom-width', hasRowsScroll && !scrollBarWidth ? '0px' : '');
  56803. dataArea.processScroll(scrollBarWidth, hasRowsScroll, hasColumnsScroll, that._scrollBarUseNative);
  56804. that._updateNoDataText(dataArea.groupElement());
  56805. that._updateLoading();
  56806. that._updateScrollPosition(columnsArea, rowsArea, dataArea);
  56807. that._testResultWidths = resultWidths;
  56808. that._testResultHeights = resultHeights
  56809. },
  56810. applyPartialDataSource: function(area, path, dataSource) {
  56811. this._dataController.applyPartialDataSource(area, path, dataSource)
  56812. }
  56813. }));
  56814. var pivotGrid = $.extend(ui.dxPivotGrid, {
  56815. cssClassNames: {
  56816. pivotGrid: 'dx-pivotgrid',
  56817. rowLines: 'dx-row-lines',
  56818. area: 'dx-pivotgrid-area',
  56819. areaData: 'dx-pivotgrid-area-data',
  56820. areaDescription: 'dx-pivotgrid-area-description',
  56821. splitter: 'dx-pivotgrid-splitter',
  56822. splitterButton: 'dx-button',
  56823. splitterButtonDisable: 'dx-button-disable',
  56824. splitterExpand: 'dx-expand',
  56825. splitterCollapse: 'dx-collapse',
  56826. bottomAraesRow: 'dx-bottom-row',
  56827. verticalScroll: 'dx-vertical-scroll',
  56828. headersVertical: 'dx-pivotgrid-vertical-headers',
  56829. headersHorizontal: 'dx-pivotgrid-horizontal-headers',
  56830. headersVerticalLastCell: 'dx-last-cell',
  56831. headersVerticalExpandBorder: 'dx-expand-border',
  56832. headersExpandCollapseImage: 'dx-expand',
  56833. headersExpanded: 'dx-pivotgrid-expanded',
  56834. headersCollapsed: 'dx-pivotgrid-collapsed',
  56835. bottomBorder: 'dx-pivotgrid-bottom-border',
  56836. total: 'dx-total',
  56837. grandTotal: 'dx-grandtotal',
  56838. rowTotal: 'dx-row-total'
  56839. },
  56840. mergeArraysByMaxValue: mergeArraysByMaxValue
  56841. })
  56842. })(jQuery, DevExpress);
  56843. /*! Module widgets-web, file ui.pivotGrid.dataSource.js */
  56844. (function($, DX) {
  56845. var pivotGrid = DX.ui.dxPivotGrid,
  56846. utils = DX.utils,
  56847. isDefined = utils.isDefined;
  56848. var DESCRIPTION_NAME_BY_AREA = {
  56849. row: "rows",
  56850. column: "columns",
  56851. data: "values",
  56852. filter: "filters"
  56853. };
  56854. function findField(fields, id) {
  56855. var i,
  56856. field;
  56857. if (fields && utils.isDefined(id))
  56858. for (i = 0; i < fields.length; i++) {
  56859. field = fields[i];
  56860. if (field.name === id || field.caption === id || field.dataField === id || field.index === id)
  56861. return i
  56862. }
  56863. return -1
  56864. }
  56865. function foreachTreeItems(items, callback, path, parentAtFirst) {
  56866. var index,
  56867. item;
  56868. if (!items)
  56869. return;
  56870. for (index = 0; index < items.length; index++) {
  56871. item = items[index];
  56872. if (item) {
  56873. if (path)
  56874. path.push(item.value);
  56875. if (parentAtFirst && callback(item, path, index, items) === false)
  56876. return false;
  56877. if (foreachTreeItems(item.children, callback, path, parentAtFirst) === false)
  56878. return false;
  56879. if (!parentAtFirst && callback(item, path, index, items) === false)
  56880. return false;
  56881. if (path)
  56882. path.pop()
  56883. }
  56884. }
  56885. }
  56886. function formatValue(value, options) {
  56887. var formatObject = {
  56888. value: value,
  56889. valueText: DX.formatHelper.format(value, options.format, options.precision) || ''
  56890. };
  56891. return options.customizeText ? options.customizeText.call(options, formatObject) : formatObject.valueText
  56892. }
  56893. function foreachDataLevel(data, callback, index, childrenField) {
  56894. var item,
  56895. i;
  56896. index = index || 0;
  56897. childrenField = childrenField || "children";
  56898. if (data.length)
  56899. callback(data, index);
  56900. for (i = 0; i < data.length; i++) {
  56901. item = data[i];
  56902. if (item[childrenField] && item[childrenField].length)
  56903. foreachDataLevel(item[childrenField], callback, index + 1, childrenField)
  56904. }
  56905. }
  56906. function getCompareFunction(valueSelector) {
  56907. return function(a, b) {
  56908. var result = 0;
  56909. if (valueSelector(a) > valueSelector(b))
  56910. result = 1;
  56911. else if (valueSelector(a) < valueSelector(b))
  56912. result = -1;
  56913. return result
  56914. }
  56915. }
  56916. DX.data.PivotGridDataSource = pivotGrid.DataSource = DX.Class.inherit(function() {
  56917. var isValuesEqual = function(value1, value2) {
  56918. return DevExpress.data.utils.toComparable(value1) === DevExpress.data.utils.toComparable(value2)
  56919. };
  56920. var findHeaderItem = function(headerItems, path) {
  56921. var pathIndex,
  56922. foundHeaderItems,
  56923. headerItem = null;
  56924. var checkHeaderItem = function(item) {
  56925. return isValuesEqual(item.value, path[pathIndex])
  56926. };
  56927. if ($.isArray(path))
  56928. for (pathIndex = 0; pathIndex < path.length && headerItems; pathIndex++) {
  56929. foundHeaderItems = $.grep(headerItems || [], checkHeaderItem);
  56930. if (foundHeaderItems.length === 0) {
  56931. headerItem = null;
  56932. break
  56933. }
  56934. headerItem = foundHeaderItems[0];
  56935. headerItems = headerItem.children
  56936. }
  56937. return headerItem
  56938. };
  56939. var getHeaderItemsLastIndex = function(headerItems, grandTotalIndex) {
  56940. var i,
  56941. lastIndex = -1,
  56942. headerItem;
  56943. if (headerItems)
  56944. for (i = 0; i < headerItems.length; i++) {
  56945. headerItem = headerItems[i];
  56946. lastIndex = Math.max(lastIndex, headerItem.index);
  56947. if (headerItem.children)
  56948. lastIndex = Math.max(lastIndex, getHeaderItemsLastIndex(headerItem.children));
  56949. else if (headerItem.collapsedChildren)
  56950. lastIndex = Math.max(lastIndex, getHeaderItemsLastIndex(headerItem.collapsedChildren))
  56951. }
  56952. if (isDefined(grandTotalIndex))
  56953. lastIndex = Math.max(lastIndex, grandTotalIndex);
  56954. return lastIndex
  56955. };
  56956. var updateHeaderItemChildren = function(headerItems, headerItem, children, grandTotalIndex) {
  56957. var applyingHeaderItemsCount = getHeaderItemsLastIndex(children) + 1,
  56958. emptyIndex = getHeaderItemsLastIndex(headerItems, grandTotalIndex) + 1,
  56959. index,
  56960. applyingItemIndexesToCurrent = [];
  56961. for (index = 0; index < applyingHeaderItemsCount; index++)
  56962. applyingItemIndexesToCurrent[index] = emptyIndex++;
  56963. headerItem.children = [];
  56964. $.extend(true, headerItem.children, children);
  56965. foreachTreeItems(headerItem.children, function(item) {
  56966. item.index = applyingItemIndexesToCurrent[item.index]
  56967. });
  56968. return applyingItemIndexesToCurrent
  56969. };
  56970. var updateHeaderItems = function(headerItems, newHeaderItems) {
  56971. var applyingItemIndexesToCurrent = [];
  56972. foreachTreeItems(headerItems, function(headerItem) {
  56973. delete headerItem.collapsedChildren
  56974. });
  56975. foreachTreeItems(newHeaderItems, function(newHeaderItem, path) {
  56976. var headerItem = findHeaderItem(headerItems, path);
  56977. if (headerItem)
  56978. applyingItemIndexesToCurrent[newHeaderItem.index] = headerItem.index
  56979. }, []);
  56980. return applyingItemIndexesToCurrent
  56981. };
  56982. var updateDataSourceCells = function(dataSource, newDataSourceCells, newRowItemIndexesToCurrent, newColumnItemIndexesToCurrent) {
  56983. var newRowIndex,
  56984. newColumnIndex,
  56985. newRowCells,
  56986. newCell,
  56987. rowIndex,
  56988. columnIndex,
  56989. dataSourceCells = dataSource.values;
  56990. if (newDataSourceCells)
  56991. for (newRowIndex = 0; newRowIndex <= newDataSourceCells.length; newRowIndex++) {
  56992. newRowCells = newDataSourceCells[newRowIndex];
  56993. rowIndex = newRowItemIndexesToCurrent[newRowIndex];
  56994. if (!isDefined(rowIndex))
  56995. rowIndex = dataSource.grandTotalRowIndex;
  56996. if (newRowCells && isDefined(rowIndex)) {
  56997. if (!dataSourceCells[rowIndex])
  56998. dataSourceCells[rowIndex] = [];
  56999. for (newColumnIndex = 0; newColumnIndex <= newRowCells.length; newColumnIndex++) {
  57000. newCell = newRowCells[newColumnIndex];
  57001. columnIndex = newColumnItemIndexesToCurrent[newColumnIndex];
  57002. if (!isDefined(columnIndex))
  57003. columnIndex = dataSource.grandTotalColumnIndex;
  57004. if (isDefined(newCell) && isDefined(columnIndex))
  57005. dataSourceCells[rowIndex][columnIndex] = newCell
  57006. }
  57007. }
  57008. }
  57009. };
  57010. function createStore(dataSourceOptions) {
  57011. var store,
  57012. storeOptions;
  57013. if ($.isPlainObject(dataSourceOptions) && dataSourceOptions.load)
  57014. store = new pivotGrid.LocalStore(dataSourceOptions);
  57015. else {
  57016. if (dataSourceOptions && !dataSourceOptions.store)
  57017. dataSourceOptions = {store: dataSourceOptions};
  57018. storeOptions = dataSourceOptions.store;
  57019. if (storeOptions.type === "xmla")
  57020. store = new pivotGrid.XmlaStore(storeOptions);
  57021. else if ($.isPlainObject(storeOptions) && storeOptions.type || storeOptions instanceof DX.data.Store || $.isArray(storeOptions))
  57022. store = new pivotGrid.LocalStore(dataSourceOptions);
  57023. else if (storeOptions instanceof DX.Class)
  57024. store = storeOptions
  57025. }
  57026. return store
  57027. }
  57028. function getExpandedPaths(dataSource, loadOptions, dimentionName) {
  57029. var result = [],
  57030. fields = loadOptions[dimentionName];
  57031. foreachTreeItems(dataSource[dimentionName], function(item, path) {
  57032. if (item.children && fields[path.length - 1] && !fields[path.length - 1].expanded)
  57033. path.length < fields.length && result.push(path.slice())
  57034. }, [], true);
  57035. if (result.length)
  57036. return result
  57037. }
  57038. function getFieldsByGroup(fields, grouppingField) {
  57039. return $.map(fields, function(field) {
  57040. if (field.groupName === grouppingField.groupName && utils.isNumber(field.groupIndex) && field.visible !== false)
  57041. return $.extend(field, {
  57042. areaIndex: grouppingField.areaIndex,
  57043. area: grouppingField.area,
  57044. dataField: field.dataField || grouppingField.dataField,
  57045. dataType: field.dataType || grouppingField.dataType,
  57046. sortBy: field.sortBy || grouppingField.sortBy,
  57047. sortOrder: field.sortOrder || grouppingField.sortOrder,
  57048. sortBySummaryField: field.sortBySummaryField || grouppingField.sortBySummaryField,
  57049. sortBySummaryPath: field.sortBySummaryPath || grouppingField.sortBySummaryPath,
  57050. visible: field.visible || grouppingField.visible
  57051. });
  57052. return null
  57053. }).sort(function(a, b) {
  57054. return a.groupIndex - b.groupIndex
  57055. })
  57056. }
  57057. function createDescriptions(fields, currentField) {
  57058. var descriptions = {
  57059. rows: [],
  57060. columns: [],
  57061. values: [],
  57062. filters: []
  57063. };
  57064. $.each(fields || [], function(_, field) {
  57065. var descriptionName = DESCRIPTION_NAME_BY_AREA[field.area],
  57066. dimension = descriptions[descriptionName],
  57067. groupName = field.groupName;
  57068. if (groupName && !utils.isNumber(field.groupIndex)) {
  57069. if (currentField && groupName === currentField.groupName)
  57070. currentField = field;
  57071. field.levels = getFieldsByGroup(fields, field)
  57072. }
  57073. if (!dimension || groupName && utils.isNumber(field.groupIndex) || field.visible === false)
  57074. return;
  57075. if (field.levels && dimension !== descriptions.filters) {
  57076. dimension.push.apply(dimension, field.levels);
  57077. if (field.filterValues && field.filterValues.length)
  57078. descriptions.filters.push(field)
  57079. }
  57080. else
  57081. dimension.push(field)
  57082. });
  57083. $.each(descriptions, function(_, fields) {
  57084. utils.normalizeIndexes(fields, 'areaIndex', currentField);
  57085. fields.sort(function(field1, field2) {
  57086. return field1.areaIndex - field2.areaIndex
  57087. })
  57088. });
  57089. return descriptions
  57090. }
  57091. function getFieldId(field) {
  57092. return (field.dataField || field.groupName || '') + (field.groupInterval ? field.groupName || '' : "NOGROUP") + (field.groupInterval || '') + (field.summaryType || '')
  57093. }
  57094. function mergeFields(fields, storeFields, retrieveFieldsOptionValue) {
  57095. var result = [],
  57096. fieldsDictionary = {},
  57097. removedFields = {},
  57098. mergedGroups = [],
  57099. dataTypes = getFieldsDataType(fields);
  57100. if (storeFields) {
  57101. $.each(storeFields, function(_, field) {
  57102. fieldsDictionary[getFieldId(field)] = field
  57103. });
  57104. $.each(fields, function(_, field) {
  57105. var fieldKey = getFieldId(field),
  57106. storeField = fieldsDictionary[fieldKey] || removedFields[fieldKey],
  57107. mergedField;
  57108. if (storeField)
  57109. mergedField = $.extend({}, storeField, field);
  57110. else
  57111. fieldsDictionary[fieldKey] = mergedField = field;
  57112. $.extend(mergedField, {dataType: dataTypes[field.dataField]});
  57113. delete fieldsDictionary[fieldKey];
  57114. removedFields[fieldKey] = storeField;
  57115. result.push(mergedField)
  57116. });
  57117. if (retrieveFieldsOptionValue)
  57118. $.each(fieldsDictionary, function(_, field) {
  57119. result.push(field)
  57120. })
  57121. }
  57122. else
  57123. result = fields;
  57124. result.push.apply(result, mergedGroups);
  57125. return result
  57126. }
  57127. function createCaption(field) {
  57128. var caption = field.dataField || field.groupName || "",
  57129. summaryType = (field.summaryType || "").toLowerCase();
  57130. if (utils.isString(field.groupInterval))
  57131. caption += "_" + field.groupInterval;
  57132. if (summaryType && summaryType !== "custom") {
  57133. summaryType = summaryType.replace(/^./, summaryType[0].toUpperCase());
  57134. if (caption.length)
  57135. summaryType = " (" + summaryType + ")"
  57136. }
  57137. else
  57138. summaryType = "";
  57139. return DX.inflector.titleize(caption) + summaryType
  57140. }
  57141. function getFieldsDataType(fields) {
  57142. var result = {};
  57143. $.each(fields, function(_, field) {
  57144. result[field.dataField] = result[field.dataField] || field.dataType
  57145. });
  57146. return result
  57147. }
  57148. function getFields(that) {
  57149. var result = $.Deferred(),
  57150. store = that._store,
  57151. storeFields = store && store.getFields(getFieldsDataType(that._fields)),
  57152. mergedFields;
  57153. $.when(storeFields).done(function(storeFields) {
  57154. that._storeFields = storeFields;
  57155. mergedFields = mergeFields(that._fields, storeFields, that._retrieveFields);
  57156. result.resolve(mergedFields)
  57157. }).fail(function() {
  57158. result.resolve(that._fields)
  57159. });
  57160. return result
  57161. }
  57162. function getSliceIndex(items, path) {
  57163. var index = null,
  57164. pathValue = (path || []).join(".");
  57165. if (pathValue.length)
  57166. foreachTreeItems(items, function(item, itemPath) {
  57167. if (pathValue === itemPath.join(".")) {
  57168. index = item.index;
  57169. return false
  57170. }
  57171. }, []);
  57172. return index
  57173. }
  57174. function getFieldSummaryValueSelector(field, dataSource, loadOptions, dimensionName) {
  57175. var values = dataSource.values,
  57176. sortBySummaryFieldIndex = findField(loadOptions.values, field.sortBySummaryField),
  57177. areRows = dimensionName === "rows",
  57178. sortByDimension = areRows ? dataSource.columns : dataSource.rows,
  57179. grandTotalIndex = areRows ? dataSource.grandTotalRowIndex : dataSource.grandTotalColumnIndex,
  57180. sortBySummaryPath = field.sortBySummaryPath || [],
  57181. sliceIndex = sortBySummaryPath.length ? getSliceIndex(sortByDimension, sortBySummaryPath) : grandTotalIndex;
  57182. if (values && values.length && sortBySummaryFieldIndex >= 0 && isDefined(sliceIndex))
  57183. return function(field) {
  57184. var rowIndex = areRows ? field.index : sliceIndex,
  57185. columnIndex = areRows ? sliceIndex : field.index;
  57186. return ((values[rowIndex] || [[]])[columnIndex] || [])[sortBySummaryFieldIndex] || null
  57187. }
  57188. }
  57189. function getSortingMethod(field, dataSource, loadOptions, dimensionName) {
  57190. var sortOrder = field.sortOrder,
  57191. defaultCompare = field.sortingMethod || getCompareFunction(function(item) {
  57192. return item.value
  57193. }),
  57194. summaryValueSelector = getFieldSummaryValueSelector(field, dataSource, loadOptions, dimensionName),
  57195. summaryCompare = summaryValueSelector && getCompareFunction(summaryValueSelector),
  57196. sortingMethod = function(a, b) {
  57197. var result = summaryCompare && summaryCompare(a, b) || 0;
  57198. if (result === 0)
  57199. result = defaultCompare(a, b);
  57200. return sortOrder === "desc" ? -result : result
  57201. };
  57202. return sortingMethod
  57203. }
  57204. function sortDimension(dataSource, loadOptions, dimensionName) {
  57205. var fields = loadOptions[dimensionName] || [],
  57206. baseIndex = loadOptions.headerName === dimensionName ? loadOptions.path.length : 0,
  57207. sortingMetodByLevel = [];
  57208. foreachDataLevel(dataSource[dimensionName], function(item, index) {
  57209. var field = fields[index] || {},
  57210. sortingMethod = sortingMetodByLevel[index] = sortingMetodByLevel[index] || getSortingMethod(field, dataSource, loadOptions, dimensionName);
  57211. item.sort(sortingMethod)
  57212. }, baseIndex)
  57213. }
  57214. function sort(loadOptions, dataSource) {
  57215. sortDimension(dataSource, loadOptions, "rows");
  57216. sortDimension(dataSource, loadOptions, "columns")
  57217. }
  57218. function formatHeaderItems(data, loadOptions, headerName) {
  57219. foreachTreeItems(data[headerName], function(item, path) {
  57220. item.text = item.text || formatValue(item.value, loadOptions[headerName][path.length - 1])
  57221. }, [])
  57222. }
  57223. function formatHeaders(loadOptions, data) {
  57224. formatHeaderItems(data, loadOptions, "columns");
  57225. formatHeaderItems(data, loadOptions, "rows")
  57226. }
  57227. pivotGrid.sort = sort;
  57228. return {
  57229. ctor: function(options) {
  57230. options = options || {};
  57231. var that = this,
  57232. store = createStore(options);
  57233. that._store = store;
  57234. that._loadedData = {
  57235. rows: [],
  57236. columns: [],
  57237. values: []
  57238. };
  57239. that._data = $.extend(true, {}, that._loadedData);
  57240. that._loadingCount = 0;
  57241. $.each(["changed", "loadError", "loadingChanged", "fieldsPrepared", "expandValueChanging"], $.proxy(function(_, eventName) {
  57242. var optionName = "on" + eventName[0].toUpperCase() + eventName.slice(1);
  57243. if (options.hasOwnProperty(optionName))
  57244. this.on(eventName, options[optionName])
  57245. }, this));
  57246. that._localSorting = !!options.localSorting;
  57247. that._retrieveFields = isDefined(options.retrieveFields) ? options.retrieveFields : true;
  57248. that._fields = options.fields || [];
  57249. that._descriptions = options.descriptions ? $.extend(createDescriptions([]), options.descriptions) : undefined;
  57250. if (!store) {
  57251. $.extend(true, that._loadedData, options.store || options);
  57252. that._data = $.extend(true, {}, that._loadedData)
  57253. }
  57254. },
  57255. getData: function() {
  57256. return this._data
  57257. },
  57258. getAreaFields: function(area, collectGroups) {
  57259. var areaFields = [],
  57260. descriptions;
  57261. if (collectGroups || area === "data") {
  57262. $.each(this._fields, function() {
  57263. if (this.area === area && !isDefined(this.groupIndex) && this.visible !== false)
  57264. areaFields.push(this)
  57265. });
  57266. utils.normalizeIndexes(areaFields, 'areaIndex');
  57267. areaFields.sort(function(field1, field2) {
  57268. return field1.areaIndex - field2.areaIndex
  57269. })
  57270. }
  57271. else {
  57272. descriptions = this._descriptions || {};
  57273. areaFields = descriptions[DESCRIPTION_NAME_BY_AREA[area]] || []
  57274. }
  57275. return areaFields
  57276. },
  57277. fields: function(fields) {
  57278. var that = this;
  57279. if (fields) {
  57280. that._fields = mergeFields(fields, that._storeFields, that._retrieveFields);
  57281. that._fieldsPrepared(that._fields)
  57282. }
  57283. return that._fields
  57284. },
  57285. field: function(id, options) {
  57286. var that = this,
  57287. field = this._fields && this._fields[utils.isNumber(id) ? id : findField(this._fields, id)],
  57288. levels;
  57289. if (field && options) {
  57290. $.each(options, function(optionName, optionValue) {
  57291. field[optionName] = optionValue;
  57292. if (optionName === "sortOrder") {
  57293. levels = field.levels || [];
  57294. for (var i = 0; i < levels.length; i++)
  57295. levels[i][optionName] = optionValue
  57296. }
  57297. });
  57298. that._descriptions = createDescriptions(this._fields, field)
  57299. }
  57300. return field
  57301. },
  57302. getFieldValues: function(index) {
  57303. var that = this,
  57304. field = this._fields && this._fields[index],
  57305. store = this.store(),
  57306. loadFields = [],
  57307. loadOptions = {
  57308. columns: loadFields,
  57309. rows: [],
  57310. values: this.getAreaFields("data"),
  57311. filters: [],
  57312. localSorting: this._localSorting
  57313. },
  57314. d = $.Deferred();
  57315. if (field && store) {
  57316. $.each(field.levels || [field], function() {
  57317. loadFields.push($.extend({}, this, {
  57318. expanded: true,
  57319. filterValues: null,
  57320. sortOrder: 'asc',
  57321. sortBySummaryField: null
  57322. }))
  57323. });
  57324. store.load(loadOptions).done(function(data) {
  57325. formatHeaders(loadOptions, data);
  57326. that._sort(loadOptions, data);
  57327. d.resolve(data.columns)
  57328. }).fail(d)
  57329. }
  57330. else
  57331. d.reject();
  57332. return d
  57333. },
  57334. load: function(options) {
  57335. var that = this,
  57336. d = $.Deferred();
  57337. options = options || {};
  57338. that._changeLoadingCount(1);
  57339. d.fail(function(e) {
  57340. that.fireEvent("loadError", [e])
  57341. }).always(function() {
  57342. that._changeLoadingCount(-1)
  57343. });
  57344. that._delayedLoadTask = DX.utils.executeAsync(function() {
  57345. that._delayedLoadTask = undefined;
  57346. if (!that._descriptions)
  57347. $.when(getFields(that)).done(function(fields) {
  57348. that._fieldsPrepared(fields);
  57349. that._loadCore(options, d)
  57350. }).fail(d.reject).fail(that._loadErrorHandler);
  57351. else
  57352. that._loadCore(options, d)
  57353. });
  57354. return d
  57355. },
  57356. _fieldsPrepared: function(fields) {
  57357. var that = this;
  57358. that._fields = fields;
  57359. $.each(fields, function(index, field) {
  57360. field.index = index;
  57361. if (!isDefined(field.caption))
  57362. field.caption = createCaption(field)
  57363. });
  57364. that.fireEvent("fieldsPrepared", [fields]);
  57365. that._descriptions = createDescriptions(fields)
  57366. },
  57367. isLoading: function() {
  57368. return this._loadingCount > 0
  57369. },
  57370. _changeLoadingCount: function(increment) {
  57371. var oldLoading = this.isLoading(),
  57372. newLoading;
  57373. this._loadingCount += increment;
  57374. newLoading = this.isLoading();
  57375. if (oldLoading ^ newLoading)
  57376. this.fireEvent("loadingChanged", [newLoading])
  57377. },
  57378. _loadCore: function(options, deferred) {
  57379. var that = this,
  57380. store = this._store,
  57381. descriptions = this._descriptions,
  57382. headerName = DESCRIPTION_NAME_BY_AREA[options.area];
  57383. options = options || {};
  57384. if (store) {
  57385. $.extend(options, descriptions);
  57386. options.columnExpandedPaths = getExpandedPaths(this._loadedData, options, "columns");
  57387. options.rowExpandedPaths = getExpandedPaths(this._loadedData, options, "rows");
  57388. if (that._localSorting)
  57389. options.localSorting = true;
  57390. if (headerName)
  57391. options.headerName = headerName;
  57392. $.when(store.load(options)).done(function(data) {
  57393. if (options.path)
  57394. that.applyPartialDataSource(options.area, options.path, data, deferred);
  57395. else {
  57396. $.extend(that._loadedData, data);
  57397. that._update(deferred)
  57398. }
  57399. deferred.resolve(that._data)
  57400. }).fail(deferred.reject)
  57401. }
  57402. else {
  57403. that._update(deferred);
  57404. deferred.resolve(that._data)
  57405. }
  57406. },
  57407. _sort: function(descriptions, data) {
  57408. var store = this._store;
  57409. if (store && store.supportSorting && (this._localSorting || !store.supportSorting()))
  57410. sort(descriptions, data)
  57411. },
  57412. _update: function(deferred) {
  57413. var that = this;
  57414. formatHeaders(that._descriptions, that._loadedData);
  57415. that._sort(that._descriptions, that._loadedData);
  57416. that._data = $.extend(true, {}, that._loadedData);
  57417. $.when(deferred).done(function() {
  57418. that.fireEvent("changed");
  57419. if (utils.isDefined(that._data.grandTotalRowIndex))
  57420. that._loadedData.grandTotalRowIndex = that._data.grandTotalRowIndex;
  57421. if (utils.isDefined(that._data.grandTotalColumnIndex))
  57422. that._loadedData.grandTotalColumnIndex = that._data.grandTotalColumnIndex
  57423. })
  57424. },
  57425. getHeaderItemPath: function(area, visibleIndex) {
  57426. var that = this,
  57427. index = 0,
  57428. result,
  57429. headerItems = area === 'column' ? that._data.columns : that._data.rows;
  57430. if (area === 'column' && that._descriptions.values.length > 1)
  57431. visibleIndex = Math.floor(visibleIndex / that._descriptions.values.length);
  57432. foreachTreeItems(headerItems, function(item, path) {
  57433. if (index === visibleIndex) {
  57434. result = path;
  57435. return false
  57436. }
  57437. index++
  57438. }, []);
  57439. return result
  57440. },
  57441. store: function() {
  57442. return this._store
  57443. },
  57444. collapseHeaderItem: function(area, path) {
  57445. var that = this,
  57446. headerItems = area === 'column' ? that._loadedData.columns : that._loadedData.rows,
  57447. headerItem = findHeaderItem(headerItems, path),
  57448. field = that.getAreaFields(area === 'columns' ? "column" : "row")[path.length - 1];
  57449. if (headerItem && headerItem.children) {
  57450. that.fireEvent("expandValueChanging", [{
  57451. area: area,
  57452. path: path,
  57453. expanded: false
  57454. }]);
  57455. if (field)
  57456. field.expanded = false;
  57457. headerItem.collapsedChildren = headerItem.children;
  57458. delete headerItem.children;
  57459. that._update();
  57460. return true
  57461. }
  57462. return false
  57463. },
  57464. collapseAll: function(fieldIndex) {
  57465. var dataChanged = false,
  57466. field = this.fields()[fieldIndex] || {};
  57467. field.expanded = false;
  57468. foreachTreeItems(this._loadedData[field.area + "s"], function(item, path) {
  57469. if (item && item.children && field.areaIndex === path.length - 1) {
  57470. item.collapsedChildren = item.children;
  57471. delete item.children;
  57472. dataChanged = true
  57473. }
  57474. }, [], true);
  57475. dataChanged && this._update()
  57476. },
  57477. expandAll: function(fieldIndex) {
  57478. var field = this.fields()[fieldIndex];
  57479. if (field && field.area) {
  57480. field.expanded = true;
  57481. this.load()
  57482. }
  57483. },
  57484. expandHeaderItem: function(area, path) {
  57485. var that = this,
  57486. hasCache,
  57487. headerItems = area === 'column' ? that._loadedData.columns : that._loadedData.rows,
  57488. headerItem = findHeaderItem(headerItems, path),
  57489. options;
  57490. if (headerItem && !headerItem.children) {
  57491. hasCache = !!headerItem.collapsedChildren;
  57492. options = {
  57493. area: area,
  57494. path: path,
  57495. expanded: true,
  57496. needExpandData: !hasCache
  57497. };
  57498. that.fireEvent("expandValueChanging", [options]);
  57499. if (hasCache) {
  57500. headerItem.children = headerItem.collapsedChildren;
  57501. delete headerItem.collapsedChildren;
  57502. that._update()
  57503. }
  57504. else
  57505. that.load(options);
  57506. return hasCache
  57507. }
  57508. return false
  57509. },
  57510. applyPartialDataSource: function(area, path, dataSource, deferred) {
  57511. var that = this,
  57512. loadedData = that._loadedData,
  57513. headerItems = area === 'column' ? loadedData.columns : loadedData.rows,
  57514. headerItem,
  57515. newRowItemIndexesToCurrent,
  57516. newColumnItemIndexesToCurrent;
  57517. if (dataSource && dataSource.values) {
  57518. dataSource.rows = dataSource.rows || [];
  57519. dataSource.columns = dataSource.columns || [];
  57520. headerItem = findHeaderItem(headerItems, path);
  57521. if (headerItem) {
  57522. if (area === 'column') {
  57523. newColumnItemIndexesToCurrent = updateHeaderItemChildren(headerItems, headerItem, dataSource.columns, loadedData.grandTotalColumnIndex);
  57524. newRowItemIndexesToCurrent = updateHeaderItems(loadedData.rows, dataSource.rows)
  57525. }
  57526. else {
  57527. newRowItemIndexesToCurrent = updateHeaderItemChildren(headerItems, headerItem, dataSource.rows, loadedData.grandTotalRowIndex);
  57528. newColumnItemIndexesToCurrent = updateHeaderItems(loadedData.columns, dataSource.columns)
  57529. }
  57530. updateDataSourceCells(loadedData, dataSource.values, newRowItemIndexesToCurrent, newColumnItemIndexesToCurrent);
  57531. that._update(deferred)
  57532. }
  57533. }
  57534. },
  57535. dispose: function() {
  57536. var that = this,
  57537. delayedLoadTask = that._delayedLoadTask;
  57538. this._disposeEvents();
  57539. if (delayedLoadTask)
  57540. delayedLoadTask.abort();
  57541. this._isDisposed = true
  57542. },
  57543. isDisposed: function() {
  57544. return !!this._isDisposed
  57545. }
  57546. }
  57547. }()).include(DX.EventsMixin);
  57548. pivotGrid.foreachTreeItems = foreachTreeItems;
  57549. pivotGrid.foreachDataLevel = foreachDataLevel;
  57550. pivotGrid.getCompareFunction = getCompareFunction;
  57551. pivotGrid.findField = findField;
  57552. pivotGrid.formatValue = formatValue
  57553. })(jQuery, DevExpress);
  57554. /*! Module widgets-web, file ui.pivotGrid.dataController.js */
  57555. (function($, DX) {
  57556. var pivotGrid = DX.ui.dxPivotGrid,
  57557. utils = DX.utils;
  57558. var DESCRIPTION_NAME_BY_AREA = {
  57559. row: "rows",
  57560. column: "columns",
  57561. data: "values",
  57562. filter: "filters"
  57563. };
  57564. pivotGrid.proxyMethod = function(instance, methodName, defaultResult) {
  57565. if (!instance[methodName])
  57566. instance[methodName] = function() {
  57567. var dataSource = this._dataSource;
  57568. return dataSource ? dataSource[methodName].apply(dataSource, arguments) : defaultResult
  57569. }
  57570. };
  57571. pivotGrid.DataController = DX.Class.inherit(function() {
  57572. var foreachTreeItems = pivotGrid.foreachTreeItems,
  57573. formatValue = pivotGrid.formatValue;
  57574. function getHeaderItemText(item, description, options) {
  57575. var text = item.text;
  57576. if (utils.isDefined(item.displayText))
  57577. text = item.displayText;
  57578. else if (utils.isDefined(item.caption))
  57579. text = item.caption;
  57580. else if (item.type === 'GT')
  57581. text = options.texts.grandTotal;
  57582. if (item.isAdditionalTotal)
  57583. text = utils.stringFormat(options.texts.total || '', text);
  57584. return text
  57585. }
  57586. var createHeaderInfo = function() {
  57587. var getHeaderItemsDepth = function(headerItems) {
  57588. var depth = 0;
  57589. foreachTreeItems(headerItems, function(item, path) {
  57590. depth = Math.max(depth, path.length)
  57591. }, []);
  57592. return depth
  57593. };
  57594. var createInfoItem = function(headerItem, breadth, isHorizontal) {
  57595. var infoItem = {
  57596. type: headerItem.type,
  57597. text: headerItem.text
  57598. };
  57599. if (headerItem.path)
  57600. infoItem.path = headerItem.path;
  57601. if (headerItem.width)
  57602. infoItem.width = headerItem.width;
  57603. if (headerItem.isLast)
  57604. infoItem.isLast = true;
  57605. if (headerItem.sorted)
  57606. infoItem.sorted = true;
  57607. if (headerItem.isMetric)
  57608. infoItem.dataIndex = headerItem.dataIndex;
  57609. if (utils.isDefined(headerItem.expanded))
  57610. infoItem.expanded = headerItem.expanded;
  57611. if (breadth > 1)
  57612. infoItem[isHorizontal ? 'colspan' : 'rowspan'] = breadth;
  57613. if (headerItem.depthSize && headerItem.depthSize > 1)
  57614. infoItem[isHorizontal ? 'rowspan' : 'colspan'] = headerItem.depthSize;
  57615. return infoItem
  57616. };
  57617. var addInfoItem = function(info, options) {
  57618. var itemInfo,
  57619. breadth = options.lastIndex - options.index || 1,
  57620. addInfoItemCore = function(info, infoItem, itemIndex, depthIndex, isHorizontal) {
  57621. var index = isHorizontal ? depthIndex : itemIndex;
  57622. while (!info[index])
  57623. info.push([]);
  57624. if (isHorizontal)
  57625. info[index].push(infoItem);
  57626. else
  57627. info[index].unshift(infoItem)
  57628. };
  57629. itemInfo = createInfoItem(options.headerItem, breadth, options.isHorizontal);
  57630. addInfoItemCore(info, itemInfo, options.index, options.depth, options.isHorizontal);
  57631. if (!options.headerItem.children || options.headerItem.children.length === 0)
  57632. return options.lastIndex + 1;
  57633. return options.lastIndex
  57634. };
  57635. var getViewHeaderItems = function(headerItems, headerDescriptions, cellDescriptions, depthSize, options) {
  57636. var cellDescriptionsCount = cellDescriptions.length,
  57637. viewHeaderItems = $.extend(true, [], headerItems);
  57638. setHeaderItemsParameters(viewHeaderItems, headerDescriptions);
  57639. if (options.showTotals !== false)
  57640. addAdditionalTotalHeaderItems(viewHeaderItems);
  57641. if (options.showGrandTotals !== false)
  57642. viewHeaderItems.push({type: 'GT'});
  57643. foreachTreeItems(viewHeaderItems, function(item, path) {
  57644. if (!item.children || item.children.length === 0)
  57645. item.depthSize = depthSize - path.length + 1
  57646. }, []);
  57647. if (cellDescriptionsCount > 1)
  57648. addMetricHeaderItems(viewHeaderItems, cellDescriptions);
  57649. foreachTreeItems(viewHeaderItems, function(item, path) {
  57650. var field = headerDescriptions[path.length - 1] || {};
  57651. item.text = getHeaderItemText(item, field, options);
  57652. if (item.type === 'D')
  57653. item.width = field.width;
  57654. item.isLast = !item.children || !item.children.length;
  57655. if (item.isLast)
  57656. $.each(options.sortBySummaryPaths, function(index, sortBySummaryPath) {
  57657. var headerPath = path;
  57658. if (!utils.isDefined(item.dataIndex)) {
  57659. sortBySummaryPath = sortBySummaryPath.slice(0);
  57660. sortBySummaryPath.pop()
  57661. }
  57662. if (item.type === "GT")
  57663. headerPath = headerPath.slice(1);
  57664. if (headerPath.join("/") === sortBySummaryPath.join("/")) {
  57665. item.sorted = true;
  57666. return false
  57667. }
  57668. })
  57669. }, []);
  57670. if (!viewHeaderItems.length)
  57671. viewHeaderItems.push({});
  57672. return viewHeaderItems
  57673. };
  57674. var setHeaderItemsParameters = function(viewHeaderItems, headerDescriptions) {
  57675. var headerDescriptionsCount = headerDescriptions && headerDescriptions.length || 0;
  57676. foreachTreeItems(viewHeaderItems, function(item) {
  57677. item.type = 'D'
  57678. });
  57679. foreachTreeItems(viewHeaderItems, function(item, path) {
  57680. item.path = path.slice(0);
  57681. if (path.length < headerDescriptionsCount && (!item.children || item.children.length !== 0))
  57682. item.expanded = !!item.children
  57683. }, [])
  57684. };
  57685. var addMetricHeaderItems = function(headerItems, cellDescriptions) {
  57686. foreachTreeItems(headerItems, function(item) {
  57687. var i;
  57688. if (!item.children || item.children.length === 0) {
  57689. item.children = [];
  57690. for (i = 0; i < cellDescriptions.length; i++)
  57691. item.children.push({
  57692. caption: cellDescriptions[i].caption,
  57693. path: item.path,
  57694. type: item.type,
  57695. value: i,
  57696. dataIndex: i,
  57697. isMetric: true
  57698. })
  57699. }
  57700. })
  57701. };
  57702. var addAdditionalTotalHeaderItems = function(headerItems) {
  57703. foreachTreeItems(headerItems, function(item, path, index, items) {
  57704. if (item.type === 'D' && item.expanded)
  57705. items.splice(index + 1, 0, $.extend(true, {}, item, {
  57706. children: null,
  57707. type: 'T',
  57708. expanded: null,
  57709. isAdditionalTotal: true
  57710. }))
  57711. }, [])
  57712. };
  57713. var fillHeaderInfo = function(info, viewHeaderItems, depthSize, isHorizontal) {
  57714. var lastIndex = 0,
  57715. index,
  57716. depth,
  57717. indexesByDepth = [0];
  57718. foreachTreeItems(viewHeaderItems, function(headerItem, path) {
  57719. depth = headerItem.isMetric ? depthSize : path.length - 1;
  57720. while (indexesByDepth.length - 1 < depth)
  57721. indexesByDepth.push(indexesByDepth[indexesByDepth.length - 1]);
  57722. index = indexesByDepth[depth] || 0;
  57723. lastIndex = addInfoItem(info, {
  57724. headerItem: headerItem,
  57725. index: index,
  57726. lastIndex: lastIndex,
  57727. depth: depth,
  57728. isHorizontal: isHorizontal
  57729. });
  57730. indexesByDepth.length = depth;
  57731. indexesByDepth.push(lastIndex)
  57732. }, [])
  57733. };
  57734. return function(headerItems, headerDescriptions, cellDescriptions, isHorizontal, options) {
  57735. var info = [],
  57736. viewHeaderItems,
  57737. depthSize = getHeaderItemsDepth(headerItems) || 1;
  57738. viewHeaderItems = getViewHeaderItems(headerItems, headerDescriptions, cellDescriptions, depthSize, options);
  57739. fillHeaderInfo(info, viewHeaderItems, depthSize, isHorizontal);
  57740. return info
  57741. }
  57742. }();
  57743. var createCellsInfo = function(dataSource, cellDescriptions, rowIndexedItems, columnIndexedItems) {
  57744. var rowIndex,
  57745. columnIndex,
  57746. valueIndex,
  57747. cells,
  57748. rowInfo,
  57749. dataSourceCells = dataSource.values,
  57750. cellDescriptionsCount = cellDescriptions ? cellDescriptions.length : 0,
  57751. cellValues,
  57752. cellInfo,
  57753. columnItem,
  57754. rowItem,
  57755. getHeaderItemType = function(headerItem) {
  57756. if (!headerItem)
  57757. return 'GT';
  57758. if (headerItem.children && headerItem.children.length > 0)
  57759. return 'T';
  57760. return 'D'
  57761. },
  57762. columnCount = 0,
  57763. info = [];
  57764. if (dataSourceCells && cellDescriptionsCount > 0) {
  57765. for (rowIndex = 0; rowIndex < dataSourceCells.length; rowIndex++)
  57766. columnCount = Math.max(columnCount, dataSourceCells[rowIndex].length);
  57767. for (rowIndex = 0; rowIndex < dataSourceCells.length; rowIndex++) {
  57768. rowItem = rowIndexedItems[rowIndex];
  57769. if (!rowItem && rowIndex !== dataSource.grandTotalRowIndex)
  57770. continue;
  57771. cells = dataSourceCells[rowIndex];
  57772. rowInfo = [];
  57773. for (columnIndex = 0; columnIndex < columnCount; columnIndex++) {
  57774. columnItem = columnIndexedItems[columnIndex];
  57775. if (!columnItem && columnIndex !== dataSource.grandTotalColumnIndex)
  57776. continue;
  57777. cellValues = cells[columnIndex];
  57778. if (!$.isArray(cellValues))
  57779. cellValues = [cellValues];
  57780. for (valueIndex = 0; valueIndex < cellDescriptionsCount; valueIndex++) {
  57781. cellInfo = {
  57782. text: formatValue(cellValues[valueIndex], cellDescriptions[valueIndex]),
  57783. columnType: getHeaderItemType(columnItem),
  57784. rowType: getHeaderItemType(rowItem),
  57785. rowPath: rowItem && rowItem.path,
  57786. columnPath: columnItem && columnItem.path,
  57787. dataIndex: valueIndex
  57788. };
  57789. if (cellDescriptions[valueIndex].width)
  57790. cellInfo.width = cellDescriptions[valueIndex].width;
  57791. if (columnItem)
  57792. rowInfo[columnItem.visibleIndex * cellDescriptionsCount + valueIndex] = cellInfo;
  57793. else if (columnIndexedItems.grandTotalVisibleIndex >= 0)
  57794. rowInfo[columnIndexedItems.grandTotalVisibleIndex * cellDescriptionsCount + valueIndex] = cellInfo
  57795. }
  57796. }
  57797. if (rowItem)
  57798. info[rowItem.visibleIndex] = rowInfo;
  57799. else if (rowIndexedItems.grandTotalVisibleIndex >= 0)
  57800. info[rowIndexedItems.grandTotalVisibleIndex] = rowInfo
  57801. }
  57802. }
  57803. return info
  57804. };
  57805. var getHeaderIndexedItems = function(headerItems, maxDepth, options) {
  57806. var visibleIndex = 0,
  57807. indexedItems = [];
  57808. foreachTreeItems(headerItems, function(headerItem, path) {
  57809. if (headerItem.children && options.showTotals === false)
  57810. return;
  57811. var indexedItem = $.extend(true, {}, headerItem, {
  57812. visibleIndex: visibleIndex++,
  57813. path: path
  57814. });
  57815. if (utils.isDefined(indexedItem.index))
  57816. indexedItems[indexedItem.index] = indexedItem;
  57817. else
  57818. indexedItems.push(indexedItem)
  57819. }, []);
  57820. if (options.showGrandTotals !== false)
  57821. indexedItems.grandTotalVisibleIndex = visibleIndex;
  57822. return indexedItems
  57823. };
  57824. var members = {
  57825. ctor: function(options) {
  57826. var that = this;
  57827. that._options = options || {};
  57828. that._dataSource = that._createDataSource(options);
  57829. that._columnsInfo = [];
  57830. that._rowsInfo = [];
  57831. that._cellsInfo = [];
  57832. that.expandValueChanging = $.Callbacks();
  57833. that.loadingChanged = $.Callbacks();
  57834. that._dataSource.load();
  57835. that._update();
  57836. that.changed = $.Callbacks()
  57837. },
  57838. _handleChanged: function() {
  57839. this._update()
  57840. },
  57841. _handleExpandValueChanging: function(e) {
  57842. this.expandValueChanging.fire(e)
  57843. },
  57844. _handleLoadingChanged: function(e) {
  57845. this.loadingChanged.fire(e)
  57846. },
  57847. _handleFieldsPrepared: function(e) {
  57848. this._options.onFieldsPrepared && this._options.onFieldsPrepared(e)
  57849. },
  57850. _createDataSource: function(options) {
  57851. var that = this,
  57852. dataSourceOptions = options.dataSource,
  57853. dataSource,
  57854. fields;
  57855. that._isSharedDataSource = dataSourceOptions instanceof pivotGrid.DataSource;
  57856. if (that._isSharedDataSource)
  57857. dataSource = dataSourceOptions;
  57858. else
  57859. dataSource = new pivotGrid.DataSource(dataSourceOptions);
  57860. that._changedHandler = $.proxy(that, "_handleChanged");
  57861. that._expandValueChangingHandler = $.proxy(that, "_handleExpandValueChanging");
  57862. that._loadingChangedHandler = $.proxy(that, "_handleLoadingChanged");
  57863. that._fieldsPreparedHandler = $.proxy(that, "_handleFieldsPrepared");
  57864. dataSource.on("changed", that._changedHandler);
  57865. dataSource.on("expandValueChanging", that._expandValueChangingHandler);
  57866. dataSource.on("loadingChanged", that._loadingChangedHandler);
  57867. dataSource.on("fieldsPrepared", that._fieldsPreparedHandler);
  57868. if (options.descriptions) {
  57869. fields = [];
  57870. $.each(DESCRIPTION_NAME_BY_AREA, function(areaName, descriptionName) {
  57871. var areaFields = options.descriptions[descriptionName];
  57872. if (areaFields)
  57873. $.each(areaFields, function(areaIndex, field) {
  57874. fields.push($.extend({
  57875. area: areaName,
  57876. areaIndex: areaIndex
  57877. }, field))
  57878. })
  57879. })
  57880. }
  57881. if (fields)
  57882. dataSource.fields(fields);
  57883. return dataSource
  57884. },
  57885. getDataSource: function() {
  57886. return this._dataSource
  57887. },
  57888. isLoading: function() {
  57889. return this._dataSource.isLoading()
  57890. },
  57891. isEmpty: function() {
  57892. var dataFields = this._dataSource.getAreaFields("data"),
  57893. data = this._dataSource.getData();
  57894. return !dataFields.length || !data.values.length
  57895. },
  57896. _update: function() {
  57897. var columnFields = this._dataSource.getAreaFields("column"),
  57898. rowFields = this._dataSource.getAreaFields("row"),
  57899. dataFields = this._dataSource.getAreaFields("data"),
  57900. dataSource = this._dataSource.getData();
  57901. var createSortPaths = function(headerFields, dataFields) {
  57902. var sortBySummaryPaths = [];
  57903. $.each(headerFields, function(index, headerField) {
  57904. var fieldIndex = pivotGrid.findField(dataFields, headerField.sortBySummaryField);
  57905. if (fieldIndex >= 0)
  57906. sortBySummaryPaths.push((headerField.sortBySummaryPath || []).concat([fieldIndex]))
  57907. });
  57908. return sortBySummaryPaths
  57909. };
  57910. var rowOptions = {
  57911. texts: this._options.texts || {},
  57912. showTotals: this._options.showRowTotals,
  57913. showGrandTotals: this._options.showRowGrandTotals,
  57914. sortBySummaryPaths: createSortPaths(columnFields, dataFields)
  57915. };
  57916. var columnOptions = {
  57917. texts: this._options.texts || {},
  57918. showTotals: this._options.showColumnTotals,
  57919. showGrandTotals: this._options.showColumnGrandTotals,
  57920. sortBySummaryPaths: createSortPaths(rowFields, dataFields)
  57921. };
  57922. var rowIndexedItems = getHeaderIndexedItems(dataSource.rows, rowFields.length - 1, rowOptions),
  57923. columnIndexedItems = getHeaderIndexedItems(dataSource.columns, columnFields.length - 1, columnOptions);
  57924. if (!utils.isDefined(dataSource.grandTotalRowIndex))
  57925. dataSource.grandTotalRowIndex = rowIndexedItems.length;
  57926. if (!utils.isDefined(dataSource.grandTotalColumnIndex))
  57927. dataSource.grandTotalColumnIndex = columnIndexedItems.length;
  57928. this._columnsInfo = createHeaderInfo(dataSource.columns, columnFields, dataFields, true, columnOptions);
  57929. this._rowsInfo = createHeaderInfo(dataSource.rows, rowFields, [], false, rowOptions);
  57930. this._cellsInfo = createCellsInfo(dataSource, dataFields, rowIndexedItems, columnIndexedItems);
  57931. this.changed && this.changed.fire()
  57932. },
  57933. getHeaderItemPath: function(area, visibleIndex) {
  57934. var that = this,
  57935. index = 0,
  57936. result,
  57937. data = that._dataSource.getData(),
  57938. dataFields = that._dataSource.getAreaFields("data"),
  57939. headerItems = area === 'column' ? data.columns : data.rows;
  57940. if (area === 'column' && dataFields.length > 1)
  57941. visibleIndex = Math.floor(visibleIndex / dataFields.length);
  57942. foreachTreeItems(headerItems, function(item, path) {
  57943. if (index === visibleIndex) {
  57944. result = path;
  57945. return false
  57946. }
  57947. index++
  57948. }, []);
  57949. return result
  57950. },
  57951. getRowsInfo: function() {
  57952. return this._rowsInfo
  57953. },
  57954. getColumnsInfo: function() {
  57955. return this._columnsInfo
  57956. },
  57957. getCellsInfo: function() {
  57958. return this._cellsInfo
  57959. },
  57960. dispose: function() {
  57961. var that = this;
  57962. if (that._isSharedDataSource) {
  57963. that._dataSource.off("changed", that._changedHandler);
  57964. that._dataSource.off("expandValueChanging", that._expandValueChangingHandler);
  57965. that._dataSource.off("loadingChanged", that._loadingChangedHandler)
  57966. }
  57967. else
  57968. that._dataSource.dispose();
  57969. that.expandValueChanging.empty();
  57970. that.changed.empty();
  57971. that.loadingChanged.empty()
  57972. }
  57973. };
  57974. pivotGrid.proxyMethod(members, "load");
  57975. pivotGrid.proxyMethod(members, "applyPartialDataSource");
  57976. pivotGrid.proxyMethod(members, "collapseHeaderItem");
  57977. pivotGrid.proxyMethod(members, "expandHeaderItem");
  57978. pivotGrid.proxyMethod(members, "getData");
  57979. return members
  57980. }())
  57981. })(jQuery, DevExpress);
  57982. /*! Module widgets-web, file ui.pivotGrid.store.xmla.js */
  57983. (function($, DX) {
  57984. DX.data.XmlaStore = DX.ui.dxPivotGrid.XmlaStore = DX.Class.inherit(function() {
  57985. var discover = '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body><Discover xmlns="urn:schemas-microsoft-com:xml-analysis"><RequestType>{2}</RequestType><Restrictions><RestrictionList><CATALOG_NAME>{0}</CATALOG_NAME><CUBE_NAME>{1}</CUBE_NAME></RestrictionList></Restrictions><Properties><PropertyList><Catalog>{0}</Catalog></PropertyList></Properties></Discover></Body></Envelope>',
  57986. execute = '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body><Execute xmlns="urn:schemas-microsoft-com:xml-analysis"><Command><Statement>{0}</Statement></Command><Properties><PropertyList><Catalog>{1}</Catalog><ShowHiddenCubes>True</ShowHiddenCubes><SspropInitAppName>Microsoft SQL Server Management Studio</SspropInitAppName><Timeout>3600</Timeout></PropertyList></Properties></Execute></Body></Envelope>',
  57987. mdx = "SELECT {2} FROM {0} {1} CELL PROPERTIES VALUE, FORMAT_STRING, LANGUAGE, BACK_COLOR, FORE_COLOR, FONT_FLAGS",
  57988. mdxFilterSelect = "(SELECT {0} FROM {1})",
  57989. mdxWith = " set [{0}] as {1}",
  57990. orderMdx = "ORDER({0}, {1}, {2})",
  57991. mdxSlice = "WHERE ({0})",
  57992. mdxNonEmpty = "NonEmpty({0}, {1})",
  57993. mdxHierarchize = "Hierarchize({{0}})",
  57994. mdxAxis = "{0} DIMENSION PROPERTIES PARENT_UNIQUE_NAME,HIERARCHY_UNIQUE_NAME ON {1}",
  57995. mdxCrossJoin = "CrossJoin({0})",
  57996. mdxGenerate = "Generate({{0}}, ({1}, {2}))",
  57997. mdxSet = "{{0}}",
  57998. utils = DX.utils,
  57999. stringFormat = utils.stringFormat,
  58000. sortOrderDictionary = {
  58001. asc: "asc",
  58002. desc: "desc"
  58003. },
  58004. sortByDictionary = {
  58005. displaytext: ".member_caption",
  58006. value: ".member_value"
  58007. },
  58008. MEASURE_DEMENSION_KEY = "DX_MEASURES",
  58009. MD_DIMTYPE_MEASURE = "2";
  58010. DX.ui.dxPivotGrid.sendRequest = function(options) {
  58011. return $.ajax(options)
  58012. };
  58013. function execXMLA(requestOptions, data) {
  58014. var deferred = $.Deferred(),
  58015. beforeSend = requestOptions.beforeSend,
  58016. ajaxSettings = {
  58017. url: requestOptions.url,
  58018. dataType: "text",
  58019. data: data,
  58020. headers: {'Content-Type': 'text/xml'},
  58021. xhrFields: {},
  58022. method: "POST"
  58023. };
  58024. if (utils.isFunction(beforeSend))
  58025. beforeSend(ajaxSettings);
  58026. DX.ui.dxPivotGrid.sendRequest(ajaxSettings).fail(function() {
  58027. deferred.reject(arguments)
  58028. }).done(function(text) {
  58029. var xml;
  58030. try {
  58031. xml = $.parseXML(text)
  58032. }
  58033. catch(e) {
  58034. deferred.reject({
  58035. statusText: e.message,
  58036. stack: e.stack,
  58037. responseText: text
  58038. })
  58039. }
  58040. deferred.resolve(xml)
  58041. });
  58042. return deferred
  58043. }
  58044. function mdxDescendants(level, levelMember, nextLevel) {
  58045. levelMember = levelMember ? ".[" + levelMember + "]" : "";
  58046. return "Descendants({" + level + levelMember + "}, " + nextLevel + ", SELF_AND_BEFORE)"
  58047. }
  58048. function getAllMember(dimention) {
  58049. return (dimention.hierarchyName || dimention.dataField) + ".[All]"
  58050. }
  58051. function getAllMembers(field) {
  58052. return field.dataField + ".allMembers"
  58053. }
  58054. function getCurrentMember(field) {
  58055. return (field.hierarchyName || field.dataField) + ".currentMember"
  58056. }
  58057. function crossJoinElements(elements) {
  58058. var elementsString = elements.join(",");
  58059. return elements.length > 1 ? stringFormat(mdxCrossJoin, elementsString) : elementsString
  58060. }
  58061. function orderField(field, orderArg, options, axisName, withArray) {
  58062. var sortOrder = sortOrderDictionary[field.sortOrder];
  58063. if (sortOrder || sortByDictionary[(field.sortBy + "").toLowerCase()])
  58064. return stringFormat(orderMdx, orderArg, getOrderValue(field, options, axisName, orderArg, withArray), sortOrder || "asc");
  58065. else
  58066. return orderArg
  58067. }
  58068. function generateCrossJoin(path, expandLevel, expandAllCount, expandIndex, slicePath, options, axisName, withArray) {
  58069. var crossJoinArgs = [],
  58070. dimensions = options[axisName],
  58071. dataField,
  58072. allMember,
  58073. fields = [],
  58074. hierarchyName,
  58075. arg,
  58076. prevDimension,
  58077. prevHierarchyName,
  58078. isLastDimesionInGroup,
  58079. isFirstDimesionInGroup,
  58080. expandAllIndex,
  58081. field,
  58082. member,
  58083. useGenerate,
  58084. i;
  58085. for (i = expandIndex; i <= expandLevel; i++) {
  58086. field = dimensions[i];
  58087. dataField = field.dataField;
  58088. prevHierarchyName = dimensions[i - 1] && dimensions[i - 1].hierarchyName;
  58089. hierarchyName = field.hierarchyName;
  58090. isLastDimesionInGroup = !hierarchyName || !dimensions[i + 1] || dimensions[i + 1].hierarchyName !== hierarchyName;
  58091. expandAllIndex = path.length + expandAllCount + expandIndex;
  58092. arg = null;
  58093. useGenerate = false;
  58094. fields.push(field);
  58095. if (i < path.length) {
  58096. if (isLastDimesionInGroup)
  58097. arg = "(" + dataField + ".[" + path[i] + "])"
  58098. }
  58099. else if (i <= expandAllIndex)
  58100. if (i === 0 && expandAllCount === 0) {
  58101. allMember = getAllMember(dimensions[expandIndex]);
  58102. if (!hierarchyName)
  58103. arg = getAllMembers(dimensions[expandIndex]);
  58104. else
  58105. arg = allMember + "," + dimensions[expandIndex].dataField
  58106. }
  58107. else if (hierarchyName) {
  58108. member = slicePath[slicePath.length - 1];
  58109. if (isLastDimesionInGroup || i === expandAllIndex)
  58110. if (prevHierarchyName === hierarchyName) {
  58111. if (slicePath.length)
  58112. prevDimension = dimensions[slicePath.length - 1];
  58113. if (!prevDimension || prevDimension.hierarchyName !== hierarchyName) {
  58114. prevDimension = dimensions[i - 1];
  58115. member = ""
  58116. }
  58117. arg = mdxDescendants(prevDimension.dataField, member, dataField)
  58118. }
  58119. else
  58120. arg = getAllMembers(field)
  58121. }
  58122. else {
  58123. arg = getAllMembers(field);
  58124. if (field.sortBySummaryField && crossJoinArgs.length && i === expandAllIndex)
  58125. useGenerate = true
  58126. }
  58127. else {
  58128. isFirstDimesionInGroup = !hierarchyName || prevHierarchyName !== hierarchyName;
  58129. if (isFirstDimesionInGroup)
  58130. arg = "(" + getAllMember(field) + ")"
  58131. }
  58132. if (arg) {
  58133. arg = stringFormat(mdxSet, arg);
  58134. arg = orderField(field, arg, options, axisName, withArray);
  58135. if (useGenerate)
  58136. arg = stringFormat(mdxGenerate, crossJoinArgs.pop(), getCurrentMember(dimensions[i - 1]), arg);
  58137. crossJoinArgs.push(arg)
  58138. }
  58139. }
  58140. return crossJoinElements(crossJoinArgs)
  58141. }
  58142. function fillCrossJoins(crossJoins, path, expandLevel, expandIndex, slicePath, options, axisName, withArray) {
  58143. var expandAllCount = -1,
  58144. dimensions = options[axisName],
  58145. dimestionIndex;
  58146. do {
  58147. expandAllCount++;
  58148. dimestionIndex = path.length + expandAllCount + expandIndex;
  58149. crossJoins.push(generateCrossJoin(path, expandLevel, expandAllCount, expandIndex, slicePath, options, axisName, withArray))
  58150. } while (dimensions[dimestionIndex] && dimensions[dimestionIndex + 1] && dimensions[dimestionIndex].expanded)
  58151. }
  58152. function declareSet(set, withArray, name) {
  58153. name = name || "DX_Set_" + withArray.length;
  58154. withArray.push(stringFormat(mdxWith, name, set));
  58155. return "[" + name + "]"
  58156. }
  58157. function getRank(field, orderArg, withArray) {
  58158. var set;
  58159. if (field.hierarchyName)
  58160. set = declareSet(stringFormat(mdxHierarchize, orderArg), withArray);
  58161. else
  58162. set = getAllMembers(field);
  58163. return "rank(" + getCurrentMember(field) + "," + set + ")"
  58164. }
  58165. function getOrderValueForSummary(field, options, axisName) {
  58166. var sortByFields = (axisName === "columns" ? options.rows : options.columns) || [],
  58167. dataFields = options.values || [],
  58168. sortBySummaryFieldIndex = DX.ui.dxPivotGrid.findField(dataFields, field.sortBySummaryField),
  58169. tupleElements = dataFields[sortBySummaryFieldIndex] ? [dataFields[sortBySummaryFieldIndex].dataField] : [],
  58170. orderPath = field.sortBySummaryPath || [],
  58171. prevElementHierarchyName;
  58172. $.each(orderPath, function(index, path) {
  58173. var sortByField = sortByFields[index];
  58174. if (sortByField)
  58175. if (sortByField.hierarchyName && sortByField.hierarchyName === prevElementHierarchyName)
  58176. tupleElements[tupleElements.length - 1] = (sortByField.hierarchyName || sortByField.dataField) + ".[" + path + "]";
  58177. else {
  58178. tupleElements.push((sortByField.hierarchyName || sortByField.dataField) + ".[" + path + "]");
  58179. prevElementHierarchyName = sortByField.hierarchyName
  58180. }
  58181. });
  58182. return tupleElements.join(",")
  58183. }
  58184. function getOrderValue(field, options, axisName, orderArg, withArray) {
  58185. var orderProperty = sortByDictionary[(field.sortBy + "").toLowerCase()];
  58186. if (field.sortBySummaryField)
  58187. return "(" + getOrderValueForSummary(field, options, axisName) + ")";
  58188. else if (orderProperty)
  58189. return getCurrentMember(field) + orderProperty;
  58190. else
  58191. return getRank(field, orderArg, withArray)
  58192. }
  58193. function generateAxisMdx(options, axisName, cells, withArray, parseOptions) {
  58194. var dimensions = options[axisName],
  58195. crossJoins = [],
  58196. path = [],
  58197. expandedPaths = [],
  58198. expandIndex = 0,
  58199. expandLevel = 0,
  58200. result = [],
  58201. cellsString = stringFormat(mdxSet, cells.join(","));
  58202. if (dimensions && dimensions.length) {
  58203. if (options.headerName === axisName) {
  58204. path = options.path;
  58205. expandLevel = expandIndex = path.length
  58206. }
  58207. else {
  58208. expandedPaths = (axisName === "columns" ? options.columnExpandedPaths : options.rowExpandedPaths) || expandedPaths;
  58209. $.each(expandedPaths, function(_, path) {
  58210. expandLevel = Math.max(expandLevel, path.length)
  58211. })
  58212. }
  58213. while (dimensions[expandLevel + 1] && dimensions[expandLevel].expanded)
  58214. expandLevel++;
  58215. fillCrossJoins(crossJoins, [], expandLevel, expandIndex, path, options, axisName, withArray);
  58216. $.each(expandedPaths, function(_, expandedPath) {
  58217. fillCrossJoins(crossJoins, expandedPath, expandLevel, expandIndex, expandedPath, options, axisName, withArray)
  58218. });
  58219. for (var i = expandLevel; i >= path.length; i--)
  58220. if (dimensions[i].hierarchyName) {
  58221. parseOptions.visibleLevels[dimensions[i].hierarchyName] = parseOptions.visibleLevels[dimensions[i].hierarchyName] || [];
  58222. parseOptions.visibleLevels[dimensions[i].hierarchyName].push(dimensions[i].dataField)
  58223. }
  58224. }
  58225. crossJoins.length && result.push(stringFormat(mdxNonEmpty, declareSet(stringFormat(mdxSet, crossJoins.join(",")), withArray, axisName), cellsString));
  58226. if (axisName === "columns" && cells.length)
  58227. result.push(cellsString);
  58228. return stringFormat(mdxAxis, crossJoinElements(result), axisName)
  58229. }
  58230. function generateAxisFieldsFilter(fields) {
  58231. var filterMembers = [];
  58232. $.each(fields, function(_, field) {
  58233. var dataField = field.dataField,
  58234. filterExpression = [],
  58235. filterValues = field.filterValues || [],
  58236. filterStringExpression;
  58237. if (field.hierarchyName && utils.isNumber(field.groupIndex))
  58238. return;
  58239. $.each(filterValues, function(_, filterValue) {
  58240. var filterMdx = dataField + ".[" + (utils.isArray(filterValue) ? filterValue[filterValue.length - 1] : filterValue) + "]";
  58241. if (field.filterType === "exclude") {
  58242. filterExpression.push(filterMdx + ".parent");
  58243. filterMdx = "Descendants(" + filterMdx + ")"
  58244. }
  58245. filterExpression.push(filterMdx)
  58246. });
  58247. if (filterValues.length) {
  58248. filterStringExpression = stringFormat(mdxSet, filterExpression.join(","));
  58249. if (field.filterType === "exclude")
  58250. filterStringExpression = "Except(" + getAllMembers(field) + "," + filterStringExpression + ")";
  58251. filterMembers.push(filterStringExpression)
  58252. }
  58253. });
  58254. return filterMembers.length ? crossJoinElements(filterMembers) : ""
  58255. }
  58256. function generateFrom(columnsFilter, rowsFilter, filter, cubeName) {
  58257. var from = "[" + cubeName + "]";
  58258. $.each([columnsFilter, rowsFilter, filter], function(_, filter) {
  58259. if (filter)
  58260. from = stringFormat(mdxFilterSelect, filter + "on 0", from)
  58261. });
  58262. return from
  58263. }
  58264. function generateMDX(options, cubeName, parseOptions) {
  58265. var columns = options.columns || [],
  58266. rows = options.rows || [],
  58267. values = options.values && options.values.length ? options.values : [{dataField: '[Measures]'}],
  58268. slice = [],
  58269. withArray = [],
  58270. axisStrings = [],
  58271. dataFields = $.map(values, function(cell) {
  58272. return cell.dataField
  58273. });
  58274. parseOptions.measureCount = values.length;
  58275. parseOptions.visibleLevels = {};
  58276. if (options.headerName && options.path)
  58277. $.each(options.path, function(index, value) {
  58278. var dimention = options[options.headerName][index];
  58279. if (!dimention.hierarchyName || dimention.hierarchyName !== options[options.headerName][index + 1].hierarchyName)
  58280. slice.push(dimention.dataField + ".[" + value + "]")
  58281. });
  58282. if (columns.length || dataFields.length)
  58283. axisStrings.push(generateAxisMdx(options, "columns", dataFields, withArray, parseOptions));
  58284. if (rows.length)
  58285. axisStrings.push(generateAxisMdx(options, "rows", dataFields, withArray, parseOptions));
  58286. if (!axisStrings.length)
  58287. return "";
  58288. var withString = (withArray.length ? "with" + withArray.join(" ") : "") + " ";
  58289. return withString + stringFormat(mdx, generateFrom(generateAxisFieldsFilter(columns), generateAxisFieldsFilter(rows), generateAxisFieldsFilter(options.filters || []), cubeName), slice.length ? stringFormat(mdxSlice, slice.join(",")) : "", axisStrings.join(","))
  58290. }
  58291. function getNumber(str) {
  58292. return parseInt(str, 10)
  58293. }
  58294. function parseAxes(xml) {
  58295. var axes = [];
  58296. $.each($(xml).find("Axis"), function(_, axisElement) {
  58297. var $axis = $(axisElement),
  58298. name = axisElement.getAttribute("name"),
  58299. axis = [],
  58300. index = 0;
  58301. if (name.indexOf("Axis") === 0 && utils.isNumber(getNumber(name.substr(4)))) {
  58302. axes.push(axis);
  58303. $.each($axis.children("Tuples").children(), function(_, tupleElement) {
  58304. var tupleMembers = $(tupleElement).children(),
  58305. $tuple,
  58306. levelSum = 0,
  58307. members = [],
  58308. level,
  58309. membersCount = tupleMembers.length - 1,
  58310. isAxisWithMeasure = axes.length === 1,
  58311. i;
  58312. if (isAxisWithMeasure)
  58313. membersCount--;
  58314. axis.push(members);
  58315. for (i = membersCount; i >= 0; i--) {
  58316. $tuple = $(tupleMembers[i]);
  58317. level = getNumber($tuple.children("LNum").text());
  58318. members[i] = {
  58319. caption: $tuple.children("Caption").text(),
  58320. level: level,
  58321. index: index++,
  58322. hasValue: !levelSum && (!!level || i === 0),
  58323. name: $tuple.children("UName").text(),
  58324. parentName: $tuple.children("PARENT_UNIQUE_NAME").text(),
  58325. levelName: $tuple.children("LName").text(),
  58326. hierarchyName: tupleMembers[i].getAttribute("Hierarchy")
  58327. };
  58328. levelSum += level
  58329. }
  58330. })
  58331. }
  58332. });
  58333. while (axes.length < 2)
  58334. axes.push([[{level: 0}]]);
  58335. return axes
  58336. }
  58337. function parseCells(xml, axes, measureCount) {
  58338. var cells = [],
  58339. cell = [],
  58340. index = 0,
  58341. measureIndex,
  58342. cellsOriginal = [],
  58343. row;
  58344. $.each($(xml).find("CellData > Cell"), function(_, xmlCell) {
  58345. var $cell = $(xmlCell),
  58346. value = parseFloat($cell.children("Value").text());
  58347. cellsOriginal[getNumber(xmlCell.getAttribute("CellOrdinal"))] = {value: isNaN(value) ? null : value}
  58348. });
  58349. $.each(axes[1], function() {
  58350. row = [];
  58351. cells.push(row);
  58352. $.each(axes[0], function() {
  58353. measureIndex = index % measureCount;
  58354. if (measureIndex === 0) {
  58355. cell = [];
  58356. row.push(cell)
  58357. }
  58358. cell.push(cellsOriginal[index] ? cellsOriginal[index].value : null);
  58359. index++
  58360. })
  58361. });
  58362. return cells
  58363. }
  58364. function getItem(hash, name, member, index) {
  58365. var item = hash[name];
  58366. if (!item) {
  58367. item = {};
  58368. hash[name] = item
  58369. }
  58370. if (!item.value && member) {
  58371. item.value = member.caption;
  58372. item.levelName = member.levelName;
  58373. item.hierarchyName = member.hierarchyName;
  58374. item.parentName = member.parentName;
  58375. item.index = index;
  58376. item.level = member.level
  58377. }
  58378. return item
  58379. }
  58380. function getVisibleChildren(item, visibleLevels) {
  58381. var result = [],
  58382. children = item.children && (item.children.length ? item.children : $.map(item.children.grandTotalHash || [], function(e) {
  58383. return e.children
  58384. })),
  58385. firstChild = children && children[0];
  58386. if (firstChild && (visibleLevels[firstChild.hierarchyName] && $.inArray(firstChild.levelName, visibleLevels[firstChild.hierarchyName]) !== -1 || !visibleLevels[firstChild.hierarchyName] || firstChild.level === 0)) {
  58387. var newChildren = $.map(children, function(child) {
  58388. return child.hierarchyName === firstChild.hierarchyName ? child : null
  58389. });
  58390. newChildren.grandTotalHash = children.grandTotalHash;
  58391. return newChildren
  58392. }
  58393. else if (firstChild)
  58394. for (var i = 0; i < children.length; i++)
  58395. if (children[i].hierarchyName === firstChild.hierarchyName)
  58396. result.push.apply(result, getVisibleChildren(children[i], visibleLevels));
  58397. return result
  58398. }
  58399. function processMember(dataIndex, member, parentItem) {
  58400. var currentItem,
  58401. children = parentItem.children = parentItem.children || [],
  58402. hash = children.hash = children.hash || {},
  58403. grandTotalHash = children.grandTotalHash = children.grandTotalHash || {};
  58404. if (member.parentName) {
  58405. parentItem = getItem(hash, member.parentName);
  58406. children = parentItem.children = parentItem.children || []
  58407. }
  58408. currentItem = getItem(hash, member.name, member, dataIndex);
  58409. if (member.hasValue && !currentItem.added) {
  58410. currentItem.index = dataIndex;
  58411. currentItem.added = true;
  58412. children.push(currentItem)
  58413. }
  58414. if ((!parentItem.value || !parentItem.parentName) && member.parentName)
  58415. grandTotalHash[member.parentName] = parentItem;
  58416. else if (grandTotalHash[parentItem.name])
  58417. delete grandTotalHash[member.parentName];
  58418. return currentItem
  58419. }
  58420. function getGrandTotalIndex(parentItem, visibleLevels) {
  58421. var grandTotalIndex;
  58422. if (parentItem.children.length === 1 && parentItem.children[0].parentName === "") {
  58423. grandTotalIndex = parentItem.children[0].index;
  58424. var grandTotalHash = parentItem.children.grandTotalHash;
  58425. parentItem.children = parentItem.children[0].children;
  58426. parentItem.children.grandTotalHash = grandTotalHash;
  58427. parentItem.children = getVisibleChildren(parentItem, visibleLevels)
  58428. }
  58429. else if (parentItem.children.length === 0)
  58430. grandTotalIndex = 0;
  58431. return grandTotalIndex
  58432. }
  58433. function fillDataSourceAxes(dataSourceAxis, axisTuples, measureCount, visibleLevels) {
  58434. var grandTotalIndex,
  58435. result = [];
  58436. $.each(axisTuples, function(tupleIndex, members) {
  58437. var parentItem = {children: result},
  58438. dataIndex = utils.isDefined(measureCount) ? Math.floor(tupleIndex / measureCount) : tupleIndex;
  58439. $.each(members, function(_, member) {
  58440. parentItem = processMember(dataIndex, member, parentItem)
  58441. })
  58442. });
  58443. var parentItem = {children: result};
  58444. parentItem.children = getVisibleChildren(parentItem, visibleLevels);
  58445. grandTotalIndex = getGrandTotalIndex(parentItem, visibleLevels);
  58446. DX.ui.dxPivotGrid.foreachTreeItems(parentItem.children, function(item) {
  58447. var children = getVisibleChildren(item, visibleLevels);
  58448. if (children.length)
  58449. item.children = children;
  58450. else
  58451. delete item.children;
  58452. delete item.levelName;
  58453. delete item.hierarchyName;
  58454. delete item.added;
  58455. delete item.parentName;
  58456. delete item.level
  58457. }, undefined, true);
  58458. $.each(parentItem.children || [], function(_, e) {
  58459. dataSourceAxis.push(e)
  58460. });
  58461. return grandTotalIndex
  58462. }
  58463. function parseResult(xml, parseOptions) {
  58464. var dataSource = {
  58465. columns: [],
  58466. rows: []
  58467. },
  58468. axes,
  58469. error = $(xml).find("Error"),
  58470. measureCount = parseOptions.measureCount;
  58471. if (error.length) {
  58472. utils.logger.error(error.attr("Description"));
  58473. return null
  58474. }
  58475. axes = parseAxes(xml);
  58476. dataSource.grandTotalColumnIndex = fillDataSourceAxes(dataSource.columns, axes[0], measureCount, parseOptions.visibleLevels);
  58477. dataSource.grandTotalRowIndex = fillDataSourceAxes(dataSource.rows, axes[1], undefined, parseOptions.visibleLevels);
  58478. dataSource.values = parseCells(xml, axes, measureCount);
  58479. return dataSource
  58480. }
  58481. function parseDiscoverRowSet(xml, schema, dimensions) {
  58482. var result = [],
  58483. isMeasure = schema === "MEASURE",
  58484. displayFolderField = isMeasure ? "MEASUREGROUP_NAME" : schema + "_DISPLAY_FOLDER";
  58485. $.each($(xml).find("row"), function(_, row) {
  58486. var $row = $(row),
  58487. hierarchyName = schema === "LEVEL" ? $row.children("HIERARCHY_UNIQUE_NAME").text() : undefined,
  58488. levelNumber = $row.children("LEVEL_NUMBER").text();
  58489. if ((levelNumber !== "0" || $row.children(schema + "_IS_VISIBLE").text() !== "true") && $row.children("DIMENSION_TYPE").text() !== MD_DIMTYPE_MEASURE) {
  58490. var dimension = isMeasure ? MEASURE_DEMENSION_KEY : $row.children("DIMENSION_UNIQUE_NAME").text();
  58491. result.push({
  58492. dimension: dimensions[dimension] || dimension,
  58493. groupIndex: levelNumber ? getNumber(levelNumber) - 1 : undefined,
  58494. dataField: $row.children(schema + "_UNIQUE_NAME").text(),
  58495. caption: $row.children(schema + "_CAPTION").text(),
  58496. hierarchyName: hierarchyName,
  58497. groupName: hierarchyName,
  58498. displayFolder: $row.children(displayFolderField).text(),
  58499. isMeasure: isMeasure
  58500. })
  58501. }
  58502. });
  58503. return result
  58504. }
  58505. function parseDimensionsDiscoverRowSet(xml) {
  58506. var result = {};
  58507. $.each($(xml).find("row"), function(_, row) {
  58508. var $row = $(row),
  58509. type = $row.children("DIMENSION_TYPE").text(),
  58510. dimensionName = type === MD_DIMTYPE_MEASURE ? MEASURE_DEMENSION_KEY : $row.children("DIMENSION_UNIQUE_NAME").text();
  58511. result[dimensionName] = $row.children("DIMENSION_CAPTION").text()
  58512. });
  58513. return result
  58514. }
  58515. return {
  58516. ctor: function(options) {
  58517. this._options = options
  58518. },
  58519. getFields: function() {
  58520. var options = this._options,
  58521. catalog = options.catalog,
  58522. cube = options.cube,
  58523. dimensionsRequest = execXMLA(options, stringFormat(discover, catalog, cube, "MDSCHEMA_DIMENSIONS")),
  58524. measuresRequest = execXMLA(options, stringFormat(discover, catalog, cube, "MDSCHEMA_MEASURES")),
  58525. hierarchiesRequest = execXMLA(options, stringFormat(discover, catalog, cube, "MDSCHEMA_HIERARCHIES")),
  58526. levelsRequest = execXMLA(options, stringFormat(discover, catalog, cube, "MDSCHEMA_LEVELS")),
  58527. result = $.Deferred();
  58528. $.when(dimensionsRequest, measuresRequest, hierarchiesRequest, levelsRequest).done(function(dimensionsResponse, measuresResponse, hierarhiesResponse, levelsResponse) {
  58529. var dimensions = parseDimensionsDiscoverRowSet(dimensionsResponse),
  58530. hierarchies = parseDiscoverRowSet(hierarhiesResponse, "HIERARCHY", dimensions),
  58531. levels = parseDiscoverRowSet(levelsResponse, "LEVEL", dimensions),
  58532. fields = parseDiscoverRowSet(measuresResponse, "MEASURE", dimensions).concat(hierarchies),
  58533. levelsByHierarchy = {};
  58534. $.each(levels, function(_, level) {
  58535. levelsByHierarchy[level.hierarchyName] = levelsByHierarchy[level.hierarchyName] || [];
  58536. levelsByHierarchy[level.hierarchyName].push(level)
  58537. });
  58538. $.each(hierarchies, function(_, hierarchy) {
  58539. if (levelsByHierarchy[hierarchy.dataField] && levelsByHierarchy[hierarchy.dataField].length > 1) {
  58540. hierarchy.groupName = hierarchy.hierarchyName = hierarchy.dataField;
  58541. fields.push.apply(fields, levelsByHierarchy[hierarchy.hierarchyName])
  58542. }
  58543. });
  58544. result.resolve(fields)
  58545. }).fail(result.reject);
  58546. return result
  58547. },
  58548. load: function(options) {
  58549. var result = $.Deferred(),
  58550. storeOptions = this._options,
  58551. data,
  58552. executeQuery,
  58553. parseOptions = {},
  58554. mdxString = generateMDX(options, storeOptions.cube, parseOptions);
  58555. if (mdxString) {
  58556. executeQuery = stringFormat(execute, mdxString, storeOptions.catalog);
  58557. $.when(execXMLA(storeOptions, executeQuery)).done(function(executeXml) {
  58558. data = parseResult(executeXml, parseOptions);
  58559. if (data)
  58560. result.resolve(data);
  58561. else
  58562. result.reject()
  58563. }).fail(result.reject)
  58564. }
  58565. else
  58566. result.resolve({
  58567. columns: [],
  58568. rows: [],
  58569. values: [],
  58570. grandTotalColumnIndex: 0,
  58571. grandTotalRowIndex: 0
  58572. });
  58573. return result
  58574. },
  58575. supportSorting: function() {
  58576. return true
  58577. }
  58578. }
  58579. }())
  58580. })(jQuery, DevExpress);
  58581. /*! Module widgets-web, file ui.pivotGrid.store.local.js */
  58582. (function($, DX) {
  58583. var dataUtils = DX.data.utils,
  58584. utils = DX.utils,
  58585. pivotGrid = DX.ui.dxPivotGrid;
  58586. pivotGrid.LocalStore = DevExpress.Class.inherit(function() {
  58587. var DATE_INTERVAL_SELECTORS = {
  58588. year: function(date) {
  58589. return date && date.getFullYear()
  58590. },
  58591. quarter: function(date) {
  58592. return date && Math.floor(date.getMonth() / 3) + 1
  58593. },
  58594. month: function(date) {
  58595. return date && date.getMonth() + 1
  58596. },
  58597. day: function(date) {
  58598. return date && date.getDate()
  58599. },
  58600. dayOfWeek: function(date) {
  58601. return date && date.getDay()
  58602. }
  58603. };
  58604. var DATE_INTERVAL_FORMATS = {
  58605. month: {
  58606. format: 'month',
  58607. dateType: 'full'
  58608. },
  58609. quarter: {
  58610. format: 'quarter',
  58611. dateType: 'full'
  58612. },
  58613. dayOfWeek: {
  58614. format: 'dayOfWeek',
  58615. dateType: 'full'
  58616. }
  58617. };
  58618. function prepareFields(fields) {
  58619. $.each(fields || [], function() {
  58620. var fieldSelector,
  58621. intervalSelector,
  58622. dataField = this.dataField,
  58623. groupInteval,
  58624. levels = this.levels;
  58625. if (!this.selector) {
  58626. if (!dataField)
  58627. fieldSelector = function(data) {
  58628. return data
  58629. };
  58630. else
  58631. fieldSelector = dataField.indexOf(".") !== -1 ? dataUtils.compileGetter(dataField) : function(data) {
  58632. return data[dataField]
  58633. };
  58634. if (levels) {
  58635. prepareFields(levels);
  58636. this.selector = function(data) {
  58637. var value = [];
  58638. $.each(levels, function(_, field) {
  58639. value.push(field.selector(data))
  58640. });
  58641. return value
  58642. }
  58643. }
  58644. else if (this.dataType === 'date') {
  58645. intervalSelector = DATE_INTERVAL_SELECTORS[this.groupInterval];
  58646. this.selector = function(data) {
  58647. var value = fieldSelector(data);
  58648. if (value && !(value instanceof Date))
  58649. value = new Date(value);
  58650. return intervalSelector ? intervalSelector(value) : value
  58651. };
  58652. this.format = this.format || DATE_INTERVAL_FORMATS[this.groupInterval]
  58653. }
  58654. else if (this.dataType === 'number') {
  58655. groupInteval = utils.isNumber(this.groupInterval) && this.groupInterval > 0 && this.groupInterval;
  58656. if (groupInteval)
  58657. this.customizeText = this.customizeText || function(formatObject) {
  58658. var secondValue = formatObject.value + groupInteval,
  58659. secondValueText = DX.formatHelper.format(secondValue, this.format, this.precision);
  58660. return formatObject.valueText && secondValueText ? formatObject.valueText + " - " + secondValueText : ""
  58661. };
  58662. this.selector = function(data) {
  58663. var value = fieldSelector(data);
  58664. if (DX.utils.isString(value))
  58665. value = Number(value);
  58666. return groupInteval ? Math.floor(value / groupInteval) * groupInteval : value
  58667. }
  58668. }
  58669. else
  58670. this.selector = fieldSelector
  58671. }
  58672. })
  58673. }
  58674. var addHierarchyItem = function(value, hierarchyItems, pathHash, childrenHash) {
  58675. var hierarchyItem = childrenHash[pathHash];
  58676. if (!hierarchyItem) {
  58677. hierarchyItem = {
  58678. value: value,
  58679. index: childrenHash.length++
  58680. };
  58681. childrenHash[pathHash] = hierarchyItem;
  58682. hierarchyItems.push(hierarchyItem)
  58683. }
  58684. return hierarchyItem
  58685. };
  58686. function fillHierarchyItemIndexesCore(indexes, options, children, expandIndex, pathHash) {
  58687. var dimension = options.dimensions[expandIndex],
  58688. expandedPathsHash = options.expandedPathsHash,
  58689. dimensionValue,
  58690. hierarchyItem;
  58691. if (dimension) {
  58692. dimensionValue = dimension.selector(options.data);
  58693. pathHash = pathHash ? pathHash + "." + dimensionValue : dimensionValue;
  58694. hierarchyItem = addHierarchyItem(dimensionValue, children, pathHash, options.childrenHash);
  58695. indexes.push(hierarchyItem.index);
  58696. if (expandedPathsHash && expandedPathsHash[pathHash] || dimension.expanded) {
  58697. if (!hierarchyItem.children)
  58698. hierarchyItem.children = [];
  58699. fillHierarchyItemIndexesCore(indexes, options, hierarchyItem.children, expandIndex + 1, pathHash)
  58700. }
  58701. }
  58702. }
  58703. function generateHierarchyItems(data, loadOptions, headers, headerName) {
  58704. var result = [0],
  58705. expandIndex = loadOptions.headerName === headerName ? loadOptions.path.length : 0,
  58706. expandedPaths = headerName === "rows" ? loadOptions.rowExpandedPaths : loadOptions.columnExpandedPaths,
  58707. options = {
  58708. data: data,
  58709. childrenHash: headers[headerName + "Hash"],
  58710. dimensions: loadOptions[headerName],
  58711. expandedPathsHash: loadOptions.headerName !== headerName && expandedPaths && expandedPaths.hash
  58712. };
  58713. fillHierarchyItemIndexesCore(result, options, headers[headerName], expandIndex);
  58714. return result
  58715. }
  58716. function generateAggregationCells(data, cells, headers, options) {
  58717. var cellSet = [],
  58718. x,
  58719. y,
  58720. rowIndex,
  58721. columnIndex;
  58722. var rowIndexes = generateHierarchyItems(data, options, headers, "rows");
  58723. var columnIndexes = generateHierarchyItems(data, options, headers, "columns");
  58724. for (y = 0; y < rowIndexes.length; y++) {
  58725. rowIndex = rowIndexes[y];
  58726. cells[rowIndex] = cells[rowIndex] || [];
  58727. for (x = 0; x < columnIndexes.length; x++) {
  58728. columnIndex = columnIndexes[x];
  58729. cellSet.push(cells[rowIndex][columnIndex] = cells[rowIndex][columnIndex] || [])
  58730. }
  58731. }
  58732. return cellSet
  58733. }
  58734. function fillHashExpandedPath(expandedPaths) {
  58735. if (expandedPaths) {
  58736. expandedPaths.hash = {};
  58737. $.each(expandedPaths, function() {
  58738. expandedPaths.hash[this.join(".")] = true
  58739. })
  58740. }
  58741. }
  58742. function prepareLoadOption(options) {
  58743. options.rows = options.rows || [];
  58744. options.columns = options.columns || [];
  58745. options.filters = options.filters || [];
  58746. fillHashExpandedPath(options.columnExpandedPaths);
  58747. fillHashExpandedPath(options.rowExpandedPaths);
  58748. prepareFields(options.columns);
  58749. prepareFields(options.rows);
  58750. prepareFields(options.values);
  58751. prepareFields(options.filters)
  58752. }
  58753. function getAggregator(field) {
  58754. if (field.summaryType === "custom") {
  58755. field.calculateCustomSummary = field.calculateCustomSummary || $.noop;
  58756. return {
  58757. seed: function() {
  58758. var options = {
  58759. summaryProcess: "start",
  58760. totalValue: undefined
  58761. };
  58762. field.calculateCustomSummary(options);
  58763. return options
  58764. },
  58765. step: function(options, value) {
  58766. options.summaryProcess = "calculate";
  58767. options.value = value;
  58768. field.calculateCustomSummary(options);
  58769. return options
  58770. },
  58771. finalize: function(options) {
  58772. options.summaryProcess = "finalize";
  58773. delete options.value;
  58774. field.calculateCustomSummary(options);
  58775. return options.totalValue
  58776. }
  58777. }
  58778. }
  58779. return dataUtils.aggregators[field.summaryType] || dataUtils.aggregators.count
  58780. }
  58781. function aggregationStep(measures, aggregationCells, data) {
  58782. for (var aggregatorIndex = 0; aggregatorIndex < measures.length; aggregatorIndex++) {
  58783. var cellField = measures[aggregatorIndex];
  58784. var cellValue = cellField.selector(data);
  58785. var aggregator = getAggregator(cellField);
  58786. for (var cellSetIndex = 0; cellSetIndex < aggregationCells.length; cellSetIndex++) {
  58787. var cell = aggregationCells[cellSetIndex];
  58788. if (cell.length <= aggregatorIndex)
  58789. cell[aggregatorIndex] = utils.isFunction(aggregator.seed) ? aggregator.seed() : aggregator.seed;
  58790. if (cell[aggregatorIndex] === undefined)
  58791. cell[aggregatorIndex] = cellValue;
  58792. else if (utils.isDefined(cellValue))
  58793. cell[aggregatorIndex] = aggregator.step(cell[aggregatorIndex], cellValue)
  58794. }
  58795. }
  58796. }
  58797. function aggregationFinalize(measures, cells) {
  58798. $.each(measures, function(aggregatorIndex, cellField) {
  58799. var aggregator = getAggregator(cellField);
  58800. if (aggregator.finalize)
  58801. $.each(cells, function(_, row) {
  58802. $.each(row, function(_, cell) {
  58803. if (cell)
  58804. cell[aggregatorIndex] = aggregator.finalize(cell[aggregatorIndex])
  58805. })
  58806. })
  58807. })
  58808. }
  58809. function areValuesEqual(filterValue, fieldValue) {
  58810. if (utils.isArray(filterValue)) {
  58811. fieldValue = fieldValue || [];
  58812. for (var i = 0; i < filterValue.length; i++)
  58813. if (filterValue[i] !== fieldValue[i])
  58814. return false;
  58815. return true
  58816. }
  58817. else
  58818. return filterValue === fieldValue
  58819. }
  58820. function createDimensionFilters(dimention) {
  58821. var filters = [];
  58822. $.each(dimention, function(_, field) {
  58823. var filterValues = field.filterValues || [],
  58824. groupName = field.groupName,
  58825. filter;
  58826. if (groupName && utils.isNumber(field.groupIndex))
  58827. return;
  58828. filter = function(dataItem) {
  58829. var value = field.selector(dataItem),
  58830. result = false;
  58831. for (var i = 0; i < filterValues.length; i++)
  58832. if (areValuesEqual(filterValues[i], value)) {
  58833. result = true;
  58834. break
  58835. }
  58836. return field.filterType === "exclude" ? !result : result
  58837. };
  58838. filterValues.length && filters.push(filter)
  58839. });
  58840. return filters
  58841. }
  58842. function createFilter(options) {
  58843. var filters = createDimensionFilters(options.rows).concat(createDimensionFilters(options.columns)).concat(createDimensionFilters(options.filters)),
  58844. expandedDimensions = options[options.headerName],
  58845. path = options.path;
  58846. if (expandedDimensions)
  58847. filters.push(function(dataItem) {
  58848. var expandValue;
  58849. for (var i = 0; i < path.length; i++) {
  58850. expandValue = expandedDimensions[i].selector(dataItem);
  58851. if (expandValue !== path[i])
  58852. return false
  58853. }
  58854. return true
  58855. });
  58856. return function(dataItem) {
  58857. for (var i = 0; i < filters.length; i++)
  58858. if (!filters[i](dataItem))
  58859. return false;
  58860. return true
  58861. }
  58862. }
  58863. function loadCore(items, options) {
  58864. var headers = {
  58865. columns: [],
  58866. rows: [],
  58867. columnsHash: {length: 1},
  58868. rowsHash: {length: 1}
  58869. },
  58870. values = [[[]]],
  58871. aggregationCells,
  58872. filter,
  58873. data,
  58874. i;
  58875. prepareLoadOption(options);
  58876. filter = createFilter(options);
  58877. for (i = 0; i < items.length; i++) {
  58878. data = items[i];
  58879. if (filter(data)) {
  58880. aggregationCells = generateAggregationCells(data, values, headers, options);
  58881. aggregationStep(options.values, aggregationCells, data)
  58882. }
  58883. }
  58884. aggregationFinalize(options.values, values);
  58885. return {
  58886. rows: headers.rows,
  58887. columns: headers.columns,
  58888. values: values,
  58889. grandTotalRowIndex: 0,
  58890. grandTotalColumnIndex: 0
  58891. }
  58892. }
  58893. function createGroupFields(item) {
  58894. return $.map(["year", "quarter", "month"], function(value, index) {
  58895. return $.extend({}, item, {
  58896. groupInterval: value,
  58897. groupIndex: index
  58898. })
  58899. })
  58900. }
  58901. function parseFields(dataSource, fieldsList, path, fieldsDataType) {
  58902. var result = [];
  58903. $.each(fieldsList || [], function(field, value) {
  58904. var dataIndex = 1,
  58905. currentPath = path.length ? path + "." + field : field,
  58906. dataType = fieldsDataType[currentPath],
  58907. getter = dataUtils.compileGetter(currentPath),
  58908. items;
  58909. while (!utils.isDefined(value) && dataSource[dataIndex]) {
  58910. value = getter(dataSource[dataIndex]);
  58911. dataIndex++
  58912. }
  58913. if (!dataType && utils.isDefined(value))
  58914. dataType = $.type(value);
  58915. items = [{
  58916. dataField: currentPath,
  58917. dataType: dataType,
  58918. groupName: dataType === "date" ? field : undefined,
  58919. groupInterval: undefined,
  58920. displayFolder: path
  58921. }];
  58922. if (dataType === "date")
  58923. items = items.concat(createGroupFields(items[0]));
  58924. else if (dataType === "object")
  58925. items = parseFields(dataSource, value, currentPath, fieldsDataType);
  58926. result.push.apply(result, items)
  58927. });
  58928. return result
  58929. }
  58930. function discover(items, fieldsDataType) {
  58931. fieldsDataType = fieldsDataType || {};
  58932. return parseFields(items, items[0], "", fieldsDataType)
  58933. }
  58934. function loadDataSource(dataSource) {
  58935. var d = $.Deferred();
  58936. if (!dataSource.isLoaded())
  58937. $.when(dataSource.load()).always(function() {
  58938. loadDataSource(dataSource).done(d.resolve).fail(d.reject)
  58939. });
  58940. else
  58941. d.resolve(dataSource.items());
  58942. return d
  58943. }
  58944. return {
  58945. ctor: function(options) {
  58946. options = $.extend(dataUtils.normalizeDataSourceOptions(options), {
  58947. paginate: false,
  58948. onChanged: null
  58949. });
  58950. this._dataSource = new DX.data.DataSource(options)
  58951. },
  58952. getFields: function(fieldsDataType) {
  58953. var that = this,
  58954. dataSource = that._dataSource,
  58955. d = $.Deferred();
  58956. loadDataSource(dataSource).done(function(data) {
  58957. d.resolve(discover(data, fieldsDataType))
  58958. }).fail(d.reject);
  58959. return d
  58960. },
  58961. load: function(options) {
  58962. var that = this,
  58963. dataSource = that._dataSource,
  58964. d = $.Deferred();
  58965. loadDataSource(dataSource).done(function(data) {
  58966. var parsedData = loadCore(data, options);
  58967. d.resolve(parsedData)
  58968. }).fail(d.reject);
  58969. return d
  58970. },
  58971. supportSorting: function() {
  58972. return false
  58973. }
  58974. }
  58975. }())
  58976. })(jQuery, DevExpress);
  58977. /*! Module widgets-web, file ui.pivotGrid.areaItem.js */
  58978. (function($, DX) {
  58979. var pivotGrid = DX.ui.dxPivotGrid,
  58980. utils = DX.utils,
  58981. Class = DX.Class;
  58982. var IE_WIDTH_CORRECTION = 1;
  58983. var getRealElementWidth = function(element, isFixed) {
  58984. return isFixed ? element.offsetWidth : element.offsetWidth + IE_WIDTH_CORRECTION
  58985. };
  58986. pivotGrid.getRealElementWidth = getRealElementWidth;
  58987. pivotGrid.AreaItem = Class.inherit({
  58988. _getRowElement: function(index) {
  58989. var that = this;
  58990. if (that._tableElement && that._tableElement.length > 0)
  58991. return that._tableElement[0].rows[index];
  58992. return null
  58993. },
  58994. _createGroupElement: function() {
  58995. return $('<div>')
  58996. },
  58997. _createTableElement: function() {
  58998. return $('<table>')
  58999. },
  59000. _renderTableContent: function(tableElement, data) {
  59001. var that = this,
  59002. rowElements = tableElement.find("tr"),
  59003. areaName = that._getAreaName(),
  59004. onCellPrepared = that.option("onCellPrepared"),
  59005. rowElement,
  59006. cellElement,
  59007. row,
  59008. cell,
  59009. rowIndex,
  59010. columnIndex;
  59011. tableElement.data("area", areaName);
  59012. tableElement.data("data", data);
  59013. if (onCellPrepared)
  59014. for (rowIndex = 0; rowIndex < data.length; rowIndex++) {
  59015. row = data[rowIndex];
  59016. rowElement = rowElements.eq(rowIndex);
  59017. for (columnIndex = 0; columnIndex < row.length; columnIndex++) {
  59018. cell = row[columnIndex];
  59019. cellElement = rowElement.children().eq(columnIndex);
  59020. onCellPrepared({
  59021. area: areaName,
  59022. rowIndex: rowIndex,
  59023. columnIndex: columnIndex,
  59024. cellElement: cellElement,
  59025. cell: cell
  59026. })
  59027. }
  59028. }
  59029. },
  59030. _getRowHeight: function(index) {
  59031. var row = this._getRowElement(index);
  59032. if (row && row.lastChild)
  59033. return row.lastChild.offsetHeight;
  59034. return 0
  59035. },
  59036. _setRowHeight: function(index, value) {
  59037. var row = this._getRowElement(index);
  59038. if (row)
  59039. row.style.height = value + 'px'
  59040. },
  59041. ctor: function(component) {
  59042. this.component = component
  59043. },
  59044. option: function() {
  59045. return this.component.option.apply(this.component, arguments)
  59046. },
  59047. getRowsLength: function() {
  59048. var that = this;
  59049. if (that._tableElement && that._tableElement.length > 0)
  59050. return that._tableElement[0].rows.length;
  59051. return 0
  59052. },
  59053. getRowsHeight: function() {
  59054. var that = this,
  59055. result = [],
  59056. rowsLength = that.getRowsLength(),
  59057. i;
  59058. for (i = 0; i < rowsLength; i++)
  59059. result.push(that._getRowHeight(i));
  59060. return result
  59061. },
  59062. setRowsHeight: function(values) {
  59063. var that = this,
  59064. totalHeight = 0,
  59065. valuesLength = values.length,
  59066. i;
  59067. for (i = 0; i < valuesLength; i++) {
  59068. totalHeight += values[i];
  59069. that._setRowHeight(i, values[i])
  59070. }
  59071. this._tableHeight = totalHeight;
  59072. this._tableElement[0].style.height = totalHeight + 'px'
  59073. },
  59074. getColumnsWidth: function() {
  59075. var rowsLength = this.getRowsLength(),
  59076. rowIndex,
  59077. isFixed = this._tableElement[0].style.tableLayout === 'fixed',
  59078. row,
  59079. i,
  59080. columnIndex,
  59081. processedCells = [],
  59082. result = [],
  59083. fillCells = function(cells, rowIndex, columnIndex, rowSpan, colSpan) {
  59084. var rowOffset,
  59085. columnOffset;
  59086. for (rowOffset = 0; rowOffset < rowSpan; rowOffset++)
  59087. for (columnOffset = 0; columnOffset < colSpan; columnOffset++) {
  59088. cells[rowIndex + rowOffset] = cells[rowIndex + rowOffset] || [];
  59089. cells[rowIndex + rowOffset][columnIndex + columnOffset] = true
  59090. }
  59091. };
  59092. if (rowsLength)
  59093. for (rowIndex = 0; rowIndex < rowsLength; rowIndex++) {
  59094. processedCells[rowIndex] = processedCells[rowIndex] || [];
  59095. row = this._getRowElement(rowIndex);
  59096. for (i = 0; i < row.cells.length; i++) {
  59097. for (columnIndex = 0; processedCells[rowIndex][columnIndex]; columnIndex++);;
  59098. fillCells(processedCells, rowIndex, columnIndex, row.cells[i].rowSpan, row.cells[i].colSpan);
  59099. if (row.cells[i].colSpan === 1)
  59100. result[columnIndex] = getRealElementWidth(row.cells[i], isFixed)
  59101. }
  59102. }
  59103. return result
  59104. },
  59105. setColumnsWidth: function(values) {
  59106. var i,
  59107. totalWidth = 0;
  59108. var colgroupElementHTML = '';
  59109. for (i = 0; i < values.length; i++) {
  59110. totalWidth += values[i];
  59111. colgroupElementHTML += '<col style="width: ' + values[i] + 'px"/>'
  59112. }
  59113. this._colgroupElement.html(colgroupElementHTML);
  59114. this._tableWidth = totalWidth;
  59115. this._tableElement[0].style.width = totalWidth + 'px';
  59116. this._tableElement[0].style.tableLayout = 'fixed'
  59117. },
  59118. resetColumnsWidth: function() {
  59119. this._colgroupElement.find('col').width('auto');
  59120. this._tableElement.css({
  59121. width: '',
  59122. tableLayout: ''
  59123. })
  59124. },
  59125. groupWidth: function(value) {
  59126. if (value === undefined)
  59127. return this._groupElement.width();
  59128. else if (value >= 0) {
  59129. this._groupWidth = value;
  59130. return this._groupElement[0].style.width = value + 'px'
  59131. }
  59132. },
  59133. groupHeight: function(value) {
  59134. if (value === undefined)
  59135. return this._groupElement.height();
  59136. else if (value >= 0) {
  59137. this._groupHeight = value;
  59138. this._groupElement[0].style.height = value + 'px'
  59139. }
  59140. },
  59141. groupElement: function() {
  59142. return this._groupElement
  59143. },
  59144. tableElement: function() {
  59145. return this._tableElement
  59146. },
  59147. element: function() {
  59148. return this._rootElement
  59149. },
  59150. headElement: function() {
  59151. return this._tableElement.find('thead')
  59152. },
  59153. render: function(rootElement, data) {
  59154. var that = this,
  59155. tableElement = that._createTableElement();
  59156. if (utils.isDefined(that._tableElement)) {
  59157. try {
  59158. that._tableElement[0].innerHTML = ''
  59159. }
  59160. catch(e) {
  59161. that._tableElement.empty()
  59162. }
  59163. that._tableElement.attr('style', '');
  59164. that._colgroupElement = $('<colgroup>').appendTo(that._tableElement);
  59165. that._renderTableContent(that._tableElement, data)
  59166. }
  59167. else {
  59168. that._groupElement = that._createGroupElement();
  59169. that._tableElement = tableElement;
  59170. that._colgroupElement = $('<colgroup>').appendTo(that._tableElement);
  59171. that._renderTableContent(that._tableElement, data);
  59172. that._tableElement.appendTo(that._groupElement);
  59173. that._groupElement.appendTo(rootElement);
  59174. that._rootElement = rootElement
  59175. }
  59176. }
  59177. })
  59178. })(jQuery, DevExpress);
  59179. /*! Module widgets-web, file ui.pivotGrid.headersArea.js */
  59180. (function($, DX) {
  59181. var ui = DX.ui,
  59182. events = ui.events,
  59183. pivotGrid = ui.dxPivotGrid,
  59184. utils = DX.utils;
  59185. pivotGrid.HorizontalHeadersArea = pivotGrid.AreaItem.inherit({
  59186. _getAreaName: function() {
  59187. return "column"
  59188. },
  59189. _getAreaClassName: function() {
  59190. return pivotGrid.cssClassNames.headersHorizontal
  59191. },
  59192. _textCellRender: function(rootElement, value) {
  59193. var $span = $('<span>');
  59194. if (!value)
  59195. $span.html("&nbsp");
  59196. else
  59197. this.option("encodeHtml") ? $span.text(value) : $span.html(value);
  59198. $span.appendTo(rootElement)
  59199. },
  59200. _createGroupElement: function() {
  59201. return $('<div>').addClass(this._getAreaClassName()).addClass(pivotGrid.cssClassNames.area)
  59202. },
  59203. _createTableElement: function() {
  59204. return $('<table>')
  59205. },
  59206. _createRow: function() {
  59207. return $('<tr>')
  59208. },
  59209. _createCell: function(cell) {
  59210. var that = this,
  59211. cellElement = $('<td>').attr({
  59212. colspan: cell.colspan,
  59213. rowspan: cell.rowspan
  59214. });
  59215. if (utils.isDefined(cell.expanded)) {
  59216. cellElement.addClass(cell.expanded ? pivotGrid.cssClassNames.headersExpanded : pivotGrid.cssClassNames.headersCollapsed).on(events.addNamespace("dxclick", this._getEventsNamespace()), function(e) {
  59217. setTimeout(function() {
  59218. var area = that._getAreaName();
  59219. if (cell.expanded)
  59220. that._dataSource.collapseHeaderItem(area, cell.path);
  59221. else
  59222. that._dataSource.expandHeaderItem(area, cell.path)
  59223. })
  59224. });
  59225. $('<span>').addClass(pivotGrid.cssClassNames.headersExpandCollapseImage).appendTo(cellElement)
  59226. }
  59227. return cellElement
  59228. },
  59229. _applyCustomStyles: function(options) {
  59230. if (options.cellIndex === options.cellsCount - 1)
  59231. options.cellElement.css('border-right', '0px');
  59232. if (options.cell.rowspan === options.rowsCount - options.rowIndex || options.rowIndex + 1 === options.rowsCount)
  59233. options.cellElement.css('border-bottom-width', '0px');
  59234. options.cellElement.toggleClass(pivotGrid.cssClassNames.rowTotal, options.cell.type === 'T' || options.cell.type === 'GT').toggleClass(pivotGrid.cssClassNames.total, options.cell.type === 'T').toggleClass(pivotGrid.cssClassNames.grandTotal, options.cell.type === 'GT');
  59235. if (options.cell.width)
  59236. options.cellElement.css("min-width", options.cell.width);
  59237. if (options.cell.sorted)
  59238. $('<span>').addClass("dx-icon-sorted").appendTo(options.cellElement)
  59239. },
  59240. _renderTableContent: function(tableElement, data) {
  59241. var that = this,
  59242. rowsCount = data.length,
  59243. row,
  59244. cell,
  59245. i,
  59246. j,
  59247. rowElement,
  59248. cellElement,
  59249. theadElement = $('<thead>').addClass(this._getAreaClassName());
  59250. tableElement.width('auto');
  59251. for (i = 0; i < rowsCount; i++) {
  59252. row = data[i];
  59253. rowElement = that._createRow();
  59254. for (j = 0; j < row.length; j++) {
  59255. cell = row[j];
  59256. cellElement = that._createCell(cell);
  59257. that._textCellRender(cellElement, cell.text);
  59258. that._applyCustomStyles({
  59259. cellElement: cellElement,
  59260. cell: cell,
  59261. cellsCount: row.length,
  59262. cellIndex: j,
  59263. rowElement: rowElement,
  59264. rowIndex: i,
  59265. rowsCount: rowsCount
  59266. });
  59267. rowElement.append(cellElement)
  59268. }
  59269. theadElement.append(rowElement)
  59270. }
  59271. tableElement.append(theadElement);
  59272. that.callBase.apply(that, arguments)
  59273. },
  59274. _getEventsNamespace: function() {
  59275. return 'dxHeadersArea'
  59276. },
  59277. hasScroll: function() {
  59278. if (this._groupWidth && this._tableWidth)
  59279. return this._tableWidth > this._groupWidth;
  59280. return false
  59281. },
  59282. processScroll: function() {
  59283. if (!this._groupElement.data('dxScrollable')) {
  59284. this._groupElement.dxScrollable({
  59285. useNative: true,
  59286. useSimulatedScrollbar: false,
  59287. showScrollbar: false,
  59288. bounceEnabled: false,
  59289. direction: "horizontal"
  59290. });
  59291. this._groupElement.find('.dx-scrollable-container').css('overflow', 'hidden')
  59292. }
  59293. },
  59294. processScrollBarSpacing: function(scrollBarWidth) {
  59295. var that = this;
  59296. if (that._groupWidth)
  59297. that.groupWidth(that._groupWidth - scrollBarWidth);
  59298. if (that._scrollBarWidth)
  59299. that._groupElement.next().remove();
  59300. that._groupElement.toggleClass(pivotGrid.cssClassNames.verticalScroll, scrollBarWidth > 0);
  59301. that._groupElement.css('float', 'left').width(that._groupHeight);
  59302. that._scrollBarWidth = scrollBarWidth
  59303. },
  59304. processStretch: function(resultSizes, hasScroll, dataFields) {
  59305. var that = this,
  59306. tableSize = 0,
  59307. groupSize = that._groupWidth,
  59308. diff,
  59309. diffElement,
  59310. onePixelElementsCount,
  59311. fixedWidthCount = 0,
  59312. i;
  59313. for (i = 0; i < resultSizes.length; i++) {
  59314. if (dataFields.length && dataFields[i % dataFields.length].width) {
  59315. if (dataFields.length > 1)
  59316. fixedWidthCount++;
  59317. resultSizes[i] = dataFields[i % dataFields.length].width
  59318. }
  59319. tableSize += resultSizes[i]
  59320. }
  59321. that._testOriginalTableSize = tableSize;
  59322. if (groupSize && !hasScroll) {
  59323. diff = groupSize - tableSize;
  59324. diffElement = Math.floor(diff / (resultSizes.length - fixedWidthCount));
  59325. onePixelElementsCount = diff - diffElement * (resultSizes.length - fixedWidthCount);
  59326. for (i = 0; i < resultSizes.length; i++) {
  59327. if (dataFields.length > 1 && dataFields[i % dataFields.length].width)
  59328. continue;
  59329. resultSizes[i] += diffElement;
  59330. if (onePixelElementsCount) {
  59331. resultSizes[i]++;
  59332. onePixelElementsCount--
  59333. }
  59334. }
  59335. }
  59336. },
  59337. ctor: function(component) {
  59338. this.callBase(component);
  59339. this._scrollBarWidth = 0
  59340. },
  59341. setDataController: function(dataController) {
  59342. this._dataSource = dataController;
  59343. return this
  59344. }
  59345. });
  59346. pivotGrid.VerticalHeadersArea = pivotGrid.HorizontalHeadersArea.inherit({
  59347. _getAreaClassName: function() {
  59348. return pivotGrid.cssClassNames.headersVertical
  59349. },
  59350. _applyCustomStyles: function(options) {
  59351. var cellElement = options.cellElement;
  59352. this.callBase(options);
  59353. cellElement.addClass(options.cellIndex === options.cellsCount - 1 ? pivotGrid.cssClassNames.headersVerticalLastCell : null);
  59354. if (options.rowIndex === options.rowsCount - 1)
  59355. cellElement.css('border-bottom', '0px');
  59356. if (options.rowIndex !== 0 && options.cell.expanded)
  59357. options.rowElement.addClass(pivotGrid.cssClassNames.headersVerticalExpandBorder)
  59358. },
  59359. _getAreaName: function() {
  59360. return "row"
  59361. },
  59362. _getEventsNamespace: function() {
  59363. return 'dxVerticalHeadersArea'
  59364. },
  59365. hasScroll: function() {
  59366. if (this._groupHeight && this._tableHeight)
  59367. return this._tableHeight > this._groupHeight;
  59368. return false
  59369. },
  59370. processScroll: function() {
  59371. if (!this._groupElement.data('dxScrollable')) {
  59372. this._groupElement.dxScrollable({
  59373. useNative: true,
  59374. useSimulatedScrollbar: false,
  59375. showScrollbar: false,
  59376. bounceEnabled: false,
  59377. direction: "vertical"
  59378. });
  59379. this._groupElement.find('.dx-scrollable-container').css('overflow', 'hidden')
  59380. }
  59381. },
  59382. processScrollBarSpacing: function(scrollBarWidth) {
  59383. var that = this;
  59384. if (that._groupHeight)
  59385. that.groupHeight(that._groupHeight - scrollBarWidth);
  59386. if (that._scrollBarWidth)
  59387. that._groupElement.next().remove();
  59388. if (scrollBarWidth)
  59389. that._groupElement.after($('<div>').width('100%').height(scrollBarWidth - 1));
  59390. that._scrollBarWidth = scrollBarWidth
  59391. }
  59392. })
  59393. })(jQuery, DevExpress);
  59394. /*! Module widgets-web, file ui.pivotGrid.dataArea.js */
  59395. (function($, DX) {
  59396. var pivotGrid = DX.ui.dxPivotGrid;
  59397. pivotGrid.DataArea = pivotGrid.AreaItem.inherit({
  59398. _getAreaName: function() {
  59399. return "data"
  59400. },
  59401. _createGroupElement: function() {
  59402. return $('<div />').addClass(pivotGrid.cssClassNames.area).addClass(pivotGrid.cssClassNames.areaData)
  59403. },
  59404. _renderTableContent: function(tableElement, data) {
  59405. var i,
  59406. j,
  59407. row,
  59408. cell,
  59409. cellText,
  59410. tableContentHTML = '',
  59411. style,
  59412. classNames;
  59413. for (i = 0; i < data.length; i++) {
  59414. tableContentHTML += '<tr>';
  59415. row = data[i];
  59416. for (j = 0; j < row.length; j++) {
  59417. cell = row[j];
  59418. classNames = [];
  59419. style = '';
  59420. if (i === data.length - 1)
  59421. style = 'border-bottom: 0px';
  59422. if (cell) {
  59423. if (cell.rowType === 'T' || cell.columnType === 'T')
  59424. classNames.push(pivotGrid.cssClassNames.total);
  59425. if (cell.rowType === 'GT' || cell.columnType === 'GT')
  59426. classNames.push(pivotGrid.cssClassNames.grandTotal);
  59427. if (cell.rowType === 'T' || cell.rowType === 'GT')
  59428. classNames.push(pivotGrid.cssClassNames.rowTotal);
  59429. cellText = cell.text || '';
  59430. if (this.option("encodeHtml") && (cellText.indexOf("<") !== -1 || cellText.indexOf(">") !== -1))
  59431. cellText = $("<div>").text(cellText).html();
  59432. if (cell.width) {
  59433. if (style)
  59434. style += '; ';
  59435. style += 'min-width: ' + cell.width + 'px'
  59436. }
  59437. }
  59438. else
  59439. cellText = '';
  59440. tableContentHTML += '<td class="' + classNames.join(' ') + '" style="' + style + '">' + cellText + '</td>'
  59441. }
  59442. tableContentHTML += '</tr>'
  59443. }
  59444. tableElement.append(tableContentHTML);
  59445. this.callBase.apply(this, arguments)
  59446. },
  59447. _processScrollCore: function(hasRowsScroll, hasColumnsScroll, useNativeScrolling) {
  59448. var that = this,
  59449. groupElement = that._groupElement,
  59450. options = {
  59451. useNative: !!useNativeScrolling,
  59452. useSimulatedScrollbar: !useNativeScrolling,
  59453. direction: "both",
  59454. bounceEnabled: false
  59455. };
  59456. if (hasColumnsScroll && !hasRowsScroll)
  59457. options.direction = "horizontal";
  59458. else if (!hasColumnsScroll)
  59459. options.direction = "vertical";
  59460. groupElement.dxScrollable(options)
  59461. },
  59462. processScroll: function(scrollBarWidth, hasRowsScroll, hasColumnsScroll, useNativeScrolling) {
  59463. var that = this,
  59464. groupElement = that._groupElement;
  59465. that._rootElement.css({
  59466. position: 'relative',
  59467. display: 'block'
  59468. });
  59469. groupElement.css('border-top-width', 0);
  59470. that._processScrollCore(hasRowsScroll, hasColumnsScroll, useNativeScrolling)
  59471. }
  59472. })
  59473. })(jQuery, DevExpress);
  59474. /*! Module widgets-web, file ui.pivotGrid.fieldChooser.js */
  59475. (function($, DX) {
  59476. var ui = DX.ui,
  59477. utils = DX.utils,
  59478. pivotGrid = ui.dxPivotGrid,
  59479. dataGrid = ui.dxDataGrid,
  59480. DIV = "<div>";
  59481. var ColumnsView = dataGrid.ColumnsView.inherit(dataGrid.sortingMixin).inherit(dataGrid.headerFilterMixin);
  59482. var HeaderFilterView = dataGrid.HeaderFilterView;
  59483. var FIELDCHOOSER_CLASS = "dx-pivotgridfieldchooser",
  59484. FIELDCHOOSER_CONTAINER_CLASS = "dx-pivotgridfieldchooser-container";
  59485. var processItems = function(groupItems, field, filterValues, isTree, level, path) {
  59486. level = level || 0;
  59487. path = path || [];
  59488. var currentField = field.levels ? field.levels[level] : field,
  59489. i;
  59490. for (i = 0; i < groupItems.length; i++) {
  59491. groupItems[i].text = groupItems[i].text || DX.formatHelper.format(groupItems[i].value, currentField.format, currentField.precision);
  59492. path.push(groupItems[i].value);
  59493. groupItems[i].filterValue = isTree ? path.slice(0) : groupItems[i].value;
  59494. if ($.inArray(isTree ? path.join("/") : groupItems[i].value, filterValues) > -1 ^ field.filterType === "exclude")
  59495. groupItems[i].selected = true;
  59496. if (groupItems[i].children) {
  59497. groupItems[i].items = groupItems[i].children;
  59498. groupItems[i].children = null;
  59499. processItems(groupItems[i].items, field, filterValues, isTree, level + 1, path)
  59500. }
  59501. path.pop()
  59502. }
  59503. };
  59504. var compareOrder = [function(a, b) {
  59505. var aValue = -!!a.isMeasure,
  59506. bValue = +!!b.isMeasure;
  59507. return aValue + bValue
  59508. }, function(a, b) {
  59509. var aValue = -!!(a.items && a.items.length),
  59510. bValue = +!!(b.items && b.items.length);
  59511. return aValue + bValue
  59512. }, function(a, b) {
  59513. var aValue = +!!(a.field && a.field.levels && a.field.levels.length),
  59514. bValue = -!!(b.field && b.field.levels && b.field.levels.length);
  59515. return aValue + bValue
  59516. }, pivotGrid.getCompareFunction(function(item) {
  59517. return item.text
  59518. })];
  59519. function compareItems(a, b) {
  59520. var result = 0,
  59521. i = 0;
  59522. while (!result && compareOrder[i])
  59523. result = compareOrder[i++](a, b);
  59524. return result
  59525. }
  59526. function getScrollable(container) {
  59527. return container.find(".dx-scrollable").dxScrollable("instance")
  59528. }
  59529. DX.registerComponent("dxPivotGridFieldChooser", ui, ui.Widget.inherit({
  59530. _setDefaultOptions: function() {
  59531. this.callBase();
  59532. this.option({
  59533. height: 400,
  59534. layout: 0,
  59535. dataSource: null,
  59536. texts: {
  59537. columnFields: Globalize.localize("dxPivotGrid-columnFields"),
  59538. rowFields: Globalize.localize("dxPivotGrid-rowFields"),
  59539. dataFields: Globalize.localize("dxPivotGrid-dataFields"),
  59540. filterFields: Globalize.localize("dxPivotGrid-filterFields"),
  59541. allFields: Globalize.localize("dxPivotGrid-allFields")
  59542. },
  59543. headerFilter: {
  59544. width: 252,
  59545. height: 300,
  59546. texts: {
  59547. emptyValue: Globalize.localize("dxDataGrid-headerFilterEmptyValue"),
  59548. ok: Globalize.localize("dxDataGrid-headerFilterOK"),
  59549. cancel: Globalize.localize("dxDataGrid-headerFilterCancel")
  59550. }
  59551. }
  59552. })
  59553. },
  59554. _refreshDataSource: function() {
  59555. var that = this;
  59556. that._expandedPaths = [];
  59557. that._changedHandler = that._changedHandler || function() {
  59558. $.each(that._dataChangedHandlers, function(_, func) {
  59559. func()
  59560. });
  59561. that._updateIndicatorsPosition()
  59562. };
  59563. if (that._dataSource) {
  59564. that._dataSource.off("changed", that._changedHandler);
  59565. that._dataSource = undefined
  59566. }
  59567. var dataSource = this.option("dataSource");
  59568. if (dataSource && dataSource.fields && dataSource.load)
  59569. that._dataSource = dataSource;
  59570. that._dataSource && that._dataSource.on("changed", that._changedHandler)
  59571. },
  59572. _init: function() {
  59573. this.callBase();
  59574. this._columnsView = new ColumnsView(this);
  59575. this._headerFilterView = new HeaderFilterView(this);
  59576. this._subscribeToEvents();
  59577. this._refreshDataSource();
  59578. this._dataChangedHandlers = []
  59579. },
  59580. _subscribeToEvents: function() {
  59581. var that = this;
  59582. that.element().on("dxclick", ".dx-area-field.dx-area-box", function(e) {
  59583. var field = $.extend(true, {}, $(e.currentTarget).data("field")),
  59584. isHeaderFilter = $(e.target).hasClass("dx-header-filter");
  59585. if (isHeaderFilter)
  59586. that._headerFilterView.showHeaderFilterMenu($(e.currentTarget), {
  59587. type: field.groupName ? 'tree' : 'list',
  59588. dataSource: {
  59589. load: function(options) {
  59590. var userData = options.userData;
  59591. if (userData.store)
  59592. return userData.store.load(options);
  59593. else {
  59594. var d = $.Deferred();
  59595. that._dataSource.getFieldValues(field.index).done(function(data) {
  59596. userData.store = new DX.data.ArrayStore(data);
  59597. userData.store.load(options).done(d.resolve).fail(d.reject)
  59598. }).fail(d.reject);
  59599. return d
  59600. }
  59601. },
  59602. postProcess: function(data) {
  59603. var filterValues = [];
  59604. if (field.filterValues)
  59605. $.each(field.filterValues, function(index, filterValue) {
  59606. filterValues.push(utils.isArray(filterValue) ? filterValue.join("/") : filterValue)
  59607. });
  59608. processItems(data, field, filterValues, !!field.groupName);
  59609. return data
  59610. }
  59611. },
  59612. filterValues: field.filterValues,
  59613. filterType: field.filterType,
  59614. apply: function() {
  59615. that._dataSource.field(field.index, {
  59616. filterValues: this.filterValues,
  59617. filterType: this.filterType
  59618. });
  59619. that._dataSource.load()
  59620. }
  59621. });
  59622. else if (field.allowSorting && field.area !== "data") {
  59623. that._dataSource.field(field.index, {sortOrder: field.sortOrder === "desc" ? "asc" : "desc"});
  59624. that._dataSource.load()
  59625. }
  59626. })
  59627. },
  59628. _setOptionsByReference: function() {
  59629. this.callBase();
  59630. $.extend(this._optionsByReference, {dataSource: true})
  59631. },
  59632. _optionChanged: function(args) {
  59633. var that = this;
  59634. switch (args.name) {
  59635. case"dataSource":
  59636. that._refreshDataSource();
  59637. that._invalidate();
  59638. break;
  59639. case"layout":
  59640. case"texts":
  59641. case"headerFilter":
  59642. that._invalidate();
  59643. break;
  59644. default:
  59645. that.callBase(args)
  59646. }
  59647. },
  59648. _clean: function() {
  59649. this.element().children("." + FIELDCHOOSER_CONTAINER_CLASS).remove()
  59650. },
  59651. _renderContentImpl: function() {
  59652. var that = this,
  59653. element = this.element(),
  59654. $col1,
  59655. $col2;
  59656. element.addClass(FIELDCHOOSER_CLASS);
  59657. that._dataChangedHandlers = [];
  59658. that._renderSortable(element);
  59659. that._headerFilterView.render(element);
  59660. var $container = $(DIV).addClass(FIELDCHOOSER_CONTAINER_CLASS).appendTo(element);
  59661. if (this.option("layout") === 0) {
  59662. $col1 = $(DIV).addClass("dx-col").appendTo($container);
  59663. $col2 = $(DIV).addClass("dx-col").appendTo($container);
  59664. this._renderArea($col1, "all");
  59665. this._renderArea($col1, "filter");
  59666. this._renderArea($col2, "row");
  59667. this._renderArea($col2, "column");
  59668. this._renderArea($col2, "data")
  59669. }
  59670. else if (this.option("layout") === 1) {
  59671. $col1 = $(DIV).addClass("dx-col").appendTo($container);
  59672. $col2 = $(DIV).addClass("dx-col").appendTo($container);
  59673. this._renderArea($col1, "all");
  59674. this._renderArea($col2, "filter");
  59675. this._renderArea($col2, "row");
  59676. this._renderArea($col2, "column");
  59677. this._renderArea($col2, "data")
  59678. }
  59679. else {
  59680. this._renderArea($container, "all");
  59681. $col1 = $(DIV).addClass("dx-col").appendTo($container);
  59682. $col2 = $(DIV).addClass("dx-col").appendTo($container);
  59683. this._renderArea($col1, "filter");
  59684. this._renderArea($col1, "row");
  59685. this._renderArea($col2, "column");
  59686. this._renderArea($col2, "data")
  59687. }
  59688. this.updateDimensions()
  59689. },
  59690. _renderSortable: function(element) {
  59691. var that = this;
  59692. that._createComponent(element, "dxSortable", {
  59693. itemSelector: ".dx-area-field",
  59694. itemContainerSelector: ".dx-area-field-container",
  59695. groupSelector: ".dx-area-fields",
  59696. itemRender: function($sourceItem, target) {
  59697. var $item;
  59698. if ($sourceItem.hasClass("dx-area-box"))
  59699. $item = $sourceItem.clone();
  59700. else
  59701. $item = $(DIV).addClass("dx-area-field").addClass("dx-area-box").text($sourceItem.text());
  59702. if (target === "drag")
  59703. $item.width(element.find(".dx-area-field-container").first().width());
  59704. return $item
  59705. },
  59706. onDragging: function(e) {
  59707. var field = e.sourceElement.data("field"),
  59708. targetGroup = e.targetGroup;
  59709. e.cancel = false;
  59710. if (field.isMeasure === true) {
  59711. if (targetGroup === "column" || targetGroup === "row" || targetGroup === "filter")
  59712. e.cancel = true
  59713. }
  59714. else if (field.isMeasure === false && targetGroup === "data")
  59715. e.cancel = true
  59716. },
  59717. onChanged: function(e) {
  59718. var dataSource = that._dataSource,
  59719. field = e.sourceElement.data("field");
  59720. e.removeSourceElement = !!e.sourceGroup;
  59721. if (field) {
  59722. dataSource.field(field.index, {
  59723. area: e.targetGroup,
  59724. areaIndex: e.targetIndex
  59725. });
  59726. dataSource.load()
  59727. }
  59728. }
  59729. })
  59730. },
  59731. _createTreeItems: function(fields, groupFieldNames, path) {
  59732. var that = this,
  59733. isMeasure,
  59734. resultItems = [],
  59735. groupedItems = [],
  59736. groupFieldName = groupFieldNames[0],
  59737. fieldsByGroup = {};
  59738. if (!groupFieldName)
  59739. $.each(fields, function(index, field) {
  59740. var icon;
  59741. if (field.isMeasure === true)
  59742. icon = "measure";
  59743. if (field.isMeasure === false)
  59744. icon = field.groupName ? "hierarchy" : "dimension";
  59745. resultItems.push({
  59746. index: field.index,
  59747. field: field,
  59748. key: field.dataField,
  59749. selected: utils.isDefined(field.area),
  59750. text: field.caption || field.dataField,
  59751. icon: icon,
  59752. isMeasure: field.isMeasure
  59753. })
  59754. });
  59755. else {
  59756. $.each(fields, function(index, field) {
  59757. var groupName = field[groupFieldName] || "";
  59758. fieldsByGroup[groupName] = fieldsByGroup[groupName] || [];
  59759. fieldsByGroup[groupName].push(field);
  59760. if (isMeasure === undefined)
  59761. isMeasure = true;
  59762. isMeasure = isMeasure && field.isMeasure === true
  59763. });
  59764. $.each(fieldsByGroup, function(groupName, fields) {
  59765. var currentPath = path ? path + '.' + groupName : groupName;
  59766. var items = that._createTreeItems(fields, groupFieldNames.slice(1), currentPath);
  59767. if (groupName)
  59768. groupedItems.push({
  59769. key: groupName,
  59770. text: groupName,
  59771. path: currentPath,
  59772. isMeasure: items.isMeasure,
  59773. expanded: $.inArray(currentPath, that._expandedPaths) >= 0,
  59774. items: items
  59775. });
  59776. else
  59777. resultItems = items
  59778. });
  59779. resultItems = groupedItems.concat(resultItems);
  59780. resultItems.isMeasure = isMeasure
  59781. }
  59782. return resultItems
  59783. },
  59784. _createFieldsDataSource: function(dataSource) {
  59785. var fields = dataSource && dataSource.fields() || [],
  59786. treeItems;
  59787. fields = $.map(fields, function(field) {
  59788. return field.visible === false || utils.isDefined(field.groupIndex) ? null : field
  59789. });
  59790. treeItems = this._createTreeItems(fields, ["dimension", "displayFolder"]);
  59791. pivotGrid.foreachDataLevel(treeItems, function(items) {
  59792. items.sort(compareItems)
  59793. }, 0, "items");
  59794. return treeItems
  59795. },
  59796. _renderFieldsTreeView: function(container) {
  59797. var that = this,
  59798. dataSource = that._dataSource,
  59799. treeView = that._createComponent(container, "dxTreeView", {
  59800. dataSource: that._createFieldsDataSource(dataSource),
  59801. showCheckBoxes: true,
  59802. itemTemplate: function(itemData, itemIndex, itemElement) {
  59803. if (itemData.icon)
  59804. utils.getImageContainer(itemData.icon).appendTo(itemElement);
  59805. $('<span>').toggleClass("dx-area-field", !itemData.items).data("field", itemData.field).text(itemData.text).appendTo(itemElement)
  59806. },
  59807. onItemCollapsed: function(e) {
  59808. var index = $.inArray(e.itemData.path, that._expandedPaths);
  59809. if (index >= 0)
  59810. that._expandedPaths.splice(index, 1)
  59811. },
  59812. onItemExpanded: function(e) {
  59813. var index = $.inArray(e.itemData.path, that._expandedPaths);
  59814. if (index < 0)
  59815. that._expandedPaths.push(e.itemData.path)
  59816. },
  59817. onItemSelected: function(e) {
  59818. var data = e.itemData,
  59819. field,
  59820. area;
  59821. if (data.items)
  59822. dataChanged();
  59823. else {
  59824. if (data.selected)
  59825. field = dataSource.fields()[data.index],
  59826. area = field && field.isMeasure ? "data" : "column";
  59827. dataSource.field(data.index, {
  59828. area: area,
  59829. areaIndex: undefined
  59830. });
  59831. dataSource.load()
  59832. }
  59833. }
  59834. }),
  59835. dataChanged = function() {
  59836. var scrollable = getScrollable(container),
  59837. scrollTop = scrollable ? scrollable.scrollTop() : 0;
  59838. treeView.option({dataSource: that._createFieldsDataSource(dataSource)});
  59839. scrollable = getScrollable(container);
  59840. if (scrollable) {
  59841. scrollable.scrollTo({y: scrollTop});
  59842. scrollable.update()
  59843. }
  59844. };
  59845. that._dataChangedHandlers.push(dataChanged)
  59846. },
  59847. _renderField: function(field) {
  59848. var that = this,
  59849. $fieldContent = $(DIV).addClass("dx-area-field-content").text(field.caption || field.dataField),
  59850. $fieldElement = $(DIV).addClass("dx-area-field").addClass("dx-area-box").data("field", field).append($fieldContent);
  59851. if (field.area !== "data") {
  59852. if (field.allowSorting)
  59853. that._columnsView._applyColumnState({
  59854. name: 'sort',
  59855. rootElement: $fieldElement,
  59856. column: {
  59857. alignment: that.option("rtlEnabled") ? 'right' : 'left',
  59858. sortOrder: field.sortOrder === 'desc' ? 'desc' : 'asc'
  59859. },
  59860. showColumnLines: true
  59861. });
  59862. if (field.allowFiltering)
  59863. that._columnsView._applyColumnState({
  59864. name: 'headerFilter',
  59865. rootElement: $fieldElement,
  59866. column: {
  59867. alignment: that.option("rtlEnabled") ? 'right' : 'left',
  59868. filterValues: field.filterValues
  59869. },
  59870. showColumnLines: true
  59871. })
  59872. }
  59873. return $fieldElement
  59874. },
  59875. _renderAreaFields: function($container, area) {
  59876. var that = this,
  59877. dataSource = that._dataSource,
  59878. fields = dataSource ? dataSource.getAreaFields(area, true) : [];
  59879. $container.empty();
  59880. $.each(fields, function() {
  59881. that._renderField(this).appendTo($container)
  59882. })
  59883. },
  59884. _renderArea: function(container, area, height) {
  59885. var that = this,
  59886. $areaContainer = $(DIV).addClass("dx-area").appendTo(container),
  59887. caption = that.option("texts." + area + "Fields"),
  59888. $fieldsContainer,
  59889. $fieldsContent,
  59890. render;
  59891. $("<span>").addClass("dx-area-icon").addClass("dx-area-icon-" + area).appendTo($areaContainer);
  59892. $("<span>").html("&nbsp;").appendTo($areaContainer);
  59893. $("<span>").addClass("dx-area-caption").text(caption).appendTo($areaContainer);
  59894. $fieldsContainer = $(DIV).addClass("dx-area-fields").height(0).appendTo($areaContainer);
  59895. if (area !== "all") {
  59896. $fieldsContent = $(DIV).addClass("dx-area-field-container").appendTo($fieldsContainer);
  59897. render = function() {
  59898. that._renderAreaFields($fieldsContent, area)
  59899. };
  59900. that._dataChangedHandlers.push(render);
  59901. render();
  59902. $fieldsContainer.attr("group", area).dxScrollable()
  59903. }
  59904. else {
  59905. $fieldsContainer.addClass("dx-treeview-border-visible");
  59906. that._renderFieldsTreeView($fieldsContainer)
  59907. }
  59908. },
  59909. _updateIndicatorsPosition: function() {
  59910. var columnsView = this._columnsView;
  59911. $.each(this.element().find(".dx-area-field.dx-area-box"), function() {
  59912. columnsView._updateIndicatorHeight($(this), "sort");
  59913. columnsView._updateIndicatorHeight($(this), "headerFilter")
  59914. })
  59915. },
  59916. updateDimensions: function() {
  59917. var that = this,
  59918. $element = this.element(),
  59919. $container = $element.children(".dx-pivotgridfieldchooser-container"),
  59920. $cols = $element.find(".dx-col"),
  59921. $areaElements = $element.find(".dx-area-fields"),
  59922. $scrollableElements = $element.find(".dx-area .dx-scrollable"),
  59923. areaHeight;
  59924. that._updateIndicatorsPosition();
  59925. $areaElements.height(0);
  59926. if (this.option("layout") === 0) {
  59927. areaHeight = Math.floor(($element.height() - $container.height()) / 3);
  59928. $areaElements.height(areaHeight);
  59929. $areaElements.eq(0).height($cols.eq(1).height() - $cols.eq(0).height() + areaHeight)
  59930. }
  59931. else if (this.option("layout") === 1) {
  59932. areaHeight = Math.floor(($element.height() - $container.height()) / 4);
  59933. $areaElements.height(areaHeight);
  59934. $areaElements.eq(0).height($cols.eq(1).height() - $cols.eq(0).height() + areaHeight)
  59935. }
  59936. else {
  59937. areaHeight = Math.floor(($element.height() - $container.height()) / 4);
  59938. $areaElements.height(areaHeight);
  59939. $areaElements.eq(0).height(areaHeight * 2)
  59940. }
  59941. $scrollableElements.dxScrollable("update")
  59942. }
  59943. }))
  59944. })(jQuery, DevExpress);
  59945. /*! Module widgets-web, file ui.scheduler.js */
  59946. (function($, DX, undefined) {
  59947. var ui = DX.ui,
  59948. utils = DX.utils;
  59949. var WIDGET_CLASS = "dx-scheduler",
  59950. WIDGET_READONLY_CLASS = "dx-scheduler-readonly",
  59951. APPOINTMENT_POPUP_CLASS = "dx-sheduler-appointment-popup",
  59952. APPOINTMENT_TOOLTIP_CLASS = "dx-scheduler-appointment-tooltip",
  59953. APPOINTMENT_TOOLTIP_TITLE_CLASS = "dx-scheduler-appointment-tooltip-title",
  59954. APPOINTMENT_TOOLTIP_DATE_CLASS = "dx-scheduler-appointment-tooltip-date",
  59955. APPOINTMENT_TOOLTIP_BUTTONS_CLASS = "dx-scheduler-appointment-tooltip-buttons",
  59956. APPOINTEMENT_POPUP_WIDTH = 610;
  59957. var WORKSPACES = {
  59958. day: "dxSchedulerWorkSpaceDay",
  59959. week: "dxSchedulerWorkSpaceWeek",
  59960. workWeek: "dxSchedulerWorkSpaceWorkWeek",
  59961. month: "dxSchedulerWorkSpaceMonth"
  59962. };
  59963. DX.registerComponent("dxScheduler", ui, ui.Widget.inherit({
  59964. _stripDateTime: function(date) {
  59965. utils.correctDateWithUnitBeginning(date, "day");
  59966. return date
  59967. },
  59968. _setDefaultOptions: function() {
  59969. this.callBase();
  59970. this.option({
  59971. views: ["day", "week"],
  59972. currentView: "day",
  59973. currentDate: this._stripDateTime(new Date),
  59974. firstDayOfWeek: undefined,
  59975. groups: [],
  59976. resources: [],
  59977. dataSource: null,
  59978. appointmentTemplate: "item",
  59979. startDayHour: 0,
  59980. endDayHour: 24,
  59981. editing: true,
  59982. onAppointmentRendered: null,
  59983. onAppointmentAdding: null,
  59984. onAppointmentAdded: null,
  59985. onAppointmentUpdating: null,
  59986. onAppointmentUpdated: null,
  59987. onAppointmentDeleting: null,
  59988. onAppointmentDeleted: null
  59989. })
  59990. },
  59991. _defaultOptionsRules: function() {
  59992. return this.callBase().concat([{
  59993. device: function(device) {
  59994. return DX.devices.real().generic && !DX.devices.isSimulator()
  59995. },
  59996. options: {focusStateEnabled: true}
  59997. }])
  59998. },
  59999. _optionChanged: function(args) {
  60000. var value = args.value;
  60001. switch (args.name) {
  60002. case"firstDayOfWeek":
  60003. this._workSpace.option("firstDayOfWeek", value);
  60004. this._header.option("firstDayOfWeek", value);
  60005. break;
  60006. case"currentDate":
  60007. value = utils.makeDate(value);
  60008. value = this._stripDateTime(value);
  60009. this._appointments.element().empty();
  60010. this._workSpace.option("currentDate", value);
  60011. this._header.option("currentDate", value);
  60012. this._filterAppointmentsByDate();
  60013. break;
  60014. case"dataSource":
  60015. this._refreshDataSource();
  60016. this._appointmentModel.setDataSource(this._dataSource);
  60017. this._filterAppointmentsByDateAndResources();
  60018. this._appointments.option("dataSource", this._dataSource);
  60019. break;
  60020. case"views":
  60021. this._header.option("views", value);
  60022. break;
  60023. case"currentView":
  60024. this._header.option("currentView", value);
  60025. this._refreshWorkSpace();
  60026. this._appointments.option("renderingStrategy", value);
  60027. this._filterAppointmentsByDateAndResources();
  60028. break;
  60029. case"appointmentTemplate":
  60030. this._appointments.option("itemTemplate", value);
  60031. break;
  60032. case"groups":
  60033. var dateRange = this._workSpace.getDateRange();
  60034. this._resourcesManager.getResourcesValueByFields(value).done($.proxy(function(groups) {
  60035. var resources = this._prepareResourcesForFilter(groups);
  60036. this._workSpace.option("groups", groups);
  60037. this._appointmentModel.filterByDateAndResources({
  60038. min: dateRange[0],
  60039. max: dateRange[1],
  60040. resources: resources,
  60041. startDayHour: this.option("startDayHour"),
  60042. endDayHour: this.option("endDayHour")
  60043. })
  60044. }, this));
  60045. break;
  60046. case"resources":
  60047. this._resourcesManager.setResources(value);
  60048. this._filterAppointmentsByResources();
  60049. break;
  60050. case"startDayHour":
  60051. this._filterAppointmentsByDate();
  60052. this._workSpace.option("startDayHour", value);
  60053. break;
  60054. case"endDayHour":
  60055. this._filterAppointmentsByDate();
  60056. this._workSpace.option("endDayHour", value);
  60057. break;
  60058. case"onAppointmentAdding":
  60059. case"onAppointmentAdded":
  60060. case"onAppointmentUpdating":
  60061. case"onAppointmentUpdated":
  60062. case"onAppointmentDeleting":
  60063. case"onAppointmentDeleted":
  60064. this._actions[args.name] = this._createActionByOption(args.name);
  60065. break;
  60066. case"onAppointmentRendered":
  60067. this._appointments.option("onItemRendered", value);
  60068. break;
  60069. case"tabIndex":
  60070. case"focusStateEnabled":
  60071. this._header.option(args.name, value);
  60072. this._workSpace.option(args.name, value);
  60073. this._appointments.option(args.name, value);
  60074. this.callBase(args);
  60075. break;
  60076. case"width":
  60077. this._header.option("width", value);
  60078. this.callBase(args);
  60079. break;
  60080. case"editing":
  60081. this.element().toggleClass(WIDGET_READONLY_CLASS, !value);
  60082. this._appointments.option({
  60083. allowDrag: value,
  60084. allowResize: value
  60085. });
  60086. this._refreshPopup();
  60087. this._hideTooltip();
  60088. break;
  60089. default:
  60090. this.callBase(args)
  60091. }
  60092. },
  60093. _filterAppointmentsByDate: function() {
  60094. var dateRange = this._workSpace.getDateRange();
  60095. this._appointmentModel.filterByDate(dateRange[0], dateRange[1], this.option("startDayHour"), this.option("endDayHour"))
  60096. },
  60097. _filterAppointmentsByResources: function() {
  60098. if (!this.option("resources") || !this.option("resources").length)
  60099. return;
  60100. var that = this;
  60101. this._resourcesManager.getResourcesValueByFields(this.option("groups")).done(function(data) {
  60102. that._appointmentModel.filterByResources(that._prepareResourcesForFilter(data))
  60103. })
  60104. },
  60105. _filterAppointmentsByDateAndResources: function() {
  60106. var dateRange = this._workSpace.getDateRange(),
  60107. that = this;
  60108. this._resourcesManager.getResourcesValueByFields(this.option("groups")).done(function(data) {
  60109. var resources = that._prepareResourcesForFilter(data);
  60110. that._appointmentModel.filterByDateAndResources({
  60111. min: dateRange[0],
  60112. max: dateRange[1],
  60113. resources: resources,
  60114. startDayHour: that.option("startDayHour"),
  60115. endDayHour: that.option("endDayHour")
  60116. })
  60117. })
  60118. },
  60119. _prepareResourcesForFilter: function(resources) {
  60120. return $.map(resources, function(resource) {
  60121. var data = [];
  60122. for (var i = 0, len = resource.items.length; i < len; i++)
  60123. data.push(resource.items[i].id);
  60124. return {
  60125. field: resource.name,
  60126. data: data
  60127. }
  60128. })
  60129. },
  60130. _dimensionChanged: function() {
  60131. this._appointments.repaint()
  60132. },
  60133. _visibilityChanged: function(visible) {
  60134. if (visible)
  60135. this._dimensionChanged()
  60136. },
  60137. _init: function() {
  60138. this.callBase();
  60139. this._initDataSource();
  60140. this.element().addClass(WIDGET_CLASS);
  60141. this.element().toggleClass(WIDGET_READONLY_CLASS, !this.option("editing"));
  60142. this._appointmentModel = new ui.dxScheduler.dxSchedulerAppointmentModel(this._dataSource);
  60143. this._resourcesManager = new ui.dxScheduler.dxSchedulerResourceManager(this.option("resources"));
  60144. this._initActions()
  60145. },
  60146. _initActions: function() {
  60147. this._actions = {
  60148. onAppointmentAdding: this._createActionByOption("onAppointmentAdding"),
  60149. onAppointmentAdded: this._createActionByOption("onAppointmentAdded"),
  60150. onAppointmentUpdating: this._createActionByOption("onAppointmentUpdating"),
  60151. onAppointmentUpdated: this._createActionByOption("onAppointmentUpdated"),
  60152. onAppointmentDeleting: this._createActionByOption("onAppointmentDeleting"),
  60153. onAppointmentDeleted: this._createActionByOption("onAppointmentDeleted")
  60154. }
  60155. },
  60156. _initAppointmentRenderedAction: function() {
  60157. return this._createActionByOption("onAppointmentRendered", {excludeValidators: ["designMode", "disabled", "readOnly"]})
  60158. },
  60159. _defaultAppointmentViewEditors: function() {
  60160. var that = this;
  60161. return [{
  60162. key: "text",
  60163. type: "dxTextBox",
  60164. label: "dxScheduler-editorLabelTitle",
  60165. cssClass: APPOINTMENT_POPUP_CLASS + "-caption"
  60166. }, {
  60167. key: "allDay",
  60168. type: "dxSwitch",
  60169. label: "dxScheduler-allDay",
  60170. cssClass: APPOINTMENT_POPUP_CLASS + "-allday",
  60171. options: {onValueChanged: function(args) {
  60172. var value = args.value,
  60173. startDateEditor = that._appointmentView.getEditorInstance("startDate"),
  60174. endDateEditor = that._appointmentView.getEditorInstance("endDate"),
  60175. startDate;
  60176. if (startDateEditor && endDateEditor) {
  60177. startDateEditor.option("format", value ? "date" : "datetime");
  60178. endDateEditor.option("format", value ? "date" : "datetime");
  60179. startDate = new Date(startDateEditor.option("value"));
  60180. if (value) {
  60181. startDate.setHours(0);
  60182. startDate.setMinutes(0);
  60183. startDateEditor.option("value", startDate);
  60184. var endDate = new Date(startDate);
  60185. endDate.setDate(startDate.getDate() + 1);
  60186. endDateEditor.option("value", endDate)
  60187. }
  60188. else if (startDateEditor.option("value")) {
  60189. startDate.setHours(that.option("startDayHour"));
  60190. startDateEditor.option("value", startDate);
  60191. endDateEditor.option("value", that._workSpace._calculateEndDate(startDateEditor.option("value")))
  60192. }
  60193. }
  60194. }}
  60195. }, {
  60196. key: "startDate",
  60197. type: "dxDateBox",
  60198. label: "dxScheduler-editorLabelStartDate",
  60199. cssClass: APPOINTMENT_POPUP_CLASS + "-start-date",
  60200. options: {
  60201. format: "datetime",
  60202. onValueChanged: function(args) {
  60203. var value = args.value,
  60204. previousValue = args.previousValue,
  60205. endDateEditor = that._appointmentView.getEditorInstance("endDate"),
  60206. endValue = endDateEditor.option("value");
  60207. if (endValue <= value) {
  60208. var duration = endValue.getTime() - previousValue.getTime();
  60209. endDateEditor.option("value", new Date(value.getTime() + duration))
  60210. }
  60211. }
  60212. }
  60213. }, {
  60214. key: "endDate",
  60215. type: "dxDateBox",
  60216. label: "dxScheduler-editorLabelEndDate",
  60217. cssClass: APPOINTMENT_POPUP_CLASS + "-end-date",
  60218. options: {
  60219. format: "datetime",
  60220. onValueChanged: function(args) {
  60221. var value = args.value,
  60222. previousValue = args.previousValue,
  60223. startDateEditor = that._appointmentView.getEditorInstance("startDate"),
  60224. startValue = startDateEditor.option("value");
  60225. if (startValue >= value) {
  60226. var duration = previousValue.getTime() - startValue.getTime();
  60227. startDateEditor.option("value", new Date(value.getTime() - duration))
  60228. }
  60229. }
  60230. }
  60231. }, {
  60232. key: "description",
  60233. type: "dxTextArea",
  60234. label: "dxScheduler-editorLabelDescription",
  60235. cssClass: APPOINTMENT_POPUP_CLASS + "-description"
  60236. }, {
  60237. key: "recurrenceRule",
  60238. type: "dxSchedulerRecurrenceEditor",
  60239. label: "dxScheduler-editorLabelRecurrence",
  60240. cssClass: APPOINTMENT_POPUP_CLASS + "-recurrence"
  60241. }]
  60242. },
  60243. _renderFocusTarget: $.noop,
  60244. _render: function() {
  60245. this.callBase();
  60246. this._renderHeader();
  60247. this._appointments = this._createComponent("<div>", "dxSchedulerAppointments", this._appointmentsConfig());
  60248. this._resourcesManager.getResourcesValueByFields(this.option("groups")).done($.proxy(function(groups) {
  60249. this._renderWorkSpace(groups);
  60250. var allDayContainerClass = this._workSpace.getAllDayContainerClass();
  60251. this._appointments.option({allDayContainer: this.element().find("." + allDayContainerClass)});
  60252. this._filterAppointmentsByDateAndResources();
  60253. this._appointments.option("dataSource", this._dataSource)
  60254. }, this))
  60255. },
  60256. _renderHeader: function() {
  60257. this._header = this._createComponent("<div>", "dxSchedulerHeader", this._headerConfig());
  60258. this.element().append(this._header.element())
  60259. },
  60260. _headerConfig: function() {
  60261. return {
  60262. observer: this,
  60263. views: this.option("views"),
  60264. firstDayOfWeek: this.option("firstDayOfWeek"),
  60265. currentView: this.option("currentView"),
  60266. currentDate: this._stripDateTime(utils.makeDate(this.option("currentDate"))),
  60267. tabIndex: this.option("tabIndex"),
  60268. focusStateEnabled: this.option("focusStateEnabled"),
  60269. width: this.option("width")
  60270. }
  60271. },
  60272. _appointmentsConfig: function() {
  60273. return {
  60274. observer: this,
  60275. renderingStrategy: this.option("currentView"),
  60276. itemTemplate: this._getTemplateByOption("appointmentTemplate"),
  60277. onItemRendered: this.option("onAppointmentRendered"),
  60278. tabIndex: this.option("tabIndex"),
  60279. focusStateEnabled: this.option("focusStateEnabled"),
  60280. allowDrag: this.option("editing"),
  60281. allowResize: this.option("editing")
  60282. }
  60283. },
  60284. _renderWorkSpace: function(groups) {
  60285. this._workSpace = this._createComponent("<div>", WORKSPACES[this.option("currentView")], this._workSpaceConfig(groups));
  60286. this._workSpace.getWorkArea().append(this._appointments.element());
  60287. this.element().append(this._workSpace.element())
  60288. },
  60289. _workSpaceConfig: function(groups) {
  60290. return {
  60291. observer: this,
  60292. currentDate: this._stripDateTime(utils.makeDate(this.option("currentDate"))),
  60293. firstDayOfWeek: this.option("firstDayOfWeek"),
  60294. groups: groups,
  60295. startDayHour: this.option("startDayHour"),
  60296. endDayHour: this.option("endDayHour"),
  60297. tabIndex: this.option("tabIndex"),
  60298. focusStateEnabled: this.option("focusStateEnabled")
  60299. }
  60300. },
  60301. _refreshWorkSpace: function() {
  60302. var allDayContainerClass = this._workSpace.getAllDayContainerClass();
  60303. this._appointments.element().detach();
  60304. this._workSpace._dispose();
  60305. this._workSpace.element().remove();
  60306. delete this._workSpace;
  60307. this._resourcesManager.getResourcesValueByFields(this.option("groups")).done($.proxy(function(groups) {
  60308. this._renderWorkSpace(groups);
  60309. this._appointments.option({allDayContainer: this.element().find("." + allDayContainerClass)})
  60310. }, this))
  60311. },
  60312. _createPopup: function() {
  60313. if (this._$popup)
  60314. return;
  60315. this._refreshPopup()
  60316. },
  60317. _refreshPopup: function() {
  60318. this._$popup = $("<div>").addClass(APPOINTMENT_POPUP_CLASS).appendTo(this.element());
  60319. this._popup = this._createComponent(this._$popup, "dxPopup", this._popupConfig());
  60320. var $popupContent = this._popup.content();
  60321. $popupContent.empty();
  60322. var editors = this._defaultAppointmentViewEditors(),
  60323. resources = this.option("resources");
  60324. if (resources && resources.length) {
  60325. this._resourcesManager.setResources(this.option("resources"));
  60326. editors = editors.concat(this._resourcesManager.getEditors())
  60327. }
  60328. this._appointmentView = new ui.dxScheduler.dxSchedulerAppointmentDetailsView($popupContent, {
  60329. editors: editors,
  60330. rtlEnabled: this.option("rtlEnabled"),
  60331. readOnly: !this.option("editing")
  60332. })
  60333. },
  60334. _popupConfig: function() {
  60335. var buttons = [];
  60336. if (this.option("editing"))
  60337. buttons = [{
  60338. shortcut: "done",
  60339. location: "after",
  60340. onClick: $.proxy(this._saveChanges, this)
  60341. }, {
  60342. shortcut: "cancel",
  60343. location: "after"
  60344. }];
  60345. return {
  60346. width: APPOINTEMENT_POPUP_WIDTH,
  60347. target: "body",
  60348. buttons: buttons,
  60349. onHiding: $.proxy(function() {
  60350. this._workSpace.focus()
  60351. }, this)
  60352. }
  60353. },
  60354. _saveChanges: function() {
  60355. var appointmentData = this._appointmentView.option("values"),
  60356. oldData = this._editAppointmentData;
  60357. if (oldData)
  60358. this._checkRecurringAppointment(oldData.recurrenceRule, $.proxy(function() {
  60359. this.updateAppointment(this._editAppointmentData, appointmentData)
  60360. }, this));
  60361. else
  60362. this.addAppointment(appointmentData)
  60363. },
  60364. _checkRecurringAppointment: function(isRecurrence, callback, isDeleted) {
  60365. if (isRecurrence)
  60366. this._showRecurrenceChangeConfirm(isDeleted).done($.proxy(function(result) {
  60367. if (result)
  60368. callback();
  60369. else
  60370. this._appointments.repaint()
  60371. }, this));
  60372. else
  60373. callback()
  60374. },
  60375. _showRecurrenceChangeConfirm: function(isDeleted) {
  60376. var message;
  60377. if (isDeleted)
  60378. message = "All occurrences of the recurring appointment will be deleted.<br> Are you sure you want to delete them?";
  60379. else
  60380. message = "All occurrences of the recurring appointment will be edited.<br> Are you sure you want to edit them?";
  60381. return ui.dialog.confirm(message, null, false)
  60382. },
  60383. _getUpdatedData: function(options) {
  60384. var target = options.data,
  60385. data = this.getTargetCellData(),
  60386. date = data.date || target.startDate,
  60387. groups = data.groups,
  60388. duration = target.endDate.getTime() - target.startDate.getTime();
  60389. var updatedData = {};
  60390. updatedData.allDay = data.allDay;
  60391. updatedData.startDate = date;
  60392. updatedData.endDate = new Date(date.getTime() + duration);
  60393. for (var name in groups)
  60394. if (groups.hasOwnProperty(name))
  60395. updatedData[name] = groups[name];
  60396. return updatedData
  60397. },
  60398. _getCoordinates: function(dates, resources, allDay) {
  60399. var result = [];
  60400. for (var i = 0; i < dates.length; i++)
  60401. result = result.concat(this._workSpace.getCoordinatesByDateInGroup(dates[i], resources, allDay));
  60402. return result
  60403. },
  60404. _subscribes: {
  60405. currentViewUpdated: function(currentView) {
  60406. this.option("currentView", currentView)
  60407. },
  60408. needCoordinates: function(options) {
  60409. var appointmentData = options.appointmentData,
  60410. startDate = options.startDate,
  60411. dateRange = this._workSpace.getDateRange(),
  60412. dates = utils.getDatesByRecurrence(appointmentData.recurrenceRule, startDate, dateRange[0], dateRange[1]);
  60413. if (!dates.length)
  60414. dates.push(startDate);
  60415. var itemResources = this._resourcesManager.getResourcesFromItem(appointmentData);
  60416. options.callback(this._getCoordinates(dates, itemResources, appointmentData.allDay))
  60417. },
  60418. showEditAppointmentPopup: function(appointmentData) {
  60419. this._editAppointmentData = appointmentData;
  60420. this.showAppointmentPopup(appointmentData)
  60421. },
  60422. showAppointmentTooltip: function(options) {
  60423. this._editAppointmentData = options.data;
  60424. this.showAppointmentTooltip(options.data, options.target)
  60425. },
  60426. hideAppointmentTooltip: function() {
  60427. this._hideTooltip()
  60428. },
  60429. showAddAppointmentPopup: function(appointmentData) {
  60430. delete this._editAppointmentData;
  60431. if (this.option("editing"))
  60432. this.showAppointmentPopup(appointmentData)
  60433. },
  60434. updateAppointmentAfterResize: function(options) {
  60435. this._checkRecurringAppointment(options.target.recurrenceRule, $.proxy(function() {
  60436. this._updateAppointment(options.target, options.data, function() {
  60437. DX.translator.move(options.$appointment, options.initialCoordinates);
  60438. options.target.startDate = utils.makeDate(options.target.startDate);
  60439. options.target.endDate = utils.makeDate(options.target.endDate);
  60440. if (this.option("currentView") === "month" || options.target.allDay || this.appointmentTakesAllDay(options.target))
  60441. options.$appointment.outerWidth(options.initialSize.width);
  60442. else
  60443. options.$appointment.outerHeight(options.initialSize.height)
  60444. })
  60445. }, this))
  60446. },
  60447. updateAppointmentAfterDrag: function(options) {
  60448. var target = options.data,
  60449. updatedData = this._getUpdatedData(options),
  60450. allDayContainerClass = this._workSpace.getAllDayContainerClass();
  60451. if (options.$appointment.parent().hasClass(allDayContainerClass) && !updatedData.allDay)
  60452. updatedData.endDate = this._workSpace._calculateEndDate(updatedData.startDate);
  60453. var appointment = $.extend({}, target, updatedData);
  60454. var targetStartDate = new Date(target.startDate);
  60455. if (this.option("currentView") === "month")
  60456. targetStartDate = this._stripDateTime(targetStartDate);
  60457. if (Math.abs(updatedData.startDate.getTime() - targetStartDate.getTime()) >= this._workSpace._getInterval())
  60458. this._checkRecurringAppointment(target.recurrenceRule, $.proxy(function() {
  60459. this._updateAppointment(target, appointment, function() {
  60460. DX.translator.move(options.$appointment, options.initialCoordinates)
  60461. })
  60462. }, this));
  60463. else
  60464. DX.translator.move(options.$appointment, options.initialCoordinates)
  60465. },
  60466. updateCurrentDate: function(date) {
  60467. this.option("currentDate", this._stripDateTime(utils.makeDate(date)))
  60468. },
  60469. getAppointmentColor: function(options) {
  60470. var resourceForPainting = this._resourcesManager.getResourceForPainting(this.option("groups"));
  60471. if (resourceForPainting) {
  60472. var field = resourceForPainting.field;
  60473. if (options.itemData[field]) {
  60474. var resourceValues = DX.utils.wrapToArray(options.itemData[field]),
  60475. resourceIndex = options.resourceIndex,
  60476. groups = this.option("groups");
  60477. if (!groups || !groups.length)
  60478. resourceIndex = 0;
  60479. var resourceValue = resourceValues[resourceIndex];
  60480. options.callback(this._resourcesManager.getResourceColor(field, resourceValue))
  60481. }
  60482. }
  60483. },
  60484. getResourceForPainting: function(options) {
  60485. options.callback(this._resourcesManager.getResourceForPainting(this.option("groups")))
  60486. },
  60487. getResourcesFromItem: function(options) {
  60488. options.callback(this._resourcesManager.getResourcesFromItem(options.itemData))
  60489. },
  60490. getCellDimensions: function(options) {
  60491. if (this._workSpace)
  60492. options.callback(this._workSpace.getCellWidth(), this._workSpace.getCellHeight(), this._workSpace.getAllDayHeight())
  60493. },
  60494. initAppointmentRenderedAction: function(options) {
  60495. options.callback(this._initAppointmentRenderedAction())
  60496. },
  60497. getMaxAllowedPosition: function(options) {
  60498. if (this._workSpace)
  60499. options.callback(this._workSpace.getMaxAllowedPosition())
  60500. },
  60501. getItemGroupIndexes: function(options) {
  60502. var groups = this._resourcesManager.getResourcesFromItem(options.item),
  60503. indexes = this._workSpace._getGroupIndexes(groups);
  60504. options.callback(indexes)
  60505. },
  60506. appointmentTakesAllDay: function(options) {
  60507. options.callback(this.appointmentTakesAllDay({
  60508. startDate: options.startDate,
  60509. endDate: options.endDate
  60510. }))
  60511. },
  60512. checkContainerVisibility: function(options) {
  60513. options.callback(this.element().is(":hidden"))
  60514. }
  60515. },
  60516. subsribe: function(subject, action) {
  60517. this._subscribes[subject] = action
  60518. },
  60519. fire: function(subject, args) {
  60520. var callback = this._subscribes[subject];
  60521. if (!$.isFunction(callback))
  60522. throw DX.Error("E1031", subject);
  60523. callback.call(this, args)
  60524. },
  60525. getTargetCellData: function() {
  60526. return this._workSpace.getDataByDroppableCell()
  60527. },
  60528. showAppointmentTooltip: function(appointmentData, $appointment) {
  60529. var that = this;
  60530. ui.tooltip.show({
  60531. target: $appointment,
  60532. contentTemplate: function($content) {
  60533. var $tooltip = that._tooltipContent(appointmentData);
  60534. $tooltip.addClass($content.attr("class"));
  60535. $content.replaceWith($tooltip)
  60536. }
  60537. })
  60538. },
  60539. _tooltipContent: function(appointmentData) {
  60540. var that = this;
  60541. var $tooltip = $("<div>").addClass(APPOINTMENT_TOOLTIP_CLASS);
  60542. $("<div>").text(appointmentData.text).addClass(APPOINTMENT_TOOLTIP_TITLE_CLASS).appendTo($tooltip);
  60543. $("<div>").addClass(APPOINTMENT_TOOLTIP_DATE_CLASS).text(that._formatTooltipDate(appointmentData.startDate, appointmentData.endDate)).appendTo($tooltip);
  60544. var $buttons = $("<div>").addClass(APPOINTMENT_TOOLTIP_BUTTONS_CLASS).appendTo($tooltip);
  60545. if (this.option("editing"))
  60546. $("<div>").appendTo($buttons).dxButton({
  60547. icon: "trash",
  60548. onClick: function() {
  60549. that._checkRecurringAppointment(appointmentData.recurrenceRule, function() {
  60550. that.deleteAppointment(appointmentData)
  60551. }, true);
  60552. that._hideTooltip()
  60553. }
  60554. });
  60555. $("<div>").appendTo($buttons).dxButton({
  60556. icon: this.option("editing") ? "edit" : "",
  60557. text: Globalize.localize("dxScheduler-openAppointment"),
  60558. onClick: function() {
  60559. that.showAppointmentPopup(appointmentData)
  60560. }
  60561. });
  60562. return $tooltip
  60563. },
  60564. _hideTooltip: function() {
  60565. ui.tooltip.hide()
  60566. },
  60567. _formatTooltipDate: function(startDate, endDate) {
  60568. var dateTimeFormat = "MMMM d h:mm tt";
  60569. if (this.option("currentView") === "month") {
  60570. var startDateString = Globalize.format(startDate, dateTimeFormat) + " - ",
  60571. endDateString = startDate.getDate() === endDate.getDate() ? Globalize.format(endDate, "t") : Globalize.format(endDate, dateTimeFormat);
  60572. return startDateString + endDateString
  60573. }
  60574. return Globalize.format(startDate, "t") + " - " + Globalize.format(endDate, "t")
  60575. },
  60576. _executeActionWhenOperationIsCompleted: function(action, appointment, e) {
  60577. var options = {appointment: appointment},
  60578. isError = e && e.name === "Error";
  60579. if (isError)
  60580. options.error = e;
  60581. action(options)
  60582. },
  60583. _updateAppointment: function(target, appointment, onUpdatePrevented) {
  60584. var updatingOptions = {
  60585. newData: appointment,
  60586. oldData: target,
  60587. cancel: false
  60588. };
  60589. this._actions["onAppointmentUpdating"](updatingOptions);
  60590. if (!updatingOptions.cancel)
  60591. this._appointmentModel.update(target, appointment).always($.proxy(function(e) {
  60592. this._executeActionWhenOperationIsCompleted(this._actions["onAppointmentUpdated"], appointment, e)
  60593. }, this));
  60594. else if ($.isFunction(onUpdatePrevented))
  60595. onUpdatePrevented.call(this)
  60596. },
  60597. showAppointmentPopup: function(appointmentData) {
  60598. this._createPopup();
  60599. this._popup.show();
  60600. this._appointmentView.option("values", appointmentData)
  60601. },
  60602. getAppointmentDetailsView: function() {
  60603. return this._appointmentView
  60604. },
  60605. getAppointmentResourceData: function(field, value) {
  60606. return this._resourcesManager.getResourceDataByValue(field, value)
  60607. },
  60608. getActions: function() {
  60609. return this._actions
  60610. },
  60611. appointmentTakesAllDay: function(appointment) {
  60612. var etalonDayDurationInHours = this.option("endDayHour") - this.option("startDayHour"),
  60613. appointmentDurationInHours = (appointment.endDate.getTime() - appointment.startDate.getTime()) / 3600000;
  60614. return appointmentDurationInHours >= etalonDayDurationInHours
  60615. },
  60616. addAppointment: function(appointment) {
  60617. if (!appointment.text)
  60618. appointment.text = "";
  60619. var addingOptions = {
  60620. appointment: appointment,
  60621. cancel: false
  60622. };
  60623. this._actions["onAppointmentAdding"](addingOptions);
  60624. if (!addingOptions.cancel)
  60625. this._appointmentModel.add(appointment).always($.proxy(function(e) {
  60626. this._executeActionWhenOperationIsCompleted(this._actions["onAppointmentAdded"], appointment, e)
  60627. }, this))
  60628. },
  60629. updateAppointment: function(target, appointment) {
  60630. this._updateAppointment(target, appointment)
  60631. },
  60632. deleteAppointment: function(appointment) {
  60633. var deletingOptions = {
  60634. appointment: appointment,
  60635. cancel: false
  60636. };
  60637. this._actions["onAppointmentDeleting"](deletingOptions);
  60638. if (!deletingOptions.cancel)
  60639. this._appointmentModel.remove(appointment).always($.proxy(function(e) {
  60640. this._executeActionWhenOperationIsCompleted(this._actions["onAppointmentDeleted"], appointment, e)
  60641. }, this))
  60642. }
  60643. }).include(ui.DataHelperMixin))
  60644. })(jQuery, DevExpress);
  60645. /*! Module widgets-web, file ui.scheduler.appointmentModel.js */
  60646. (function($, DX, undefined) {
  60647. var utils = DX.utils;
  60648. var AppointmentModel = DX.Class.inherit({
  60649. _resourceFilter: function(itemData, resources) {
  60650. var result = true;
  60651. for (var i = 0, len = resources.length; i < len; i++) {
  60652. var resourceField = resources[i].field,
  60653. resourceData = resources[i].data;
  60654. if (itemData.hasOwnProperty(resourceField))
  60655. if (!$.isArray(itemData[resourceField])) {
  60656. if ($.inArray(itemData[resourceField], resourceData) === -1) {
  60657. result = false;
  60658. break
  60659. }
  60660. }
  60661. else {
  60662. result = false;
  60663. for (var j = 0, itemDataCount = itemData[resourceField].length; j < itemDataCount; j++)
  60664. if ($.inArray(itemData[resourceField][j], resourceData) > -1) {
  60665. result = true;
  60666. break
  60667. }
  60668. }
  60669. else {
  60670. result = false;
  60671. break
  60672. }
  60673. }
  60674. return result
  60675. },
  60676. ctor: function(dataSource) {
  60677. this.setDataSource(dataSource)
  60678. },
  60679. setDataSource: function(dataSource) {
  60680. this._dataSource = dataSource
  60681. },
  60682. filterByDate: function(min, max, startDayHour, endDayHour) {
  60683. if (!this._dataSource)
  60684. return;
  60685. var filter = this._prepareDateFilter(min, max, startDayHour, endDayHour);
  60686. this._dataSource.filter(filter);
  60687. this._dataSource.load()
  60688. },
  60689. _prepareDateFilter: function(min, max, startDayHour, endDayHour) {
  60690. var ds = this._dataSource;
  60691. return function(itemData) {
  60692. if ($.isFunction(ds._mapFunc))
  60693. itemData = ds._mapFunc(itemData);
  60694. var currentDate = utils.makeDate(itemData.startDate),
  60695. rule = itemData.recurrenceRule,
  60696. isAllDay = itemData.allDay;
  60697. var stripDateTime = function(date) {
  60698. date = new Date(date);
  60699. utils.correctDateWithUnitBeginning(date, "day");
  60700. return date
  60701. };
  60702. var result = utils.dateInRange(currentDate, min, max) && !rule || utils.dateInRange(currentDate, stripDateTime(min), max) && isAllDay || utils.dateInRecurrenceRange(rule, currentDate, min, max);
  60703. if (result && startDayHour)
  60704. result = currentDate.getHours() >= startDayHour || isAllDay;
  60705. if (result && endDayHour)
  60706. result = currentDate.getHours() <= endDayHour || isAllDay;
  60707. return result
  60708. }
  60709. },
  60710. filterByResources: function(resources) {
  60711. if (!this._dataSource)
  60712. return;
  60713. var filter = this._prepareResourcesFilter(resources);
  60714. this._dataSource.filter(filter);
  60715. this._dataSource.load()
  60716. },
  60717. _prepareResourcesFilter: function(resources) {
  60718. return $.proxy(function(itemData) {
  60719. return this._resourceFilter(itemData, resources)
  60720. }, this)
  60721. },
  60722. filterByDateAndResources: function(options) {
  60723. if (!this._dataSource)
  60724. return;
  60725. this._dataSource.filter($.proxy(function(itemData) {
  60726. var dateFilter = this._prepareDateFilter(options.min, options.max, options.startDayHour, options.endDayHour),
  60727. resourceFilter = this._prepareResourcesFilter(options.resources);
  60728. return dateFilter(itemData) && resourceFilter(itemData)
  60729. }, this));
  60730. this._dataSource.load()
  60731. },
  60732. add: function(data) {
  60733. return this._dataSource.store().insert(data).done($.proxy(function() {
  60734. this._dataSource.load()
  60735. }, this))
  60736. },
  60737. update: function(target, data) {
  60738. return this._dataSource.store().update(target, data).done($.proxy(function() {
  60739. this._dataSource.load()
  60740. }, this))
  60741. },
  60742. remove: function(target) {
  60743. return this._dataSource.store().remove(target).done($.proxy(function() {
  60744. this._dataSource.load()
  60745. }, this))
  60746. }
  60747. });
  60748. DX.ui.dxScheduler.dxSchedulerAppointmentModel = AppointmentModel
  60749. })(jQuery, DevExpress);
  60750. /*! Module widgets-web, file ui.scheduler.recurrenceEditor.js */
  60751. (function($, DX, undefined) {
  60752. var utils = DX.utils;
  60753. var RECURRENCE_EDITOR = "dx-recurrence-editor",
  60754. LABEL_PREFIX = "-label",
  60755. RECURRENCE_EDITOR_CONTAINER = "dx-recurrence-editor-container",
  60756. SWITCH_EDITOR = "dx-recurrence-switch",
  60757. SWITCH_REPEAT_END_EDITOR = "dx-recurrence-switch-repeat-end",
  60758. FREQUENCY_EDITOR = "dx-recurrence-radiogroup-freq",
  60759. INTERVAL_EDITOR = "dx-recurrence-numberbox-interval",
  60760. INTERVAL_EDITOR_FIELD = "dx-recurrence-interval-field",
  60761. REPEAT_END_EDITOR = "dx-recurrence-repeat-end",
  60762. REPEAT_END_EDITOR_FIELD = "dx-recurrence-repeat-end-field",
  60763. REPEAT_END_EDITOR_CONTAINER = "dx-recurrence-repeat-end-container",
  60764. REPEAT_TYPE_EDITOR = "dx-recurrence-radiogroup-repeat-type",
  60765. REPEAT_COUNT_EDITOR = "dx-recurrence-numberbox-repeat-count",
  60766. REPEAT_UNTIL_DATE_EDITOR = "dx-recurrence-datebox-until-date",
  60767. REPEAT_ON_EDITOR = "dx-recurrence-repeat-on",
  60768. REPEAT_ON_WEEK_EDITOR = "dx-recurrence-repeat-on-week",
  60769. DAY_OF_WEEK = "dx-recurrence-checkbox-day-of-week",
  60770. REPEAT_ON_MONTH_EDITOR = "dx-recurrence-repeat-on-month",
  60771. DAY_OF_MONTH = "dx-recurrence-numberbox-day-of-month",
  60772. REPEAT_ON_YEAR_EDITOR = "dx-recurrence-repeat-on-year",
  60773. MONTH_OF_YEAR = "dx-recurrence-selectbox-month-of-year",
  60774. FIELD_CLASS = "dx-field",
  60775. FIELD_LABEL_CLASS = "dx-field-label",
  60776. FIELD_VALUE_CLASS = "dx-field-value",
  60777. frequencies = [{
  60778. text: function() {
  60779. return Globalize.localize("dxScheduler-recurrenceDaily")
  60780. },
  60781. value: "DAILY"
  60782. }, {
  60783. text: function() {
  60784. return Globalize.localize("dxScheduler-recurrenceWeekly")
  60785. },
  60786. value: "WEEKLY"
  60787. }, {
  60788. text: function() {
  60789. return Globalize.localize("dxScheduler-recurrenceMonthly")
  60790. },
  60791. value: "MONTHLY"
  60792. }, {
  60793. text: function() {
  60794. return Globalize.localize("dxScheduler-recurrenceYearly")
  60795. },
  60796. value: "YEARLY"
  60797. }],
  60798. repeatEndTypes = [{
  60799. text: function() {
  60800. return Globalize.localize("dxScheduler-recurrenceRepeatCount")
  60801. },
  60802. value: "count"
  60803. }, {
  60804. text: function() {
  60805. return Globalize.localize("dxScheduler-recurrenceRepeatOnDate")
  60806. },
  60807. value: "until"
  60808. }];
  60809. var RecurrenceRule = DX.Class.inherit({
  60810. ctor: function(recurrence) {
  60811. this._recurrenceRule = DX.utils.getRecurrenceRule(recurrence)
  60812. },
  60813. makeRules: function(string) {
  60814. var that = this;
  60815. that._recurrenceRule = utils.getRecurrenceRule(string)
  60816. },
  60817. makeRule: function(field, value) {
  60818. if (!value) {
  60819. delete this._recurrenceRule[field];
  60820. return
  60821. }
  60822. if (utils.isDefined(field)) {
  60823. if (field === "until")
  60824. delete this._recurrenceRule.count;
  60825. if (field === "count")
  60826. delete this._recurrenceRule.until;
  60827. this._recurrenceRule[field] = value
  60828. }
  60829. },
  60830. repeatableRule: function() {
  60831. var rules = this._recurrenceRule;
  60832. if ("count" in rules)
  60833. return "count";
  60834. if ("until" in rules)
  60835. return "until";
  60836. return null
  60837. },
  60838. recurrenceString: function() {
  60839. return utils.getRecurrenceString(this._recurrenceRule)
  60840. },
  60841. rules: function() {
  60842. return this._recurrenceRule
  60843. },
  60844. daysFromByDayRule: function() {
  60845. var result = [];
  60846. if (this._recurrenceRule.byday)
  60847. result = this._recurrenceRule.byday.split(",");
  60848. return result
  60849. }
  60850. });
  60851. DX.registerComponent("dxSchedulerRecurrenceEditor", DX.ui.dxScheduler, DX.ui.Editor.inherit({
  60852. _setDefaultOptions: function() {
  60853. this.callBase();
  60854. this.option({
  60855. value: null,
  60856. onValueChanged: null,
  60857. startDate: new Date
  60858. })
  60859. },
  60860. _init: function() {
  60861. this.callBase();
  60862. this._recurrenceRule = new RecurrenceRule(this.option("value"))
  60863. },
  60864. _render: function() {
  60865. this.callBase();
  60866. this.element().addClass(RECURRENCE_EDITOR);
  60867. this._renderSwitch();
  60868. this._$container = $("<div>").addClass(RECURRENCE_EDITOR_CONTAINER).appendTo(this.element());
  60869. this._renderEditors();
  60870. this._renderContainerVisibility()
  60871. },
  60872. _renderSwitch: function() {
  60873. var $switchEditor = $("<div>").addClass(SWITCH_EDITOR);
  60874. this._switchEditor = this._createComponent($switchEditor, "dxSwitch", {
  60875. value: false,
  60876. onValueChanged: $.proxy(this._switchValueChangeHandler, this)
  60877. });
  60878. this.element().append($switchEditor)
  60879. },
  60880. _switchValueChangeHandler: function(args) {
  60881. var value = args.value;
  60882. this._renderContainerVisibility(value);
  60883. if (!this.option("value") && value)
  60884. this._handleDefaults();
  60885. else if (!value) {
  60886. this._recurrenceRule.makeRules("");
  60887. this.option("value", "")
  60888. }
  60889. },
  60890. _renderContainerVisibility: function(value) {
  60891. if (value) {
  60892. this._$container.show();
  60893. DX.utils.triggerShownEvent(this._$container)
  60894. }
  60895. else
  60896. this._$container.hide()
  60897. },
  60898. _handleDefaults: function() {
  60899. this._recurrenceRule.makeRule("freq", "DAILY");
  60900. this.option("value", this._recurrenceRule.recurrenceString())
  60901. },
  60902. _renderEditors: function() {
  60903. this._renderFreqEditor();
  60904. this._renderIntervalEditor();
  60905. this._renderRepeatOnEditor();
  60906. this._renderRepeatEndSwitch();
  60907. this._renderRepeatEndEditor();
  60908. this._renderRepeatEndVisibility()
  60909. },
  60910. _renderFreqEditor: function() {
  60911. var freq = this._recurrenceRule.rules().freq || "DAILY";
  60912. var $freqEditor = $("<div>").addClass(FREQUENCY_EDITOR).addClass(FIELD_VALUE_CLASS);
  60913. this._freqEditor = this._createComponent($freqEditor, "dxRadioGroup", {
  60914. field: "freq",
  60915. items: frequencies,
  60916. value: freq,
  60917. valueExpr: "value",
  60918. displayExpr: "text",
  60919. layout: "horizontal",
  60920. onValueChanged: $.proxy(this._valueChangedHandler, this)
  60921. });
  60922. var $field = $("<div>").addClass(FIELD_CLASS).append($freqEditor);
  60923. this._$container.append($field)
  60924. },
  60925. _renderIntervalEditor: function() {
  60926. var freq = this._recurrenceRule.rules().freq || "DAILY";
  60927. var $intervalEditor = $("<div>").addClass(INTERVAL_EDITOR).addClass(FIELD_VALUE_CLASS);
  60928. var $intervalEditorLabel = $("<div>").text(Globalize.localize("dxScheduler-recurrenceEvery") + ":").addClass(INTERVAL_EDITOR + LABEL_PREFIX).addClass(FIELD_LABEL_CLASS);
  60929. this._$intervalTypeLabel = $("<div>").text(Globalize.localize("dxScheduler-recurrenceRepeat" + freq.charAt(0).toUpperCase() + freq.substr(1).toLowerCase())).addClass(REPEAT_TYPE_EDITOR + LABEL_PREFIX);
  60930. var interval = this._recurrenceRule.rules().interval || 1;
  60931. this._intervalEditor = this._createComponent($intervalEditor, "dxNumberBox", {
  60932. field: "interval",
  60933. min: 1,
  60934. value: interval,
  60935. showSpinButtons: true,
  60936. useTouchSpinButtons: false,
  60937. onValueChanged: $.proxy(this._valueChangedHandler, this)
  60938. });
  60939. var $field = $("<div>").addClass(FIELD_CLASS).addClass(INTERVAL_EDITOR_FIELD).append($intervalEditorLabel, $intervalEditor, this._$intervalTypeLabel);
  60940. this._$container.append($field)
  60941. },
  60942. _renderRepeatOnEditor: function() {
  60943. var freq = this._recurrenceRule.rules().freq;
  60944. if (!utils.isDefined(this._$repeatOnEditor))
  60945. this._$repeatOnEditor = $("<div>").addClass(REPEAT_ON_EDITOR).addClass(FIELD_CLASS).appendTo(this._$container);
  60946. if (!freq || freq === "DAILY") {
  60947. this._clearRepeatOnEditor();
  60948. this._clearRepeatOnLabel();
  60949. return
  60950. }
  60951. if (!utils.isDefined(this._$repeatOnLabel))
  60952. this._renderRepeatOnLabel(this._$repeatOnEditor);
  60953. if (freq === "WEEKLY" && !this._$repeatOnWeek) {
  60954. this._renderRepeatOnWeekEditor();
  60955. return
  60956. }
  60957. if (freq === "MONTHLY" && !this._$repeatOnMonth) {
  60958. this._renderRepeatOnMonthEditor();
  60959. return
  60960. }
  60961. if (freq === "YEARLY" && !this._$repeatOnYear) {
  60962. this._renderRepeatOnYearEditor();
  60963. return
  60964. }
  60965. },
  60966. _renderRepeatOnLabel: function($element) {
  60967. this._$repeatOnLabel = $("<div>").text(Globalize.localize("dxScheduler-recurrenceOn") + ":").addClass(REPEAT_ON_EDITOR + LABEL_PREFIX).addClass(FIELD_LABEL_CLASS);
  60968. $element.append(this._$repeatOnLabel)
  60969. },
  60970. _clearRepeatOnEditor: function() {
  60971. if (utils.isDefined(this._$repeatOnWeek)) {
  60972. this._$repeatOnWeek.detach();
  60973. this._$repeatOnWeek.remove();
  60974. delete this._$repeatOnWeek
  60975. }
  60976. if (utils.isDefined(this._$repeatOnMonth)) {
  60977. this._$repeatOnMonth.detach();
  60978. this._$repeatOnMonth.remove();
  60979. delete this._$repeatOnMonth
  60980. }
  60981. if (utils.isDefined(this._$repeatOnYear)) {
  60982. this._$repeatOnYear.detach();
  60983. this._$repeatOnYear.remove();
  60984. delete this._$repeatOnYear
  60985. }
  60986. },
  60987. _clearRepeatOnEditorValues: function() {
  60988. this._recurrenceRule.makeRule("bymonth", "");
  60989. this._recurrenceRule.makeRule("bymonthday", "");
  60990. this._recurrenceRule.makeRule("byday", "")
  60991. },
  60992. _clearRepeatOnLabel: function() {
  60993. if (utils.isDefined(this._$repeatOnLabel)) {
  60994. this._$repeatOnLabel.detach();
  60995. this._$repeatOnLabel.remove();
  60996. delete this._$repeatOnLabel
  60997. }
  60998. },
  60999. _renderRepeatOnWeekEditor: function() {
  61000. this._clearRepeatOnEditor();
  61001. this._$repeatOnWeek = $("<div>").addClass(REPEAT_ON_WEEK_EDITOR).addClass(FIELD_VALUE_CLASS).appendTo(this._$repeatOnEditor);
  61002. var days = Globalize.culture().calendar.days.namesShort,
  61003. daysFromRules = this._daysOfWeekByRules();
  61004. this._daysOfWeek = [];
  61005. for (var i = 0; i < 7; i++) {
  61006. var checkBoxText = days[i].toUpperCase();
  61007. var $day = $("<div>").addClass(DAY_OF_WEEK),
  61008. day = this._createComponent($day, "dxCheckBox", {
  61009. text: checkBoxText,
  61010. value: $.inArray(checkBoxText, daysFromRules) > -1 ? true : false,
  61011. onValueChanged: $.proxy(this._repeatByDayValueChangeHandler, this)
  61012. });
  61013. this._daysOfWeek[i] = day;
  61014. this._$repeatOnWeek.append($day)
  61015. }
  61016. },
  61017. _daysOfWeekByRules: function() {
  61018. var days = Globalize.culture().calendar.days.namesShort;
  61019. var daysByRule = this._recurrenceRule.daysFromByDayRule();
  61020. if (!daysByRule.length)
  61021. daysByRule = [days[this.option("startDate").getDay()].toUpperCase()];
  61022. return daysByRule
  61023. },
  61024. _repeatByDayValueChangeHandler: function() {
  61025. var byDayRule = "";
  61026. $.each(this._daysOfWeek, function(index, day) {
  61027. if (day.option("value")) {
  61028. var dayName = day.option("text");
  61029. if (!byDayRule)
  61030. byDayRule = dayName;
  61031. else
  61032. byDayRule = byDayRule + "," + dayName
  61033. }
  61034. });
  61035. this._recurrenceRule.makeRule("byday", byDayRule);
  61036. this.option("value", this._recurrenceRule.recurrenceString())
  61037. },
  61038. _renderRepeatOnMonthEditor: function() {
  61039. this._clearRepeatOnEditor();
  61040. this._$repeatOnMonth = $("<div>").addClass(REPEAT_ON_MONTH_EDITOR).addClass(FIELD_VALUE_CLASS).appendTo(this._$repeatOnEditor);
  61041. this._renderDayOfMonthEditor(this._$repeatOnMonth)
  61042. },
  61043. _renderRepeatOnYearEditor: function() {
  61044. this._clearRepeatOnEditor();
  61045. this._$repeatOnYear = $("<div>").addClass(REPEAT_ON_YEAR_EDITOR).addClass(FIELD_VALUE_CLASS).appendTo(this._$repeatOnEditor);
  61046. var months = [],
  61047. monthsNames = Globalize.cultures["default"].calendar.months.names;
  61048. for (var i = 0; i < 12; i++)
  61049. months[i] = {
  61050. value: String(i + 1),
  61051. text: monthsNames[i]
  61052. };
  61053. var bymonth = this._monthOfYearByRules();
  61054. var $monthOfYear = $("<div>").addClass(MONTH_OF_YEAR).appendTo(this._$repeatOnYear);
  61055. var monthChanged = function(args) {
  61056. this._valueChangedHandler.call(this, args);
  61057. var monthValue = parseInt(args.component.option("value"));
  61058. if (this._dayEditor && monthValue) {
  61059. var maxAllowedDay = new Date((new Date).getFullYear(), parseInt(monthValue), 0).getDate();
  61060. if (monthValue === 2)
  61061. maxAllowedDay = 29;
  61062. this._dayEditor.option("max", maxAllowedDay)
  61063. }
  61064. };
  61065. this._monthEditor = this._createComponent($monthOfYear, "dxSelectBox", {
  61066. field: "bymonth",
  61067. items: months,
  61068. value: bymonth,
  61069. displayExpr: "text",
  61070. valueExpr: "value",
  61071. onValueChanged: $.proxy(monthChanged, this)
  61072. });
  61073. this._renderDayOfMonthEditor(this._$repeatOnYear)
  61074. },
  61075. _monthOfYearByRules: function() {
  61076. var monthByRule = this._recurrenceRule.rules().bymonth;
  61077. if (!monthByRule)
  61078. monthByRule = this.option("startDate").getMonth();
  61079. return monthByRule
  61080. },
  61081. _renderDayOfMonthEditor: function($element) {
  61082. var bymonthday = this._dayOfMonthByRules();
  61083. var $dayEditor = $("<div>").addClass(DAY_OF_MONTH);
  61084. this._dayEditor = this._createComponent($dayEditor, "dxNumberBox", {
  61085. field: "bymonthday",
  61086. min: 1,
  61087. max: 31,
  61088. showSpinButtons: true,
  61089. useTouchSpinButtons: false,
  61090. value: bymonthday,
  61091. onValueChanged: $.proxy(this._valueChangedHandler, this)
  61092. });
  61093. $element.append($dayEditor)
  61094. },
  61095. _dayOfMonthByRules: function() {
  61096. var dayByRule = this._recurrenceRule.rules().bymonthday;
  61097. if (!dayByRule)
  61098. dayByRule = this.option("startDate").getDate();
  61099. return dayByRule
  61100. },
  61101. _renderRepeatEndSwitch: function() {
  61102. var that = this;
  61103. var $switchEndEditor = $("<div>").addClass(SWITCH_REPEAT_END_EDITOR).addClass(FIELD_VALUE_CLASS),
  61104. $switchEndLabel = $("<div>").text(Globalize.localize("dxScheduler-recurrenceEnd") + ":").addClass(INTERVAL_EDITOR + LABEL_PREFIX).addClass(FIELD_LABEL_CLASS);
  61105. this._switchEndEditor = this._createComponent($switchEndEditor, "dxSwitch", {
  61106. value: that._recurrenceRule.repeatableRule() ? true : false,
  61107. onValueChanged: $.proxy(this._repeatEndSwitchValueChangeHandler, this)
  61108. });
  61109. $("<div>").addClass(FIELD_CLASS).addClass(REPEAT_END_EDITOR_FIELD).append($switchEndLabel, $switchEndEditor).appendTo(this._$container)
  61110. },
  61111. _repeatEndSwitchValueChangeHandler: function(args) {
  61112. var value = args.value;
  61113. this._renderRepeatEndVisibility(value);
  61114. if (!this._recurrenceRule.rules().count && !this._recurrenceRule.rules().until && value)
  61115. this._handleRepeatEndDefaults();
  61116. else if (!value) {
  61117. this._recurrenceRule.makeRule("count", "");
  61118. this._recurrenceRule.makeRule("until", "");
  61119. this.option("value", this._recurrenceRule.recurrenceString())
  61120. }
  61121. },
  61122. _renderRepeatEndVisibility: function(value) {
  61123. if (!value)
  61124. this._$repeatEndEditor.hide();
  61125. else
  61126. this._$repeatEndEditor.show()
  61127. },
  61128. _handleRepeatEndDefaults: function() {
  61129. this._recurrenceRule.makeRule("count", 1);
  61130. this.option("value", this._recurrenceRule.recurrenceString())
  61131. },
  61132. _renderRepeatEndEditor: function(rule) {
  61133. rule = utils.isDefined(rule) ? rule : this._recurrenceRule.repeatableRule();
  61134. if (!rule)
  61135. rule = "count";
  61136. if (!utils.isDefined(this._$repeatEndEditor)) {
  61137. this._$repeatEndEditor = $("<div>").addClass(REPEAT_END_EDITOR_CONTAINER).addClass(FIELD_CLASS).appendTo(this._$container);
  61138. this._renderRepeatEndTypeEditor()
  61139. }
  61140. },
  61141. _renderRepeatEndTypeEditor: function() {
  61142. var repeatType = this._recurrenceRule.repeatableRule() || "count",
  61143. that = this;
  61144. this._$repeatTypeEditor = $("<div>").addClass(REPEAT_TYPE_EDITOR).addClass(FIELD_VALUE_CLASS).appendTo(this._$repeatEndEditor);
  61145. this._repeatTypeEditor = this._createComponent(this._$repeatTypeEditor, "dxRadioGroup", {
  61146. items: repeatEndTypes,
  61147. value: repeatType,
  61148. displayExpr: "text",
  61149. valueExpr: "value",
  61150. itemTemplate: function(itemData) {
  61151. if (itemData.value === "count")
  61152. return that._renderRepeatCountEditor();
  61153. else
  61154. return that._renderRepeatUntilEditor()
  61155. },
  61156. layout: "vertical",
  61157. onValueChanged: $.proxy(this._repeatTypeValueChangedHandler, this)
  61158. });
  61159. this._disableRepeatEndParts(repeatType)
  61160. },
  61161. _repeatTypeValueChangedHandler: function(args) {
  61162. var value = args.value;
  61163. this._disableRepeatEndParts(value);
  61164. if (value === "until")
  61165. this._recurrenceRule.makeRule(value, utils.getAsciiStringByDate(this._repeatUntilDate.option("value")));
  61166. else if (value === "count")
  61167. this._recurrenceRule.makeRule(value, this._repeatCountEditor.option("value"));
  61168. this.option("value", this._recurrenceRule.recurrenceString())
  61169. },
  61170. _disableRepeatEndParts: function(value) {
  61171. if (value === "until") {
  61172. this._repeatCountEditor.option("disabled", true);
  61173. this._repeatUntilDate.option("disabled", false)
  61174. }
  61175. else if (value === "count") {
  61176. this._repeatCountEditor.option("disabled", false);
  61177. this._repeatUntilDate.option("disabled", true)
  61178. }
  61179. },
  61180. _renderRepeatCountEditor: function() {
  61181. var repeatCount = this._recurrenceRule.rules().count || 1,
  61182. $editorTemplate = $("<div>");
  61183. $("<div>").text(Globalize.localize("dxScheduler-recurrenceAfter") + ":").addClass(REPEAT_END_EDITOR + LABEL_PREFIX).appendTo($editorTemplate);
  61184. this._$repeatCountEditor = $("<div>").addClass(REPEAT_COUNT_EDITOR).addClass(FIELD_VALUE_CLASS).appendTo($editorTemplate);
  61185. $("<div>").text(Globalize.localize("dxScheduler-recurrenceRepeatCount")).addClass(REPEAT_END_EDITOR + LABEL_PREFIX).appendTo($editorTemplate);
  61186. this._repeatCountEditor = this._createComponent(this._$repeatCountEditor, "dxNumberBox", {
  61187. field: "count",
  61188. min: 1,
  61189. showSpinButtons: true,
  61190. useTouchSpinButtons: false,
  61191. value: repeatCount,
  61192. onValueChanged: $.proxy(this._repeatCountValueChangeHandler, this)
  61193. });
  61194. return $editorTemplate
  61195. },
  61196. _repeatCountValueChangeHandler: function(args) {
  61197. if (this._recurrenceRule.repeatableRule() !== "count")
  61198. return;
  61199. var value = args.value;
  61200. this._recurrenceRule.makeRule("count", value);
  61201. this.option("value", this._recurrenceRule.recurrenceString())
  61202. },
  61203. _renderRepeatUntilEditor: function() {
  61204. var repeatUntil = this._recurrenceRule.rules().until || new Date,
  61205. $editorTemplate = $("<div>");
  61206. $("<div>").text(Globalize.localize("dxScheduler-recurrenceOn") + ":").addClass(REPEAT_END_EDITOR + LABEL_PREFIX).appendTo($editorTemplate);
  61207. this._$repeatDateEditor = $("<div>").addClass(REPEAT_UNTIL_DATE_EDITOR).addClass(FIELD_VALUE_CLASS).appendTo($editorTemplate);
  61208. this._repeatUntilDate = this._createComponent(this._$repeatDateEditor, "dxDateBox", {
  61209. field: "until",
  61210. value: repeatUntil,
  61211. format: "date",
  61212. onValueChanged: $.proxy(this._repeatUntilValueChangeHandler, this)
  61213. });
  61214. return $editorTemplate
  61215. },
  61216. _repeatUntilValueChangeHandler: function(args) {
  61217. if (this._recurrenceRule.repeatableRule() !== "until")
  61218. return;
  61219. var value = args.value;
  61220. if (typeof value !== "string")
  61221. value = utils.getAsciiStringByDate(value);
  61222. this._recurrenceRule.makeRule("until", value);
  61223. this.option("value", this._recurrenceRule.recurrenceString())
  61224. },
  61225. _valueChangedHandler: function(args) {
  61226. var value = args.component.option("value"),
  61227. field = args.component.option("field");
  61228. if (field === "freq")
  61229. this._clearRepeatOnEditorValues();
  61230. this._recurrenceRule.makeRule(field, value);
  61231. this.option("value", this._recurrenceRule.recurrenceString() || "")
  61232. },
  61233. _optionChanged: function(args) {
  61234. switch (args.name) {
  61235. case"value":
  61236. this._recurrenceRule.makeRules(args.value);
  61237. this._switchEditor.option("value", !!args.value);
  61238. this._repeatTypeEditor.option("value", this._recurrenceRule.repeatableRule() || "count");
  61239. this._renderRepeatEndEditor();
  61240. this._renderRepeatOnEditor();
  61241. this._changeEditorsValues(this._recurrenceRule.rules());
  61242. this.callBase(args);
  61243. break;
  61244. case"startDate":
  61245. this._clearRepeatOnEditor();
  61246. this._renderRepeatOnEditor();
  61247. break;
  61248. default:
  61249. this.callBase(args)
  61250. }
  61251. },
  61252. _changeEditorsValues: function(rules) {
  61253. this._freqEditor.option("value", rules.freq);
  61254. this._changeRepeatTypeLabel();
  61255. this._intervalEditor.option("value", rules.interval);
  61256. this._changeRepeatCountValue();
  61257. this._changeRepeatUntilValue();
  61258. this._changeCheckBoxesValue();
  61259. this._changeDayOfMonthValue();
  61260. this._changeMonthOfYearValue()
  61261. },
  61262. _changeRepeatTypeLabel: function() {
  61263. var $labels = this.element().find("." + REPEAT_TYPE_EDITOR + LABEL_PREFIX);
  61264. if (!$labels.length)
  61265. return;
  61266. var freq = this._recurrenceRule.rules().freq || "DAILY";
  61267. $.each($labels, function(_, $label) {
  61268. $($label).text(Globalize.localize("dxScheduler-recurrenceRepeat" + freq.charAt(0).toUpperCase() + freq.substr(1).toLowerCase()))
  61269. })
  61270. },
  61271. _changeRepeatCountValue: function() {
  61272. if (!this._$repeatCountEditor)
  61273. return;
  61274. var count = this._recurrenceRule.rules().count || 1;
  61275. this._repeatCountEditor.option("value", count)
  61276. },
  61277. _changeRepeatUntilValue: function() {
  61278. if (!this._$repeatDateEditor)
  61279. return;
  61280. var date = this._recurrenceRule.rules().until || new Date;
  61281. this._repeatUntilDate.option("value", date)
  61282. },
  61283. _changeCheckBoxesValue: function() {
  61284. if (!this._$repeatOnWeek)
  61285. return;
  61286. var daysByRule = this._daysOfWeekByRules();
  61287. $.each(this._daysOfWeek, function(index, day) {
  61288. day.option("value", $.inArray(day.option("text"), daysByRule) > -1)
  61289. })
  61290. },
  61291. _changeDayOfMonthValue: function() {
  61292. if (!this._$repeatOnMonth && !this._$repeatOnYear)
  61293. return;
  61294. var day = this._dayOfMonthByRules() || 1;
  61295. this._dayEditor.option("value", day)
  61296. },
  61297. _changeMonthOfYearValue: function() {
  61298. if (!this._$repeatOnYear)
  61299. return;
  61300. var month = this._monthOfYearByRules() || 1;
  61301. this._monthEditor.option("value", month)
  61302. }
  61303. }))
  61304. })(jQuery, DevExpress);
  61305. /*! Module widgets-web, file ui.scheduler.appointmentDetailsView.js */
  61306. (function($, DX, undefined) {
  61307. var EDITOR_LABEL_PREFIX = "dx-scheduler-editor-label-",
  61308. FIELD_CLASS = "dx-field",
  61309. FILED_POSTFIX = "-field",
  61310. FIELD_LABEL_CLASS = "dx-field-label",
  61311. FIELD_VALUE_CLASS = "dx-field-value",
  61312. FIELDSET_CLASS = "dx-fieldset";
  61313. var AppointmentDetailsView = DX.DOMComponent.inherit({
  61314. _setDefaultOptions: function() {
  61315. this.callBase();
  61316. this.option({
  61317. values: {},
  61318. editors: [],
  61319. readOnly: false
  61320. })
  61321. },
  61322. _optionChanged: function(args) {
  61323. switch (args.name) {
  61324. case"values":
  61325. this._setEditorValues(args.value);
  61326. break;
  61327. case"editors":
  61328. break;
  61329. case"readOnly":
  61330. break;
  61331. default:
  61332. this.callBase(args)
  61333. }
  61334. },
  61335. _setEditorValues: function(values) {
  61336. var editors = this.option("editors");
  61337. for (var i = 0, length = editors.length; i < length; i++) {
  61338. var editor = editors[i],
  61339. type = editor.type,
  61340. $editor = this.element().find("." + editor.cssClass),
  61341. instance = $editor[type]("instance");
  61342. if (editor.key === "recurrenceRule")
  61343. instance.option("startDate", values.startDate);
  61344. var value = values ? values[editor.key] : null;
  61345. instance.option(this._getEditorValueOptions(type, value))
  61346. }
  61347. },
  61348. _render: function() {
  61349. var editors = this.option("editors");
  61350. this._$fieldset = $("<div>").addClass(FIELDSET_CLASS);
  61351. this._scrollable = this._createComponent("<div>", "dxScrollable", {useKeyboard: false});
  61352. this._scrollable.content().append(this._$fieldset);
  61353. for (var i = 0, length = editors.length; i < length; i++)
  61354. this._renderEditor(editors[i]);
  61355. this.element().append(this._scrollable.element())
  61356. },
  61357. _renderEditor: function(editor) {
  61358. var scrollable = this._scrollable,
  61359. values = this.option("values"),
  61360. key = editor.key,
  61361. type = editor.type,
  61362. valueOptions = this._getEditorValueOptions(type, values[key]),
  61363. options = $.extend(valueOptions, editor.options, {
  61364. onValueChanged: function(arg) {
  61365. if (editor.options && editor.options.onValueChanged)
  61366. editor.options.onValueChanged(arg);
  61367. scrollable.update();
  61368. values[key] = arg.values ? arg.values : arg.value;
  61369. if (values[key] === undefined || DX.utils.isEmptyArray(values[key]))
  61370. delete values[key]
  61371. },
  61372. readOnly: this.option("readOnly")
  61373. });
  61374. var $field = $("<div>").addClass(FIELD_CLASS).addClass(editor.cssClass + FILED_POSTFIX);
  61375. var labelText = Globalize.localize(editor.label) || editor.label,
  61376. $label = $("<div>").text(labelText + ":").addClass(EDITOR_LABEL_PREFIX + key.toLowerCase()),
  61377. $editor = $("<div>").addClass(editor.cssClass);
  61378. var instance = this._createComponent($editor, type, options);
  61379. instance.setAria("label", labelText);
  61380. $label.addClass(FIELD_LABEL_CLASS);
  61381. if (key !== "recurrenceRule")
  61382. $editor.addClass(FIELD_VALUE_CLASS);
  61383. $field.append($label, $editor);
  61384. this._$fieldset.append($field)
  61385. },
  61386. _getEditorValueOptions: function(type, value) {
  61387. var result = {value: value};
  61388. if (type === "dxTagBox")
  61389. result = {values: value ? DX.utils.wrapToArray(value) : []};
  61390. return result
  61391. },
  61392. getEditorInstance: function(key) {
  61393. var result = null,
  61394. editors = this.option("editors");
  61395. for (var i = 0, length = editors.length; i < length; i++) {
  61396. var editor = editors[i];
  61397. if (editor.key === key)
  61398. result = this.element().find("." + editor.cssClass)[editor.type]("instance")
  61399. }
  61400. return result
  61401. }
  61402. });
  61403. DX.ui.dxScheduler.dxSchedulerAppointmentDetailsView = AppointmentDetailsView
  61404. })(jQuery, DevExpress);
  61405. /*! Module widgets-web, file ui.scheduler.resourceManager.js */
  61406. (function($, DX, undefined) {
  61407. var utils = DX.utils,
  61408. dataUtils = DX.data.utils;
  61409. var RESOURCE_CLASS_PREFIX = "dx-scheduler-resource-",
  61410. DEFAULT_VALUE_EXPR = "id",
  61411. DEFAULT_DISPLAY_EXPR = "text";
  61412. var ResourceManager = DX.Class.inherit({
  61413. _wrapDataSource: function(dataSource) {
  61414. if (dataSource instanceof DX.data.DataSource)
  61415. return dataSource;
  61416. return new DX.data.DataSource({
  61417. store: new DevExpress.data.ArrayStore(dataSource),
  61418. pageSize: 0
  61419. })
  61420. },
  61421. _mapResourceData: function(resource, data) {
  61422. var valueGetter = dataUtils.compileGetter(resource.valueExpr || DEFAULT_VALUE_EXPR),
  61423. displayGetter = dataUtils.compileGetter(resource.displayExpr || DEFAULT_DISPLAY_EXPR);
  61424. return $.map(data, function(item) {
  61425. return {
  61426. id: valueGetter(item),
  61427. text: displayGetter(item)
  61428. }
  61429. })
  61430. },
  61431. ctor: function(resources) {
  61432. this.setResources(resources)
  61433. },
  61434. setResources: function(resources) {
  61435. this._resources = resources;
  61436. this._resourceFields = $.map(resources || [], function(resource) {
  61437. return resource.field
  61438. })
  61439. },
  61440. getResources: function() {
  61441. return this._resources || []
  61442. },
  61443. getEditors: function() {
  61444. var result = [];
  61445. $.each(this.getResources(), function(i, resource) {
  61446. result.push({
  61447. options: {
  61448. dataSource: resource.dataSource,
  61449. displayExpr: resource.displayExpr || DEFAULT_DISPLAY_EXPR,
  61450. valueExpr: resource.valueExpr || DEFAULT_VALUE_EXPR
  61451. },
  61452. key: resource.field,
  61453. type: resource.allowMultiple ? "dxTagBox" : "dxSelectBox",
  61454. label: resource.label || resource.field,
  61455. cssClass: RESOURCE_CLASS_PREFIX + resource.field.toLowerCase()
  61456. })
  61457. });
  61458. return result
  61459. },
  61460. getResourceDataByValue: function(field, value) {
  61461. var result = $.Deferred(),
  61462. that = this;
  61463. $.each(this.getResources(), function(_, resource) {
  61464. if (resource.field === field) {
  61465. var dataSource = that._wrapDataSource(resource.dataSource);
  61466. dataSource.filter(resource.valueExpr || DEFAULT_VALUE_EXPR, value);
  61467. dataSource.load().done(function(data) {
  61468. result.resolve(data[0])
  61469. }).fail(function() {
  61470. result.reject()
  61471. });
  61472. return false
  61473. }
  61474. });
  61475. return result.promise()
  61476. },
  61477. getResourcesFromItem: function(itemData) {
  61478. var that = this,
  61479. result = null;
  61480. $.each(itemData, function(name) {
  61481. if ($.inArray(name, that._resourceFields) > -1) {
  61482. if (!result)
  61483. result = {};
  61484. result[name] = utils.wrapToArray(itemData[name])
  61485. }
  61486. });
  61487. return result
  61488. },
  61489. getResourcesValueByFields: function(groups) {
  61490. var result = $.Deferred(),
  61491. that = this,
  61492. deferreds = [];
  61493. $.each(this.getResourcesByFields(groups), function(i, resource) {
  61494. var deferred = $.Deferred();
  61495. that._wrapDataSource(resource.dataSource).load().done(function(data) {
  61496. deferred.resolve({
  61497. name: resource.field,
  61498. items: that._mapResourceData(resource, data)
  61499. });
  61500. deferreds.push(deferred)
  61501. }).fail(function() {
  61502. deferred.reject()
  61503. })
  61504. });
  61505. $.when.apply(null, deferreds).done(function() {
  61506. result.resolve(Array.prototype.slice.call(arguments))
  61507. }).fail(function() {
  61508. result.reject()
  61509. });
  61510. return result.promise()
  61511. },
  61512. getResourceColor: function(field, value) {
  61513. var result = $.Deferred(),
  61514. color;
  61515. this.getResourceDataByValue(field, value).done(function(data) {
  61516. if (data)
  61517. color = data.color;
  61518. result.resolve(color)
  61519. }).fail(function() {
  61520. result.reject()
  61521. });
  61522. return result.promise()
  61523. },
  61524. getResourcesByFields: function(fields) {
  61525. return $.grep(this.getResources(), function(resource) {
  61526. return $.inArray(resource.field, fields) > -1
  61527. })
  61528. },
  61529. getResourceForPainting: function(groups) {
  61530. var resources = this.getResources(),
  61531. result;
  61532. $.each(resources, function(index, resource) {
  61533. if (resource.mainColor) {
  61534. result = resource;
  61535. return false
  61536. }
  61537. });
  61538. if (!result) {
  61539. if ($.isArray(groups) && groups.length)
  61540. resources = this.getResourcesByFields(groups);
  61541. result = resources[resources.length - 1]
  61542. }
  61543. return result
  61544. }
  61545. });
  61546. DX.ui.dxScheduler.dxSchedulerResourceManager = ResourceManager
  61547. })(jQuery, DevExpress);
  61548. /*! Module widgets-web, file ui.scheduler.publisherMixin.js */
  61549. (function($, DX, undefined) {
  61550. var ui = DX.ui;
  61551. ui.dxScheduler.PublisherMixin = {notifyObserver: function(subject, args) {
  61552. var observer = this.option("observer");
  61553. if (observer)
  61554. observer.fire(subject, args)
  61555. }}
  61556. })(jQuery, DevExpress);
  61557. /*! Module widgets-web, file ui.scheduler.navigator.js */
  61558. (function($, DX, undefined) {
  61559. var ui = DX.ui,
  61560. utils = DX.utils;
  61561. var ELEMENT_CLASS = "dx-scheduler-navigator",
  61562. NEXT_BUTTON_CLASS = "dx-scheduler-navigator-next",
  61563. CAPTION_BUTTON_CLASS = "dx-scheduler-navigator-caption",
  61564. PREVIOUS_BUTTON_CLASS = "dx-scheduler-navigator-previous";
  61565. var getWeekCaption = function(date, shift) {
  61566. var firstWeekDate = utils.getFirstWeekDate(date, shift ? this.option("firstDayOfWeek") || 1 : this.option("firstDayOfWeek")),
  61567. lastWeekDate = new Date(firstWeekDate);
  61568. shift = shift || 6;
  61569. lastWeekDate = new Date(lastWeekDate.setDate(lastWeekDate.getDate() + shift));
  61570. return Globalize.format(firstWeekDate, " d") + "-" + Globalize.format(lastWeekDate, "d MMMM yyyy")
  61571. };
  61572. var CONFIG = {
  61573. day: {
  61574. duration: 1,
  61575. setter: "setDate",
  61576. getter: "getDate",
  61577. getCaption: function(date) {
  61578. return Globalize.format(date, "d MMMM yyyy")
  61579. }
  61580. },
  61581. week: {
  61582. duration: 7,
  61583. setter: "setDate",
  61584. getter: "getDate",
  61585. getCaption: getWeekCaption
  61586. },
  61587. workWeek: {
  61588. duration: 7,
  61589. setter: "setDate",
  61590. getter: "getDate",
  61591. getCaption: function(date) {
  61592. return getWeekCaption.call(this, date, 4)
  61593. }
  61594. },
  61595. month: {
  61596. duration: 1,
  61597. setter: "setMonth",
  61598. getter: "getMonth",
  61599. getCaption: function(date) {
  61600. return Globalize.format(date, "MMMM yyyy")
  61601. }
  61602. }
  61603. };
  61604. DX.registerComponent("dxSchedulerNavigator", ui.dxScheduler, ui.Widget.inherit({
  61605. _setDefaultOptions: function() {
  61606. this.callBase();
  61607. this.option({
  61608. date: new Date,
  61609. step: "day",
  61610. firstDayOfWeek: undefined
  61611. })
  61612. },
  61613. _optionChanged: function(args) {
  61614. switch (args.name) {
  61615. case"step":
  61616. case"date":
  61617. this._renderCaption();
  61618. break;
  61619. case"firstDayOfWeek":
  61620. if (this._calendar)
  61621. this._calendar.option(args.name, args.value);
  61622. break;
  61623. case"tabIndex":
  61624. case"focusStateEnabled":
  61625. this._next.option(args.name, args.value);
  61626. this._caption.option(args.name, args.value);
  61627. this._prev.option(args.name, args.value);
  61628. this.callBase(args);
  61629. break;
  61630. default:
  61631. this.callBase(args)
  61632. }
  61633. },
  61634. _init: function() {
  61635. this.callBase();
  61636. this.element().addClass(ELEMENT_CLASS);
  61637. this._initButtons()
  61638. },
  61639. _initButtons: function() {
  61640. var $next = $("<div>").addClass(NEXT_BUTTON_CLASS);
  61641. this._next = this._createComponent($next, "dxButton", {
  61642. icon: "chevronnext",
  61643. onClick: $.proxy(this._updateCurrentDate, this, 1),
  61644. focusStateEnabled: this.option("focusStateEnabled"),
  61645. tabIndex: this.option("tabIndex"),
  61646. _templates: {}
  61647. });
  61648. var $caption = $("<div>").addClass(CAPTION_BUTTON_CLASS);
  61649. this._caption = this._createComponent($caption, "dxButton", {
  61650. focusStateEnabled: this.option("focusStateEnabled"),
  61651. tabIndex: this.option("tabIndex"),
  61652. _templates: {}
  61653. });
  61654. var $prev = $("<div>").addClass(PREVIOUS_BUTTON_CLASS);
  61655. this._prev = this._createComponent($prev, "dxButton", {
  61656. icon: "chevronprev",
  61657. onClick: $.proxy(this._updateCurrentDate, this, -1),
  61658. focusStateEnabled: this.option("focusStateEnabled"),
  61659. tabIndex: this.option("tabIndex"),
  61660. _templates: {}
  61661. });
  61662. this.setAria("label", "Next period", $next);
  61663. this.setAria("label", "Previous period", $prev);
  61664. this.element().append($prev, $caption, $next)
  61665. },
  61666. _updateCurrentDate: function(direction) {
  61667. var stepConfig = this._getConfig(),
  61668. offset = stepConfig.duration * direction,
  61669. date = new Date(this.option("date"));
  61670. date[stepConfig.setter](date[stepConfig.getter]() + offset);
  61671. this.notifyObserver("updateCurrentDate", date)
  61672. },
  61673. _renderFocusTarget: $.noop,
  61674. _render: function() {
  61675. this.callBase();
  61676. this._renderPopover();
  61677. this._renderCaption()
  61678. },
  61679. _renderPopover: function() {
  61680. this._popover = this._createComponent("<div>", "dxPopover", {
  61681. target: this._caption.element(),
  61682. onContentReady: $.proxy(this._popoverContentReadyHandler, this)
  61683. });
  61684. this._popover.element().appendTo(this.element())
  61685. },
  61686. _popoverContentReadyHandler: function() {
  61687. this._calendar = this._createComponent($("<div>"), "dxCalendar", this._calendarOptions());
  61688. this._popover.content().append(this._calendar.element())
  61689. },
  61690. _calendarOptions: function() {
  61691. return {
  61692. firstDayOfWeek: this.option("firstDayOfWeek"),
  61693. value: this.option("date"),
  61694. onValueChanged: $.proxy(function(e) {
  61695. this.notifyObserver("updateCurrentDate", e.value);
  61696. this._popover.hide()
  61697. }, this)
  61698. }
  61699. },
  61700. _renderCaption: function() {
  61701. var date = this.option("date"),
  61702. caption = this._getConfig().getCaption.call(this, date);
  61703. this._caption.option({
  61704. text: caption,
  61705. onClick: $.proxy(function() {
  61706. this._popover.toggle()
  61707. }, this)
  61708. })
  61709. },
  61710. _getConfig: function() {
  61711. var step = this.option("step"),
  61712. config = CONFIG[step];
  61713. if (!config)
  61714. throw DX.Error("E1033", step);
  61715. return config
  61716. }
  61717. }).include(ui.dxScheduler.PublisherMixin))
  61718. })(jQuery, DevExpress);
  61719. /*! Module widgets-web, file ui.scheduler.header.js */
  61720. (function($, DX, undefined) {
  61721. var ui = DX.ui;
  61722. var COMPONENT_CLASS = "dx-scheduler-header",
  61723. VIEW_SWITCHER_CLASS = "dx-scheduler-view-switcher";
  61724. DX.registerComponent("dxSchedulerHeader", ui.dxScheduler, ui.Widget.inherit({
  61725. _setDefaultOptions: function() {
  61726. this.callBase();
  61727. this.option({
  61728. views: [],
  61729. currentView: "day",
  61730. firstDayOfWeek: undefined,
  61731. currentDate: new Date
  61732. })
  61733. },
  61734. _optionChanged: function(args) {
  61735. var value = args.value;
  61736. switch (args.name) {
  61737. case"views":
  61738. this._viewSwitcher.option("items", value);
  61739. break;
  61740. case"currentView":
  61741. this._viewSwitcher.option("selectedItem", value);
  61742. this._navigator.option("step", value);
  61743. break;
  61744. case"currentDate":
  61745. this._navigator.option("date", value);
  61746. break;
  61747. case"firstDayOfWeek":
  61748. this._navigator.option("firstDayOfWeek", value);
  61749. break;
  61750. case"tabIndex":
  61751. case"focusStateEnabled":
  61752. this._viewSwitcher.option(args.name, value);
  61753. this._navigator.option(args.name, value);
  61754. this.callBase(args);
  61755. break;
  61756. default:
  61757. this.callBase(args)
  61758. }
  61759. },
  61760. _init: function() {
  61761. this.callBase();
  61762. this.element().addClass(COMPONENT_CLASS);
  61763. this._navigator = this._createComponent("<div>", "dxSchedulerNavigator", {
  61764. date: this.option("currentDate"),
  61765. step: this.option("currentView"),
  61766. firstDayOfWeek: this.option("firstDayOfWeek"),
  61767. tabIndex: this.option("tabIndex"),
  61768. focusStateEnabled: this.option("focusStateEnabled"),
  61769. observer: this.option("observer")
  61770. });
  61771. this._navigator.element().appendTo(this.element());
  61772. var $viewSwitcher = $("<div>").addClass(VIEW_SWITCHER_CLASS).appendTo(this.element());
  61773. this._viewSwitcher = this._createComponent($viewSwitcher, "dxTabs", {
  61774. selectionRequired: true,
  61775. scrollingEnabled: false,
  61776. onSelectionChanged: $.proxy(this._updateCurrentView, this),
  61777. items: this.option("views"),
  61778. itemTemplate: function(item) {
  61779. return $("<span>").addClass("dx-tab-text").text(Globalize.localize("dxScheduler-switcher" + DX.inflector.camelize(item, true)))
  61780. },
  61781. selectedItem: this.option("currentView"),
  61782. tabIndex: this.option("tabIndex"),
  61783. focusStateEnabled: this.option("focusStateEnabled")
  61784. })
  61785. },
  61786. _updateCurrentView: function(e) {
  61787. var selectedItem = e.component.option("selectedItem");
  61788. this.notifyObserver("currentViewUpdated", selectedItem)
  61789. },
  61790. _renderFocusTarget: $.noop
  61791. }).include(ui.dxScheduler.PublisherMixin))
  61792. })(jQuery, DevExpress);
  61793. /*! Module widgets-web, file ui.scheduler.workSpace.js */
  61794. (function($, DX, undefined) {
  61795. var ui = DX.ui,
  61796. utils = DX.utils,
  61797. events = ui.events;
  61798. var COMPONENT_CLASS = "dx-scheduler-work-space",
  61799. GROUPED_WORKSPACE_CLASS = "dx-scheduler-work-space-grouped",
  61800. TIME_PANEL_CLASS = "dx-scheduler-time-panel",
  61801. TIME_PANEL_CELL_CLASS = "dx-scheduler-time-panel-cell",
  61802. TIME_PANEL_ROW_CLASS = "dx-scheduler-time-panel-row",
  61803. ALL_DAY_PANEL_CLASS = "dx-scheduler-all-day-panel",
  61804. ALL_DAY_TABLE_CLASS = "dx-scheduler-all-day-table",
  61805. ALL_DAY_CONTAINER_CLASS = "dx-scheduler-all-day-container",
  61806. ALL_DAY_TITLE_CLASS = "dx-scheduler-all-day-title",
  61807. ALL_DAY_TABLE_CELL_CLASS = "dx-scheduler-all-day-table-cell",
  61808. ALL_DAY_TABLE_ROW_CLASS = "dx-scheduler-all-day-table-row",
  61809. HEADER_PANEL_CLASS = "dx-scheduler-header-panel",
  61810. HEADER_PANEL_CELL_CLASS = "dx-scheduler-header-panel-cell",
  61811. HEADER_ROW_CLASS = "dx-scheduler-header-row",
  61812. GROUP_ROW_CLASS = "dx-scheduler-group-row",
  61813. GROUP_HEADER_CLASS = "dx-scheduler-group-header",
  61814. DATE_TABLE_CLASS = "dx-scheduler-date-table",
  61815. DATE_TABLE_CELL_CLASS = "dx-scheduler-date-table-cell",
  61816. DATE_TABLE_ROW_CLASS = "dx-scheduler-date-table-row",
  61817. DATE_TABLE_CURRENT_DATE_CLASS = "dx-scheduler-date-table-current-date",
  61818. DATE_TABLE_OTHER_MONTH_DATE_CLASS = "dx-scheduler-date-table-other-month",
  61819. DATE_TABLE_DROPPABLE_CELL_CLASS = "dx-scheduler-date-table-droppable-cell",
  61820. SCHEDULER_WORKSPACE_DXPOINTERDOWN_EVENT_NAME = events.addNamespace("dxpointerdown", "dxSchedulerWorkSpace"),
  61821. SCHEDULER_CELL_DXDRAGENTER_EVENT_NAME = events.addNamespace("dxdragenter", "dxSchedulerDateTable"),
  61822. SCHEDULER_CELL_DXDROP_EVENT_NAME = events.addNamespace("dxdrop", "dxSchedulerDateTable"),
  61823. FOCUSED_STATE_CLASS = "dx-state-focused",
  61824. CELL_DATA = "dxCellData";
  61825. DX.registerComponent("dxSchedulerWorkSpace", ui.dxScheduler, ui.Widget.inherit({
  61826. _supportedKeys: function() {
  61827. var isRTL = this.option("rtlEnabled");
  61828. var click = function(e) {
  61829. e.preventDefault();
  61830. e.stopPropagation();
  61831. if (this._$focusedCell && this._$focusedCell.length)
  61832. this._showAddAppointmentPopup(this._$focusedCell)
  61833. };
  61834. return $.extend(this.callBase(), {
  61835. enter: click,
  61836. space: click,
  61837. downArrow: function(e) {
  61838. e.preventDefault();
  61839. e.stopPropagation();
  61840. var cellIndex = this._getFocusedCell().index(),
  61841. $row = this._getFocusedCell().parent(),
  61842. $cell = $row.next().children().eq(cellIndex);
  61843. this._setFocusedCell($cell)
  61844. },
  61845. upArrow: function(e) {
  61846. e.preventDefault();
  61847. e.stopPropagation();
  61848. var cellIndex = this._getFocusedCell().index(),
  61849. $row = this._getFocusedCell().parent(),
  61850. $cell = $row.prev().children().eq(cellIndex);
  61851. this._setFocusedCell($cell)
  61852. },
  61853. rightArrow: function(e) {
  61854. e.preventDefault();
  61855. e.stopPropagation();
  61856. var $cell = isRTL ? this._getFocusedCell().prev() : this._getFocusedCell().next();
  61857. this._setFocusedCell($cell)
  61858. },
  61859. leftArrow: function(e) {
  61860. e.preventDefault();
  61861. e.stopPropagation();
  61862. var $cell = isRTL ? this._getFocusedCell().next() : this._getFocusedCell().prev();
  61863. this._setFocusedCell($cell)
  61864. }
  61865. })
  61866. },
  61867. _getFocusedCell: function() {
  61868. return this._$focusedCell || this._$dateTable.find("." + DATE_TABLE_CELL_CLASS).eq(0)
  61869. },
  61870. _setFocusedCell: function($cell) {
  61871. if (!$cell.length)
  61872. return;
  61873. this._releaseFocusedCell();
  61874. $cell.addClass(FOCUSED_STATE_CLASS);
  61875. if (utils.isDefined(this._$focusedCell))
  61876. this.setAria("label", undefined, this._$focusedCell);
  61877. this._$focusedCell = $cell;
  61878. this.setAria("label", "Add appointment", this._$focusedCell);
  61879. this._scrollable.scrollToElement($cell)
  61880. },
  61881. _releaseFocusedCell: function() {
  61882. if (utils.isDefined(this._$focusedCell))
  61883. this._$focusedCell.removeClass(FOCUSED_STATE_CLASS)
  61884. },
  61885. _focusTarget: function() {
  61886. return this.element()
  61887. },
  61888. _focusInHandler: function(e) {
  61889. if ($(e.target).is(this._focusTarget()) && this._isCellClick !== false) {
  61890. delete this._isCellClick;
  61891. this.callBase.apply(this, arguments);
  61892. var $cell = this._getFocusedCell();
  61893. this._setFocusedCell($cell)
  61894. }
  61895. },
  61896. _focusOutHandler: function(e) {
  61897. this.callBase.apply(this, arguments);
  61898. this._releaseFocusedCell()
  61899. },
  61900. _activeStateUnit: "." + DATE_TABLE_CELL_CLASS + ", ." + ALL_DAY_TABLE_CELL_CLASS,
  61901. _setDefaultOptions: function() {
  61902. this.callBase();
  61903. this.option({
  61904. currentDate: new Date,
  61905. firstDayOfWeek: undefined,
  61906. startDayHour: 0,
  61907. endDayHour: 24,
  61908. hoursInterval: 0.5,
  61909. activeStateEnabled: true,
  61910. hoverStateEnabled: true,
  61911. groups: []
  61912. })
  61913. },
  61914. _optionChanged: function(args) {
  61915. var that = this;
  61916. function rerenderView() {
  61917. that._cleanView();
  61918. that._setFirstViewDate();
  61919. that._renderView()
  61920. }
  61921. switch (args.name) {
  61922. case"firstDayOfWeek":
  61923. case"currentDate":
  61924. case"groups":
  61925. this._toggleGroupedClass();
  61926. rerenderView();
  61927. break;
  61928. case"startDayHour":
  61929. case"endDayHour":
  61930. rerenderView();
  61931. break;
  61932. default:
  61933. this.callBase(args)
  61934. }
  61935. },
  61936. _init: function() {
  61937. this.callBase();
  61938. this.element().addClass(COMPONENT_CLASS);
  61939. this._$headerPanel = $("<table>").addClass(HEADER_PANEL_CLASS);
  61940. this._$allDayTable = $("<table>").addClass(ALL_DAY_TABLE_CLASS);
  61941. this._$allDayPanel = $("<div>").append($("<div>").addClass(ALL_DAY_CONTAINER_CLASS)).append($("<div>").addClass(ALL_DAY_TITLE_CLASS).text(Globalize.localize("dxScheduler-allDay"))).append(this._$allDayTable).addClass(ALL_DAY_PANEL_CLASS);
  61942. this._$timePanel = $("<table>").addClass(TIME_PANEL_CLASS);
  61943. this._$dateTable = $("<table>").addClass(DATE_TABLE_CLASS);
  61944. this._scrollable = this._createComponent("<div>", "dxScrollable", {useKeyboard: false});
  61945. this._scrollable.content().append(this._$timePanel, this._$dateTable);
  61946. this.element().append(this._$headerPanel, this._$allDayPanel, this._scrollable.element());
  61947. this.element().addClass(this._getElementClass())
  61948. },
  61949. _getElementClass: $.noop,
  61950. _getRowCount: $.noop,
  61951. _getCellCount: $.noop,
  61952. _render: function() {
  61953. this.callBase();
  61954. this._setFirstViewDate();
  61955. this._renderView();
  61956. this._toggleGroupedClass();
  61957. this._attachEvents()
  61958. },
  61959. _setFirstViewDate: function() {
  61960. this._firstViewDate = utils.getFirstWeekDate(this.option("currentDate"), this._firstDayOfWeek());
  61961. if (this.option("startDayHour"))
  61962. this._firstViewDate.setHours(this.option("startDayHour"))
  61963. },
  61964. _firstDayOfWeek: function() {
  61965. return this.option("firstDayOfWeek")
  61966. },
  61967. _renderView: function() {
  61968. this._renderHeaderPanel();
  61969. this._renderAllDayPanel();
  61970. this._renderTimePanel();
  61971. this._renderDateTable()
  61972. },
  61973. _toggleGroupedClass: function() {
  61974. this.element().toggleClass(GROUPED_WORKSPACE_CLASS, this.option("groups").length > 0)
  61975. },
  61976. _attachEvents: function() {
  61977. var pointerDownAction = this._createAction($.proxy(this._pointerDownHandler, this));
  61978. this.element().off(SCHEDULER_WORKSPACE_DXPOINTERDOWN_EVENT_NAME).on(SCHEDULER_WORKSPACE_DXPOINTERDOWN_EVENT_NAME, function(e) {
  61979. pointerDownAction({jQueryEvent: e})
  61980. })
  61981. },
  61982. _pointerDownHandler: function(e) {
  61983. var $target = $(e.jQueryEvent.target);
  61984. if (!$target.hasClass(DATE_TABLE_CELL_CLASS) && !$target.hasClass(ALL_DAY_TABLE_CELL_CLASS)) {
  61985. this._isCellClick = false;
  61986. return
  61987. }
  61988. this._isCellClick = true;
  61989. if ($target.hasClass(FOCUSED_STATE_CLASS))
  61990. this._showAddAppointmentPopup($target);
  61991. else
  61992. this._setFocusedCell($target)
  61993. },
  61994. _showAddAppointmentPopup: function($cell) {
  61995. var cellData = $cell.data(CELL_DATA),
  61996. args = $.extend(cellData, cellData.groups);
  61997. delete cellData.groups;
  61998. this.notifyObserver("showAddAppointmentPopup", args)
  61999. },
  62000. _renderHeaderPanel: function() {
  62001. var $head = $("<thead>");
  62002. this._renderGroupHeader($head);
  62003. this._renderDateHeader($head);
  62004. this._$headerPanel.append($head)
  62005. },
  62006. _renderDateHeader: function($element) {
  62007. var $headerRow = $("<tr>").addClass(HEADER_ROW_CLASS),
  62008. count = this._getCellCount(),
  62009. groupCount = this._getGroupCount() || 1;
  62010. for (var j = 0; j < groupCount; j++)
  62011. for (var i = 0; i < count; i++) {
  62012. var text = this._getHeaderText(i),
  62013. $cell = $("<th>").text(text).addClass(HEADER_PANEL_CELL_CLASS).attr("title", text);
  62014. $headerRow.append($cell)
  62015. }
  62016. $element.append($headerRow)
  62017. },
  62018. _renderGroupHeader: function($element) {
  62019. var groupCount = this._getGroupCount();
  62020. if (groupCount) {
  62021. var groupRows = this._makeGroupRows(this.option("groups"));
  62022. this.element().attr("dx-group-row-count", groupRows.length);
  62023. $element.append(groupRows)
  62024. }
  62025. },
  62026. _makeGroupRows: function(groups) {
  62027. var repeatCount = 1,
  62028. groupCount = groups.length,
  62029. cellCount = this._getCellCount() || 1,
  62030. rows = [];
  62031. for (var i = 0; i < groupCount; i++) {
  62032. if (i > 0)
  62033. repeatCount = groups[i - 1].items.length * repeatCount;
  62034. var cells = this._makeGroupRowCells(groups[i].items, repeatCount);
  62035. rows.push($("<tr>").addClass(GROUP_ROW_CLASS).append(cells))
  62036. }
  62037. var maxCellCount = rows[groupCount - 1].find("th").length;
  62038. for (var j = 0; j < groupCount; j++) {
  62039. var $cell = rows[j].find("th"),
  62040. colspan = maxCellCount / $cell.length * cellCount;
  62041. if (colspan > 1)
  62042. $cell.attr("colspan", colspan)
  62043. }
  62044. return rows
  62045. },
  62046. _makeGroupRowCells: function(items, repeatCount) {
  62047. var cells = [],
  62048. itemCount = items.length;
  62049. for (var i = 0; i < repeatCount; i++)
  62050. for (var j = 0; j < itemCount; j++)
  62051. cells.push($("<th>").addClass(GROUP_HEADER_CLASS).text(items[j].text));
  62052. return cells
  62053. },
  62054. _renderAllDayPanel: function() {
  62055. var cellCount = this._getCellCount() * (this._getGroupCount() || 1),
  62056. that = this;
  62057. this._renderTableBody({
  62058. container: this._$allDayTable,
  62059. rowCount: 1,
  62060. cellCount: cellCount,
  62061. cellClass: ALL_DAY_TABLE_CELL_CLASS,
  62062. rowClass: ALL_DAY_TABLE_ROW_CLASS,
  62063. dataGenerator: function($cell, rowIndex, cellIndex) {
  62064. var startDate = that._getDateByCellIndexes(rowIndex, cellIndex);
  62065. utils.correctDateWithUnitBeginning(startDate, "day");
  62066. var data = {
  62067. startDate: startDate,
  62068. endDate: new Date(startDate.getTime() + 24 * 60 * 60000),
  62069. allDay: true
  62070. };
  62071. var groups = that._getCellGroups(cellIndex);
  62072. if (groups.length)
  62073. data.groups = {};
  62074. for (var i = 0; i < groups.length; i++)
  62075. data.groups[groups[i].name] = groups[i].id;
  62076. $cell.data(CELL_DATA, data)
  62077. }
  62078. })
  62079. },
  62080. _renderTimePanel: function() {
  62081. this._renderTableBody({
  62082. container: this._$timePanel,
  62083. rowCount: this._calculateDayDuration(),
  62084. cellCount: 1,
  62085. cellClass: TIME_PANEL_CELL_CLASS,
  62086. rowClass: TIME_PANEL_ROW_CLASS
  62087. });
  62088. var startDayHour = this.option("startDayHour");
  62089. this._$timePanel.find("td").each(function(index) {
  62090. $(this).text(Globalize.format(new Date(new Date(1970, 0).getTime() + 3600000 * (startDayHour + index)), "t"))
  62091. })
  62092. },
  62093. _calculateDayDuration: function() {
  62094. return this.option("endDayHour") - this.option("startDayHour")
  62095. },
  62096. _renderDateTable: function() {
  62097. var cellCount = this._getCellCount() * (this._getGroupCount() || 1),
  62098. that = this;
  62099. this._renderTableBody({
  62100. container: this._$dateTable,
  62101. rowCount: this._getRowCount(),
  62102. cellCount: cellCount,
  62103. cellClass: DATE_TABLE_CELL_CLASS,
  62104. rowClass: DATE_TABLE_ROW_CLASS,
  62105. dataGenerator: function($cell, rowIndex, cellIndex) {
  62106. var startDate = that._getDateByCellIndexes(rowIndex, cellIndex),
  62107. data = {
  62108. startDate: startDate,
  62109. endDate: that._calculateEndDate(startDate),
  62110. allDay: that._getTableAllDay()
  62111. };
  62112. $cell.toggleClass(DATE_TABLE_CURRENT_DATE_CLASS, that._isCurrentDateCell(startDate)).toggleClass(DATE_TABLE_OTHER_MONTH_DATE_CLASS, that._isOtherMonth(startDate));
  62113. var groups = that._getCellGroups(cellIndex);
  62114. if (groups.length)
  62115. data.groups = {};
  62116. for (var i = 0; i < groups.length; i++)
  62117. data.groups[groups[i].name] = groups[i].id;
  62118. $cell.data(CELL_DATA, data)
  62119. }
  62120. });
  62121. this._attachTableEvents()
  62122. },
  62123. _getTableAllDay: function() {
  62124. return false
  62125. },
  62126. _isCurrentDateCell: function(cellDate) {
  62127. var today = new Date;
  62128. return utils.sameMonthAndYear(cellDate, today) && cellDate.getDate() === today.getDate()
  62129. },
  62130. _isOtherMonth: function(cellDate) {
  62131. return cellDate.getMonth() !== this.option("currentDate").getMonth()
  62132. },
  62133. _calculateEndDate: function(startDate) {
  62134. return new Date(startDate.getTime() + this._getInterval())
  62135. },
  62136. _getGroupCount: function() {
  62137. var groups = this.option("groups"),
  62138. result = 0;
  62139. for (var i = 0, len = groups.length; i < len; i++)
  62140. if (!i)
  62141. result = groups[i].items.length;
  62142. else
  62143. result *= groups[i].items.length;
  62144. return result
  62145. },
  62146. _getPathToLeaf: function(leafIndex) {
  62147. var tree = this._createGroupTree(this.option("groups")[0], 0);
  62148. function findLeafByIndex(data, index) {
  62149. for (var i = 0; i < data.length; i++)
  62150. if (data[i].leafIndex === index)
  62151. return data[i];
  62152. else {
  62153. var leaf = findLeafByIndex(data[i].children, index);
  62154. if (leaf)
  62155. return leaf
  62156. }
  62157. }
  62158. function makeBranch(leaf, result) {
  62159. result = result || [];
  62160. result.push(leaf.value);
  62161. if (leaf.parent)
  62162. makeBranch(leaf.parent, result);
  62163. return result
  62164. }
  62165. var leaf = findLeafByIndex(tree, leafIndex);
  62166. return makeBranch(leaf).reverse()
  62167. },
  62168. _getCellGroups: function(index) {
  62169. var result = [];
  62170. if (this._getGroupCount()) {
  62171. var groupIndex = Math.floor(index / this._getCellCount()),
  62172. groups = this.option("groups");
  62173. if (groupIndex < 0)
  62174. return;
  62175. var path = this._getPathToLeaf(groupIndex);
  62176. for (var i = 0; i < groups.length; i++)
  62177. result.push({
  62178. name: groups[i].name,
  62179. id: path[i]
  62180. })
  62181. }
  62182. return result
  62183. },
  62184. _attachTableEvents: function() {
  62185. var $currentTarget,
  62186. cellHeight,
  62187. cellWidth;
  62188. this._getDateTables().off(SCHEDULER_CELL_DXDRAGENTER_EVENT_NAME).off(SCHEDULER_CELL_DXDROP_EVENT_NAME).on(SCHEDULER_CELL_DXDRAGENTER_EVENT_NAME, "td", {itemSizeFunc: function($element) {
  62189. if (!cellHeight)
  62190. cellHeight = $element.height();
  62191. if (!cellWidth)
  62192. cellWidth = $element.width();
  62193. return {
  62194. width: cellWidth,
  62195. height: cellHeight
  62196. }
  62197. }}, function(e) {
  62198. if ($currentTarget)
  62199. $currentTarget.removeClass(DATE_TABLE_DROPPABLE_CELL_CLASS);
  62200. $currentTarget = $(e.target);
  62201. $currentTarget.addClass(DATE_TABLE_DROPPABLE_CELL_CLASS)
  62202. }).on(SCHEDULER_CELL_DXDROP_EVENT_NAME, "td", function(e) {
  62203. $(e.target).removeClass(DATE_TABLE_DROPPABLE_CELL_CLASS);
  62204. cellHeight = 0;
  62205. cellWidth = 0
  62206. })
  62207. },
  62208. _getDateTables: function() {
  62209. return this._$dateTable.add(this._$allDayTable)
  62210. },
  62211. _getInterval: function() {
  62212. return this.option("hoursInterval") * 3600000
  62213. },
  62214. _getHeaderText: function(headerIndex) {
  62215. return Globalize.format(this._getDateByIndex(headerIndex), this._getFormat()).toUpperCase()
  62216. },
  62217. _getDateByIndex: DX.abstract,
  62218. _getFormat: DX.abstract,
  62219. _getCellText: function(rowIndex, cellIndex) {
  62220. return ""
  62221. },
  62222. _calculateCellIndex: function(rowIndex, cellIndex) {
  62223. cellIndex = cellIndex % this._getCellCount();
  62224. var virtualRowCount = this._getVirtualRowCount();
  62225. return (this._getRowCount() + virtualRowCount) * cellIndex + rowIndex
  62226. },
  62227. _getVirtualRowCount: function() {
  62228. return this.option("startDayHour") / this.option("hoursInterval") + this._getEndDayHours() / this.option("hoursInterval")
  62229. },
  62230. _getEndDayHours: function() {
  62231. return 24 - this.option("endDayHour")
  62232. },
  62233. _getEndDayMilliseconds: function() {
  62234. return this._getEndDayHours() * 3600000
  62235. },
  62236. _renderTableBody: function(options) {
  62237. var rows = [];
  62238. for (var i = 0; i < options.rowCount; i++) {
  62239. var $row = $("<tr>");
  62240. if (options.rowClass)
  62241. $row.addClass(options.rowClass);
  62242. for (var j = 0; j < options.cellCount; j++) {
  62243. var $td = $("<td>").text(this._getCellText(i, j));
  62244. if (options.cellClass)
  62245. $td.addClass(options.cellClass);
  62246. if ($.isFunction(options.dataGenerator))
  62247. options.dataGenerator($td, i, j);
  62248. $row.append($td)
  62249. }
  62250. rows.push($row)
  62251. }
  62252. options.container.append($("<tbody>").append(rows))
  62253. },
  62254. _cleanView: function() {
  62255. this._$headerPanel.empty();
  62256. this._$dateTable.empty();
  62257. this._$timePanel.empty();
  62258. this._$allDayTable.empty()
  62259. },
  62260. getWorkArea: function() {
  62261. return this._scrollable.content()
  62262. },
  62263. _getCellCoordinatesByIndex: function(index) {
  62264. var cellIndex = Math.floor(index / this._getRowCount()),
  62265. rowIndex = index - this._getRowCount() * cellIndex;
  62266. return {
  62267. cellIndex: cellIndex,
  62268. rowIndex: rowIndex
  62269. }
  62270. },
  62271. _createGroupTree: function(group, groupIndex) {
  62272. var leafIndex = 0;
  62273. function make(group, groupIndex, result, parent) {
  62274. result = result || [];
  62275. for (var i = 0; i < group.items.length; i++) {
  62276. var resultItem = {
  62277. name: group.name,
  62278. value: group.items[i].id,
  62279. children: [],
  62280. parent: parent ? parent : null
  62281. };
  62282. result.push(resultItem);
  62283. var nextGroupIndex = groupIndex + 1;
  62284. if (this.option("groups")[nextGroupIndex])
  62285. make.call(this, this.option("groups")[nextGroupIndex], nextGroupIndex, resultItem.children, resultItem);
  62286. if (!resultItem.children.length) {
  62287. resultItem.leafIndex = leafIndex;
  62288. leafIndex++
  62289. }
  62290. }
  62291. return result
  62292. }
  62293. return make.call(this, group, groupIndex)
  62294. },
  62295. _hasGroupItem: function(groups, groupName, itemValue) {
  62296. var group = groups[groupName];
  62297. if (group)
  62298. if ($.inArray(itemValue, group) > -1)
  62299. return true;
  62300. return false
  62301. },
  62302. _grep: function(tree, groups, result) {
  62303. result = result || [];
  62304. for (var i = 0; i < tree.length; i++) {
  62305. if (!this._hasGroupItem(groups, tree[i].name, tree[i].value))
  62306. continue;
  62307. if (utils.isDefined(tree[i].leafIndex))
  62308. result.push(tree[i].leafIndex);
  62309. if (tree[i].children)
  62310. this._grep(tree[i].children, groups, result)
  62311. }
  62312. return result
  62313. },
  62314. _getDateByCellIndexes: function(rowIndex, cellIndex) {
  62315. var millisecondsOffset = this._getInterval() * this._calculateCellIndex(rowIndex, cellIndex);
  62316. return new Date(this._firstViewDate.getTime() + millisecondsOffset)
  62317. },
  62318. _getCellTimeOffset: function(dateTimeStamp) {
  62319. var timeInterval = this._getInterval(),
  62320. timeOffset = dateTimeStamp % timeInterval;
  62321. return timeOffset ? timeOffset / timeInterval : 0
  62322. },
  62323. _calculateTimeDurationBetweenFirstViewDateAndCurrentDate: function(currentDate, allDay) {
  62324. var firstViewDate = this._firstViewDate.getTime();
  62325. if (allDay)
  62326. firstViewDate = firstViewDate - this.option("startDayHour") * 60 * 60 * 1000;
  62327. var result = currentDate.getTime() - firstViewDate,
  62328. days = Math.floor(result / (24 * 60 * 60 * 1000));
  62329. if (!allDay)
  62330. result = result - days * this.option("startDayHour") * 3600000 - days * this._getEndDayMilliseconds();
  62331. return result
  62332. },
  62333. _getGroupIndexes: function(groups) {
  62334. var indexes = [];
  62335. if (groups && this.option("groups").length) {
  62336. var tree = this._createGroupTree(this.option("groups")[0], 0);
  62337. indexes = this._grep(tree, groups)
  62338. }
  62339. return indexes
  62340. },
  62341. _updateIndex: function(index) {
  62342. return index * this._getRowCount()
  62343. },
  62344. getCoordinatesByDate: function(date, groupIndex, allDay) {
  62345. var isRtl = this.option("rtlEnabled"),
  62346. stepsCount = this._getCellCount() * this._getRowCount(),
  62347. timeInterval = allDay ? 24 * 60 * 60 * 1000 : this._getInterval(),
  62348. dateTimeStamp = this._calculateTimeDurationBetweenFirstViewDateAndCurrentDate(date, allDay);
  62349. groupIndex = groupIndex || 0;
  62350. var index = Math.floor(dateTimeStamp / timeInterval);
  62351. if (allDay)
  62352. index = this._updateIndex(index);
  62353. Math.ceil(index / this._getRowCount()) * this.option("startDayHour") * 2;
  62354. if (index < 0 || index >= stepsCount)
  62355. return {
  62356. top: -1000,
  62357. left: -1000
  62358. };
  62359. var cellCoordinates = this._getCellCoordinatesByIndex(index),
  62360. $cell = this._$dateTable.find("tr").eq(cellCoordinates.rowIndex).find("td").eq(cellCoordinates.cellIndex + groupIndex * this._getCellCount()),
  62361. position = $cell.position();
  62362. position.top += $cell.height() * this._getCellTimeOffset(dateTimeStamp);
  62363. if (isRtl)
  62364. position.left += $cell.outerWidth();
  62365. return position
  62366. },
  62367. getCoordinatesByDateInGroup: function(date, groups, allDay) {
  62368. var indexes = this._getGroupIndexes(groups),
  62369. result = [];
  62370. if (indexes.length)
  62371. for (var i = 0; i < indexes.length; i++)
  62372. result.push(this.getCoordinatesByDate(date, indexes[i], allDay));
  62373. else
  62374. result.push(this.getCoordinatesByDate(date, 0, allDay));
  62375. return result
  62376. },
  62377. getDataByDroppableCell: function() {
  62378. var cellData = this._getDateTables().find("." + DATE_TABLE_DROPPABLE_CELL_CLASS).data(CELL_DATA);
  62379. return {
  62380. date: cellData.startDate,
  62381. allDay: cellData.allDay,
  62382. groups: cellData.groups
  62383. }
  62384. },
  62385. _getLastViewDate: function() {
  62386. var dateOfLastViewCell = this._getDateByCellIndexes(this._getRowCount() - 1, this._getCellCount() - 1);
  62387. return new Date(dateOfLastViewCell.getTime() + this._getInterval() - 60000)
  62388. },
  62389. getDateRange: function() {
  62390. return [this._firstViewDate, this._getLastViewDate()]
  62391. },
  62392. getCellWidth: function() {
  62393. return this.element().find("." + DATE_TABLE_CELL_CLASS).first().outerWidth()
  62394. },
  62395. getCellHeight: function() {
  62396. return this.element().find("." + DATE_TABLE_CELL_CLASS).first().outerHeight()
  62397. },
  62398. getAllDayHeight: function() {
  62399. return this.element().find("." + ALL_DAY_PANEL_CLASS + " td").first().outerHeight()
  62400. },
  62401. getMaxAllowedPosition: function() {
  62402. var result = [],
  62403. isRtl = this.option("rtlEnabled");
  62404. this._$dateTable.find("tr").first().find("td:nth-child(" + this._getCellCount() + "n)").each(function(_, cell) {
  62405. var maxPosition = $(cell).position().left;
  62406. if (!isRtl)
  62407. maxPosition += $(cell).outerWidth();
  62408. result.push(maxPosition)
  62409. });
  62410. return result
  62411. },
  62412. getAllDayContainerClass: function() {
  62413. return ALL_DAY_CONTAINER_CLASS
  62414. }
  62415. }).include(ui.dxScheduler.PublisherMixin))
  62416. })(jQuery, DevExpress);
  62417. /*! Module widgets-web, file ui.scheduler.workSpaceDay.js */
  62418. (function($, DX, undefined) {
  62419. var ui = DX.ui;
  62420. var DAY_CLASS = "dx-scheduler-work-space-day";
  62421. DX.registerComponent("dxSchedulerWorkSpaceDay", ui.dxScheduler, ui.dxScheduler.dxSchedulerWorkSpace.inherit({
  62422. _getElementClass: function() {
  62423. return DAY_CLASS
  62424. },
  62425. _getRowCount: function() {
  62426. var day = this._calculateDayDuration();
  62427. return day / this.option("hoursInterval")
  62428. },
  62429. _getCellCount: function() {
  62430. return 1
  62431. },
  62432. _setFirstViewDate: function() {
  62433. this._firstViewDate = this.option("currentDate");
  62434. if (this.option("startDayHour"))
  62435. this._firstViewDate.setHours(this.option("startDayHour"))
  62436. },
  62437. _getDateByIndex: function() {
  62438. return this._firstViewDate
  62439. },
  62440. _getFormat: function() {
  62441. return "D"
  62442. },
  62443. _renderDateHeader: $.noop
  62444. }))
  62445. })(jQuery, DevExpress);
  62446. /*! Module widgets-web, file ui.scheduler.workSpaceWeek.js */
  62447. (function($, DX, undefined) {
  62448. var ui = DX.ui;
  62449. var WEEK_CLASS = "dx-scheduler-work-space-week";
  62450. DX.registerComponent("dxSchedulerWorkSpaceWeek", ui.dxScheduler, ui.dxScheduler.dxSchedulerWorkSpace.inherit({
  62451. _getElementClass: function() {
  62452. return WEEK_CLASS
  62453. },
  62454. _getRowCount: function() {
  62455. var day = this._calculateDayDuration();
  62456. return day / this.option("hoursInterval")
  62457. },
  62458. _getCellCount: function() {
  62459. return 7
  62460. },
  62461. _getDateByIndex: function(headerIndex) {
  62462. var resultDate = new Date(this._firstViewDate);
  62463. resultDate.setDate(this._firstViewDate.getDate() + headerIndex);
  62464. return resultDate
  62465. },
  62466. _getFormat: function() {
  62467. return "ddd d"
  62468. }
  62469. }))
  62470. })(jQuery, DevExpress);
  62471. /*! Module widgets-web, file ui.scheduler.workSpaceWorkWeek.js */
  62472. (function($, DX, undefined) {
  62473. var ui = DX.ui;
  62474. var WORK_WEEK_CLASS = "dx-scheduler-work-space-work-week";
  62475. var weekendCounter = 0;
  62476. DX.registerComponent("dxSchedulerWorkSpaceWorkWeek", ui.dxScheduler, ui.dxScheduler.dxSchedulerWorkSpaceWeek.inherit({
  62477. _getElementClass: function() {
  62478. return WORK_WEEK_CLASS
  62479. },
  62480. _getCellCount: function() {
  62481. return 5
  62482. },
  62483. _firstDayOfWeek: function() {
  62484. return this.option("firstDayOfWeek") || 1
  62485. },
  62486. _getDateByIndex: function(headerIndex) {
  62487. var resultDate = new Date(this._firstViewDate);
  62488. resultDate.setDate(this._firstViewDate.getDate() + headerIndex + weekendCounter);
  62489. var day = resultDate.getDay();
  62490. if (day % 6 === 0) {
  62491. weekendCounter = Math.floor(day / 6 + 1);
  62492. resultDate.setDate(resultDate.getDate() + weekendCounter)
  62493. }
  62494. return resultDate
  62495. },
  62496. _renderHeaderPanel: function() {
  62497. weekendCounter = 0;
  62498. this.callBase()
  62499. }
  62500. }))
  62501. })(jQuery, DevExpress);
  62502. /*! Module widgets-web, file ui.scheduler.workSpaceMonth.js */
  62503. (function($, DX, undefined) {
  62504. var ui = DX.ui,
  62505. utils = DX.utils;
  62506. var MONTH_CLASS = "dx-scheduler-work-space-month";
  62507. var DAYS_IN_WEEK = 7,
  62508. DAY_IN_MILLISECONDS = 86400000;
  62509. DX.registerComponent("dxSchedulerWorkSpaceMonth", ui.dxScheduler, ui.dxScheduler.dxSchedulerWorkSpace.inherit({
  62510. _getElementClass: function() {
  62511. return MONTH_CLASS
  62512. },
  62513. _getRowCount: function() {
  62514. return 6
  62515. },
  62516. _getCellCount: function() {
  62517. return DAYS_IN_WEEK
  62518. },
  62519. _getDateByIndex: function(headerIndex) {
  62520. var resultDate = new Date(this._firstViewDate);
  62521. resultDate.setDate(this._firstViewDate.getDate() + headerIndex);
  62522. return resultDate
  62523. },
  62524. _getFormat: function() {
  62525. return "ddd"
  62526. },
  62527. _calculateCellIndex: function(rowIndex, cellIndex) {
  62528. cellIndex = cellIndex % this._getCellCount();
  62529. return rowIndex * this._getCellCount() + cellIndex
  62530. },
  62531. _getInterval: function() {
  62532. return DAY_IN_MILLISECONDS
  62533. },
  62534. _calculateEndDate: function(startDate) {
  62535. var startDateCopy = new Date(startDate);
  62536. return new Date(startDateCopy.setHours(this.option("endDayHour")))
  62537. },
  62538. _calculateTimeDurationBetweenFirstViewDateAndCurrentDate: function(currentDate) {
  62539. return currentDate.getTime() - (this._firstViewDate.getTime() - this.option("startDayHour") * 3600000)
  62540. },
  62541. _getCellCoordinatesByIndex: function(index) {
  62542. var rowIndex = Math.floor(index / this._getCellCount()),
  62543. cellIndex = index - this._getCellCount() * rowIndex;
  62544. return {
  62545. rowIndex: rowIndex,
  62546. cellIndex: cellIndex
  62547. }
  62548. },
  62549. _renderTimePanel: $.noop,
  62550. _renderAllDayPanel: $.noop,
  62551. _getTableAllDay: $.noop,
  62552. _getCellTimeOffset: function() {
  62553. return 0
  62554. },
  62555. _setFirstViewDate: function() {
  62556. var firstMonthDate = DX.utils.getFirstMonthDate(this.option("currentDate"));
  62557. this._firstViewDate = utils.getFirstWeekDate(firstMonthDate, this.option("firstDayOfWeek"));
  62558. if (this.option("startDayHour"))
  62559. this._firstViewDate.setHours(this.option("startDayHour"))
  62560. },
  62561. _getDate: function(week, day) {
  62562. var result = new Date(this._firstViewDate);
  62563. result.setDate(result.getDate() + week * DAYS_IN_WEEK + day);
  62564. return result
  62565. },
  62566. _getCellText: function(rowIndex, cellIndex) {
  62567. cellIndex = cellIndex % this._getCellCount();
  62568. var date = this._getDate(rowIndex, cellIndex);
  62569. return Globalize.format(date, "dd")
  62570. },
  62571. _updateIndex: function(index) {
  62572. return index
  62573. },
  62574. getCoordinatesByDates: function(startDate, endDate) {
  62575. var result = [],
  62576. date = new Date(startDate);
  62577. while (date <= endDate) {
  62578. result.push(this.getCoordinatesByDate(date));
  62579. date.setDate(date.getDate() + 7);
  62580. date = utils.getFirstWeekDate(date, this.option("firstDayOfWeek"))
  62581. }
  62582. return result
  62583. }
  62584. }))
  62585. })(jQuery, DevExpress);
  62586. /*! Module widgets-web, file ui.scheduler.appointments.js */
  62587. (function($, DX, undefined) {
  62588. var ui = DX.ui,
  62589. translator = DX.translator,
  62590. events = ui.events;
  62591. var COMPONENT_CLASS = "dx-scheduler-appointments",
  62592. APPOINTMENT_ITEM_CLASS = "dx-scheduler-appointment",
  62593. RECURRENCE_APPOINTMENT_CLASS = "dx-scheduler-appointment-recurrence",
  62594. EMPTY_APPOINTMENT_CLASS = "dx-scheduler-appointment-empty",
  62595. REDUCED_APPOINTMENT_CLASS = "dx-scheduler-appointment-reduced",
  62596. REDUCED_APPOINTMENT_ICON = "dx-appointment-reduced-icon";
  62597. var MONTH_APPOINTMENT_DEFAULT_SIZE = 15,
  62598. MONTH_APPOINTMENT_DEFAULT_OFFSET = 3,
  62599. MONTH_APPOINTMENT_HEIGHT_RATIO = 0.6,
  62600. APPOINTMENT_DEFAULT_SIZE = 20,
  62601. WEEK_APPOINTMENT_DEFAULT_OFFSET = 10,
  62602. EMPTY_APPOINTMENT_MAX_WIDTH = 45;
  62603. var REDUCED_APPOINTMENT_POINTERENTER_EVENT_NAME = events.addNamespace("dxpointerenter", "dxSchedulerAppointment"),
  62604. REDUCED_APPOINTMENT_POINTERLEAVE_EVENT_NAME = events.addNamespace("dxpointerleave", "dxSchedulerAppointment"),
  62605. DBLCLICK_EVENT_NAME = events.addNamespace("dxdblclick", "dxSchedulerAppointment");
  62606. var BaseRenderingStrategy = DX.Class.inherit({
  62607. ctor: function(instance) {
  62608. this.instance = instance;
  62609. this.isRtl = instance.option("rtlEnabled")
  62610. },
  62611. resizableConfig: DX.abstract,
  62612. handleResize: DX.abstract,
  62613. renderAppointmentGeometry: function($appointment, coordinates) {
  62614. var geometry = this.getAppointmentGeometry(coordinates);
  62615. translator.move($appointment, {
  62616. top: geometry.top,
  62617. left: geometry.left
  62618. });
  62619. $appointment.css({
  62620. width: geometry.width,
  62621. height: geometry.height
  62622. });
  62623. this._geometry = geometry
  62624. },
  62625. getAppointmentGeometry: function() {
  62626. return {
  62627. height: 0,
  62628. width: 0,
  62629. top: 0,
  62630. left: 0
  62631. }
  62632. },
  62633. createTaskPositionMap: function(items) {
  62634. var length = items.length;
  62635. if (!length)
  62636. return;
  62637. var map = [];
  62638. for (var i = 0; i < length; i++)
  62639. map.push(this._getItemPosition(items[i]));
  62640. var positionArray = this._getSortedPositions(map),
  62641. resultPositions = this._getResultPositions(positionArray);
  62642. return this._getExtendedPositionMap(map, resultPositions)
  62643. },
  62644. _getItemPosition: function(item) {
  62645. var height = this.calculateAppointmentHeight(item),
  62646. width = this.calculateAppointmentWidth(item),
  62647. position = this.instance._getAppointmentCoordinates(item),
  62648. allDay = this.isAllDay(item),
  62649. appointmentReduced = false;
  62650. for (var j = 0; j < position.length; j++) {
  62651. if (allDay)
  62652. position[j].top = 0;
  62653. if ((this._needVerifyItemSize() || allDay) && this.instance._maxAllowedPosition) {
  62654. var currentMaxAllowedPosition = this._getCurrentMaxAllowedPosition(j, item);
  62655. if (this.isAppointmentGreaterThan(currentMaxAllowedPosition, {
  62656. left: position[j].left,
  62657. width: width
  62658. })) {
  62659. appointmentReduced = true;
  62660. if (this.isRtl)
  62661. width = Math.floor(position[j].left - currentMaxAllowedPosition);
  62662. else
  62663. width = currentMaxAllowedPosition - Math.floor(position[j].left)
  62664. }
  62665. }
  62666. $.extend(position[j], {
  62667. height: height,
  62668. width: width,
  62669. allDay: allDay,
  62670. appointmentReduced: appointmentReduced
  62671. })
  62672. }
  62673. return position
  62674. },
  62675. _needVerifyItemSize: function() {
  62676. return false
  62677. },
  62678. _getCurrentMaxAllowedPosition: function(index, item) {
  62679. this.instance.notifyObserver("getItemGroupIndexes", {
  62680. item: item,
  62681. callback: function(indexes) {
  62682. if (indexes.length)
  62683. index = indexes[index]
  62684. }
  62685. });
  62686. return Math.floor(this.instance._maxAllowedPosition[index])
  62687. },
  62688. calculateAppointmentHeight: function() {
  62689. return 0
  62690. },
  62691. calculateAppointmentWidth: function() {
  62692. return 0
  62693. },
  62694. isAppointmentGreaterThan: function(etalon, comparisonParameters) {
  62695. if (this.isRtl)
  62696. return comparisonParameters.left - comparisonParameters.width < etalon;
  62697. return comparisonParameters.left + comparisonParameters.width > etalon
  62698. },
  62699. isAllDay: function() {
  62700. return false
  62701. },
  62702. _getSortedPositions: function(arr) {
  62703. var result = [];
  62704. for (var i = 0, arrLength = arr.length; i < arrLength; i++)
  62705. for (var j = 0, itemLength = arr[i].length; j < itemLength; j++) {
  62706. var item = arr[i][j];
  62707. result.push({
  62708. i: i,
  62709. j: j,
  62710. top: item.top,
  62711. left: item.left,
  62712. isStart: true,
  62713. allDay: item.allDay
  62714. }, {
  62715. i: i,
  62716. j: j,
  62717. top: item.top + item.height,
  62718. left: item.left + item.width,
  62719. isStart: false,
  62720. allDay: item.allDay
  62721. })
  62722. }
  62723. result.sort($.proxy(this._sortCondition, this));
  62724. return result
  62725. },
  62726. _sortCondition: DX.abstract,
  62727. _rowCondition: function(a, b) {
  62728. var columnCondition = a.left - b.left,
  62729. rowCondition = a.top - b.top;
  62730. return columnCondition ? columnCondition : rowCondition ? rowCondition : a.isStart - b.isStart
  62731. },
  62732. _columnCondition: function(a, b) {
  62733. var columnCondition = a.left - b.left,
  62734. rowCondition = a.top - b.top;
  62735. return rowCondition ? rowCondition : columnCondition ? columnCondition : a.isStart - b.isStart
  62736. },
  62737. _getResultPositions: function(sortedArray) {
  62738. var stack = [],
  62739. indexes = [],
  62740. result = [],
  62741. position;
  62742. for (var i = 0; i < sortedArray.length; i++) {
  62743. var current = sortedArray[i],
  62744. j;
  62745. if (current.isStart) {
  62746. position = undefined;
  62747. for (j = 0; j < indexes.length; j++)
  62748. if (!indexes[j]) {
  62749. position = j;
  62750. indexes[j] = true;
  62751. break
  62752. }
  62753. if (position === undefined) {
  62754. position = indexes.length;
  62755. indexes.push(true);
  62756. for (j = 0; j < stack.length; j++)
  62757. stack[j].count++
  62758. }
  62759. stack.push({
  62760. index: position,
  62761. count: indexes.length,
  62762. i: current.i,
  62763. j: current.j
  62764. })
  62765. }
  62766. else {
  62767. var removeIndex = this._findIndexByKey(stack, "i", "j", current.i, current.j),
  62768. resultItem = stack[removeIndex];
  62769. stack.splice(removeIndex, 1);
  62770. indexes[resultItem.index] = false;
  62771. if (!stack.length)
  62772. indexes = [];
  62773. result.push(resultItem)
  62774. }
  62775. }
  62776. return result.sort(function(a, b) {
  62777. var columnCondition = a.j - b.j,
  62778. rowCondition = a.i - b.i;
  62779. return rowCondition ? rowCondition : columnCondition
  62780. })
  62781. },
  62782. _findIndexByKey: function(arr, ikey, jkey, ivalue, jvalue) {
  62783. var result = 0;
  62784. for (var i = 0, len = arr.length; i < len; i++)
  62785. if (arr[i][ikey] === ivalue && arr[i][jkey] === jvalue) {
  62786. result = i;
  62787. break
  62788. }
  62789. return result
  62790. },
  62791. _getExtendedPositionMap: function(map, positions) {
  62792. var positionCounter = 0;
  62793. for (var i = 0, mapLength = map.length; i < mapLength; i++)
  62794. for (var j = 0, itemLength = map[i].length; j < itemLength; j++) {
  62795. map[i][j].index = positions[positionCounter].index;
  62796. map[i][j].count = positions[positionCounter++].count
  62797. }
  62798. return map
  62799. },
  62800. _startDate: function(item) {
  62801. var startDate = this.instance._getStartDate(item);
  62802. if (isNaN(startDate.getTime()))
  62803. throw DX.Error("E1032", item.text);
  62804. return startDate
  62805. },
  62806. _endDate: function(item) {
  62807. var endDate = this.instance._getEndDate(item);
  62808. if (!endDate)
  62809. endDate = new Date(this._startDate(item).getTime() + this.instance.option("appointmentDurationInMinutes") * 60000);
  62810. item.endDate = endDate;
  62811. return endDate
  62812. }
  62813. });
  62814. var WeekRenderingStrategy = BaseRenderingStrategy.inherit({
  62815. resizableConfig: function(appointment) {
  62816. if (this.isAllDay(appointment))
  62817. return {
  62818. minWidth: this.instance._defaultWidth,
  62819. step: this.instance._defaultWidth,
  62820. handles: "right left"
  62821. };
  62822. return {
  62823. minHeight: this.instance._defaultHeight,
  62824. step: this.instance._defaultHeight,
  62825. handles: "top bottom"
  62826. }
  62827. },
  62828. handleResize: function(args, start, end, appointment, initialSize) {
  62829. var handle,
  62830. deltaTime;
  62831. if (this.isAllDay(appointment)) {
  62832. var cellWidth = this.instance._defaultWidth || APPOINTMENT_DEFAULT_SIZE;
  62833. handle = "dx-resizable-handle-left";
  62834. deltaTime = 24 * 60 * 60000 * ((args.width - initialSize.width) / cellWidth) || 1
  62835. }
  62836. else {
  62837. handle = "dx-resizable-handle-top";
  62838. var deltaHeight = args.height - initialSize.height;
  62839. deltaTime = 60000 * deltaHeight / this.instance._defaultHeight * this.instance.option("appointmentDurationInMinutes")
  62840. }
  62841. var cond = $(args.jQueryEvent.target).hasClass(handle),
  62842. startTime = cond ? start.getTime() - deltaTime : start.getTime(),
  62843. endTime = cond ? end.getTime() : end.getTime() + deltaTime;
  62844. return [startTime, endTime]
  62845. },
  62846. renderAppointmentGeometry: function($appointment, coordinates) {
  62847. this.callBase($appointment, coordinates);
  62848. if (this._geometry.width < EMPTY_APPOINTMENT_MAX_WIDTH)
  62849. $appointment.addClass(EMPTY_APPOINTMENT_CLASS)
  62850. },
  62851. getAppointmentGeometry: function(coordinates) {
  62852. if (coordinates.allDay)
  62853. return this._getAllDayAppointmentGeometry(coordinates);
  62854. return this._getSimpleAppointmentGeometry(coordinates)
  62855. },
  62856. _getMinuteHeight: function() {
  62857. return this.instance._defaultHeight / this.instance.option("appointmentDurationInMinutes")
  62858. },
  62859. _getAllDayAppointmentGeometry: function(coordinates) {
  62860. var maxHeight = this.instance._allDayHeight || APPOINTMENT_DEFAULT_SIZE,
  62861. index = coordinates.index,
  62862. count = coordinates.count,
  62863. height = maxHeight / (count > 3 ? 3 : count),
  62864. width = coordinates.width,
  62865. top = coordinates.top + index * height,
  62866. left = coordinates.left;
  62867. if (count > 3)
  62868. if (index > 1) {
  62869. top = coordinates.top;
  62870. left = coordinates.left + (index - 2) * MONTH_APPOINTMENT_DEFAULT_SIZE;
  62871. height = MONTH_APPOINTMENT_DEFAULT_SIZE,
  62872. width = MONTH_APPOINTMENT_DEFAULT_SIZE;
  62873. coordinates.skipResizing = true
  62874. }
  62875. else
  62876. top += height;
  62877. if (this.isRtl)
  62878. left -= width;
  62879. return {
  62880. height: height,
  62881. width: width,
  62882. top: top,
  62883. left: left
  62884. }
  62885. },
  62886. _getSimpleAppointmentGeometry: function(coordinates) {
  62887. var maxWidth = this.instance._defaultWidth - WEEK_APPOINTMENT_DEFAULT_OFFSET || APPOINTMENT_DEFAULT_SIZE,
  62888. width = maxWidth / coordinates.count,
  62889. height = coordinates.height,
  62890. top = coordinates.top,
  62891. left = coordinates.left + coordinates.index * width;
  62892. if (this.isRtl)
  62893. left -= maxWidth;
  62894. return {
  62895. height: height,
  62896. width: width,
  62897. top: top,
  62898. left: left
  62899. }
  62900. },
  62901. isAllDay: function(item) {
  62902. var startDate = this._startDate(item),
  62903. endDate = this._endDate(item),
  62904. appointmentTakesAllDay = false;
  62905. this.instance.notifyObserver("appointmentTakesAllDay", {
  62906. startDate: startDate,
  62907. endDate: endDate,
  62908. callback: function(result) {
  62909. appointmentTakesAllDay = result
  62910. }
  62911. });
  62912. return item.allDay || appointmentTakesAllDay
  62913. },
  62914. calculateAppointmentWidth: function(appointment) {
  62915. if (!this.isAllDay(appointment))
  62916. return 0;
  62917. var startDate = this._startDate(appointment),
  62918. endDate = this._endDate(appointment),
  62919. cellWidth = this.instance._defaultWidth || APPOINTMENT_DEFAULT_SIZE;
  62920. var durationInHours = (endDate.getTime() - startDate.getTime()) / 3600000;
  62921. var width = Math.ceil(durationInHours / 24) * cellWidth;
  62922. return width
  62923. },
  62924. calculateAppointmentHeight: function(appointment) {
  62925. if (this.isAllDay(appointment))
  62926. return 0;
  62927. var startDate = this._startDate(appointment),
  62928. endDate = this._endDate(appointment);
  62929. var durationInMinutes = (endDate.getTime() - startDate.getTime()) / 60000,
  62930. minHeight = APPOINTMENT_DEFAULT_SIZE;
  62931. var height = Math.round(durationInMinutes * this._getMinuteHeight());
  62932. if (height < minHeight)
  62933. height = minHeight;
  62934. return height
  62935. },
  62936. _sortCondition: function(a, b) {
  62937. var allDayCondition = a.allDay - b.allDay;
  62938. return allDayCondition ? allDayCondition : this._rowCondition(a, b)
  62939. }
  62940. });
  62941. var MonthRenderingStrategy = BaseRenderingStrategy.inherit({
  62942. resizableConfig: function() {
  62943. return {
  62944. minWidth: this.instance._defaultWidth,
  62945. minHeight: 0,
  62946. step: this.instance._defaultWidth,
  62947. handles: "right left"
  62948. }
  62949. },
  62950. _needVerifyItemSize: function() {
  62951. return true
  62952. },
  62953. handleResize: function(args, start, end, appointment, initialSize) {
  62954. var isLeft = $(args.jQueryEvent.target).hasClass("dx-resizable-handle-left") && !this.isRtl || $(args.jQueryEvent.target).hasClass("dx-resizable-handle-right") && this.isRtl,
  62955. cellWidth = this.instance._defaultWidth || APPOINTMENT_DEFAULT_SIZE,
  62956. initialWidth = initialSize.width,
  62957. deltaTime = 24 * 60 * 60000 * (Math.round(args.width / cellWidth) - Math.round(initialWidth / cellWidth) || 1),
  62958. startTime = isLeft ? start.getTime() - deltaTime : start.getTime(),
  62959. endTime = isLeft ? end.getTime() : end.getTime() + deltaTime;
  62960. return [startTime, endTime]
  62961. },
  62962. calculateAppointmentWidth: function(appointment) {
  62963. var startDate = this._startDate(appointment),
  62964. endDate = this._endDate(appointment),
  62965. cellWidth = this.instance._defaultWidth || APPOINTMENT_DEFAULT_SIZE;
  62966. var durationInHours = (endDate.getTime() - startDate.getTime()) / 3600000;
  62967. var width = Math.ceil(durationInHours / 24) * cellWidth;
  62968. return width
  62969. },
  62970. renderAppointmentGeometry: function($appointment, coordinates) {
  62971. this.callBase($appointment, coordinates);
  62972. if (coordinates.index > 1)
  62973. $appointment.addClass(EMPTY_APPOINTMENT_CLASS)
  62974. },
  62975. getAppointmentGeometry: function(coordinates) {
  62976. var maxHeight = this.instance._defaultHeight || APPOINTMENT_DEFAULT_SIZE,
  62977. index = coordinates.index,
  62978. height = MONTH_APPOINTMENT_HEIGHT_RATIO * maxHeight / 2,
  62979. width = coordinates.width,
  62980. top = (1 - MONTH_APPOINTMENT_HEIGHT_RATIO) * maxHeight + coordinates.top + index * height,
  62981. left = coordinates.left;
  62982. if (index > 1) {
  62983. top = coordinates.top + MONTH_APPOINTMENT_DEFAULT_OFFSET;
  62984. left = coordinates.left + (index - 2) * (MONTH_APPOINTMENT_DEFAULT_SIZE + MONTH_APPOINTMENT_DEFAULT_OFFSET) + MONTH_APPOINTMENT_DEFAULT_OFFSET;
  62985. height = MONTH_APPOINTMENT_DEFAULT_SIZE,
  62986. width = MONTH_APPOINTMENT_DEFAULT_SIZE;
  62987. coordinates.skipResizing = true
  62988. }
  62989. if (this.isRtl)
  62990. left -= width;
  62991. return {
  62992. height: height,
  62993. width: width,
  62994. top: top,
  62995. left: left
  62996. }
  62997. },
  62998. _sortCondition: function(a, b) {
  62999. return this._columnCondition(a, b)
  63000. }
  63001. });
  63002. DX.registerComponent("dxSchedulerAppointments", ui.dxScheduler, ui.CollectionWidget.inherit({
  63003. _supportedKeys: function(e) {
  63004. var that = this;
  63005. var moveAppointmentBack = function(e) {
  63006. var itemData = that._getItemData(e.target);
  63007. if (itemData.initialCoordinates)
  63008. DX.translator.move($(e.target), itemData.initialCoordinates);
  63009. if (itemData.initialSize) {
  63010. $(e.target).outerWidth(itemData.initialSize.width);
  63011. $(e.target).outerHeight(itemData.initialSize.height)
  63012. }
  63013. itemData._escPressed = true
  63014. };
  63015. return $.extend(this.callBase(), {escape: $.proxy(moveAppointmentBack, this)})
  63016. },
  63017. _moveFocus: $.noop,
  63018. _focusTarget: function() {
  63019. return this._itemElements()
  63020. },
  63021. _focusInHandler: function(e) {
  63022. this.callBase.apply(this, arguments);
  63023. this.option("focusedElement", $(e.target))
  63024. },
  63025. _setDefaultOptions: function() {
  63026. this.callBase();
  63027. this.option({
  63028. noDataText: null,
  63029. activeStateEnabled: true,
  63030. hoverStateEnabled: true,
  63031. tabIndex: 0,
  63032. appointmentDurationInMinutes: 30,
  63033. allDayContainer: null,
  63034. renderingStrategy: "day",
  63035. allowDrag: true,
  63036. allowResize: true
  63037. })
  63038. },
  63039. _optionChanged: function(args) {
  63040. switch (args.name) {
  63041. case"appointmentDurationInMinutes":
  63042. break;
  63043. case"renderingStrategy":
  63044. this._initRenderingStrategy();
  63045. this.repaint();
  63046. break;
  63047. case"allDayContainer":
  63048. break;
  63049. case"allowDrag":
  63050. case"allowResize":
  63051. this.repaint();
  63052. break;
  63053. default:
  63054. this.callBase(args)
  63055. }
  63056. },
  63057. _itemClass: function() {
  63058. return APPOINTMENT_ITEM_CLASS
  63059. },
  63060. _itemContainer: function() {
  63061. var $container = this.callBase(),
  63062. $result = $container,
  63063. $allDayContainer = this.option("allDayContainer");
  63064. if ($allDayContainer)
  63065. $result = $container.add($allDayContainer);
  63066. return $result
  63067. },
  63068. _cleanItemContainer: function() {
  63069. this.callBase();
  63070. var $allDayContainer = this.option("allDayContainer");
  63071. if ($allDayContainer)
  63072. $allDayContainer.empty()
  63073. },
  63074. _init: function() {
  63075. this.callBase();
  63076. this._initRenderingStrategy();
  63077. this.element().addClass(COMPONENT_CLASS);
  63078. this._appointmentClickTimeout;
  63079. this._preventSingleAppointmentClick = false
  63080. },
  63081. _initRenderingStrategy: function() {
  63082. this._renderingStrategy = this.option("renderingStrategy") === "month" ? new MonthRenderingStrategy(this) : new WeekRenderingStrategy(this)
  63083. },
  63084. _executeItemRenderAction: function(index, itemData, itemElement) {
  63085. var action = this._getItemRenderAction();
  63086. if (action)
  63087. action({
  63088. appointmentElement: itemElement,
  63089. appointmentIndex: index,
  63090. appointment: itemData
  63091. })
  63092. },
  63093. _createItemRenderAction: function() {
  63094. this.notifyObserver("initAppointmentRenderedAction", {callback: $.proxy(function(action) {
  63095. this._itemRenderAction = action
  63096. }, this)});
  63097. return this._itemRenderAction
  63098. },
  63099. _getStartDate: function(obj) {
  63100. var result = obj.startDate;
  63101. return DX.utils.makeDate(result)
  63102. },
  63103. _getEndDate: function(obj) {
  63104. var result = obj.endDate;
  63105. if (result)
  63106. return DX.utils.makeDate(result);
  63107. return result
  63108. },
  63109. _itemClickHandler: function(e) {
  63110. var target = e.currentTarget,
  63111. data = this._getItemData(target);
  63112. this._normalizeAppointmentDates(data);
  63113. this._appointmentClickTimeout = setTimeout($.proxy(function() {
  63114. if (!this._preventSingleAppointmentClick)
  63115. this.notifyObserver("showAppointmentTooltip", {
  63116. data: data,
  63117. target: target
  63118. });
  63119. this._preventSingleAppointmentClick = false
  63120. }, this), 300);
  63121. this.callBase(e)
  63122. },
  63123. _normalizeAppointmentDates: function(appointmentData) {
  63124. var startDate = DX.utils.makeDate(appointmentData.startDate),
  63125. endDate = DX.utils.makeDate(appointmentData.endDate);
  63126. appointmentData.startDate = startDate;
  63127. appointmentData.endDate = endDate
  63128. },
  63129. _renderItems: function(items) {
  63130. if (this._isContainerInvisible())
  63131. return;
  63132. this.notifyObserver("getCellDimensions", {callback: $.proxy(function(width, height, allDayHeight) {
  63133. this._defaultWidth = width;
  63134. this._defaultHeight = height;
  63135. this._allDayHeight = allDayHeight
  63136. }, this)});
  63137. this.notifyObserver("getMaxAllowedPosition", {callback: $.proxy(function(result) {
  63138. if (result)
  63139. this._maxAllowedPosition = result
  63140. }, this)});
  63141. this._positionMap = this._renderingStrategy.createTaskPositionMap(items);
  63142. this.callBase(items)
  63143. },
  63144. _renderItem: function(index, itemData) {
  63145. var $allDayContainer = this.option("allDayContainer"),
  63146. $container = this.itemsContainer().not($allDayContainer);
  63147. if (this._renderingStrategy.isAllDay(itemData) && $allDayContainer)
  63148. $container = $allDayContainer;
  63149. this.callBase(index, itemData, $container)
  63150. },
  63151. _postprocessRenderItem: function(args) {
  63152. var $appointment = args.itemElement,
  63153. itemData = args.itemData,
  63154. itemSettings = this._positionMap[args.itemIndex];
  63155. this._attachAppointmentDblclick($appointment, itemData);
  63156. this._paintAppointment($appointment, 0);
  63157. itemData.recurrenceRule && $appointment.addClass(RECURRENCE_APPOINTMENT_CLASS);
  63158. this._applyResourceDataAttr($appointment);
  63159. this._renderAppointmentClones($appointment, itemSettings);
  63160. this._renderingStrategy.renderAppointmentGeometry($appointment, itemSettings[0]);
  63161. this._renderDraggable($appointment);
  63162. if (!itemSettings[0].skipResizing)
  63163. this._renderResizable($appointment);
  63164. if (itemSettings[0].appointmentReduced)
  63165. this._renderAppointmentReducedIcon($appointment)
  63166. },
  63167. _isContainerInvisible: function() {
  63168. var isContainerInvisible = false;
  63169. this.notifyObserver("checkContainerVisibility", {callback: function(result) {
  63170. isContainerInvisible = result
  63171. }});
  63172. return isContainerInvisible
  63173. },
  63174. _attachAppointmentDblclick: function($appointment, appointmentData) {
  63175. $appointment.off(DBLCLICK_EVENT_NAME).on(DBLCLICK_EVENT_NAME, $.proxy(function(e) {
  63176. clearTimeout(this._appointmentClickTimeout);
  63177. this._preventSingleAppointmentClick = true;
  63178. this.notifyObserver("showEditAppointmentPopup", appointmentData)
  63179. }, this))
  63180. },
  63181. _getAppointmentCoordinates: function(itemData) {
  63182. var startDate = this._getStartDate(itemData),
  63183. coordinates = [{
  63184. top: 0,
  63185. left: 0
  63186. }];
  63187. this.notifyObserver("needCoordinates", {
  63188. startDate: startDate,
  63189. appointmentData: itemData,
  63190. callback: function(value) {
  63191. coordinates = value
  63192. }
  63193. });
  63194. return coordinates
  63195. },
  63196. _applyResourceDataAttr: function($appointment) {
  63197. this.notifyObserver("getResourcesFromItem", {
  63198. itemData: this._getItemData($appointment),
  63199. callback: function(resources) {
  63200. if (resources)
  63201. $.each(resources, function(name, values) {
  63202. var attr = "data-" + name.toLowerCase() + "-";
  63203. for (var i = 0; i < values.length; i++)
  63204. $appointment.attr(attr + values[i], true)
  63205. })
  63206. }
  63207. })
  63208. },
  63209. _renderDraggable: function($appointment) {
  63210. if (!this.option("allowDrag"))
  63211. return;
  63212. var that = this,
  63213. appointmentData = that._getItemData($appointment);
  63214. this._createComponent($appointment, "dxDraggable", {
  63215. onDragStart: function(e) {
  63216. that.notifyObserver("hideAppointmentTooltip");
  63217. e.jQueryEvent.targetElements = $appointment.closest(".dx-scheduler");
  63218. appointmentData.initialSize = {
  63219. width: e.width,
  63220. height: e.height
  63221. };
  63222. appointmentData.initialCoordinates = DX.translator.locate(e.element)
  63223. },
  63224. onDragEnd: function(e) {
  63225. var itemData = that._getItemData($appointment);
  63226. if (itemData._escPressed) {
  63227. delete itemData._escPressed;
  63228. e.jQueryEvent.cancel = true;
  63229. return
  63230. }
  63231. that._dragEndHandler(e, appointmentData.initialCoordinates)
  63232. },
  63233. area: this.element().closest(".dx-scrollable-content")
  63234. })
  63235. },
  63236. _renderResizable: function($appointment) {
  63237. if (!this.option("allowResize"))
  63238. return;
  63239. var appointmentData = this._getItemData($appointment),
  63240. config = this._renderingStrategy.resizableConfig(appointmentData);
  63241. $.extend(config, {
  63242. area: this.element().closest(".dx-scrollable-content"),
  63243. onResizeStart: $.proxy(function(e) {
  63244. appointmentData.initialSize = {
  63245. width: e.width,
  63246. height: e.height
  63247. };
  63248. appointmentData.initialCoordinates = DX.translator.locate(e.element)
  63249. }, this),
  63250. onResizeEnd: $.proxy(function(e) {
  63251. if (appointmentData._escPressed) {
  63252. delete appointmentData._escPressed;
  63253. e.jQueryEvent.cancel = true;
  63254. return
  63255. }
  63256. this._resizeEndHandler(e, appointmentData.initialSize, appointmentData.initialCoordinates)
  63257. }, this)
  63258. });
  63259. this._createComponent($appointment, "dxResizable", config)
  63260. },
  63261. _paintAppointment: function($appointment, resourceIndex) {
  63262. this.notifyObserver("getAppointmentColor", {
  63263. itemData: this._getItemData($appointment),
  63264. resourceIndex: resourceIndex,
  63265. callback: function(d) {
  63266. d.done(function(color) {
  63267. if (color)
  63268. $appointment.css("background-color", color)
  63269. })
  63270. }
  63271. })
  63272. },
  63273. _renderAppointmentReducedIcon: function($appointment) {
  63274. $appointment.toggleClass(REDUCED_APPOINTMENT_CLASS, true);
  63275. var $icon = $("<div>").addClass(REDUCED_APPOINTMENT_ICON).appendTo($appointment),
  63276. endDate = this._getEndDate(this._getItemData($appointment));
  63277. $icon.off(REDUCED_APPOINTMENT_POINTERENTER_EVENT_NAME).on(REDUCED_APPOINTMENT_POINTERENTER_EVENT_NAME, function() {
  63278. ui.tooltip.show({
  63279. target: $icon,
  63280. content: Globalize.localize("dxScheduler-editorLabelEndDate") + ": " + Globalize.format(endDate, "d MMMM yyyy")
  63281. })
  63282. }).off(REDUCED_APPOINTMENT_POINTERLEAVE_EVENT_NAME).on(REDUCED_APPOINTMENT_POINTERLEAVE_EVENT_NAME, function() {
  63283. ui.tooltip.hide()
  63284. })
  63285. },
  63286. _renderAppointmentClones: function($appointment, coordinates) {
  63287. var coordinateCount = coordinates.length;
  63288. if (coordinateCount > 1) {
  63289. var clones = [],
  63290. itemData = this._getItemData($appointment),
  63291. resourceForPainting = this._getResourceForPainting();
  63292. for (var i = coordinateCount - 1; i > 0; i--) {
  63293. var $clone = $appointment.clone(true);
  63294. $appointment.after($clone);
  63295. translator.clearCache($clone);
  63296. this._renderingStrategy.renderAppointmentGeometry($clone, coordinates[i]);
  63297. this._renderDraggable($clone);
  63298. if (!coordinates[i].skipResizing)
  63299. this._renderResizable($clone);
  63300. if (coordinates[i].appointmentReduced)
  63301. this._renderAppointmentReducedIcon($clone);
  63302. clones.push($clone)
  63303. }
  63304. if (resourceForPainting) {
  63305. var resourceValues = DX.utils.wrapToArray(itemData[resourceForPainting]);
  63306. this._loop(resourceValues, coordinateCount - 1, function(elementIndex, iterationIndex) {
  63307. this._paintAppointment(clones[iterationIndex], elementIndex)
  63308. }, 1)
  63309. }
  63310. }
  63311. },
  63312. _getResourceForPainting: function() {
  63313. var resourceForPainting;
  63314. this.notifyObserver("getResourceForPainting", {callback: function(resource) {
  63315. if (resource)
  63316. resourceForPainting = resource.field
  63317. }});
  63318. return resourceForPainting
  63319. },
  63320. _loop: function(array, iterationCount, callback, startIndex) {
  63321. startIndex = startIndex || 0;
  63322. var arrayLength = array.length;
  63323. for (var i = 0; i < iterationCount; i++) {
  63324. var elementIndex = startIndex + i;
  63325. if (elementIndex >= arrayLength)
  63326. elementIndex = elementIndex % arrayLength;
  63327. callback.call(this, elementIndex, i)
  63328. }
  63329. },
  63330. _resizeEndHandler: function(e, initialSize, initialCoordinates) {
  63331. var itemData = this._getItemData(e.element),
  63332. startDate = this._getStartDate(itemData),
  63333. endDate = this._getEndDate(itemData);
  63334. var dateRange = this._renderingStrategy.handleResize(e, startDate, endDate, itemData, initialSize);
  63335. var updatedDates = {};
  63336. updatedDates.startDate = new Date(dateRange[0]);
  63337. updatedDates.endDate = new Date(dateRange[1]);
  63338. var data = $.extend({}, itemData, updatedDates);
  63339. this.notifyObserver("updateAppointmentAfterResize", {
  63340. target: itemData,
  63341. data: data,
  63342. $appointment: e.element,
  63343. initialSize: initialSize,
  63344. initialCoordinates: initialCoordinates
  63345. })
  63346. },
  63347. _dragEndHandler: function(e, initialCoordinates) {
  63348. var itemData = this._getItemData(e.element);
  63349. this._normalizeAppointmentDates(itemData);
  63350. this.notifyObserver("updateAppointmentAfterDrag", {
  63351. data: itemData,
  63352. $appointment: e.element,
  63353. initialCoordinates: initialCoordinates
  63354. })
  63355. }
  63356. }).include(ui.dxScheduler.PublisherMixin))
  63357. })(jQuery, DevExpress);
  63358. /*! Module widgets-web, file clientExporter.js */
  63359. (function(DX, $) {
  63360. var utils = DX.utils;
  63361. DX.registerComponent("dxClientExporter", DX, DX.Component.inherit({
  63362. NAME: "dxClientExporter",
  63363. _getDocumentCreator: function(exportableComponent, options) {
  63364. if (options.format === "EXCEL")
  63365. return new DX.dxClientExporter.ExcelCreator(exportableComponent.getDataProvider(), $.extend({rtlEnabled: exportableComponent.option("rtlEnabled")}, options))
  63366. },
  63367. exportTo: function(options) {
  63368. var that = this,
  63369. eventArgs,
  63370. exportingAction = this.option("exportingAction"),
  63371. exportedAction = this.option("exportedAction"),
  63372. data,
  63373. documentCreator,
  63374. exportableComponent = options.component;
  63375. if (exportableComponent) {
  63376. eventArgs = {
  63377. fileName: options.fileName,
  63378. format: options.format,
  63379. cancel: false
  63380. };
  63381. utils.isDefined(exportingAction) && exportingAction(eventArgs);
  63382. if (!eventArgs.cancel) {
  63383. documentCreator = that._getDocumentCreator(exportableComponent, options);
  63384. documentCreator.ready().done(function() {
  63385. data = documentCreator.getData(utils.isFunction(window.Blob));
  63386. utils.isDefined(exportedAction) && exportedAction();
  63387. DX.dxClientExporter.fileSaver.saveAs(eventArgs.fileName, options.format, data, options.proxyUrl)
  63388. })
  63389. }
  63390. }
  63391. }
  63392. }))
  63393. })(DevExpress, jQuery);
  63394. /*! Module widgets-web, file excelCreator.js */
  63395. (function($, DX) {
  63396. var utils = DX.utils,
  63397. Class = DX.Class,
  63398. exporter = DX.dxClientExporter,
  63399. XML_TAG = "<?xml version=\"1.0\" encoding=\"utf-8\"?>",
  63400. GROUP_SHEET_PR_XML = "<sheetPr><outlinePr summaryBelow=\"0\"/></sheetPr>",
  63401. SINGLE_SHEET_PR_XML = "<sheetPr/>",
  63402. BASE_STYLE_XML = "<fonts count=\"2\"><font><sz val=\"11\"/><color theme=\"1\"/><name val=\"Calibri\"/><family val=\"2\"/><scheme val=\"minor\"/></font><font><b/><sz val=\"11\"/><color theme=\"1\"/><name val=\"Calibri\"/><family val=\"2\"/><scheme val=\"minor\"/></font></fonts><fills count=\"1\"><fill><patternFill patternType=\"none\"/></fill></fills><borders count=\"1\"><border><left style=\"thin\"><color rgb=\"FFD3D3D3\"/></left><right style=\"thin\"><color rgb=\"FFD3D3D3\"/></right><top style=\"thin\"><color rgb=\"FFD3D3D3\"/></top><bottom style=\"thin\"><color rgb=\"FFD3D3D3\"/></bottom></border></borders><cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs>",
  63403. OPEN_XML_FORMAT_URL = "http://schemas.openxmlformats.org",
  63404. RELATIONSHIP_PART_NAME = "rels",
  63405. XL_FOLDER_NAME = "xl",
  63406. WORKBOOK_FILE_NAME = "workbook.xml",
  63407. CONTENTTYPES_FILE_NAME = "[Content_Types].xml",
  63408. SHAREDSTRING_FILE_NAME = "sharedStrings.xml",
  63409. STYLE_FILE_NAME = "styles.xml",
  63410. WORKSHEETS_FOLDER = "worksheets",
  63411. WORKSHEET_FILE_NAME = "sheet1.xml",
  63412. UNSUPPORTED_DEFINED_DATE_FORMATS = ["quarter", "quarterAndYear", "millisecond"],
  63413. DEFAULT_DATE_FORMAT = "shortDate",
  63414. DEFINED_NUMBER_FORMTATS = {
  63415. thousands: "#,##0{0},&quot;K&quot;",
  63416. millions: "#,##0{0},,&quot;M&quot;",
  63417. billions: "#,##0{0},,,&quot;B&quot;",
  63418. trillions: "#,##0{0},,,,&quot;T&quot;",
  63419. percent: "0{0}%",
  63420. decimal: "#{0}",
  63421. fixedPoint: "#,##0{0}",
  63422. exponential: "0{0}E+00",
  63423. currency: " "
  63424. },
  63425. EXCEL_START_TIME = new Date("12/30/1899").getTime(),
  63426. DAYS_COUNT_BEFORE_29_FEB_1900 = 60,
  63427. BOLD_STYLES_COUNT = 4,
  63428. MAX_DIGIT_WIDTH_IN_PIXELS = 7,
  63429. CUSTOM_FORMAT_START_INDEX = 165;
  63430. exporter.excelFormatConverter = {
  63431. _applyPrecision: function(format, precision) {
  63432. var result,
  63433. i;
  63434. if (precision > 0) {
  63435. result = format !== "decimal" ? "." : "";
  63436. for (i = 0; i < precision; i++)
  63437. result += "0";
  63438. return result
  63439. }
  63440. return ""
  63441. },
  63442. _getCurrencyFormat: function() {
  63443. var currency = Globalize.cultures[Globalize.cultureSelector].numberFormat.currency,
  63444. i,
  63445. result,
  63446. symbol,
  63447. encodeSymbols;
  63448. if (utils.isArray(currency.pattern)) {
  63449. encodeSymbols = {
  63450. n: "#,##0{0}",
  63451. "'": "\\'",
  63452. "\\(": "\\(",
  63453. "\\)": "\\)",
  63454. " ": "\\ ",
  63455. "\"": "&quot;",
  63456. "\\$": currency.symbol
  63457. };
  63458. result = currency.pattern.slice();
  63459. for (symbol in encodeSymbols)
  63460. for (i = 0; i < result.length; i++)
  63461. result[i] = result[i].replace(new RegExp(symbol, "g"), encodeSymbols[symbol]);
  63462. return result.length === 2 ? result[1] + "_);" + result[0] : result[0]
  63463. }
  63464. },
  63465. _convertDateFormat: function(format) {
  63466. if (!DX.DateTimeFormat[format.toLowerCase()] || $.inArray(format, UNSUPPORTED_DEFINED_DATE_FORMATS) !== -1)
  63467. format = DEFAULT_DATE_FORMAT;
  63468. var datePatterns = Globalize.cultures[Globalize.cultureSelector].calendar.patterns,
  63469. pattern = DX.DateTimeFormat[format.toLowerCase()];
  63470. if (utils.isDefined(datePatterns[pattern]))
  63471. pattern = datePatterns[pattern];
  63472. return pattern.replace(/\//g, "\\/").replace(/ /g, "\\ ").replace(/,/g, "\\,").replace(/:/g, "\\:").replace(/tt/g, "AM/PM").replace(/N/g, "#\\,###")
  63473. },
  63474. _convertNumberFormat: function(format, precision) {
  63475. var result,
  63476. excelFormat = format === "currency" ? this._getCurrencyFormat() : DEFINED_NUMBER_FORMTATS[format];
  63477. if (excelFormat)
  63478. result = utils.stringFormat(excelFormat, this._applyPrecision(format, precision));
  63479. return result
  63480. },
  63481. convertFormat: function(format, precision, type) {
  63482. if (utils.isDefined(format))
  63483. if (type === "date")
  63484. return exporter.excelFormatConverter._convertDateFormat(format);
  63485. else if (DEFINED_NUMBER_FORMTATS[format])
  63486. return exporter.excelFormatConverter._convertNumberFormat(format, precision)
  63487. }
  63488. };
  63489. exporter.ExcelCreator = Class.inherit({
  63490. _getXMLTag: function(tagName, attributes, content) {
  63491. var result = ["<"],
  63492. key;
  63493. result.push(tagName);
  63494. for (key in attributes) {
  63495. result.push(" ");
  63496. result.push(key);
  63497. result.push("=\"");
  63498. result.push(attributes[key]);
  63499. result.push("\"")
  63500. }
  63501. if (utils.isDefined(content)) {
  63502. result.push(">");
  63503. result.push(content);
  63504. result.push("</");
  63505. result.push(tagName);
  63506. result.push(">")
  63507. }
  63508. else
  63509. result.push(" />");
  63510. return result.join("")
  63511. },
  63512. _getDataProviderRowIndex: function(dpRowIndex) {
  63513. return dpRowIndex - !!this._dataProvider.isHeadersVisible()
  63514. },
  63515. _getExcelRowIndex: function(exRowIndex) {
  63516. return exRowIndex + !!this._dataProvider.isHeadersVisible()
  63517. },
  63518. _getCellIndex: function(rowIndex, cellIndex) {
  63519. var sheetIndex = '',
  63520. max = 26,
  63521. charCode;
  63522. if (this._maxIndex[0] < Number(rowIndex))
  63523. this._maxIndex[0] = Number(rowIndex);
  63524. if (this._maxIndex[1] < Number(cellIndex))
  63525. this._maxIndex[1] = Number(cellIndex);
  63526. do {
  63527. charCode = 65 + (cellIndex > max ? cellIndex % max : Math.ceil(cellIndex));
  63528. sheetIndex = String.fromCharCode(charCode) + sheetIndex;
  63529. cellIndex = Math.floor(cellIndex / max)
  63530. } while (cellIndex);
  63531. sheetIndex += rowIndex;
  63532. return sheetIndex
  63533. },
  63534. _getDataType: function(dataType) {
  63535. var validTypes = {
  63536. boolean: "b",
  63537. date: "d",
  63538. number: "n",
  63539. string: "s"
  63540. };
  63541. return utils.isDefined(validTypes[dataType]) ? validTypes[dataType] : "s"
  63542. },
  63543. _appendFormat: function(format, precision, dataType) {
  63544. format = exporter.excelFormatConverter.convertFormat(format, precision, dataType);
  63545. if (format) {
  63546. if ($.inArray(format, this._styleFormat) === -1)
  63547. this._styleFormat.push(format);
  63548. return $.inArray(format, this._styleFormat) + 1
  63549. }
  63550. },
  63551. _appendString: function(value) {
  63552. if (utils.isDefined(value) && value.length) {
  63553. if ($.inArray(value, this._stringArray) === -1) {
  63554. if (value.indexOf("&") > 0)
  63555. value = value.replace(new RegExp("&", "g"), "&amp;");
  63556. this._stringArray.push(value)
  63557. }
  63558. return $.inArray(value, this._stringArray)
  63559. }
  63560. },
  63561. _getExcelDateValue: function(date) {
  63562. var days,
  63563. totalTime;
  63564. if (utils.isDefined(date)) {
  63565. days = Math.floor((date.getTime() - EXCEL_START_TIME) / (1000 * 60 * 60 * 24));
  63566. if (days < DAYS_COUNT_BEFORE_29_FEB_1900)
  63567. days--;
  63568. totalTime = (date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds()) / (24 * 3600);
  63569. return days + totalTime
  63570. }
  63571. },
  63572. _prepareValue: function(rowIndex, cellIndex) {
  63573. var value = this._dataProvider.getCellValue(rowIndex, cellIndex),
  63574. type = this._getDataType(this._dataProvider.getCellType(rowIndex, cellIndex)),
  63575. formatID = this._styleArray[cellIndex + BOLD_STYLES_COUNT].formatID,
  63576. format = DX.utils.isNumber(formatID) ? this._styleFormat[formatID - 1] : null;
  63577. switch (type) {
  63578. case"s":
  63579. value = this._appendString(value);
  63580. break;
  63581. case"d":
  63582. value = this._getExcelDateValue(value, format);
  63583. type = "n";
  63584. break
  63585. }
  63586. return {
  63587. value: value,
  63588. type: type
  63589. }
  63590. },
  63591. _getHeadersArray: function() {
  63592. var i,
  63593. columns = this._dataProvider.getColumns(),
  63594. result = [],
  63595. startIndex = !this._rtlEnabled ? 0 : columns.length - 1,
  63596. endIndex = !this._rtlEnabled ? columns.length : -1,
  63597. counter = !this._rtlEnabled ? 1 : -1;
  63598. for (i = startIndex; i !== endIndex; i += counter)
  63599. result.push({
  63600. style: 0,
  63601. type: "s",
  63602. value: this._appendString(columns[i].caption)
  63603. });
  63604. return result
  63605. },
  63606. _getDataArray: function() {
  63607. var rowIndex,
  63608. cellIndex,
  63609. cellsArray,
  63610. cellData,
  63611. result = [],
  63612. type,
  63613. styleID,
  63614. columns = this._dataProvider.getColumns(),
  63615. startIndex = !this._rtlEnabled ? 0 : columns.length - 1,
  63616. endIndex = !this._rtlEnabled ? columns.length : -1;
  63617. for (rowIndex = 0; rowIndex < this._dataProvider.getRowsCount(); rowIndex++) {
  63618. cellsArray = [];
  63619. for (cellIndex = startIndex; cellIndex !== endIndex; cellIndex += !this._rtlEnabled ? 1 : -1) {
  63620. cellData = this._prepareValue(rowIndex, cellIndex);
  63621. type = cellData.type;
  63622. if (!this._dataProvider.isGroupRow(rowIndex) && utils.isDefined(this._styleArray[cellIndex + BOLD_STYLES_COUNT].formatID) && cellData.type !== "s")
  63623. type = "n";
  63624. styleID = cellIndex + BOLD_STYLES_COUNT;
  63625. if (this._dataProvider.isGroupRow(rowIndex))
  63626. styleID = BOLD_STYLES_COUNT - 1;
  63627. if (this._dataProvider.isTotalRow(rowIndex))
  63628. styleID = this._getBoldStyleID(columns[cellIndex].alignment);
  63629. cellsArray.push({
  63630. style: styleID,
  63631. value: cellData.value,
  63632. type: type
  63633. })
  63634. }
  63635. if (rowIndex && !this._needSheetPr && this._dataProvider.getGroupLevel(this._getDataProviderRowIndex(rowIndex)) > 0)
  63636. this._needSheetPr = true;
  63637. result.push(cellsArray)
  63638. }
  63639. return result
  63640. },
  63641. _getBoldStyleID: function(alignment) {
  63642. for (var i = 0; i < BOLD_STYLES_COUNT - 1; i++)
  63643. if (this._styleArray[i].alignment === alignment)
  63644. return i
  63645. },
  63646. _culculateWidth: function(pixelsWidth) {
  63647. return Math.min(255, Math.floor((pixelsWidth - 5) / MAX_DIGIT_WIDTH_IN_PIXELS * 100 + 0.5) / 100)
  63648. },
  63649. _prepareStyleData: function() {
  63650. var i,
  63651. column,
  63652. wrapText = Number(!!this._options.wrapTextEnabled),
  63653. alignments = ["center", "left", "right"],
  63654. columns = this._dataProvider.getColumns();
  63655. for (i = 0; i < alignments.length; i++)
  63656. this._styleArray.push({
  63657. bold: true,
  63658. alignment: alignments[i],
  63659. wrapText: wrapText
  63660. });
  63661. this._styleArray.push({
  63662. bold: true,
  63663. alignment: this._rtlEnabled ? "right" : "left",
  63664. wrapText: 0
  63665. });
  63666. for (i = 0; i < columns.length; i++) {
  63667. column = columns[i];
  63668. this._styleArray.push({
  63669. alignment: utils.isDefined(column.alignment) ? column.alignment : "left",
  63670. formatID: this._appendFormat(column.format, column.precision, column.dataType),
  63671. wrapText: wrapText
  63672. });
  63673. this._colsArray.push(this._culculateWidth(column.width))
  63674. }
  63675. },
  63676. _prepareCellData: function() {
  63677. if (this._dataProvider.isHeadersVisible())
  63678. this._cellsArray.push(this._getHeadersArray());
  63679. this._cellsArray = this._cellsArray.concat(this._getDataArray())
  63680. },
  63681. _createXMLRelationships: function(xmlRelationships) {
  63682. return this._getXMLTag("Relationships", {xmlns: OPEN_XML_FORMAT_URL + "/package/2006/relationships"}, xmlRelationships)
  63683. },
  63684. _createXMLRelationship: function(id, type, target) {
  63685. return this._getXMLTag("Relationship", {
  63686. Id: "rId" + id,
  63687. Type: OPEN_XML_FORMAT_URL + "/officeDocument/2006/relationships/" + type,
  63688. Target: target
  63689. })
  63690. },
  63691. _getWorkbookContent: function() {
  63692. var content = "<bookViews><workbookView xWindow=\"0\" yWindow=\"0\" windowWidth=\"0\" windowHeight=\"0\"/></bookViews><sheets><sheet name=\"Sheet\" sheetId=\"1\" r:id=\"rId1\" /></sheets><definedNames><definedName name=\"_xlnm.Print_Titles\" localSheetId=\"0\">Sheet!$1:$1</definedName><definedName name=\"_xlnm._FilterDatabase\" hidden=\"0\" localSheetId=\"0\">Sheet!$A$1:$F$6332</definedName></definedNames>";
  63693. return XML_TAG + this._getXMLTag("workbook", {
  63694. "xmlns:r": OPEN_XML_FORMAT_URL + "/officeDocument/2006/relationships",
  63695. xmlns: OPEN_XML_FORMAT_URL + "/spreadsheetml/2006/main"
  63696. }, content)
  63697. },
  63698. _getContentTypesContent: function() {
  63699. return XML_TAG + "<Types xmlns=\"" + OPEN_XML_FORMAT_URL + "/package/2006/content-types\"><Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\" /><Default Extension=\"xml\" ContentType=\"application/xml\" /><Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\" /><Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\" /><Override PartName=\"/xl/sharedStrings.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml\" /><Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\" /></Types>"
  63700. },
  63701. _generateStylesXML: function() {
  63702. var xlFolder = this._zip.folder(XL_FOLDER_NAME),
  63703. styleIndex,
  63704. style,
  63705. xmlStyles = [],
  63706. formatIndex,
  63707. XML = "";
  63708. for (formatIndex in this._styleFormat)
  63709. this._styleFormat[formatIndex] = this._getXMLTag("numFmt", {
  63710. numFmtId: Number(formatIndex) + CUSTOM_FORMAT_START_INDEX,
  63711. formatCode: this._styleFormat[formatIndex]
  63712. });
  63713. XML += this._getXMLTag("numFmts", {count: this._styleFormat.length}, this._styleFormat.join(""));
  63714. XML += BASE_STYLE_XML;
  63715. for (styleIndex in this._styleArray) {
  63716. style = this._styleArray[styleIndex];
  63717. xmlStyles.push(this._getXMLTag("xf", {
  63718. xfId: 0,
  63719. applyAlignment: 1,
  63720. fontId: Number(!!style.bold),
  63721. applyNumberFormat: utils.isDefined(style.formatID) ? 1 : 0,
  63722. numFmtId: utils.isDefined(style.formatID) ? Number(style.formatID) + CUSTOM_FORMAT_START_INDEX - 1 : 0
  63723. }, this._getXMLTag("alignment", {
  63724. horizontal: style.alignment,
  63725. wrapText: style.wrapText
  63726. })))
  63727. }
  63728. XML += this._getXMLTag("cellXfs", {count: xmlStyles.length}, xmlStyles.join(""));
  63729. XML += this._getXMLTag("cellStyles", {count: 1}, this._getXMLTag("cellStyle", {
  63730. name: "Normal",
  63731. xfId: 0,
  63732. builtinId: 0
  63733. }));
  63734. XML = XML_TAG + this._getXMLTag("styleSheet", {xmlns: OPEN_XML_FORMAT_URL + "/spreadsheetml/2006/main"}, XML);
  63735. xlFolder.file(STYLE_FILE_NAME, XML);
  63736. this._styleArray = []
  63737. },
  63738. _generateStringsXML: function() {
  63739. var xlFolder = this._zip.folder(XL_FOLDER_NAME),
  63740. stringIndex,
  63741. sharedStringXml = XML_TAG;
  63742. for (stringIndex in this._stringArray)
  63743. this._stringArray[stringIndex] = this._getXMLTag("si", {}, this._getXMLTag("t", {}, this._stringArray[stringIndex]));
  63744. sharedStringXml += this._getXMLTag("sst", {
  63745. xmlns: OPEN_XML_FORMAT_URL + "/spreadsheetml/2006/main",
  63746. count: this._stringArray.length,
  63747. uniqueCount: this._stringArray.length
  63748. }, this._stringArray.join(""));
  63749. xlFolder.file(SHAREDSTRING_FILE_NAME, sharedStringXml);
  63750. this._stringArray = []
  63751. },
  63752. _generateWorksheetXML: function() {
  63753. var colIndex,
  63754. rowIndex,
  63755. cellData,
  63756. xmlCells,
  63757. maxCellIndex,
  63758. counter = 0,
  63759. xmlRows = [],
  63760. rSpans = "1:" + this._colsArray.length,
  63761. xmlResult = [["<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"x14ac\" xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\">", this._needSheetPr ? GROUP_SHEET_PR_XML : SINGLE_SHEET_PR_XML, "<dimension ref=\"A1:", this._getCellIndex(this._maxIndex[0], this._maxIndex[1]) + "\"/><sheetViews><sheetView tabSelected=\"1\" workbookViewId=\"0\"><pane ySplit=\"1\" topLeftCell=\"A2\" activePane=\"bottomLeft\" state=\"frozen\"/></sheetView></sheetViews><sheetFormatPr defaultRowHeight=\"15\" outlineLevelRow=\"", this._dataProvider.getRowsCount() > 0 ? this._dataProvider.getGroupLevel(0) : 0, "\" x14ac:dyDescent=\"0.25\"/>"].join("")];
  63762. for (colIndex in this._colsArray)
  63763. this._colsArray[colIndex] = this._getXMLTag("col", {
  63764. width: this._colsArray[colIndex],
  63765. min: Number(colIndex) + 1,
  63766. max: Number(colIndex) + 1
  63767. });
  63768. xmlResult.push(this._getXMLTag("cols", [], this._colsArray.join("")) + "<sheetData>");
  63769. for (rowIndex in this._cellsArray) {
  63770. xmlCells = [];
  63771. for (colIndex in this._cellsArray[rowIndex]) {
  63772. rowIndex = Number(rowIndex);
  63773. cellData = this._cellsArray[rowIndex][colIndex];
  63774. xmlCells.push(this._getXMLTag("c", {
  63775. r: this._getCellIndex(rowIndex + 1, colIndex),
  63776. s: cellData.style,
  63777. t: cellData.type
  63778. }, utils.isDefined(cellData.value) ? this._getXMLTag("v", {}, cellData.value) : null))
  63779. }
  63780. xmlRows.push(this._getXMLTag("row", {
  63781. r: Number(rowIndex) + 1,
  63782. spans: rSpans,
  63783. outlineLevel: !Number(rowIndex) ? 0 : this._dataProvider.getGroupLevel(this._getDataProviderRowIndex(rowIndex)),
  63784. "x14ac:dyDescent": "0.25"
  63785. }, xmlCells.join("")));
  63786. this._cellsArray[rowIndex] = null;
  63787. if (counter++ > 10000) {
  63788. xmlResult.push(xmlRows.join(""));
  63789. xmlRows = [];
  63790. counter = 0
  63791. }
  63792. }
  63793. xmlResult.push(xmlRows.join(""));
  63794. xmlRows = [];
  63795. maxCellIndex = this._getCellIndex(this._maxIndex[0], this._maxIndex[1]);
  63796. xmlResult.push("</sheetData>" + (this._options.autoFilterEnabled ? "<autoFilter ref=\"A1:" + maxCellIndex + "\" />" : "") + "<ignoredErrors><ignoredError sqref=\"A1:" + maxCellIndex + "\" numberStoredAsText=\"1\" /></ignoredErrors></worksheet>");
  63797. this._zip.folder(XL_FOLDER_NAME).folder(WORKSHEETS_FOLDER).file(WORKSHEET_FILE_NAME, xmlResult.join(""));
  63798. this._colsArray = [];
  63799. this._cellsArray = [];
  63800. xmlResult = []
  63801. },
  63802. _generateCommonXML: function() {
  63803. var relsFileContent = XML_TAG + this._createXMLRelationships(this._createXMLRelationship(1, "officeDocument", "xl/" + WORKBOOK_FILE_NAME)),
  63804. xmlRelationships,
  63805. xlFolder = this._zip.folder(XL_FOLDER_NAME),
  63806. relsXML = XML_TAG;
  63807. this._zip.folder("_" + RELATIONSHIP_PART_NAME).file("." + RELATIONSHIP_PART_NAME, relsFileContent);
  63808. xmlRelationships = this._createXMLRelationship(1, "worksheet", "worksheets/" + WORKSHEET_FILE_NAME) + this._createXMLRelationship(2, "styles", STYLE_FILE_NAME) + this._createXMLRelationship(3, "sharedStrings", SHAREDSTRING_FILE_NAME);
  63809. relsXML += this._createXMLRelationships(xmlRelationships);
  63810. xlFolder.folder("_" + RELATIONSHIP_PART_NAME).file(WORKBOOK_FILE_NAME + ".rels", relsXML);
  63811. xlFolder.file(WORKBOOK_FILE_NAME, this._getWorkbookContent());
  63812. this._zip.file(CONTENTTYPES_FILE_NAME, this._getContentTypesContent())
  63813. },
  63814. _generateContent: function() {
  63815. this._prepareStyleData();
  63816. this._prepareCellData();
  63817. this._generateWorkXML();
  63818. this._generateCommonXML()
  63819. },
  63820. _generateWorkXML: function() {
  63821. this._generateStylesXML();
  63822. this._generateStringsXML();
  63823. this._generateWorksheetXML()
  63824. },
  63825. ctor: function(dataProvider, options) {
  63826. this._rtlEnabled = options && !!options.rtlEnabled;
  63827. this._options = options;
  63828. this._maxIndex = [1, 2];
  63829. this._stringArray = [];
  63830. this._styleArray = [];
  63831. this._colsArray = [];
  63832. this._cellsArray = [];
  63833. this._styleFormat = [];
  63834. this._needSheetPr = false;
  63835. this._dataProvider = dataProvider;
  63836. this._zip = new JSZip
  63837. },
  63838. ready: function() {
  63839. return this._dataProvider.ready()
  63840. },
  63841. getData: function(isBlob) {
  63842. this._generateContent();
  63843. return this._zip.generate({
  63844. type: isBlob ? "blob" : "base64",
  63845. compression: "DEFLATE"
  63846. })
  63847. }
  63848. });
  63849. exporter.__internals = {
  63850. CONTENTTYPES_FILE_NAME: CONTENTTYPES_FILE_NAME,
  63851. RELATIONSHIP_PART_NAME: RELATIONSHIP_PART_NAME,
  63852. XL_FOLDER_NAME: XL_FOLDER_NAME,
  63853. WORKBOOK_FILE_NAME: WORKBOOK_FILE_NAME,
  63854. STYLE_FILE_NAME: STYLE_FILE_NAME,
  63855. WORKSHEET_FILE_NAME: WORKSHEET_FILE_NAME,
  63856. WORKSHEETS_FOLDER: WORKSHEETS_FOLDER,
  63857. SHAREDSTRING_FILE_NAME: SHAREDSTRING_FILE_NAME,
  63858. GROUP_SHEET_PR_XML: GROUP_SHEET_PR_XML,
  63859. SINGLE_SHEET_PR_XML: SINGLE_SHEET_PR_XML
  63860. }
  63861. })(jQuery, DevExpress);
  63862. /*! Module widgets-web, file fileSaver.js */
  63863. (function(DX, $) {
  63864. var exporter = DX.dxClientExporter,
  63865. utils = DX.utils,
  63866. MIME_TYPES = {
  63867. CSS: "text/css",
  63868. EXCEL: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
  63869. },
  63870. FILE_EXTESIONS = {
  63871. EXCEL: "xlsx",
  63872. CSS: "css"
  63873. };
  63874. exporter.fileSaver = {
  63875. _linkDownloader: function(fileName, href, callback) {
  63876. var exportLinkElement = document.createElement('a'),
  63877. attributes = {
  63878. download: fileName,
  63879. href: href
  63880. };
  63881. if (utils.isDefined(callback))
  63882. attributes["onclick"] = callback;
  63883. document.body.appendChild(exportLinkElement);
  63884. $(exportLinkElement).css({display: "none"}).text("load").attr(attributes)[0].click();
  63885. return exportLinkElement
  63886. },
  63887. _formDownloader: function(proxyUrl, fileName, contentType, data, callback) {
  63888. var formAttributes = {
  63889. method: "post",
  63890. action: proxyUrl,
  63891. enctype: "multipart/form-data"
  63892. },
  63893. exportForm = $("<form>").css({display: "none"}).attr(formAttributes);
  63894. if (utils.isDefined(callback))
  63895. exportForm.submit(callback);
  63896. exportForm.append("<input type=\"hidden\" name=\"fileName\" value=\"" + fileName + "\" />");
  63897. exportForm.append("<input type=\"hidden\" name=\"contentType\" value=\"" + contentType + "\" />");
  63898. exportForm.append("<input type=\"hidden\" name=\"data\" value=\"" + data + "\" />");
  63899. exportForm.appendTo("body");
  63900. exportForm.submit();
  63901. if (exportForm.submit())
  63902. exportForm.remove();
  63903. return exportForm
  63904. },
  63905. _saveByProxy: function(proxyUrl, fileName, format, data, callback) {
  63906. fileName += "." + FILE_EXTESIONS[format];
  63907. return this._formDownloader(proxyUrl, fileName, MIME_TYPES[format], data, callback)
  63908. },
  63909. _saveBase64As: function(fileName, format, data, linkClick) {
  63910. var href = "data:" + MIME_TYPES[format] + ";base64," + data;
  63911. fileName += "." + FILE_EXTESIONS[format];
  63912. return this._linkDownloader(fileName, href, linkClick)
  63913. },
  63914. _saveBlobAs: function(fileName, format, data, linkClick) {
  63915. this._blobSaved = false;
  63916. fileName += "." + FILE_EXTESIONS[format];
  63917. data = data.slice(0, data.size, MIME_TYPES[format]);
  63918. if (utils.isDefined(navigator.msSaveOrOpenBlob)) {
  63919. navigator.msSaveOrOpenBlob(data, fileName);
  63920. this._blobSaved = true
  63921. }
  63922. else {
  63923. var URL = window.URL || window.webkitURL || window.mozURL || window.msURL || window.oURL;
  63924. linkClick = utils.isDefined(linkClick) ? linkClick : function() {
  63925. var link = $('#dxExportLink');
  63926. URL.revokeObjectURL(link.attr('href'));
  63927. link.remove();
  63928. exporter.blobSaved = true
  63929. };
  63930. if (utils.isDefined(URL))
  63931. return this._linkDownloader(fileName, URL.createObjectURL(data), linkClick)
  63932. }
  63933. },
  63934. saveAs: function(fileName, format, data, proxyURL) {
  63935. if (utils.isFunction(window.Blob))
  63936. this._saveBlobAs(fileName, format, data);
  63937. else if (utils.isDefined(proxyURL) && !utils.isDefined(navigator.userAgent.match(/iPad/i)))
  63938. this._saveByProxy(proxyURL, fileName, format, data);
  63939. else {
  63940. if (!utils.isDefined(navigator.userAgent.match(/iPad/i)))
  63941. DX.log("E1034");
  63942. if (DX.browser.msie && parseInt(DX.browser.version) < 10)
  63943. return;
  63944. this._saveBase64As(fileName, format, data)
  63945. }
  63946. }
  63947. }
  63948. })(DevExpress, jQuery);
  63949. DevExpress.MOD_WIDGETS_WEB = true
  63950. }
  63951. if (!DevExpress.MOD_FRAMEWORK) {
  63952. if (!window.DevExpress)
  63953. throw Error('Required module is not referenced: core');
  63954. /*! Module framework, file framework.js */
  63955. (function($, DX, undefined) {
  63956. var mergeWithReplace = function(targetArray, arrayToMerge, needReplaceFn) {
  63957. var result = [];
  63958. for (var i = 0, length = targetArray.length; i < length; i++)
  63959. if (!needReplaceFn(targetArray[i], arrayToMerge))
  63960. result.push(targetArray[i]);
  63961. result.push.apply(result, arrayToMerge);
  63962. return result
  63963. };
  63964. var prepareCommandToReplace = function(targetCommand, commandsToMerge) {
  63965. var needToReplace = false;
  63966. $.each(commandsToMerge, function(_, commandToMerge) {
  63967. var idEqual = targetCommand.option("id") === commandToMerge.option("id") && commandToMerge.option("id"),
  63968. behaviorEqual = targetCommand.option("behavior") === commandToMerge.option("behavior") && targetCommand.option("behavior");
  63969. needToReplace = idEqual || behaviorEqual;
  63970. if (behaviorEqual && commandToMerge.option("onExecute") === null)
  63971. commandToMerge.option("onExecute", targetCommand.option("onExecute"));
  63972. if (needToReplace) {
  63973. targetCommand.element().remove();
  63974. return false
  63975. }
  63976. });
  63977. return needToReplace
  63978. };
  63979. var mergeCommands = function(targetCommands, commandsToMerge) {
  63980. return mergeWithReplace(targetCommands, commandsToMerge, prepareCommandToReplace)
  63981. };
  63982. var resolvePropertyValue = function(command, containerOptions, propertyName, defaultValue) {
  63983. var containerOption = containerOptions ? containerOptions[propertyName] : undefined,
  63984. defaultOption = containerOption === undefined ? defaultValue : containerOption,
  63985. commandOption = command.option(propertyName);
  63986. return commandOption === undefined || commandOption === defaultValue ? defaultOption : commandOption
  63987. };
  63988. var resolveTextValue = function(command, containerOptions) {
  63989. var showText = resolvePropertyValue(command, containerOptions, "showText"),
  63990. hasIcon = !!command.option("icon"),
  63991. titleValue = resolvePropertyValue(command, containerOptions, "title", "");
  63992. return showText || !hasIcon ? titleValue : ""
  63993. };
  63994. var resolveIconValue = function(command, containerOptions, propertyName) {
  63995. var showIcon = resolvePropertyValue(command, containerOptions, "showIcon"),
  63996. hasText = !!command.option("title"),
  63997. iconValue = resolvePropertyValue(command, containerOptions, propertyName, "");
  63998. return showIcon || !hasText ? iconValue : ""
  63999. };
  64000. var resolveTypeValue = function(command, containerOptions) {
  64001. return resolvePropertyValue(command, containerOptions, "type")
  64002. };
  64003. DX.framework = {
  64004. utils: {
  64005. mergeCommands: mergeCommands,
  64006. commandToContainer: {
  64007. resolveTypeValue: resolveTypeValue,
  64008. resolveIconValue: resolveIconValue,
  64009. resolveTextValue: resolveTextValue,
  64010. resolvePropertyValue: resolvePropertyValue
  64011. }
  64012. },
  64013. templateProvider: DX.ui.KoTemplateProvider
  64014. }
  64015. })(jQuery, DevExpress);
  64016. /*! Module framework, file framework.errors.js */
  64017. (function($, DX) {
  64018. $.extend(DX.ERROR_MESSAGES, {
  64019. E3001: "Routing rule is not found for the '{0}' URI.",
  64020. E3002: "The passed object cannot be formatted into a URI string by the application's router. An appropriate route should be registered.",
  64021. E3003: "Unable to navigate. Application is being initialized.",
  64022. E3004: "Cannot execute the command: {0}.",
  64023. E3005: "The '{0}' command {1} is not registered in the application's command mapping. Go to http://dxpr.es/1bTjfj1 for more details.",
  64024. E3006: "Unknown navigation target: '{0}'. Use the 'current', 'back' or 'blank' values.",
  64025. E3007: "Error while restoring the application state. The state has been cleared. Refresh the page.",
  64026. E3008: "Unable to go back.",
  64027. E3009: "Unable to go forward.",
  64028. E3010: "The command's 'id' option should be specified.\r\nProcessed markup: {0}\n",
  64029. E3011: "Layout controller cannot be resolved. There are no appropriate layout controllers for the current context. Check browser console for details.",
  64030. E3012: "Layout controller cannot be resolved. Two or more layout controllers suit the current context. Check browser console for details.",
  64031. E3013: "The '{0}' template with the '{1}' name is not found. Make sure the case is correct in the specified view name and the template fits the current context.",
  64032. E3014: "All the children of the dxView element should be either of the dxCommand or dxContent type.\r\nProcessed markup: {0}",
  64033. E3015: "The 'exec' method should be called before the 'finalize' method.",
  64034. E3016: "Unknown transition type '{0}'.",
  64035. E3018: "Unable to parse options.\nMessage: {0};\nOptions value: {1}.",
  64036. E3019: "View templates should be updated according to the 13.1 changes. Go to http://dxpr.es/15ikrJA for more details.",
  64037. E3020: "Concurrent templates are found:\r\n{0}Target device:\r\n{1}.",
  64038. E3021: "Remote template cannot be loaded.\r\nUrl:{0}\r\nError:{1}.",
  64039. E3022: "Cannot initialize the HtmlApplication component.",
  64040. E3023: "Navigation item is not found",
  64041. W3001: "A view with the '{0}' key doesn't exist.",
  64042. W3002: "A view with the '{0}' key has already been released.",
  64043. W3003: "Layout resolving context:\n{0}\nAvailable layout controller registrations:\n{1}\n",
  64044. W3004: "Layout resolving context:\n{0}\nConcurent layout controller registrations for the context:\n{1}\n",
  64045. W3005: "Direct hash-based navigation is detected. Use data-bind=\"dxAction: url\" instead of href=\"#url\".\nFound markup:\n{0}\n"
  64046. })
  64047. })(jQuery, DevExpress);
  64048. /*! Module framework, file framework.routing.js */
  64049. (function($, DX) {
  64050. var JSON_URI_PREFIX = encodeURIComponent("json:");
  64051. var Class = DX.Class;
  64052. DX.framework.Route = Class.inherit({
  64053. _trimSeparators: function(str) {
  64054. return str.replace(/^[\/.]+|\/+$/g, "")
  64055. },
  64056. _escapeRe: function(str) {
  64057. return str.replace(/\W/g, "\\$1")
  64058. },
  64059. _checkConstraint: function(param, constraint) {
  64060. param = String(param);
  64061. if (typeof constraint === "string")
  64062. constraint = new RegExp(constraint);
  64063. var match = constraint.exec(param);
  64064. if (!match || match[0] !== param)
  64065. return false;
  64066. return true
  64067. },
  64068. _ensureReady: function() {
  64069. var that = this;
  64070. if (this._patternRe)
  64071. return false;
  64072. this._pattern = this._trimSeparators(this._pattern);
  64073. this._patternRe = "";
  64074. this._params = [];
  64075. this._segments = [];
  64076. this._separators = [];
  64077. this._pattern.replace(/[^\/]+/g, function(segment, index) {
  64078. that._segments.push(segment);
  64079. if (index)
  64080. that._separators.push(that._pattern.substr(index - 1, 1))
  64081. });
  64082. $.each(this._segments, function(index) {
  64083. var isStatic = true,
  64084. segment = this,
  64085. separator = index ? that._separators[index - 1] : "";
  64086. if (segment.charAt(0) === ":") {
  64087. isStatic = false;
  64088. segment = segment.substr(1);
  64089. that._params.push(segment);
  64090. that._patternRe += "(?:" + separator + "([^/]*))";
  64091. if (segment in that._defaults)
  64092. that._patternRe += "?"
  64093. }
  64094. else
  64095. that._patternRe += separator + that._escapeRe(segment)
  64096. });
  64097. this._patternRe = new RegExp("^" + this._patternRe + "$")
  64098. },
  64099. ctor: function(pattern, defaults, constraints) {
  64100. this._pattern = pattern || "";
  64101. this._defaults = defaults || {};
  64102. this._constraints = constraints || {}
  64103. },
  64104. parse: function(uri) {
  64105. var that = this;
  64106. this._ensureReady();
  64107. var matches = this._patternRe.exec(uri);
  64108. if (!matches)
  64109. return false;
  64110. var result = $.extend({}, this._defaults);
  64111. $.each(this._params, function(i) {
  64112. var index = i + 1;
  64113. if (matches.length >= index && matches[index])
  64114. result[this] = that.parseSegment(matches[index])
  64115. });
  64116. $.each(this._constraints, function(key) {
  64117. if (!that._checkConstraint(result[key], that._constraints[key])) {
  64118. result = false;
  64119. return false
  64120. }
  64121. });
  64122. return result
  64123. },
  64124. format: function(routeValues) {
  64125. var that = this,
  64126. query = "";
  64127. this._ensureReady();
  64128. var mergeValues = $.extend({}, this._defaults),
  64129. useStatic = 0,
  64130. ret = [],
  64131. dels = [],
  64132. unusedRouteValues = {};
  64133. $.each(routeValues, function(paramName, paramValue) {
  64134. routeValues[paramName] = that.formatSegment(paramValue);
  64135. if (!(paramName in mergeValues))
  64136. unusedRouteValues[paramName] = true
  64137. });
  64138. $.each(this._segments, function(index, segment) {
  64139. ret[index] = index ? that._separators[index - 1] : '';
  64140. if (segment.charAt(0) === ':') {
  64141. var paramName = segment.substr(1);
  64142. if (!(paramName in routeValues) && !(paramName in that._defaults)) {
  64143. ret = null;
  64144. return false
  64145. }
  64146. if (paramName in that._constraints && !that._checkConstraint(routeValues[paramName], that._constraints[paramName])) {
  64147. ret = null;
  64148. return false
  64149. }
  64150. if (paramName in routeValues) {
  64151. if (routeValues[paramName] !== undefined) {
  64152. mergeValues[paramName] = routeValues[paramName];
  64153. ret[index] += routeValues[paramName];
  64154. useStatic = index
  64155. }
  64156. delete unusedRouteValues[paramName]
  64157. }
  64158. else if (paramName in mergeValues) {
  64159. ret[index] += mergeValues[paramName];
  64160. dels.push(index)
  64161. }
  64162. }
  64163. else {
  64164. ret[index] += segment;
  64165. useStatic = index
  64166. }
  64167. });
  64168. $.each(mergeValues, function(key, value) {
  64169. if (!!value && $.inArray(":" + key, that._segments) === -1 && routeValues[key] !== value) {
  64170. ret = null;
  64171. return false
  64172. }
  64173. });
  64174. var unusedCount = 0;
  64175. if (!$.isEmptyObject(unusedRouteValues)) {
  64176. query = "?";
  64177. $.each(unusedRouteValues, function(key) {
  64178. query += key + "=" + routeValues[key] + "&";
  64179. unusedCount++
  64180. });
  64181. query = query.substr(0, query.length - 1)
  64182. }
  64183. if (ret === null)
  64184. return false;
  64185. if (dels.length)
  64186. $.map(dels, function(i) {
  64187. if (i >= useStatic)
  64188. ret[i] = ''
  64189. });
  64190. var path = ret.join('');
  64191. path = path.replace(/\/+$/, "");
  64192. return {
  64193. uri: path + query,
  64194. unusedCount: unusedCount
  64195. }
  64196. },
  64197. formatSegment: function(value) {
  64198. if ($.isArray(value) || $.isPlainObject(value))
  64199. return JSON_URI_PREFIX + encodeURIComponent(JSON.stringify(value));
  64200. return encodeURIComponent(value)
  64201. },
  64202. parseSegment: function(value) {
  64203. if (value.substr(0, JSON_URI_PREFIX.length) === JSON_URI_PREFIX)
  64204. try {
  64205. return $.parseJSON(decodeURIComponent(value.substr(JSON_URI_PREFIX.length)))
  64206. }
  64207. catch(x) {}
  64208. return decodeURIComponent(value)
  64209. }
  64210. });
  64211. DX.framework.Router = DX.Class.inherit({
  64212. ctor: function() {
  64213. this._registry = []
  64214. },
  64215. _trimSeparators: function(str) {
  64216. return str.replace(/^[\/.]+|\/+$/g, "")
  64217. },
  64218. _createRoute: function(pattern, defaults, constraints) {
  64219. return new DX.framework.Route(pattern, defaults, constraints)
  64220. },
  64221. register: function(pattern, defaults, constraints) {
  64222. this._registry.push(this._createRoute(pattern, defaults, constraints))
  64223. },
  64224. _parseQuery: function(query) {
  64225. var result = {},
  64226. values = query.split("&");
  64227. $.each(values, function(index, value) {
  64228. var keyValuePair = value.split("=");
  64229. result[keyValuePair[0]] = decodeURIComponent(keyValuePair[1])
  64230. });
  64231. return result
  64232. },
  64233. parse: function(uri) {
  64234. var that = this,
  64235. ret;
  64236. uri = this._trimSeparators(uri);
  64237. var parts = uri.split("?", 2),
  64238. path = parts[0],
  64239. query = parts[1];
  64240. $.each(this._registry, function() {
  64241. var result = this.parse(path);
  64242. if (result !== false) {
  64243. ret = result;
  64244. if (query)
  64245. ret = $.extend(ret, that._parseQuery(query));
  64246. return false
  64247. }
  64248. });
  64249. return ret ? ret : false
  64250. },
  64251. format: function(obj) {
  64252. var ret = false,
  64253. minUnusedCount = 99999;
  64254. obj = obj || {};
  64255. $.each(this._registry, function() {
  64256. var toFormat = $.extend(true, {}, obj);
  64257. var result = this.format(toFormat);
  64258. if (result !== false)
  64259. if (minUnusedCount > result.unusedCount) {
  64260. minUnusedCount = result.unusedCount;
  64261. ret = result.uri
  64262. }
  64263. });
  64264. return ret
  64265. }
  64266. });
  64267. DX.framework.Route.__internals = {JSON_URI_PREFIX: JSON_URI_PREFIX}
  64268. })(jQuery, DevExpress);
  64269. /*! Module framework, file framework.command.js */
  64270. (function($, DX) {
  64271. var Command = DX.DOMComponent.inherit({
  64272. ctor: function(element, options) {
  64273. if ($.isPlainObject(element)) {
  64274. options = element;
  64275. element = $("<div />")
  64276. }
  64277. this.beforeExecute = $.Callbacks();
  64278. this.afterExecute = $.Callbacks();
  64279. this._callbacksToEvents("Command", ["beforeExecute", "afterExecute"]);
  64280. this.callBase(element, options)
  64281. },
  64282. _setDeprecatedOptions: function() {
  64283. this.callBase();
  64284. $.extend(this._deprecatedOptions, {
  64285. action: {
  64286. since: "14.2",
  64287. alias: "onExecute"
  64288. },
  64289. iconSrc: {
  64290. since: "15.1",
  64291. alias: "icon"
  64292. }
  64293. })
  64294. },
  64295. _setDefaultOptions: function() {
  64296. this.callBase();
  64297. this.option({
  64298. onExecute: null,
  64299. id: null,
  64300. title: "",
  64301. icon: "",
  64302. visible: true,
  64303. disabled: false
  64304. })
  64305. },
  64306. execute: function() {
  64307. var isDisabled = this._options.disabled;
  64308. if ($.isFunction(isDisabled))
  64309. isDisabled = !!isDisabled.apply(this, arguments);
  64310. if (isDisabled)
  64311. throw DX.Error("E3004", this._options.id);
  64312. this.fireEvent("beforeExecute", arguments);
  64313. this._createActionByOption("onExecute").apply(this, arguments);
  64314. this.fireEvent("afterExecute", arguments)
  64315. },
  64316. _render: function() {
  64317. this.callBase();
  64318. this.element().addClass("dx-command")
  64319. },
  64320. _renderDisabledState: $.noop,
  64321. _dispose: function() {
  64322. this.callBase();
  64323. this.element().removeData(this.NAME);
  64324. this.beforeExecute.empty();
  64325. this.afterExecute.empty()
  64326. }
  64327. });
  64328. DX.registerComponent("dxCommand", DX.framework, Command)
  64329. })(jQuery, DevExpress);
  64330. /*! Module framework, file framework.commandMapping.js */
  64331. (function($, DX) {
  64332. DX.framework.CommandMapping = DX.Class.inherit({
  64333. ctor: function() {
  64334. this._commandMappings = {};
  64335. this._containerDefaults = {}
  64336. },
  64337. setDefaults: function(containerId, defaults) {
  64338. this._containerDefaults[containerId] = defaults;
  64339. return this
  64340. },
  64341. mapCommands: function(containerId, commandMappings) {
  64342. var that = this;
  64343. $.each(commandMappings, function(index, commandMapping) {
  64344. if (typeof commandMapping === "string")
  64345. commandMapping = {id: commandMapping};
  64346. var commandId = commandMapping.id;
  64347. var mappings = that._commandMappings[containerId] || {};
  64348. mappings[commandId] = $.extend({
  64349. showIcon: true,
  64350. showText: true
  64351. }, that._containerDefaults[containerId] || {}, commandMapping);
  64352. that._commandMappings[containerId] = mappings
  64353. });
  64354. this._initExistingCommands();
  64355. return this
  64356. },
  64357. unmapCommands: function(containerId, commandIds) {
  64358. var that = this;
  64359. $.each(commandIds, function(index, commandId) {
  64360. var mappings = that._commandMappings[containerId] || {};
  64361. if (mappings)
  64362. delete mappings[commandId]
  64363. });
  64364. this._initExistingCommands()
  64365. },
  64366. getCommandMappingForContainer: function(commandId, containerId) {
  64367. return (this._commandMappings[containerId] || {})[commandId]
  64368. },
  64369. checkCommandsExist: function(commands) {
  64370. var that = this,
  64371. result = $.grep(commands, function(commandName, index) {
  64372. return $.inArray(commandName, that._existingCommands) < 0 && $.inArray(commandName, commands) === index
  64373. });
  64374. if (result.length !== 0)
  64375. throw DX.Error("E3005", result.join("', '"), result.length === 1 ? " is" : "s are");
  64376. },
  64377. load: function(config) {
  64378. if (!config)
  64379. return;
  64380. var that = this;
  64381. $.each(config, function(name, container) {
  64382. that.setDefaults(name, container.defaults);
  64383. that.mapCommands(name, container.commands)
  64384. });
  64385. return this
  64386. },
  64387. _initExistingCommands: function() {
  64388. var that = this;
  64389. this._existingCommands = [];
  64390. $.each(that._commandMappings, function(name, _commands) {
  64391. $.each(_commands, function(index, command) {
  64392. if ($.inArray(command.id, that._existingCommands) < 0)
  64393. that._existingCommands.push(command.id)
  64394. })
  64395. })
  64396. }
  64397. });
  64398. DX.framework.CommandMapping.defaultMapping = {
  64399. "global-navigation": {
  64400. defaults: {
  64401. showIcon: true,
  64402. showText: true
  64403. },
  64404. commands: []
  64405. },
  64406. "ios-header-toolbar": {
  64407. defaults: {
  64408. showIcon: false,
  64409. showText: true,
  64410. location: "after"
  64411. },
  64412. commands: ["edit", "save", {
  64413. id: "back",
  64414. location: "before"
  64415. }, {
  64416. id: "cancel",
  64417. location: "before"
  64418. }, {
  64419. id: "create",
  64420. showIcon: true,
  64421. showText: false
  64422. }]
  64423. },
  64424. "ios-action-sheet": {
  64425. defaults: {
  64426. showIcon: false,
  64427. showText: true
  64428. },
  64429. commands: []
  64430. },
  64431. "ios-view-footer": {
  64432. defaults: {
  64433. showIcon: false,
  64434. showText: true
  64435. },
  64436. commands: [{
  64437. id: "delete",
  64438. type: "danger"
  64439. }]
  64440. },
  64441. "android-header-toolbar": {
  64442. defaults: {
  64443. showIcon: true,
  64444. showText: false,
  64445. location: "after"
  64446. },
  64447. commands: [{
  64448. id: "back",
  64449. showIcon: false,
  64450. location: "before"
  64451. }, "create", {
  64452. id: "save",
  64453. showText: true,
  64454. showIcon: false,
  64455. location: "after"
  64456. }, {
  64457. id: "edit",
  64458. showText: false,
  64459. location: "after"
  64460. }, {
  64461. id: "cancel",
  64462. showText: false,
  64463. location: "before"
  64464. }, {
  64465. id: "delete",
  64466. showText: false,
  64467. location: "after"
  64468. }]
  64469. },
  64470. "android-simple-toolbar": {
  64471. defaults: {
  64472. showIcon: true,
  64473. showText: false,
  64474. location: "after"
  64475. },
  64476. commands: [{
  64477. id: "back",
  64478. showIcon: false,
  64479. location: "before"
  64480. }, {id: "create"}, {
  64481. id: "save",
  64482. showText: true,
  64483. showIcon: false,
  64484. location: "after"
  64485. }, {
  64486. id: "edit",
  64487. showText: false,
  64488. location: "after"
  64489. }, {
  64490. id: "cancel",
  64491. showText: false,
  64492. location: "before"
  64493. }, {
  64494. id: "delete",
  64495. showText: false,
  64496. location: "after"
  64497. }]
  64498. },
  64499. "android-footer-toolbar": {
  64500. defaults: {location: "after"},
  64501. commands: [{
  64502. id: "create",
  64503. showText: false,
  64504. location: "center"
  64505. }, {
  64506. id: "edit",
  64507. showText: false,
  64508. location: "before"
  64509. }, {
  64510. id: "delete",
  64511. location: "menu"
  64512. }, {
  64513. id: "save",
  64514. showIcon: false,
  64515. location: "before"
  64516. }]
  64517. },
  64518. "generic-header-toolbar": {
  64519. defaults: {
  64520. showIcon: false,
  64521. showText: true,
  64522. location: "after"
  64523. },
  64524. commands: ["edit", "save", {
  64525. id: "back",
  64526. location: "before"
  64527. }, {
  64528. id: "cancel",
  64529. location: "before"
  64530. }, {
  64531. id: "create",
  64532. showIcon: true,
  64533. showText: false
  64534. }]
  64535. },
  64536. "generic-view-footer": {
  64537. defaults: {
  64538. showIcon: false,
  64539. showText: true
  64540. },
  64541. commands: [{
  64542. id: "delete",
  64543. type: "danger"
  64544. }]
  64545. },
  64546. "win8-appbar": {
  64547. defaults: {location: "after"},
  64548. commands: ["edit", "cancel", "save", "delete", {
  64549. id: "create",
  64550. location: "before"
  64551. }, {
  64552. id: "refresh",
  64553. location: "before"
  64554. }]
  64555. },
  64556. "win8-toolbar": {
  64557. defaults: {
  64558. showText: false,
  64559. location: "before"
  64560. },
  64561. commands: [{id: "previousPage"}]
  64562. },
  64563. "win8-phone-appbar": {
  64564. defaults: {location: "center"},
  64565. commands: ["create", "edit", "cancel", "save", "refresh", {
  64566. id: "delete",
  64567. location: "menu"
  64568. }]
  64569. },
  64570. "win8-split-toolbar": {
  64571. defaults: {
  64572. showIcon: true,
  64573. showText: false,
  64574. location: "after"
  64575. },
  64576. commands: [{
  64577. id: "back",
  64578. showIcon: false,
  64579. location: "before"
  64580. }, {id: "create"}, {
  64581. id: "save",
  64582. showText: true,
  64583. location: "before"
  64584. }, {
  64585. id: "edit",
  64586. showText: true,
  64587. location: "menu"
  64588. }, {
  64589. id: "cancel",
  64590. showText: true,
  64591. location: "menu"
  64592. }, {
  64593. id: "delete",
  64594. showText: true,
  64595. location: "menu"
  64596. }]
  64597. },
  64598. "win8-master-detail-toolbar": {
  64599. defaults: {
  64600. showText: false,
  64601. location: "before"
  64602. },
  64603. commands: ["back"]
  64604. },
  64605. "desktop-toolbar": {
  64606. defaults: {
  64607. showIcon: false,
  64608. showText: true,
  64609. location: "after"
  64610. },
  64611. commands: ["cancel", "create", "edit", "save", {
  64612. id: "delete",
  64613. type: "danger"
  64614. }]
  64615. }
  64616. }
  64617. })(jQuery, DevExpress);
  64618. /*! Module framework, file framework.viewCache.js */
  64619. (function($, DX, undefined) {
  64620. var Class = DX.Class;
  64621. DX.framework.ViewCache = Class.inherit({
  64622. ctor: function() {
  64623. this._cache = {};
  64624. this.viewRemoved = $.Callbacks();
  64625. this._callbacksToEvents("ViewCache", ["viewRemoved"])
  64626. },
  64627. setView: function(key, viewInfo) {
  64628. this._cache[key] = viewInfo
  64629. },
  64630. getView: function(key) {
  64631. return this._cache[key]
  64632. },
  64633. removeView: function(key) {
  64634. var result = this._cache[key];
  64635. if (result) {
  64636. delete this._cache[key];
  64637. this.fireEvent("viewRemoved", [{viewInfo: result}])
  64638. }
  64639. return result
  64640. },
  64641. clear: function() {
  64642. var that = this;
  64643. $.each(this._cache, function(key) {
  64644. that.removeView(key)
  64645. })
  64646. },
  64647. hasView: function(key) {
  64648. return key in this._cache
  64649. }
  64650. }).include(DX.EventsMixin);
  64651. DX.framework.NullViewCache = DX.framework.ViewCache.inherit({setView: function(key, viewInfo) {
  64652. this.callBase(key, viewInfo);
  64653. this.removeView(key)
  64654. }});
  64655. DX.framework.ConditionalViewCacheDecorator = Class.inherit({
  64656. ctor: function(options) {
  64657. this._filter = options.filter;
  64658. this._viewCache = options.viewCache;
  64659. this.viewRemoved = this._viewCache.viewRemoved;
  64660. this._events = this._viewCache._events
  64661. },
  64662. setView: function(key, viewInfo) {
  64663. this._viewCache.setView(key, viewInfo);
  64664. if (!this._filter(key, viewInfo))
  64665. this._viewCache.removeView(key)
  64666. },
  64667. getView: function(key) {
  64668. return this._viewCache.getView(key)
  64669. },
  64670. removeView: function(key) {
  64671. return this._viewCache.removeView(key)
  64672. },
  64673. clear: function() {
  64674. return this._viewCache.clear()
  64675. },
  64676. hasView: function(key) {
  64677. return this._viewCache.hasView(key)
  64678. }
  64679. }).include(DX.EventsMixin);
  64680. var DEFAULT_VIEW_CACHE_CAPACITY = 10;
  64681. DX.framework.CapacityViewCacheDecorator = Class.inherit({
  64682. ctor: function(options) {
  64683. this._keys = [];
  64684. this._size = options.size || DEFAULT_VIEW_CACHE_CAPACITY;
  64685. this._viewCache = options.viewCache;
  64686. this.viewRemoved = this._viewCache.viewRemoved;
  64687. this._events = this._viewCache._events
  64688. },
  64689. setView: function(key, viewInfo) {
  64690. if (!this.hasView(key)) {
  64691. if (this._keys.length === this._size)
  64692. this.removeView(this._keys[0]);
  64693. this._keys.push(key)
  64694. }
  64695. this._viewCache.setView(key, viewInfo)
  64696. },
  64697. getView: function(key) {
  64698. var index = $.inArray(key, this._keys);
  64699. if (index < 0)
  64700. return null;
  64701. this._keys.push(key);
  64702. this._keys.splice(index, 1);
  64703. return this._viewCache.getView(key)
  64704. },
  64705. removeView: function(key) {
  64706. var index = $.inArray(key, this._keys);
  64707. if (index > -1)
  64708. this._keys.splice(index, 1);
  64709. return this._viewCache.removeView(key)
  64710. },
  64711. clear: function() {
  64712. this._keys = [];
  64713. return this._viewCache.clear()
  64714. },
  64715. hasView: function(key) {
  64716. return this._viewCache.hasView(key)
  64717. }
  64718. }).include(DX.EventsMixin);
  64719. DX.framework.HistoryDependentViewCacheDecorator = Class.inherit({
  64720. ctor: function(options) {
  64721. this._viewCache = options.viewCache || new DX.framework.ViewCache;
  64722. this._navigationManager = options.navigationManager;
  64723. this._navigationManager.on("itemRemoved", $.proxy(this._onNavigationItemRemoved, this));
  64724. this.viewRemoved = this._viewCache.viewRemoved;
  64725. this._events = this._viewCache._events
  64726. },
  64727. _onNavigationItemRemoved: function(item) {
  64728. this.removeView(item.key)
  64729. },
  64730. setView: function(key, viewInfo) {
  64731. this._viewCache.setView(key, viewInfo)
  64732. },
  64733. getView: function(key) {
  64734. return this._viewCache.getView(key)
  64735. },
  64736. removeView: function(key) {
  64737. return this._viewCache.removeView(key)
  64738. },
  64739. clear: function() {
  64740. return this._viewCache.clear()
  64741. },
  64742. hasView: function(key) {
  64743. return this._viewCache.hasView(key)
  64744. }
  64745. }).include(DX.EventsMixin)
  64746. })(jQuery, DevExpress);
  64747. /*! Module framework, file framework.stateManager.js */
  64748. (function($, DX, undefined) {
  64749. var Class = DX.Class;
  64750. DX.framework.MemoryKeyValueStorage = Class.inherit({
  64751. ctor: function() {
  64752. this.storage = {}
  64753. },
  64754. getItem: function(key) {
  64755. return this.storage[key]
  64756. },
  64757. setItem: function(key, value) {
  64758. this.storage[key] = value
  64759. },
  64760. removeItem: function(key) {
  64761. delete this.storage[key]
  64762. }
  64763. });
  64764. DX.framework.StateManager = Class.inherit({
  64765. ctor: function(options) {
  64766. options = options || {};
  64767. this.storage = options.storage || new DX.framework.MemoryKeyValueStorage;
  64768. this.stateSources = options.stateSources || []
  64769. },
  64770. addStateSource: function(stateSource) {
  64771. this.stateSources.push(stateSource)
  64772. },
  64773. removeStateSource: function(stateSource) {
  64774. var index = $.inArray(stateSource, this.stateSources);
  64775. if (index > -1) {
  64776. this.stateSources.splice(index, 1);
  64777. stateSource.removeState(this.storage)
  64778. }
  64779. },
  64780. saveState: function() {
  64781. var that = this;
  64782. $.each(this.stateSources, function(index, stateSource) {
  64783. stateSource.saveState(that.storage)
  64784. })
  64785. },
  64786. restoreState: function() {
  64787. var that = this;
  64788. $.each(this.stateSources, function(index, stateSource) {
  64789. stateSource.restoreState(that.storage)
  64790. })
  64791. },
  64792. clearState: function() {
  64793. var that = this;
  64794. $.each(this.stateSources, function(index, stateSource) {
  64795. stateSource.removeState(that.storage)
  64796. })
  64797. }
  64798. })
  64799. })(jQuery, DevExpress);
  64800. /*! Module framework, file framework.browserAdapters.js */
  64801. (function($, DX, undefined) {
  64802. var Class = DX.Class;
  64803. var ROOT_PAGE_URL = "__root__",
  64804. BUGGY_ANDROID_BUFFER_PAGE_URL = "__buffer__";
  64805. DX.framework.DefaultBrowserAdapter = Class.inherit({
  64806. ctor: function(options) {
  64807. options = options || {};
  64808. this._window = options.window || window;
  64809. this.popState = $.Callbacks();
  64810. $(this._window).on("hashchange", $.proxy(this._onHashChange, this));
  64811. this._tasks = DX.createQueue();
  64812. this.canWorkInPureBrowser = true
  64813. },
  64814. replaceState: function(uri) {
  64815. var that = this;
  64816. return this._addTask(function() {
  64817. uri = that._normalizeUri(uri);
  64818. that._window.history.replaceState(null, null, "#" + uri);
  64819. that._currentTask.resolve()
  64820. })
  64821. },
  64822. pushState: function(uri) {
  64823. var that = this;
  64824. return this._addTask(function() {
  64825. uri = that._normalizeUri(uri);
  64826. that._window.history.pushState(null, null, "#" + uri);
  64827. that._currentTask.resolve()
  64828. })
  64829. },
  64830. createRootPage: function() {
  64831. return this.replaceState(ROOT_PAGE_URL)
  64832. },
  64833. _onHashChange: function() {
  64834. if (this._currentTask)
  64835. this._currentTask.resolve();
  64836. this.popState.fire()
  64837. },
  64838. back: function() {
  64839. var that = this;
  64840. return this._addTask(function() {
  64841. that._window.history.back()
  64842. })
  64843. },
  64844. getHash: function() {
  64845. return this._normalizeUri(this._window.location.hash)
  64846. },
  64847. isRootPage: function() {
  64848. return this.getHash() === ROOT_PAGE_URL
  64849. },
  64850. _normalizeUri: function(uri) {
  64851. return (uri || "").replace(/^#+/, "")
  64852. },
  64853. _addTask: function(task) {
  64854. var that = this,
  64855. d = $.Deferred();
  64856. this._tasks.add(function() {
  64857. that._currentTask = d;
  64858. task();
  64859. return d
  64860. });
  64861. return d.promise()
  64862. }
  64863. });
  64864. DX.framework.OldBrowserAdapter = DX.framework.DefaultBrowserAdapter.inherit({
  64865. ctor: function() {
  64866. this._innerEventCount = 0;
  64867. this.callBase.apply(this, arguments);
  64868. this._skipNextEvent = false
  64869. },
  64870. replaceState: function(uri) {
  64871. var that = this;
  64872. uri = that._normalizeUri(uri);
  64873. if (that.getHash() !== uri) {
  64874. that._addTask(function() {
  64875. that._skipNextEvent = true;
  64876. that._window.history.back()
  64877. });
  64878. return that._addTask(function() {
  64879. that._skipNextEvent = true;
  64880. that._window.location.hash = uri
  64881. })
  64882. }
  64883. return $.Deferred().resolve().promise()
  64884. },
  64885. pushState: function(uri) {
  64886. var that = this;
  64887. uri = this._normalizeUri(uri);
  64888. if (this.getHash() !== uri)
  64889. return that._addTask(function() {
  64890. that._skipNextEvent = true;
  64891. that._window.location.hash = uri
  64892. });
  64893. return $.Deferred().resolve().promise()
  64894. },
  64895. createRootPage: function() {
  64896. return this.pushState(ROOT_PAGE_URL)
  64897. },
  64898. _onHashChange: function() {
  64899. var currentTask = this._currentTask;
  64900. this._currentTask = null;
  64901. if (this._skipNextEvent)
  64902. this._skipNextEvent = false;
  64903. else
  64904. this.popState.fire();
  64905. if (currentTask)
  64906. currentTask.resolve()
  64907. }
  64908. });
  64909. DX.framework.BuggyAndroidBrowserAdapter = DX.framework.OldBrowserAdapter.inherit({createRootPage: function() {
  64910. this.pushState(BUGGY_ANDROID_BUFFER_PAGE_URL);
  64911. return this.callBase()
  64912. }});
  64913. DX.framework.HistorylessBrowserAdapter = DX.framework.DefaultBrowserAdapter.inherit({
  64914. ctor: function(options) {
  64915. options = options || {};
  64916. this._window = options.window || window;
  64917. this.popState = $.Callbacks();
  64918. $(this._window).on("dxback", $.proxy(this._onHashChange, this));
  64919. this._currentHash = this._window.location.hash
  64920. },
  64921. replaceState: function(uri) {
  64922. this._currentHash = this._normalizeUri(uri);
  64923. return $.Deferred().resolve().promise()
  64924. },
  64925. pushState: function(uri) {
  64926. return this.replaceState(uri)
  64927. },
  64928. createRootPage: function() {
  64929. return this.replaceState(ROOT_PAGE_URL)
  64930. },
  64931. getHash: function() {
  64932. return this._normalizeUri(this._currentHash)
  64933. },
  64934. back: function() {
  64935. return this.replaceState(ROOT_PAGE_URL)
  64936. },
  64937. _onHashChange: function() {
  64938. var promise = this.back();
  64939. this.popState.fire();
  64940. return promise
  64941. }
  64942. });
  64943. DX.framework.BuggyCordovaWP81BrowserAdapter = DX.framework.DefaultBrowserAdapter.inherit({ctor: function(options) {
  64944. this.callBase(options);
  64945. this.canWorkInPureBrowser = false
  64946. }})
  64947. })(jQuery, DevExpress);
  64948. /*! Module framework, file framework.navigationDevices.js */
  64949. (function($, DX, undefined) {
  64950. var Class = DX.Class;
  64951. var SESSION_KEY = "dxPhoneJSApplication";
  64952. DX.framework.HistoryBasedNavigationDevice = Class.inherit({
  64953. ctor: function(options) {
  64954. options = options || {};
  64955. this._browserAdapter = options.browserAdapter || this._createBrowserAdapter(options);
  64956. this.uriChanged = $.Callbacks();
  64957. this._browserAdapter.popState.add($.proxy(this._onPopState, this))
  64958. },
  64959. init: $.noop,
  64960. getUri: function() {
  64961. return this._browserAdapter.getHash()
  64962. },
  64963. setUri: function(uri, replaceCurrent) {
  64964. if (replaceCurrent)
  64965. return this._browserAdapter.replaceState(uri);
  64966. else if (uri !== this.getUri())
  64967. return this._browserAdapter.pushState(uri);
  64968. else
  64969. return $.Deferred().resolve().promise()
  64970. },
  64971. back: function() {
  64972. return this._browserAdapter.back()
  64973. },
  64974. _onPopState: function() {
  64975. this.uriChanged.fire(this.getUri())
  64976. },
  64977. _isBuggyAndroid2: function() {
  64978. var realDevice = DX.devices.real();
  64979. var version = realDevice.version;
  64980. return realDevice.platform === "android" && version.length > 1 && (version[0] === 2 && version[1] < 4 || version[0] < 2)
  64981. },
  64982. _isBuggyAndroid4: function() {
  64983. var realDevice = DX.devices.real();
  64984. var version = realDevice.version;
  64985. return realDevice.platform === "android" && version.length > 1 && version[0] === 4 && version[1] === 0
  64986. },
  64987. _isWindowsPhone8: function() {
  64988. var realDevice = DX.devices.real();
  64989. return realDevice.platform === "win8" && realDevice.phone
  64990. },
  64991. _createBrowserAdapter: function(options) {
  64992. var sourceWindow = options.window || window,
  64993. supportPushReplace = sourceWindow.history.replaceState && sourceWindow.history.pushState,
  64994. result;
  64995. if (this._isWindowsPhone8())
  64996. result = new DX.framework.BuggyCordovaWP81BrowserAdapter(options);
  64997. else if (sourceWindow !== sourceWindow.top)
  64998. result = new DX.framework.HistorylessBrowserAdapter(options);
  64999. else if (this._isBuggyAndroid4())
  65000. result = new DX.framework.BuggyAndroidBrowserAdapter(options);
  65001. else if (this._isBuggyAndroid2() || !supportPushReplace)
  65002. result = new DX.framework.OldBrowserAdapter(options);
  65003. else
  65004. result = new DX.framework.DefaultBrowserAdapter(options);
  65005. return result
  65006. }
  65007. });
  65008. DX.framework.StackBasedNavigationDevice = DX.framework.HistoryBasedNavigationDevice.inherit({
  65009. ctor: function(options) {
  65010. this.callBase(options);
  65011. this.backInitiated = $.Callbacks();
  65012. this._rootStateHandler = null;
  65013. $(window).on("unload", this._saveBrowserState)
  65014. },
  65015. init: function() {
  65016. var that = this;
  65017. if (that._browserAdapter.canWorkInPureBrowser)
  65018. return that._initRootPage().done(function() {
  65019. if (that._browserAdapter.isRootPage())
  65020. that._browserAdapter.pushState("")
  65021. });
  65022. else
  65023. return $.Deferred().resolve().promise()
  65024. },
  65025. setUri: function(uri) {
  65026. return this.callBase(uri, !this._browserAdapter.isRootPage())
  65027. },
  65028. _saveBrowserState: function() {
  65029. if (window.sessionStorage)
  65030. sessionStorage.setItem(SESSION_KEY, true)
  65031. },
  65032. _initRootPage: function() {
  65033. var hash = this.getUri();
  65034. if (!window.sessionStorage || sessionStorage.getItem(SESSION_KEY))
  65035. return $.Deferred().resolve().promise();
  65036. sessionStorage.removeItem(SESSION_KEY);
  65037. this._browserAdapter.createRootPage();
  65038. return this._browserAdapter.pushState(hash)
  65039. },
  65040. _onPopState: function() {
  65041. if (this._browserAdapter.isRootPage())
  65042. if (this._rootStateHandler)
  65043. this._rootStateHandler();
  65044. else
  65045. this.backInitiated.fire();
  65046. else {
  65047. if (!this._rootStateHandler)
  65048. this._createRootStateHndler();
  65049. this.back()
  65050. }
  65051. },
  65052. _createRootStateHndler: function() {
  65053. var uri = this.getUri();
  65054. this._rootStateHandler = function() {
  65055. this.uriChanged.fire(uri);
  65056. this._rootStateHandler = null
  65057. }
  65058. }
  65059. })
  65060. })(jQuery, DevExpress);
  65061. /*! Module framework, file framework.navigationManager.js */
  65062. (function($, DX, undefined) {
  65063. var Class = DX.Class;
  65064. var NAVIGATION_TARGETS = {
  65065. current: "current",
  65066. blank: "blank",
  65067. back: "back"
  65068. },
  65069. STORAGE_HISTORY_KEY = "__history";
  65070. DX.framework.HistoryBasedNavigationManager = Class.inherit({
  65071. ctor: function(options) {
  65072. options = options || {};
  65073. this._currentItem = undefined;
  65074. this._previousItem = undefined;
  65075. this.navigating = $.Callbacks();
  65076. this.navigated = $.Callbacks();
  65077. this.navigationCanceled = $.Callbacks();
  65078. this.navigatingBack = $.Callbacks();
  65079. this.itemRemoved = $.Callbacks();
  65080. this._callbacksToEvents("DefaultLayoutController", ["navigating", "navigated", "navigationCanceled", "navigatingBack", "itemRemoved"]);
  65081. this._createNavigationDevice(options)
  65082. },
  65083. _createNavigationDevice: function(options) {
  65084. this._navigationDevice = options.navigationDevice || new DX.framework.HistoryBasedNavigationDevice;
  65085. this._navigationDevice.uriChanged.add($.proxy(this._uriChangedHandler, this))
  65086. },
  65087. _uriChangedHandler: function(uri) {
  65088. while (DX.hideTopOverlayCallback.fire());
  65089. this._forceNavigate = true;
  65090. this.navigate(uri)
  65091. },
  65092. _syncUriWithCurrentNavigationItem: function() {
  65093. var currentUri = this._currentItem && this._currentItem.uri;
  65094. this._navigationDevice.setUri(currentUri, true)
  65095. },
  65096. _cancelNavigation: function(args) {
  65097. this._syncUriWithCurrentNavigationItem();
  65098. this.fireEvent("navigationCanceled", [args])
  65099. },
  65100. _getDefaultOptions: function() {
  65101. return {
  65102. direction: "none",
  65103. target: NAVIGATION_TARGETS.blank
  65104. }
  65105. },
  65106. _updateHistory: function(uri, options) {
  65107. this._previousItem = this._currentItem;
  65108. this._currentItem = {
  65109. uri: uri,
  65110. key: uri
  65111. };
  65112. this._navigationDevice.setUri(uri, options.target === NAVIGATION_TARGETS.current)
  65113. },
  65114. _setCurrentItem: function(item) {
  65115. this._currentItem = item
  65116. },
  65117. navigate: function(uri, options) {
  65118. options = options || {};
  65119. var that = this,
  65120. isFirstNavigate = !that._currentItem,
  65121. currentItem = that._currentItem || {},
  65122. targetItem = options.item || {},
  65123. currentUri = currentItem.uri,
  65124. currentKey = currentItem.key,
  65125. targetKey = targetItem.key,
  65126. args;
  65127. if (uri === undefined)
  65128. uri = that._navigationDevice.getUri();
  65129. if (/^_back$/.test(uri)) {
  65130. that.back();
  65131. return
  65132. }
  65133. options = $.extend(that._getDefaultOptions(), options || {});
  65134. if (isFirstNavigate)
  65135. options.target = NAVIGATION_TARGETS.current;
  65136. args = {
  65137. currentUri: currentUri,
  65138. uri: uri,
  65139. cancel: false,
  65140. navigateWhen: [],
  65141. options: options
  65142. };
  65143. that.fireEvent("navigating", [args]);
  65144. uri = args.uri;
  65145. if (args.cancel || currentUri === uri && (targetKey === undefined || targetKey === currentKey) && !that._forceNavigate)
  65146. that._cancelNavigation(args);
  65147. else {
  65148. that._forceNavigate = false;
  65149. $.when.apply($, args.navigateWhen).done(function() {
  65150. DX.utils.executeAsync(function() {
  65151. that._updateHistory(uri, options);
  65152. that.fireEvent("navigated", [{
  65153. uri: uri,
  65154. previousUri: currentUri,
  65155. options: options,
  65156. item: that._currentItem
  65157. }])
  65158. })
  65159. })
  65160. }
  65161. },
  65162. back: function() {
  65163. return this._navigationDevice.back()
  65164. },
  65165. previousItem: function() {
  65166. return this._previousItem
  65167. },
  65168. currentItem: function(item) {
  65169. if (arguments.length > 0) {
  65170. if (!item)
  65171. throw DX.Error("E3023");
  65172. this._setCurrentItem(item)
  65173. }
  65174. else
  65175. return this._currentItem
  65176. },
  65177. rootUri: function() {
  65178. return this._currentItem && this._currentItem.uri
  65179. },
  65180. canBack: function() {
  65181. return true
  65182. },
  65183. saveState: $.noop,
  65184. restoreState: $.noop,
  65185. removeState: $.noop
  65186. }).include(DX.EventsMixin);
  65187. DX.framework.StackBasedNavigationManager = DX.framework.HistoryBasedNavigationManager.inherit({
  65188. ctor: function(options) {
  65189. options = options || {};
  65190. this.callBase(options);
  65191. this._createNavigationStacks(options);
  65192. DX.hardwareBackButton.add($.proxy(this._deviceBackInitiated, this));
  65193. this._stateStorageKey = options.stateStorageKey || STORAGE_HISTORY_KEY
  65194. },
  65195. init: function() {
  65196. return this._navigationDevice.init()
  65197. },
  65198. _createNavigationDevice: function(options) {
  65199. if (!options.navigationDevice)
  65200. options.navigationDevice = new DX.framework.StackBasedNavigationDevice;
  65201. this.callBase(options);
  65202. this._navigationDevice.backInitiated.add($.proxy(this._deviceBackInitiated, this))
  65203. },
  65204. _uriChangedHandler: function(uri) {
  65205. this.navigate(uri)
  65206. },
  65207. _createNavigationStacks: function(options) {
  65208. this.navigationStacks = {};
  65209. this._keepPositionInStack = options.keepPositionInStack;
  65210. this.currentStack = new DX.framework.NavigationStack
  65211. },
  65212. _deviceBackInitiated: function() {
  65213. if (!DX.hideTopOverlayCallback.fire())
  65214. this.back({isHardwareButton: true});
  65215. else
  65216. this._syncUriWithCurrentNavigationItem()
  65217. },
  65218. _getDefaultOptions: function() {
  65219. return {target: NAVIGATION_TARGETS.blank}
  65220. },
  65221. _createNavigationStack: function() {
  65222. var result = new DX.framework.NavigationStack;
  65223. result.itemsRemoved.add($.proxy(this._removeItems, this));
  65224. return result
  65225. },
  65226. _setCurrentItem: function(item) {
  65227. this._setCurrentStack(item.stack);
  65228. this.currentStack.currentItem(item);
  65229. this.callBase(item);
  65230. this._syncUriWithCurrentNavigationItem()
  65231. },
  65232. _setCurrentStack: function(stackOrStackKey) {
  65233. var stack,
  65234. stackKey;
  65235. if (typeof stackOrStackKey === "string") {
  65236. stackKey = stackOrStackKey;
  65237. if (!(stackKey in this.navigationStacks))
  65238. this.navigationStacks[stackKey] = this._createNavigationStack();
  65239. stack = this.navigationStacks[stackKey]
  65240. }
  65241. else {
  65242. stack = stackOrStackKey;
  65243. stackKey = $.map(this.navigationStacks, function(stack, key) {
  65244. if (stack === stackOrStackKey)
  65245. return key;
  65246. return null
  65247. })[0]
  65248. }
  65249. this.currentStack = stack;
  65250. this.currentStackKey = stackKey
  65251. },
  65252. _getViewTargetStackKey: function(uri, isRoot) {
  65253. var result;
  65254. if (isRoot)
  65255. if (this.navigationStacks[uri] !== undefined)
  65256. result = uri;
  65257. else {
  65258. for (var stackKey in this.navigationStacks)
  65259. if (this.navigationStacks[stackKey].items[0].uri === uri) {
  65260. result = stackKey;
  65261. break
  65262. }
  65263. result = result || uri
  65264. }
  65265. else
  65266. result = this.currentStackKey || uri;
  65267. return result
  65268. },
  65269. _updateHistory: function(uri, options) {
  65270. var isRoot = options.root,
  65271. forceIsRoot = isRoot,
  65272. forceToRoot = false,
  65273. stackKey = options.stack || this._getViewTargetStackKey(uri, isRoot),
  65274. previousStack = this.currentStack,
  65275. keepPositionInStack = options.keepPositionInStack !== undefined ? options.keepPositionInStack : this._keepPositionInStack;
  65276. this._setCurrentStack(stackKey);
  65277. if (isRoot || !this.currentStack.items.length) {
  65278. forceToRoot = this.currentStack === previousStack;
  65279. forceIsRoot = true
  65280. }
  65281. if (isRoot && this.currentStack.items.length) {
  65282. if (!keepPositionInStack || forceToRoot) {
  65283. this.currentStack.currentIndex = 0;
  65284. if (this.currentItem().uri !== uri)
  65285. this.currentStack.navigate(uri, true)
  65286. }
  65287. options.direction = options.direction || "none"
  65288. }
  65289. else {
  65290. var prevIndex = this.currentStack.currentIndex,
  65291. prevItem = this.currentItem() || {};
  65292. switch (options.target) {
  65293. case NAVIGATION_TARGETS.blank:
  65294. this.currentStack.navigate(uri);
  65295. break;
  65296. case NAVIGATION_TARGETS.current:
  65297. this.currentStack.navigate(uri, true);
  65298. break;
  65299. case NAVIGATION_TARGETS.back:
  65300. if (this.currentStack.currentIndex > 0)
  65301. this.currentStack.back(uri);
  65302. else
  65303. this.currentStack.navigate(uri, true);
  65304. break;
  65305. default:
  65306. throw DX.Error("E3006", options.target);
  65307. }
  65308. if (options.direction === undefined) {
  65309. var indexDelta = this.currentStack.currentIndex - prevIndex;
  65310. if (indexDelta < 0)
  65311. options.direction = this.currentStack.currentItem().backDirection || "backward";
  65312. else if (indexDelta > 0 && this.currentStack.currentIndex > 0)
  65313. options.direction = "forward";
  65314. else
  65315. options.direction = "none"
  65316. }
  65317. prevItem.backDirection = options.direction === "forward" ? "backward" : "none"
  65318. }
  65319. options.root = forceIsRoot;
  65320. this._currentItem = this.currentStack.currentItem();
  65321. this._syncUriWithCurrentNavigationItem()
  65322. },
  65323. _removeItems: function(items) {
  65324. var that = this;
  65325. $.each(items, function(index, item) {
  65326. that.fireEvent("itemRemoved", [item])
  65327. })
  65328. },
  65329. back: function(options) {
  65330. options = options || {};
  65331. var navigatingBackArgs = $.extend({cancel: false}, options);
  65332. this.fireEvent("navigatingBack", [navigatingBackArgs]);
  65333. if (navigatingBackArgs.cancel) {
  65334. this._syncUriWithCurrentNavigationItem();
  65335. return
  65336. }
  65337. var item = this.previousItem(navigatingBackArgs.stack);
  65338. if (item)
  65339. this.navigate(item.uri, {
  65340. stack: navigatingBackArgs.stack,
  65341. target: NAVIGATION_TARGETS.back,
  65342. item: item
  65343. });
  65344. else
  65345. this.callBase()
  65346. },
  65347. rootUri: function() {
  65348. return this.currentStack.items.length ? this.currentStack.items[0].uri : this.callBase()
  65349. },
  65350. canBack: function(stackKey) {
  65351. var stack = stackKey ? this.navigationStacks[stackKey] : this.currentStack;
  65352. return stack.canBack()
  65353. },
  65354. saveState: function(storage) {
  65355. if (this.currentStack.items.length) {
  65356. var state = {
  65357. navigationStacks: {},
  65358. currentStackKey: this.currentStackKey
  65359. };
  65360. $.each(this.navigationStacks, function(stackKey, stack) {
  65361. var stackState = {};
  65362. state.navigationStacks[stackKey] = stackState;
  65363. stackState.currentIndex = stack.currentIndex;
  65364. stackState.items = $.map(stack.items, function(item) {
  65365. return {
  65366. key: item.key,
  65367. uri: item.uri
  65368. }
  65369. })
  65370. });
  65371. var json = JSON.stringify(state);
  65372. storage.setItem(this._stateStorageKey, json)
  65373. }
  65374. else
  65375. this.removeState(storage)
  65376. },
  65377. restoreState: function(storage) {
  65378. if (this.disableRestoreState)
  65379. return;
  65380. var json = storage.getItem(this._stateStorageKey);
  65381. if (json)
  65382. try {
  65383. var that = this,
  65384. state = JSON.parse(json);
  65385. $.each(state.navigationStacks, function(stackKey, stackState) {
  65386. var stack = that._createNavigationStack();
  65387. that.navigationStacks[stackKey] = stack;
  65388. stack.currentIndex = stackState.currentIndex;
  65389. stack.items = $.map(stackState.items, function(item) {
  65390. item.stack = stack;
  65391. return item
  65392. })
  65393. });
  65394. this.currentStackKey = state.currentStackKey;
  65395. this.currentStack = this.navigationStacks[this.currentStackKey];
  65396. this._currentItem = this.currentStack.currentItem();
  65397. this._navigationDevice.setUri(this.currentItem().uri);
  65398. this._forceNavigate = true
  65399. }
  65400. catch(e) {
  65401. this.removeState(storage);
  65402. throw DX.Error("E3007");
  65403. }
  65404. },
  65405. removeState: function(storage) {
  65406. storage.removeItem(this._stateStorageKey)
  65407. },
  65408. currentIndex: function() {
  65409. return this.currentStack.currentIndex
  65410. },
  65411. previousItem: function(stackKey) {
  65412. var stack = this.navigationStacks[stackKey] || this.currentStack;
  65413. return stack.previousItem()
  65414. },
  65415. getItemByIndex: function(index) {
  65416. return this.currentStack.items[index]
  65417. },
  65418. clearHistory: function() {
  65419. this.currentStack.clear()
  65420. },
  65421. itemByKey: function(itemKey) {
  65422. var result;
  65423. $.each(this.navigationStacks, function(stackKey, stack) {
  65424. var item = stack.itemByKey(itemKey);
  65425. if (item) {
  65426. result = item;
  65427. return false
  65428. }
  65429. });
  65430. return result
  65431. },
  65432. currentItem: function(itemOrItemKey) {
  65433. var item;
  65434. if (arguments.length > 0) {
  65435. if (typeof itemOrItemKey === "string")
  65436. item = this.itemByKey(itemOrItemKey);
  65437. else if ($.isPlainObject(itemOrItemKey))
  65438. item = itemOrItemKey;
  65439. this.callBase(item)
  65440. }
  65441. else
  65442. return this.callBase()
  65443. }
  65444. });
  65445. DX.framework.NavigationStack = Class.inherit({
  65446. ctor: function(options) {
  65447. options = options || {};
  65448. this.itemsRemoved = $.Callbacks();
  65449. this.clear()
  65450. },
  65451. currentItem: function(item) {
  65452. if (item) {
  65453. for (var i = 0; i < this.items.length; i++)
  65454. if (item === this.items[i]) {
  65455. this.currentIndex = i;
  65456. break
  65457. }
  65458. }
  65459. else
  65460. return this.items[this.currentIndex]
  65461. },
  65462. previousItem: function() {
  65463. return this.items.length > 1 ? this.items[this.currentIndex - 1] : undefined
  65464. },
  65465. canBack: function() {
  65466. return this.currentIndex > 0
  65467. },
  65468. clear: function() {
  65469. this._deleteItems(this.items);
  65470. this.items = [];
  65471. this.currentIndex = -1
  65472. },
  65473. back: function(uri) {
  65474. this.currentIndex--;
  65475. if (this.currentIndex < 0)
  65476. throw DX.Error("E3008");
  65477. var currentItem = this.currentItem();
  65478. if (currentItem.uri !== uri)
  65479. this._updateItem(this.currentIndex, uri)
  65480. },
  65481. forward: function() {
  65482. this.currentIndex++;
  65483. if (this.currentIndex >= this.items.length)
  65484. throw DX.Error("E3009");
  65485. },
  65486. navigate: function(uri, replaceCurrent) {
  65487. if (this.currentIndex < this.items.length && this.currentIndex > -1 && this.items[this.currentIndex].uri === uri)
  65488. return;
  65489. if (replaceCurrent && this.currentIndex > -1)
  65490. this.currentIndex--;
  65491. if (this.currentIndex + 1 < this.items.length && this.items[this.currentIndex + 1].uri === uri)
  65492. this.currentIndex++;
  65493. else {
  65494. var toDelete = this.items.splice(this.currentIndex + 1, this.items.length - this.currentIndex - 1);
  65495. this.items.push({stack: this});
  65496. this.currentIndex++;
  65497. this._updateItem(this.currentIndex, uri);
  65498. this._deleteItems(toDelete)
  65499. }
  65500. return this.currentItem()
  65501. },
  65502. itemByKey: function(key) {
  65503. for (var i = 0; i < this.items.length; i++) {
  65504. var item = this.items[i];
  65505. if (item.key === key)
  65506. return item
  65507. }
  65508. },
  65509. _updateItem: function(index, uri) {
  65510. var item = this.items[index];
  65511. item.uri = uri;
  65512. item.key = this.items[0].uri + "_" + index + "_" + uri
  65513. },
  65514. _deleteItems: function(items) {
  65515. if (items)
  65516. this.itemsRemoved.fire(items)
  65517. }
  65518. });
  65519. DX.framework.HistoryBasedNavigationManager.NAVIGATION_TARGETS = NAVIGATION_TARGETS
  65520. })(jQuery, DevExpress);
  65521. /*! Module framework, file framework.actionExecutors.js */
  65522. (function($, DX, undefined) {
  65523. function prepareNavigateOptions(options, actionArguments) {
  65524. if (actionArguments.args) {
  65525. var sourceEventArguments = actionArguments.args[0];
  65526. options.jQueryEvent = sourceEventArguments.jQueryEvent
  65527. }
  65528. if ((actionArguments.component || {}).NAME === "dxCommand")
  65529. $.extend(options, actionArguments.component.option())
  65530. }
  65531. DX.framework.createActionExecutors = function(app) {
  65532. return {
  65533. routing: {execute: function(e) {
  65534. var action = e.action,
  65535. options = {},
  65536. routeValues,
  65537. uri;
  65538. if ($.isPlainObject(action)) {
  65539. routeValues = action.routeValues;
  65540. if (routeValues && $.isPlainObject(routeValues))
  65541. options = action.options;
  65542. else
  65543. routeValues = action;
  65544. uri = app.router.format(routeValues);
  65545. prepareNavigateOptions(options, e);
  65546. app.navigate(uri, options);
  65547. e.handled = true
  65548. }
  65549. }},
  65550. hash: {execute: function(e) {
  65551. if (typeof e.action !== "string" || e.action.charAt(0) !== "#")
  65552. return;
  65553. var uriTemplate = e.action.substr(1),
  65554. args = e.args[0],
  65555. uri = uriTemplate;
  65556. var defaultEvaluate = function(expr) {
  65557. var getter = DX.data.utils.compileGetter(expr),
  65558. model = e.args[0].model;
  65559. return getter(model)
  65560. };
  65561. var evaluate = args.evaluate || defaultEvaluate;
  65562. uri = uriTemplate.replace(/\{([^}]+)\}/g, function(entry, expr) {
  65563. expr = $.trim(expr);
  65564. if (expr.indexOf(",") > -1)
  65565. expr = $.map(expr.split(","), $.trim);
  65566. var value = evaluate(expr);
  65567. if (value === undefined)
  65568. value = "";
  65569. value = DX.framework.Route.prototype.formatSegment(value);
  65570. return value
  65571. });
  65572. var options = {};
  65573. prepareNavigateOptions(options, e);
  65574. app.navigate(uri, options);
  65575. e.handled = true
  65576. }}
  65577. }
  65578. }
  65579. })(jQuery, DevExpress);
  65580. /*! Module framework, file framework.application.js */
  65581. (function($, DX) {
  65582. var Class = DX.Class,
  65583. BACK_COMMAND_TITLE,
  65584. INIT_IN_PROGRESS = "InProgress",
  65585. INIT_COMPLETE = "Inited",
  65586. frameworkNS = DX.framework;
  65587. DX.framework.Application = Class.inherit({
  65588. ctor: function(options) {
  65589. options = options || {};
  65590. this._options = options;
  65591. this.namespace = options.namespace || window;
  65592. this._applicationMode = options.mode ? options.mode : "mobileApp";
  65593. this.components = [];
  65594. BACK_COMMAND_TITLE = DX.localization.localizeString("@Back");
  65595. this.router = options.router || new DX.framework.Router;
  65596. var navigationManagers = {
  65597. mobileApp: DX.framework.StackBasedNavigationManager,
  65598. webSite: DX.framework.HistoryBasedNavigationManager
  65599. };
  65600. this.navigationManager = options.navigationManager || new navigationManagers[this._applicationMode]({keepPositionInStack: options.navigateToRootViewMode === "keepHistory"});
  65601. this.navigationManager.on("navigating", $.proxy(this._onNavigating, this));
  65602. this.navigationManager.on("navigatingBack", $.proxy(this._onNavigatingBack, this));
  65603. this.navigationManager.on("navigated", $.proxy(this._onNavigated, this));
  65604. this.navigationManager.on("navigationCanceled", $.proxy(this._onNavigationCanceled, this));
  65605. this.stateManager = options.stateManager || new DX.framework.StateManager({storage: options.stateStorage || sessionStorage});
  65606. this.stateManager.addStateSource(this.navigationManager);
  65607. this.viewCache = this._createViewCache(options);
  65608. this.commandMapping = this._createCommandMapping(options.commandMapping);
  65609. this.createNavigation(options.navigation);
  65610. this.beforeViewSetup = $.Callbacks();
  65611. this.afterViewSetup = $.Callbacks();
  65612. this.viewShowing = $.Callbacks();
  65613. this.viewShown = $.Callbacks();
  65614. this.viewHidden = $.Callbacks();
  65615. this.viewDisposing = $.Callbacks();
  65616. this.viewDisposed = $.Callbacks();
  65617. this.navigating = $.Callbacks();
  65618. this.navigatingBack = $.Callbacks();
  65619. this.initialized = $.Callbacks();
  65620. this._callbacksToEvents("HtmlApplication", ["beforeViewSetup", "afterViewSetup", "viewShowing", "viewShown", "viewHidden", "viewDisposing", "viewDisposed", "navigating", "navigatingBack", "initialized"]);
  65621. this._isNavigating = false;
  65622. this._viewLinksHash = {};
  65623. DX.registerActionExecutor(DX.framework.createActionExecutors(this));
  65624. this.components.push(this.router);
  65625. this.components.push(this.navigationManager)
  65626. },
  65627. _createViewCache: function(options) {
  65628. var result;
  65629. if (options.viewCache)
  65630. result = options.viewCache;
  65631. else if (options.disableViewCache)
  65632. result = new DX.framework.NullViewCache;
  65633. else
  65634. result = new DX.framework.CapacityViewCacheDecorator({
  65635. size: options.viewCacheSize,
  65636. viewCache: new DX.framework.ViewCache
  65637. });
  65638. result.on("viewRemoved", $.proxy(function(e) {
  65639. this._releaseViewLink(e.viewInfo)
  65640. }, this));
  65641. return result
  65642. },
  65643. _createCommandMapping: function(commandMapping) {
  65644. var result = commandMapping;
  65645. if (!(commandMapping instanceof DX.framework.CommandMapping)) {
  65646. result = new DX.framework.CommandMapping;
  65647. result.load(DX.framework.CommandMapping.defaultMapping || {}).load(commandMapping || {})
  65648. }
  65649. return result
  65650. },
  65651. createNavigation: function(navigationConfig) {
  65652. this.navigation = this._createNavigationCommands(navigationConfig);
  65653. this._mapNavigationCommands(this.navigation, this.commandMapping)
  65654. },
  65655. _createNavigationCommands: function(commandConfig) {
  65656. if (!commandConfig)
  65657. return [];
  65658. var generatedIdCount = 0;
  65659. return $.map(commandConfig, function(item) {
  65660. var command;
  65661. if (item instanceof frameworkNS.dxCommand)
  65662. command = item;
  65663. else
  65664. command = new frameworkNS.dxCommand($.extend({root: true}, item));
  65665. if (!command.option("id"))
  65666. command.option("id", "navigation_" + generatedIdCount++);
  65667. return command
  65668. })
  65669. },
  65670. _mapNavigationCommands: function(navigationCommands, commandMapping) {
  65671. var navigationCommandIds = $.map(navigationCommands, function(command) {
  65672. return command.option("id")
  65673. });
  65674. commandMapping.mapCommands("global-navigation", navigationCommandIds)
  65675. },
  65676. _callComponentMethod: function(methodName, args) {
  65677. var tasks = [];
  65678. $.each(this.components, function(index, component) {
  65679. if (component[methodName] && $.isFunction(component[methodName])) {
  65680. var result = component[methodName](args);
  65681. if (result && result.done)
  65682. tasks.push(result)
  65683. }
  65684. });
  65685. return $.when.apply($, tasks)
  65686. },
  65687. init: function() {
  65688. var that = this;
  65689. that._initState = INIT_IN_PROGRESS;
  65690. return that._callComponentMethod("init").done(function() {
  65691. that._initState = INIT_COMPLETE;
  65692. that._processEvent("initialized")
  65693. }).fail(function(error) {
  65694. throw error || DX.Error("E3022");
  65695. })
  65696. },
  65697. _onNavigatingBack: function(args) {
  65698. this._processEvent("navigatingBack", args)
  65699. },
  65700. _onNavigating: function(args) {
  65701. var that = this;
  65702. if (that._isNavigating) {
  65703. that._pendingNavigationArgs = args;
  65704. args.cancel = true;
  65705. return
  65706. }
  65707. else {
  65708. that._isNavigating = true;
  65709. delete that._pendingNavigationArgs
  65710. }
  65711. var routeData = this.router.parse(args.uri);
  65712. if (!routeData)
  65713. throw DX.Error("E3001", args.uri);
  65714. var uri = this.router.format(routeData);
  65715. if (args.uri !== uri && uri) {
  65716. args.cancel = true;
  65717. DX.utils.executeAsync(function() {
  65718. that.navigate(uri, args.options)
  65719. })
  65720. }
  65721. else
  65722. that._processEvent("navigating", args)
  65723. },
  65724. _onNavigated: function(args) {
  65725. var that = this,
  65726. direction = args.options.direction,
  65727. resultDeferred,
  65728. viewInfo = that._acquireViewInfo(args.item, args.options);
  65729. if (!viewInfo.model) {
  65730. this._processEvent("beforeViewSetup", {viewInfo: viewInfo});
  65731. that._createViewModel(viewInfo);
  65732. that._createViewCommands(viewInfo);
  65733. this._processEvent("afterViewSetup", {viewInfo: viewInfo})
  65734. }
  65735. that._highlightCurrentNavigationCommand(viewInfo);
  65736. resultDeferred = that._showView(viewInfo, direction).always(function() {
  65737. that._isNavigating = false;
  65738. var pendingArgs = that._pendingNavigationArgs;
  65739. if (pendingArgs)
  65740. DX.utils.executeAsync(function() {
  65741. that.navigate(pendingArgs.uri, pendingArgs.options)
  65742. })
  65743. });
  65744. return resultDeferred
  65745. },
  65746. _isViewReadyToShow: function(viewInfo) {
  65747. return !!viewInfo.model
  65748. },
  65749. _onNavigationCanceled: function(args) {
  65750. var that = this;
  65751. if (!that._pendingNavigationArgs || that._pendingNavigationArgs.uri !== args.uri) {
  65752. var currentItem = that.navigationManager.currentItem();
  65753. if (currentItem)
  65754. DX.utils.executeAsync(function() {
  65755. var viewInfo = that._acquireViewInfo(currentItem, args.options);
  65756. that._highlightCurrentNavigationCommand(viewInfo, true)
  65757. });
  65758. that._isNavigating = false
  65759. }
  65760. },
  65761. _disposeRemovedViews: function() {
  65762. var that = this,
  65763. args;
  65764. $.each(that._viewLinksHash, function(key, link) {
  65765. if (!link.linkCount) {
  65766. args = {viewInfo: link.viewInfo};
  65767. that._processEvent("viewDisposing", args, args.viewInfo.model);
  65768. that._disposeView(link.viewInfo);
  65769. that._processEvent("viewDisposed", args, args.viewInfo.model);
  65770. delete that._viewLinksHash[key]
  65771. }
  65772. })
  65773. },
  65774. _onViewHidden: function(viewInfo) {
  65775. var args = {viewInfo: viewInfo};
  65776. this._processEvent("viewHidden", args, args.viewInfo.model)
  65777. },
  65778. _disposeView: function(viewInfo) {
  65779. var commands = viewInfo.commands || [];
  65780. $.each(commands, function(index, command) {
  65781. command._dispose()
  65782. })
  65783. },
  65784. _acquireViewInfo: function(navigationItem, navigateOptions) {
  65785. var viewInfo = this.viewCache.getView(navigationItem.key);
  65786. if (!viewInfo) {
  65787. viewInfo = this._createViewInfo(navigationItem, navigateOptions);
  65788. this._obtainViewLink(viewInfo);
  65789. this.viewCache.setView(navigationItem.key, viewInfo)
  65790. }
  65791. return viewInfo
  65792. },
  65793. _processEvent: function(eventName, args, model) {
  65794. this._callComponentMethod(eventName, args);
  65795. this.fireEvent(eventName, [args]);
  65796. var modelMethod = (model || {})[eventName];
  65797. if (modelMethod)
  65798. modelMethod.call(model, args)
  65799. },
  65800. _createViewInfo: function(navigationItem, navigateOptions) {
  65801. var uri = navigationItem.uri,
  65802. routeData = this.router.parse(uri);
  65803. var viewInfo = {
  65804. viewName: routeData.view,
  65805. routeData: routeData,
  65806. uri: uri,
  65807. key: navigationItem.key,
  65808. canBack: this.canBack(),
  65809. navigateOptions: navigateOptions,
  65810. previousViewInfo: this._getPreviousViewInfo(navigateOptions)
  65811. };
  65812. return viewInfo
  65813. },
  65814. _createViewModel: function(viewInfo) {
  65815. viewInfo.model = viewInfo.model || this._callViewCodeBehind(viewInfo)
  65816. },
  65817. _createViewCommands: function(viewInfo) {
  65818. viewInfo.commands = viewInfo.model.commands || [];
  65819. if (viewInfo.canBack && this._applicationMode !== "webSite")
  65820. this._appendBackCommand(viewInfo)
  65821. },
  65822. _callViewCodeBehind: function(viewInfo) {
  65823. var setupFunc = $.noop,
  65824. routeData = viewInfo.routeData;
  65825. if (routeData.view in this.namespace)
  65826. setupFunc = this.namespace[routeData.view];
  65827. return setupFunc.call(this.namespace, routeData, viewInfo) || {}
  65828. },
  65829. _appendBackCommand: function(viewInfo) {
  65830. var commands = viewInfo.commands,
  65831. that = this,
  65832. stackKey = this.navigationManager.currentStackKey,
  65833. backTitle = BACK_COMMAND_TITLE;
  65834. if (that._options.useViewTitleAsBackText)
  65835. backTitle = ((viewInfo.previousViewInfo || {}).model || {}).title || backTitle;
  65836. var toMergeTo = [new DX.framework.dxCommand({
  65837. id: "back",
  65838. title: backTitle,
  65839. behavior: "back",
  65840. onExecute: function() {
  65841. that.back({stack: stackKey})
  65842. },
  65843. icon: "arrowleft",
  65844. type: "back",
  65845. renderStage: that._options.useViewTitleAsBackText ? "onViewRendering" : "onViewShown"
  65846. })];
  65847. var result = DX.framework.utils.mergeCommands(toMergeTo, commands);
  65848. commands.length = 0;
  65849. commands.push.apply(commands, result)
  65850. },
  65851. _showView: function(viewInfo, direction) {
  65852. var that = this;
  65853. var eventArgs = {
  65854. viewInfo: viewInfo,
  65855. direction: direction
  65856. };
  65857. return that._showViewImpl(eventArgs.viewInfo, eventArgs.direction).done(function() {
  65858. DX.utils.executeAsync(function() {
  65859. that._processEvent("viewShown", eventArgs, viewInfo.model);
  65860. that._disposeRemovedViews()
  65861. })
  65862. })
  65863. },
  65864. _highlightCurrentNavigationCommand: function(viewInfo, forceUpdate) {
  65865. var that = this,
  65866. selectedCommand,
  65867. currentNavigationItemId = viewInfo.model && viewInfo.model.currentNavigationItemId;
  65868. if (currentNavigationItemId !== undefined)
  65869. $.each(this.navigation, function(index, command) {
  65870. if (command.option("id") === currentNavigationItemId) {
  65871. selectedCommand = command;
  65872. return false
  65873. }
  65874. });
  65875. if (!selectedCommand)
  65876. $.each(this.navigation, function(index, command) {
  65877. var commandUri = command.option("onExecute");
  65878. if (DX.utils.isString(commandUri)) {
  65879. commandUri = commandUri.replace(/^#+/, "");
  65880. if (commandUri === that.navigationManager.rootUri()) {
  65881. selectedCommand = command;
  65882. return false
  65883. }
  65884. }
  65885. });
  65886. $.each(this.navigation, function(index, command) {
  65887. if (forceUpdate && command === selectedCommand && command.option("highlighted"))
  65888. command.fireEvent("optionChanged", [{
  65889. name: "highlighted",
  65890. value: true,
  65891. previousValue: true
  65892. }]);
  65893. command.option("highlighted", command === selectedCommand)
  65894. })
  65895. },
  65896. _showViewImpl: DX.abstract,
  65897. _obtainViewLink: function(viewInfo) {
  65898. var key = viewInfo.key;
  65899. if (!this._viewLinksHash[key])
  65900. this._viewLinksHash[key] = {
  65901. viewInfo: viewInfo,
  65902. linkCount: 1
  65903. };
  65904. else
  65905. this._viewLinksHash[key].linkCount++
  65906. },
  65907. _releaseViewLink: function(viewInfo) {
  65908. if (this._viewLinksHash[viewInfo.key] === undefined)
  65909. DX.log("W3001", viewInfo.key);
  65910. if (this._viewLinksHash[viewInfo.key].linkCount === 0)
  65911. DX.log("W3002", viewInfo.key);
  65912. this._viewLinksHash[viewInfo.key].linkCount--
  65913. },
  65914. navigate: function(uri, options) {
  65915. var that = this;
  65916. if ($.isPlainObject(uri)) {
  65917. uri = that.router.format(uri);
  65918. if (uri === false)
  65919. throw DX.Error("E3002");
  65920. }
  65921. if (!that._initState)
  65922. that.init().done(function() {
  65923. that.restoreState();
  65924. that.navigate(uri, options)
  65925. });
  65926. else if (that._initState === INIT_COMPLETE) {
  65927. if (!that._isNavigating || uri)
  65928. that.navigationManager.navigate(uri, options)
  65929. }
  65930. else
  65931. throw DX.Error("E3003");
  65932. },
  65933. canBack: function(stackKey) {
  65934. return this.navigationManager.canBack(stackKey)
  65935. },
  65936. _getPreviousViewInfo: function(navigateOptions) {
  65937. var previousNavigationItem = this.navigationManager.previousItem(navigateOptions.stack),
  65938. result;
  65939. if (previousNavigationItem)
  65940. result = this.viewCache.getView(previousNavigationItem.key);
  65941. return result
  65942. },
  65943. back: function(options) {
  65944. this.navigationManager.back(options)
  65945. },
  65946. saveState: function() {
  65947. this.stateManager.saveState()
  65948. },
  65949. restoreState: function() {
  65950. this.stateManager.restoreState()
  65951. },
  65952. clearState: function() {
  65953. this.stateManager.clearState()
  65954. }
  65955. }).include(DX.EventsMixin)
  65956. })(jQuery, DevExpress);
  65957. /*! Module framework, file framework.html.js */
  65958. (function($, DX, undefined) {
  65959. DX.framework.html = {
  65960. layoutSets: {},
  65961. animationSets: {
  65962. "native": {
  65963. "view-content-change": [{animation: "slide"}, {
  65964. animation: "ios7-slide",
  65965. device: {platform: "ios"}
  65966. }, {
  65967. animation: "none",
  65968. device: {
  65969. deviceType: "desktop",
  65970. platform: "generic"
  65971. }
  65972. }, {
  65973. animation: "none",
  65974. device: {grade: "C"}
  65975. }],
  65976. "view-header-toolbar": [{animation: "ios7-toolbar"}, {
  65977. animation: "slide",
  65978. device: {grade: "B"}
  65979. }, {
  65980. animation: "none",
  65981. device: {grade: "C"}
  65982. }]
  65983. },
  65984. "default": {
  65985. "view-content-change": [{animation: "slide"}, {
  65986. animation: "ios7-slide",
  65987. device: {platform: "ios"}
  65988. }, {
  65989. animation: "fade",
  65990. device: {
  65991. deviceType: "desktop",
  65992. platform: "generic"
  65993. }
  65994. }, {
  65995. animation: "none",
  65996. device: {grade: "C"}
  65997. }],
  65998. "view-content-rendered": [{animation: "fade"}, {
  65999. animation: "none",
  66000. device: {grade: "C"}
  66001. }],
  66002. "view-header-toolbar": [{animation: "ios7-toolbar"}, {
  66003. animation: "slide",
  66004. device: {grade: "B"}
  66005. }, {
  66006. animation: "none",
  66007. device: {grade: "C"}
  66008. }],
  66009. "command-rendered": [{animation: "stagger-fade-drop"}, {
  66010. animation: "fade",
  66011. device: {grade: "B"}
  66012. }, {
  66013. animation: "fade",
  66014. device: {deviceType: "desktop"}
  66015. }, {
  66016. animation: "none",
  66017. device: {grade: "C"}
  66018. }],
  66019. "list-item-rendered": [{
  66020. animation: "stagger-3d-drop",
  66021. device: {grade: "A"}
  66022. }, {
  66023. animation: "fade",
  66024. device: {deviceType: "desktop"}
  66025. }, {
  66026. animation: "none",
  66027. device: {grade: "C"}
  66028. }],
  66029. "detail-item-rendered": [{
  66030. animation: "stagger-3d-drop",
  66031. device: {grade: "A"}
  66032. }, {
  66033. animation: "fade",
  66034. device: {deviceType: "desktop"}
  66035. }, {
  66036. animation: "none",
  66037. device: {grade: "C"}
  66038. }],
  66039. "edit-item-rendered": [{
  66040. animation: "stagger-3d-drop",
  66041. device: {grade: "A"}
  66042. }, {
  66043. animation: "fade",
  66044. device: {deviceType: "desktop"}
  66045. }, {
  66046. animation: "none",
  66047. device: {grade: "C"}
  66048. }]
  66049. },
  66050. slide: {
  66051. "view-content-change": [{animation: "slide"}, {
  66052. animation: "ios7-slide",
  66053. device: {platform: "ios"}
  66054. }, {
  66055. animation: "fade",
  66056. device: {
  66057. deviceType: "desktop",
  66058. platform: "generic"
  66059. }
  66060. }, {
  66061. animation: "none",
  66062. device: {grade: "C"}
  66063. }],
  66064. "view-content-rendered": [{animation: "fade"}, {
  66065. animation: "none",
  66066. device: {grade: "C"}
  66067. }],
  66068. "view-header-toolbar": [{animation: "ios7-toolbar"}, {
  66069. animation: "slide",
  66070. device: {grade: "B"}
  66071. }, {
  66072. animation: "none",
  66073. device: {grade: "C"}
  66074. }],
  66075. "command-rendered": [{animation: "stagger-fade-drop"}, {
  66076. animation: "fade",
  66077. device: {grade: "B"}
  66078. }, {
  66079. animation: "fade",
  66080. device: {deviceType: "desktop"}
  66081. }, {
  66082. animation: "none",
  66083. device: {grade: "C"}
  66084. }],
  66085. "list-item-rendered": [{
  66086. animation: "stagger-fade-slide",
  66087. device: {grade: "A"}
  66088. }, {
  66089. animation: "fade",
  66090. device: {deviceType: "desktop"}
  66091. }, {
  66092. animation: "none",
  66093. device: {grade: "C"}
  66094. }],
  66095. "detail-item-rendered": [{
  66096. animation: "stagger-fade-slide",
  66097. device: {grade: "A"}
  66098. }, {
  66099. animation: "fade",
  66100. device: {deviceType: "desktop"}
  66101. }, {
  66102. animation: "none",
  66103. device: {grade: "C"}
  66104. }],
  66105. "edit-item-rendered": [{
  66106. animation: "stagger-fade-slide",
  66107. device: {grade: "A"}
  66108. }, {
  66109. animation: "fade",
  66110. device: {deviceType: "desktop"}
  66111. }, {
  66112. animation: "none",
  66113. device: {grade: "C"}
  66114. }]
  66115. },
  66116. zoom: {
  66117. "view-content-change": [{animation: "slide"}, {
  66118. animation: "ios7-slide",
  66119. device: {platform: "ios"}
  66120. }, {
  66121. animation: "fade",
  66122. device: {
  66123. deviceType: "desktop",
  66124. platform: "generic"
  66125. }
  66126. }, {
  66127. animation: "none",
  66128. device: {grade: "C"}
  66129. }],
  66130. "view-content-rendered": [{animation: "fade"}, {
  66131. animation: "none",
  66132. device: {grade: "C"}
  66133. }],
  66134. "view-header-toolbar": [{animation: "ios7-toolbar"}, {
  66135. animation: "slide",
  66136. device: {grade: "B"}
  66137. }, {
  66138. animation: "fade",
  66139. device: {deviceType: "desktop"}
  66140. }, {
  66141. animation: "none",
  66142. device: {grade: "C"}
  66143. }],
  66144. "command-rendered": [{animation: "stagger-fade-zoom"}, {
  66145. animation: "fade",
  66146. device: {grade: "B"}
  66147. }, {
  66148. animation: "fade",
  66149. device: {deviceType: "desktop"}
  66150. }, {
  66151. animation: "none",
  66152. device: {grade: "C"}
  66153. }],
  66154. "list-item-rendered": [{
  66155. animation: "stagger-fade-zoom",
  66156. device: {grade: "A"}
  66157. }, {
  66158. animation: "fade",
  66159. device: {deviceType: "desktop"}
  66160. }, {
  66161. animation: "none",
  66162. device: {grade: "C"}
  66163. }],
  66164. "detail-item-rendered": [{
  66165. animation: "stagger-fade-zoom",
  66166. device: {grade: "A"}
  66167. }, {
  66168. animation: "fade",
  66169. device: {deviceType: "desktop"}
  66170. }, {
  66171. animation: "none",
  66172. device: {grade: "C"}
  66173. }],
  66174. "edit-item-rendered": [{
  66175. animation: "stagger-fade-zoom",
  66176. device: {grade: "A"}
  66177. }, {
  66178. animation: "fade",
  66179. device: {deviceType: "desktop"}
  66180. }, {
  66181. animation: "none",
  66182. device: {grade: "C"}
  66183. }]
  66184. }
  66185. }
  66186. }
  66187. })(jQuery, DevExpress);
  66188. /*! Module framework, file framework.widgetCommandAdapters.js */
  66189. (function($, DX) {
  66190. var commandToContainer = DX.framework.utils.commandToContainer,
  66191. DX_COMMAND_TO_WIDGET_ADAPTER = "dxCommandToWidgetAdapter";
  66192. var WidgetItemWrapperBase = DX.Class.inherit({
  66193. ctor: function(command, containerOptions) {
  66194. this.command = command;
  66195. this.containerOptions = containerOptions;
  66196. this._createWidgetItem(command, containerOptions);
  66197. this._commandChangedHandler = $.proxy(this._onCommandChanged, this);
  66198. command.on("optionChanged", this._commandChangedHandler)
  66199. },
  66200. _createWidgetItem: function(command, containerOptions) {
  66201. this.widgetItem = $.extend({
  66202. command: command,
  66203. containerOptions: containerOptions
  66204. }, containerOptions, command.option());
  66205. this._updateItem()
  66206. },
  66207. _onCommandChanged: function(args) {
  66208. var optionName = args.name,
  66209. newValue = args.value,
  66210. oldValue = args.previousValue;
  66211. this.widgetItem[optionName] = newValue;
  66212. this._updateItem(optionName, newValue, oldValue)
  66213. },
  66214. _updateItem: function(optionName, newValue, oldValue){},
  66215. dispose: function() {
  66216. if (this.command)
  66217. this.command.off("optionChanged", this._commandChangedHandler);
  66218. delete this.command;
  66219. delete this.containerOptions;
  66220. delete this.widgetItem;
  66221. delete this.updateItemHandler
  66222. }
  66223. });
  66224. var WidgetAdapterBase = DX.Class.inherit({
  66225. ctor: function($widgetElement) {
  66226. this.$widgetElement = $widgetElement;
  66227. this.$widgetElement.data(DX_COMMAND_TO_WIDGET_ADAPTER, this);
  66228. this.widget = this._getWidgetByElement($widgetElement);
  66229. this._widgetWidgetContentReadyHandler = $.proxy(this._onWidgetContentReady, this);
  66230. this._widgetWidgetItemRenderedHandler = $.proxy(this._onWidgetItemRendered, this);
  66231. this._widgetDisposingHandler = $.proxy(this._onWidgetDisposing, this);
  66232. this.widget.on("itemRendered", this._widgetWidgetItemRenderedHandler);
  66233. this.widget.on("contentReady", this._widgetWidgetContentReadyHandler);
  66234. this.widget.on("disposing", this._widgetDisposingHandler);
  66235. this.itemWrappers = [];
  66236. this._transitionExecutor = new DX.TransitionExecutor
  66237. },
  66238. addCommand: function(command, containerOptions) {
  66239. var itemWrapper = this._createItemWrapper(command, containerOptions);
  66240. this.itemWrappers.push(itemWrapper);
  66241. this._addItemToWidget(itemWrapper);
  66242. this.refresh();
  66243. this._commandChangedHandler = $.proxy(this._onCommandChanged, this);
  66244. itemWrapper.command.on("optionChanged", this._commandChangedHandler)
  66245. },
  66246. beginUpdate: function() {
  66247. this.widget.beginUpdate()
  66248. },
  66249. endUpdate: function() {
  66250. this.widget.endUpdate();
  66251. return this.animationDeferred
  66252. },
  66253. _onWidgetItemRendered: function(e) {
  66254. if (e.itemData.isJustAdded && e.itemElement.is(":visible")) {
  66255. this._transitionExecutor.enter(e.itemElement, "command-rendered");
  66256. delete e.itemData.isJustAdded
  66257. }
  66258. },
  66259. _onWidgetContentReady: function(e) {
  66260. this.animationDeferred = this._transitionExecutor.start()
  66261. },
  66262. _onWidgetDisposing: function() {
  66263. this.dispose(true)
  66264. },
  66265. _onCommandChanged: function(args) {
  66266. if (args.name !== "highlighted")
  66267. this.refresh()
  66268. },
  66269. _addItemToWidget: function(itemWrapper) {
  66270. var items = this.widget.option("items");
  66271. items.push(itemWrapper.widgetItem);
  66272. if (this.widget.element().is(":visible"))
  66273. itemWrapper.widgetItem.isJustAdded = true
  66274. },
  66275. refresh: function() {
  66276. var items = this.widget.option("items");
  66277. this.widget.option("items", items)
  66278. },
  66279. clear: function(widgetDisposing) {
  66280. var that = this;
  66281. $.each(that.itemWrappers, function(index, itemWrapper) {
  66282. itemWrapper.command.off("optionChanged", that._commandChangedHandler);
  66283. itemWrapper.dispose()
  66284. });
  66285. this.itemWrappers.length = 0;
  66286. if (!widgetDisposing)
  66287. this._clearWidgetItems()
  66288. },
  66289. _clearWidgetItems: function() {
  66290. this.widget.option("items", [])
  66291. },
  66292. dispose: function(widgetDisposing) {
  66293. this.clear(widgetDisposing);
  66294. if (this.widget) {
  66295. this.widget.off("itemRendered", this._widgetWidgetItemRenderedHandler);
  66296. this.widget.off("contentReady", this._widgetContentReadyHandler);
  66297. this.widget.off("disposing", this._widgetDisposingHandler);
  66298. this.$widgetElement.removeData(DX_COMMAND_TO_WIDGET_ADAPTER);
  66299. delete this.widget;
  66300. delete this.$widgetElement
  66301. }
  66302. }
  66303. });
  66304. var CommandToWidgetAdapter = DX.Class.inherit({
  66305. ctor: function(createAdapter) {
  66306. this.createAdapter = createAdapter
  66307. },
  66308. _getWidgetAdapter: function($container) {
  66309. var widgetAdapter = $container.data(DX_COMMAND_TO_WIDGET_ADAPTER);
  66310. if (!widgetAdapter)
  66311. widgetAdapter = this.createAdapter($container);
  66312. return widgetAdapter
  66313. },
  66314. addCommand: function($container, command, containerOptions) {
  66315. var widgetAdapter = this._getWidgetAdapter($container);
  66316. widgetAdapter.addCommand(command, containerOptions)
  66317. },
  66318. clearContainer: function($container) {
  66319. var widgetAdapter = this._getWidgetAdapter($container);
  66320. widgetAdapter.clear()
  66321. },
  66322. beginUpdate: function($container) {
  66323. var widgetAdapter = this._getWidgetAdapter($container);
  66324. widgetAdapter.beginUpdate()
  66325. },
  66326. endUpdate: function($container) {
  66327. var widgetAdapter = this._getWidgetAdapter($container);
  66328. return widgetAdapter.endUpdate()
  66329. }
  66330. });
  66331. var dxToolbarItemWrapper = WidgetItemWrapperBase.inherit({_updateItem: function() {
  66332. var widgetItem = this.widgetItem,
  66333. command = this.command,
  66334. containerOptions = this.containerOptions,
  66335. location = commandToContainer.resolvePropertyValue(command, containerOptions, "location"),
  66336. optionsTarget;
  66337. widgetItem.location = location;
  66338. if (location === "menu")
  66339. optionsTarget = widgetItem;
  66340. else {
  66341. optionsTarget = $.extend({}, widgetItem);
  66342. widgetItem.options = optionsTarget;
  66343. widgetItem.widget = "button"
  66344. }
  66345. optionsTarget.onClick = function(e) {
  66346. command.execute(e)
  66347. };
  66348. optionsTarget.text = commandToContainer.resolveTextValue(command, containerOptions);
  66349. optionsTarget.disabled = command.option("disabled");
  66350. optionsTarget.icon = commandToContainer.resolveIconValue(command, containerOptions, "icon");
  66351. optionsTarget.type = commandToContainer.resolveTypeValue(command, containerOptions)
  66352. }});
  66353. var dxToolbarAdapter = WidgetAdapterBase.inherit({
  66354. ctor: function($widgetElement) {
  66355. this.callBase($widgetElement)
  66356. },
  66357. _getWidgetByElement: function($element) {
  66358. return $element.dxToolbar("instance")
  66359. },
  66360. _createItemWrapper: function(command, containerOptions) {
  66361. return new dxToolbarItemWrapper(command, containerOptions)
  66362. },
  66363. addCommand: function(command, containerOptions) {
  66364. this.callBase(command, containerOptions);
  66365. this.widget.option("visible", true)
  66366. }
  66367. });
  66368. var dxActionSheetItemWrapper = WidgetItemWrapperBase.inherit({_updateItem: function() {
  66369. var widgetItem = this.widgetItem,
  66370. command = this.command,
  66371. containerOptions = this.containerOptions;
  66372. widgetItem.text = commandToContainer.resolveTextValue(command, containerOptions);
  66373. widgetItem.icon = commandToContainer.resolveIconValue(command, containerOptions, "icon")
  66374. }});
  66375. var dxActionSheetAdapter = WidgetAdapterBase.inherit({
  66376. _createItemWrapper: function(command, containerOptions) {
  66377. return new dxActionSheetItemWrapper(command, containerOptions)
  66378. },
  66379. _getWidgetByElement: function($element) {
  66380. return $element.dxActionSheet("instance")
  66381. }
  66382. });
  66383. var dxListItemWrapper = WidgetItemWrapperBase.inherit({
  66384. _createWidgetItem: function(command, containerOptions) {
  66385. this.callBase(command, containerOptions);
  66386. this.widgetItem.onClick = $.proxy(this._itemClick, this)
  66387. },
  66388. _updateItem: function() {
  66389. var widgetItem = this.widgetItem,
  66390. command = this.command,
  66391. containerOptions = this.containerOptions;
  66392. widgetItem.title = commandToContainer.resolveTextValue(command, containerOptions);
  66393. widgetItem.icon = commandToContainer.resolveIconValue(command, containerOptions, "icon")
  66394. },
  66395. _itemClick: function(e) {
  66396. this.command.execute(e)
  66397. }
  66398. });
  66399. var dxListAdapter = WidgetAdapterBase.inherit({
  66400. _createItemWrapper: function(command, containerOptions) {
  66401. return new dxListItemWrapper(command, containerOptions)
  66402. },
  66403. _getWidgetByElement: function($element) {
  66404. return $element.dxList("instance")
  66405. }
  66406. });
  66407. var dxNavBarItemWrapper = WidgetItemWrapperBase.inherit({_updateItem: function(optionName, newValue, oldValue) {
  66408. var command = this.command,
  66409. containerOptions = this.containerOptions;
  66410. if (optionName !== "highlighted") {
  66411. this.widgetItem.text = commandToContainer.resolveTextValue(command, containerOptions);
  66412. this.widgetItem.icon = commandToContainer.resolveIconValue(command, containerOptions, "icon")
  66413. }
  66414. }});
  66415. var dxNavBarAdapter = WidgetAdapterBase.inherit({
  66416. ctor: function($widgetElement) {
  66417. this.callBase($widgetElement);
  66418. this.widget.option("onItemClick", $.proxy(this._onNavBarItemClick, this))
  66419. },
  66420. _onNavBarItemClick: function(e) {
  66421. var items = this.widget.option("items");
  66422. for (var i = items.length; --i; )
  66423. items[i].command.option("highlighted", false);
  66424. e.itemData.command.execute(e)
  66425. },
  66426. _getWidgetByElement: function($element) {
  66427. return $element.dxNavBar("instance")
  66428. },
  66429. _createItemWrapper: function(command, containerOptions) {
  66430. return new dxNavBarItemWrapper(command, containerOptions)
  66431. },
  66432. addCommand: function(command, containerOptions) {
  66433. this.callBase(command, containerOptions);
  66434. this._updateSelectedIndex()
  66435. },
  66436. _onCommandChanged: function(args) {
  66437. var optionName = args.name,
  66438. newValue = args.value;
  66439. if (optionName !== "highlighted" || newValue)
  66440. this._updateSelectedIndex();
  66441. this.callBase(args)
  66442. },
  66443. _updateSelectedIndex: function() {
  66444. var items = this.widget.option("items");
  66445. for (var i = 0, itemsCount = items.length; i < itemsCount; i++)
  66446. if (items[i].highlighted) {
  66447. this.widget.option("selectedIndex", i);
  66448. break
  66449. }
  66450. }
  66451. });
  66452. var dxPivotAdapter = WidgetAdapterBase.inherit({
  66453. ctor: function($widgetElement) {
  66454. this.callBase($widgetElement);
  66455. this.widget.option("onSelectionChanged", $.proxy(this._onPivotSelectionChange, this))
  66456. },
  66457. _onPivotSelectionChange: function(e) {
  66458. if (e.addedItems.length && e.removedItems.length && e.addedItems[0] && e.addedItems[0].command)
  66459. e.addedItems[0].command.execute(e)
  66460. },
  66461. _getWidgetByElement: function($element) {
  66462. return $element.dxPivot("instance")
  66463. },
  66464. _createItemWrapper: function(command, containerOptions) {
  66465. return new dxToolbarItemWrapper(command, containerOptions)
  66466. },
  66467. addCommand: function(command, containerOptions) {
  66468. this.callBase(command, containerOptions);
  66469. this._updateSelectedIndex()
  66470. },
  66471. _onCommandChanged: function(args) {
  66472. var optionName = args.name,
  66473. newValue = args.value;
  66474. if (optionName === "visible")
  66475. this._rerenderPivot();
  66476. else if (optionName !== "highlighted" || newValue)
  66477. this._updateSelectedIndex()
  66478. },
  66479. _addItemToWidget: function(itemWrapper) {
  66480. if (itemWrapper.command.option("visible"))
  66481. this.callBase(itemWrapper)
  66482. },
  66483. _updateSelectedIndex: function() {
  66484. var pivot = this.widget,
  66485. items = pivot.option("items") || [];
  66486. DX.fx.off = true;
  66487. for (var i = 0, itemsCount = items.length; i < itemsCount; i++)
  66488. if (items[i].highlighted) {
  66489. pivot.option("selectedIndex", i);
  66490. break
  66491. }
  66492. DX.fx.off = false
  66493. },
  66494. _rerenderPivot: function() {
  66495. var that = this;
  66496. that.widget.option("items", []);
  66497. $.each(that.itemWrappers, function(index, itemWrapper) {
  66498. if (itemWrapper.command.option("visible"))
  66499. that._addItemToWidget(itemWrapper)
  66500. });
  66501. that.refresh();
  66502. that._updateSelectedIndex()
  66503. }
  66504. });
  66505. var dxSlideOutItemWrapper = WidgetItemWrapperBase.inherit({_updateItem: function(optionName, newValue, oldValue) {
  66506. var widgetItem = this.widgetItem,
  66507. command = this.command,
  66508. containerOptions = this.containerOptions;
  66509. if (name !== "highlighted") {
  66510. widgetItem.title = commandToContainer.resolveTextValue(command, containerOptions);
  66511. widgetItem.icon = commandToContainer.resolveIconValue(command, containerOptions, "icon")
  66512. }
  66513. }});
  66514. var dxSlideOutAdapter = WidgetAdapterBase.inherit({
  66515. ctor: function($widgetElement) {
  66516. this.callBase($widgetElement);
  66517. this.widget.option("onItemClick", $.proxy(this._onSlideOutItemClick, this))
  66518. },
  66519. _onSlideOutItemClick: function(e) {
  66520. e.itemData.command.execute(e)
  66521. },
  66522. _getWidgetByElement: function($element) {
  66523. return $element.dxSlideOut("instance")
  66524. },
  66525. _createItemWrapper: function(command, containerOptions) {
  66526. return new dxSlideOutItemWrapper(command, containerOptions)
  66527. },
  66528. _updateSelectedIndex: function() {
  66529. var items = this.widget.option("items") || [];
  66530. for (var i = 0, itemsCount = items.length; i < itemsCount; i++)
  66531. if (items[i].highlighted) {
  66532. this.widget.option("selectedIndex", i);
  66533. break
  66534. }
  66535. },
  66536. addCommand: function(command, containerOptions) {
  66537. this.callBase(command, containerOptions);
  66538. this._updateSelectedIndex()
  66539. },
  66540. _onCommandChanged: function(args) {
  66541. var optionName = args.name,
  66542. newValue = args.value;
  66543. if (optionName !== "highlighted" || newValue)
  66544. this._updateSelectedIndex();
  66545. this.callBase(args)
  66546. }
  66547. });
  66548. var adapters = DX.framework.html.commandToDXWidgetAdapters = {};
  66549. adapters.dxToolbar = new CommandToWidgetAdapter(function($widgetElement) {
  66550. return new dxToolbarAdapter($widgetElement)
  66551. });
  66552. adapters.dxActionSheet = new CommandToWidgetAdapter(function($widgetElement) {
  66553. return new dxActionSheetAdapter($widgetElement)
  66554. });
  66555. adapters.dxList = new CommandToWidgetAdapter(function($widgetElement) {
  66556. return new dxListAdapter($widgetElement)
  66557. });
  66558. adapters.dxNavBar = new CommandToWidgetAdapter(function($widgetElement) {
  66559. return new dxNavBarAdapter($widgetElement)
  66560. });
  66561. adapters.dxPivot = new CommandToWidgetAdapter(function($widgetElement) {
  66562. return new dxPivotAdapter($widgetElement)
  66563. });
  66564. adapters.dxSlideOut = new CommandToWidgetAdapter(function($widgetElement) {
  66565. return new dxSlideOutAdapter($widgetElement)
  66566. });
  66567. DX.framework.html.WidgetItemWrapperBase = WidgetItemWrapperBase;
  66568. DX.framework.html.WidgetAdapterBase = WidgetAdapterBase
  66569. })(jQuery, DevExpress);
  66570. /*! Module framework, file framework.commandManager.js */
  66571. (function($, DX, undefined) {
  66572. var Class = DX.Class;
  66573. var CommandContainer = DX.DOMComponent.inherit({
  66574. ctor: function(element, options) {
  66575. if ($.isPlainObject(element)) {
  66576. options = element;
  66577. element = $("<div />")
  66578. }
  66579. this.callBase(element, options)
  66580. },
  66581. _setDefaultOptions: function() {
  66582. this.callBase();
  66583. this.option({id: null})
  66584. },
  66585. _render: function() {
  66586. this.callBase();
  66587. this.element().addClass("dx-command-container")
  66588. }
  66589. });
  66590. DX.registerComponent("dxCommandContainer", DX.framework, CommandContainer);
  66591. DX.framework.html.CommandManager = Class.inherit({
  66592. ctor: function(options) {
  66593. options = options || {};
  66594. this.defaultWidgetAdapter = options.defaultWidgetAdapter || this._getDefaultWidgetAdapter();
  66595. this.commandMapping = options.commandMapping || new DX.framework.CommandMapping
  66596. },
  66597. _getDefaultWidgetAdapter: function() {
  66598. return {
  66599. addCommand: $.noop,
  66600. clearContainer: $.noop
  66601. }
  66602. },
  66603. _getContainerAdapter: function($container) {
  66604. var componentNames = $container.data("dxComponents"),
  66605. adapters = DX.framework.html.commandToDXWidgetAdapters;
  66606. if (componentNames)
  66607. for (var index in componentNames) {
  66608. var widgetName = componentNames[index];
  66609. if (widgetName in adapters)
  66610. return adapters[widgetName]
  66611. }
  66612. return this.defaultWidgetAdapter
  66613. },
  66614. findCommands: function($view) {
  66615. var result = $.map($view.addBack().find(".dx-command"), function(element) {
  66616. return $(element).dxCommand("instance")
  66617. });
  66618. return result
  66619. },
  66620. findCommandContainers: function($markup) {
  66621. var result = $.map($markup.find(".dx-command-container"), function(element) {
  66622. return $(element).dxCommandContainer("instance")
  66623. });
  66624. return result
  66625. },
  66626. _checkCommandId: function(id, command) {
  66627. if (id === null)
  66628. throw DX.Error("E3010", command.element().get(0).outerHTML);
  66629. },
  66630. renderCommandsToContainers: function(commands, containers) {
  66631. var that = this,
  66632. commandHash = {},
  66633. commandIds = [],
  66634. deferreds = [];
  66635. $.each(commands, function(i, command) {
  66636. var id = command.option("id");
  66637. that._checkCommandId(id, command);
  66638. commandIds.push(id);
  66639. commandHash[id] = command
  66640. });
  66641. that.commandMapping.checkCommandsExist(commandIds);
  66642. $.each(containers, function(k, container) {
  66643. var commandInfos = [];
  66644. $.each(commandHash, function(id, command) {
  66645. var commandId = id;
  66646. var commandOptions = that.commandMapping.getCommandMappingForContainer(commandId, container.option("id"));
  66647. if (commandOptions)
  66648. commandInfos.push({
  66649. command: command,
  66650. options: commandOptions
  66651. })
  66652. });
  66653. if (commandInfos.length) {
  66654. var deferred = that._attachCommandsToContainer(container.element(), commandInfos);
  66655. if (deferred)
  66656. deferreds.push(deferred)
  66657. }
  66658. });
  66659. return $.when.apply($, deferreds)
  66660. },
  66661. clearContainer: function(container) {
  66662. var $container = container.element(),
  66663. adapter = this._getContainerAdapter($container);
  66664. adapter.clearContainer($container)
  66665. },
  66666. _arrangeCommandsToContainers: function(commands, containers) {
  66667. DX.log("W0002", "CommandManager", "_arrangeCommandsToContainers", "14.1", "Use the 'renderCommandsToContainers' method instead.");
  66668. this.renderCommandsToContainers(commands, containers)
  66669. },
  66670. _attachCommandsToContainer: function($container, commandInfos) {
  66671. var adapter = this._getContainerAdapter($container),
  66672. result;
  66673. if (adapter.beginUpdate)
  66674. adapter.beginUpdate($container);
  66675. $.each(commandInfos, function(index, commandInfo) {
  66676. adapter.addCommand($container, commandInfo.command, commandInfo.options)
  66677. });
  66678. if (adapter.endUpdate)
  66679. result = adapter.endUpdate($container);
  66680. return result
  66681. }
  66682. })
  66683. })(jQuery, DevExpress);
  66684. /*! Module framework, file framework.layoutController.js */
  66685. (function($, DX, undefined) {
  66686. var Class = DX.Class,
  66687. HIDDEN_BAG_ID = "__hidden-bag",
  66688. TRANSITION_SELECTOR = ".dx-transition:not(.dx-transition .dx-transition)",
  66689. CONTENT_SELECTOR = ".dx-content",
  66690. DEFAULT_COMMAND_RENDER_STAGE = "onViewShown";
  66691. var transitionSelector = function(transitionName) {
  66692. return ".dx-transition-" + transitionName
  66693. };
  66694. DX.framework.html.DefaultLayoutController = Class.inherit({
  66695. ctor: function(options) {
  66696. options = options || {};
  66697. this.name = options.name || "";
  66698. this._layoutModel = options.layoutModel || {};
  66699. this._defaultPaneName = options.defaultPaneName || "content";
  66700. this._transitionDuration = options.transitionDuration === undefined ? 400 : options.transitionDuration;
  66701. this.viewReleased = $.Callbacks();
  66702. this.viewRendered = $.Callbacks();
  66703. this._callbacksToEvents("DefaultLayoutController", ["viewReleased", "viewRendered"])
  66704. },
  66705. init: function(options) {
  66706. options = options || {};
  66707. this._visibleViews = {};
  66708. this._$viewPort = options.$viewPort || $("body");
  66709. this._commandManager = options.commandManager;
  66710. this._viewEngine = options.viewEngine;
  66711. this.transitionExecutor = new DX.TransitionExecutor;
  66712. this._prepareTemplates();
  66713. this._$viewPort.append(this._getRootElement());
  66714. this._hideElements(this._getRootElement());
  66715. if (options.templateContext) {
  66716. this._templateContext = options.templateContext;
  66717. this._proxiedTemplateContextChangedHandler = $.proxy(this._templateContextChangedHandler, this)
  66718. }
  66719. },
  66720. activate: function() {
  66721. var $rootElement = this._getRootElement();
  66722. this._showElements($rootElement);
  66723. this._attachRefreshViewRequiredHandler();
  66724. return $.Deferred().resolve().promise()
  66725. },
  66726. deactivate: function() {
  66727. this._releaseVisibleViews();
  66728. this._hideElements(this._getRootElement());
  66729. this._detachRefreshViewRequiredHandler();
  66730. return $.Deferred().resolve().promise()
  66731. },
  66732. activeViewInfo: function() {
  66733. return this._visibleViews[this._defaultPaneName]
  66734. },
  66735. _applyTemplate: function($elements, model) {
  66736. $elements.each(function(i, element) {
  66737. DX.framework.templateProvider.applyTemplate(element, model)
  66738. })
  66739. },
  66740. _releaseVisibleViews: function() {
  66741. var that = this;
  66742. $.each(this._visibleViews, function(index, viewInfo) {
  66743. that._hideView(viewInfo);
  66744. that._releaseView(viewInfo)
  66745. });
  66746. this._visibleViews = {}
  66747. },
  66748. _templateContextChangedHandler: function() {
  66749. $.each(this._visibleViews, $.proxy(function(index, viewInfo) {
  66750. this.showView(viewInfo)
  66751. }, this))
  66752. },
  66753. _attachRefreshViewRequiredHandler: function() {
  66754. if (this._templateContext)
  66755. this._templateContext.on("optionChanged", this._proxiedTemplateContextChangedHandler)
  66756. },
  66757. _detachRefreshViewRequiredHandler: function() {
  66758. if (this._templateContextChanged)
  66759. this._templateContext.off("optionChanged", this._proxiedTemplateContextChangedHandler)
  66760. },
  66761. _getPreviousViewInfo: function(viewInfo) {
  66762. return this._visibleViews[this._getViewPaneName(viewInfo.viewTemplateInfo)]
  66763. },
  66764. _prepareTemplates: function() {
  66765. var that = this;
  66766. var $layoutTemplate = that._viewEngine.getLayoutTemplate(this._getLayoutTemplateName());
  66767. that._$layoutTemplate = $layoutTemplate;
  66768. that._$mainLayout = that._createEmptyLayout();
  66769. that._showElements(that._$mainLayout);
  66770. that._applyTemplate(that._$mainLayout, that._layoutModel);
  66771. that._$navigationWidget = that._createNavigationWidget()
  66772. },
  66773. renderNavigation: function(navigationCommands) {
  66774. this._clearNavigationWidget();
  66775. this._renderNavigationImpl(navigationCommands)
  66776. },
  66777. _renderNavigationImpl: function(navigationCommands) {
  66778. this._renderCommands(this._$mainLayout, navigationCommands)
  66779. },
  66780. _createNavigationWidget: function() {
  66781. var containers = this._findCommandContainers(this._$mainLayout),
  66782. result;
  66783. $.each(containers, function(k, container) {
  66784. if (container.option("id") === "global-navigation") {
  66785. result = container.element();
  66786. return false
  66787. }
  66788. });
  66789. return result
  66790. },
  66791. _clearNavigationWidget: function() {
  66792. if (this._$navigationWidget)
  66793. this._commandManager.clearContainer(this._$navigationWidget.dxCommandContainer("instance"))
  66794. },
  66795. _getRootElement: function() {
  66796. return this._$mainLayout
  66797. },
  66798. _getViewFrame: function(viewInfo) {
  66799. return this._$mainLayout
  66800. },
  66801. _getLayoutTemplateName: function() {
  66802. return this.name
  66803. },
  66804. _applyModelToTransitionElements: function($markup, model) {
  66805. var that = this;
  66806. this._getTransitionElements($markup).each(function(i, item) {
  66807. that._applyTemplate($(item).children(), model)
  66808. })
  66809. },
  66810. _createViewLayoutTemplate: function() {
  66811. var that = this;
  66812. var $viewLayoutTemplate = that._$layoutTemplate.clone();
  66813. this._hideElements($viewLayoutTemplate);
  66814. return $viewLayoutTemplate
  66815. },
  66816. _createEmptyLayout: function() {
  66817. var that = this;
  66818. var $result = that._$layoutTemplate.clone();
  66819. this._hideElements($result);
  66820. this._getTransitionElements($result).empty();
  66821. $result.children(CONTENT_SELECTOR).remove();
  66822. return $result
  66823. },
  66824. _getTransitionElements: function($markup) {
  66825. return $markup.find(TRANSITION_SELECTOR).addBack(TRANSITION_SELECTOR)
  66826. },
  66827. showView: function(viewInfo, direction) {
  66828. direction = direction || "forward";
  66829. var that = this,
  66830. previousViewInfo = that._getPreviousViewInfo(viewInfo),
  66831. previousViewTemplateId = previousViewInfo === viewInfo ? previousViewInfo.currentViewTemplateId : undefined;
  66832. this._defineCurrentViewTemplateId(viewInfo);
  66833. if (previousViewTemplateId && previousViewTemplateId === viewInfo.currentViewTemplateId && viewInfo === previousViewInfo)
  66834. return $.Deferred().resolve().promise();
  66835. that._ensureViewRendered(viewInfo);
  66836. this.fireEvent("viewShowing", [viewInfo]);
  66837. return this._showViewImpl(viewInfo, direction, previousViewTemplateId).done(function() {
  66838. that._onViewShown(viewInfo)
  66839. })
  66840. },
  66841. disposeView: function(viewInfo) {
  66842. this._clearRenderResult(viewInfo)
  66843. },
  66844. _clearRenderResult: function(viewInfo) {
  66845. if (viewInfo.renderResult) {
  66846. viewInfo.renderResult.$markup.remove();
  66847. viewInfo.renderResult.$viewItems.remove();
  66848. delete viewInfo.renderResult
  66849. }
  66850. },
  66851. _prepareViewTemplate: function($viewTemplate, viewInfo){},
  66852. _renderViewImpl: function($viewTemplate, viewInfo) {
  66853. var that = this,
  66854. allowedChildrenSelector = ".dx-command,.dx-content,script",
  66855. $layout = this._createViewLayoutTemplate(),
  66856. $viewItems,
  66857. isSimplifiedMarkup = true,
  66858. outOfContentItems = $();
  66859. if ($viewTemplate.children(allowedChildrenSelector).length === 0)
  66860. this._viewEngine._wrapViewDefaultContent($viewTemplate);
  66861. $viewItems = $viewTemplate.children();
  66862. this._applyModelToTransitionElements($layout, viewInfo.model);
  66863. this._viewEngine.applyLayout($viewTemplate, $layout);
  66864. $viewItems.each(function(i, item) {
  66865. var $item = $(item);
  66866. that._applyTemplate($item, viewInfo.model);
  66867. if ($item.is(allowedChildrenSelector))
  66868. isSimplifiedMarkup = false;
  66869. else
  66870. outOfContentItems = outOfContentItems.add($item)
  66871. });
  66872. if (outOfContentItems.length && !isSimplifiedMarkup)
  66873. throw DX.Error("E3014", outOfContentItems[0].outerHTML);
  66874. viewInfo.renderResult = viewInfo.renderResult || {};
  66875. viewInfo.renderResult.$viewItems = $viewItems;
  66876. viewInfo.renderResult.$markup = $layout
  66877. },
  66878. _renderCommands: function($markup, commands) {
  66879. var commandContainers = this._findCommandContainers($markup);
  66880. this._commandManager.renderCommandsToContainers(commands, commandContainers)
  66881. },
  66882. _prepareViewCommands: function(viewInfo) {
  66883. var $viewItems = viewInfo.renderResult.$viewItems,
  66884. viewCommands = this._commandManager.findCommands($viewItems),
  66885. commandsToRenderMap = {};
  66886. viewInfo.commands = DX.framework.utils.mergeCommands(viewInfo.commands || [], viewCommands);
  66887. viewInfo.commandsToRenderMap = commandsToRenderMap;
  66888. $.each(viewInfo.commands, function(index, command) {
  66889. var renderStage = command.option("renderStage") || DEFAULT_COMMAND_RENDER_STAGE,
  66890. targetArray = commandsToRenderMap[renderStage] = commandsToRenderMap[renderStage] || [];
  66891. targetArray.push(command)
  66892. })
  66893. },
  66894. _applyViewCommands: function(viewInfo, renderStage) {
  66895. renderStage = renderStage || DEFAULT_COMMAND_RENDER_STAGE;
  66896. var commandsToRender = viewInfo.commandsToRenderMap[renderStage],
  66897. $markup = viewInfo.renderResult.$markup;
  66898. if (commandsToRender) {
  66899. this._renderCommands($markup, commandsToRender);
  66900. delete viewInfo.commandsToRenderMap[renderStage]
  66901. }
  66902. },
  66903. _findCommandContainers: function($markup) {
  66904. return DX.utils.createComponents($markup, ["dxCommandContainer"])
  66905. },
  66906. _defineCurrentViewTemplateId: function(viewInfo) {
  66907. var viewTemplateInstance = viewInfo.$viewTemplate ? viewInfo.$viewTemplate.dxView("instance") : this._viewEngine.getViewTemplateInfo(viewInfo.viewName),
  66908. currentViewTemplateId = viewTemplateInstance.getId();
  66909. viewInfo.currentViewTemplateId = currentViewTemplateId
  66910. },
  66911. _ensureViewRendered: function(viewInfo) {
  66912. var $cachedMarkup = viewInfo.renderResult && viewInfo.renderResult.markupCache[viewInfo.currentViewTemplateId];
  66913. if ($cachedMarkup)
  66914. viewInfo.renderResult.$markup = $cachedMarkup;
  66915. else {
  66916. this._renderView(viewInfo);
  66917. viewInfo.renderResult.markupCache = viewInfo.renderResult.markupCache || {};
  66918. viewInfo.renderResult.markupCache[viewInfo.currentViewTemplateId] = viewInfo.renderResult.$markup
  66919. }
  66920. },
  66921. _renderView: function(viewInfo) {
  66922. var $viewTemplate = viewInfo.$viewTemplate || this._viewEngine.getViewTemplate(viewInfo.viewName);
  66923. this._prepareViewTemplate($viewTemplate, viewInfo);
  66924. this._renderViewImpl($viewTemplate, viewInfo);
  66925. this._prepareViewCommands(viewInfo);
  66926. this._applyViewCommands(viewInfo, "onViewRendering");
  66927. this._appendViewToLayout(viewInfo);
  66928. $viewTemplate.remove();
  66929. this._onRenderComplete(viewInfo);
  66930. this.fireEvent("viewRendered", [viewInfo])
  66931. },
  66932. _appendViewToLayout: function(viewInfo) {
  66933. var that = this,
  66934. $viewFrame = that._getViewFrame(viewInfo),
  66935. $markup = viewInfo.renderResult.$markup,
  66936. $transitionContentElements = $(),
  66937. animationItems = [];
  66938. $.each($markup.find(".dx-content-placeholder"), function(index, el) {
  66939. DX.framework.prepareTransition($(el), $(el).attr("data-dx-content-placeholder-name"))
  66940. });
  66941. $.each(that._getTransitionElements($viewFrame), function(index, transitionElement) {
  66942. var $transition = $(transitionElement),
  66943. $viewElement = $markup.find(transitionSelector($transition.attr("data-dx-transition-name"))).children(),
  66944. animationItem = {
  66945. $element: $viewElement,
  66946. animation: $transition.attr("data-dx-transition-type")
  66947. };
  66948. animationItems.push(animationItem);
  66949. that._hideViewElements($viewElement);
  66950. $transition.append($viewElement);
  66951. $transitionContentElements = $transitionContentElements.add($viewElement)
  66952. });
  66953. that._$mainLayout.append(viewInfo.renderResult.$viewItems.filter(".dx-command"));
  66954. $markup.remove();
  66955. viewInfo.renderResult.$markup = $transitionContentElements;
  66956. viewInfo.renderResult.animationItems = animationItems
  66957. },
  66958. _onRenderComplete: function(viewInfo){},
  66959. _onViewShown: function(viewInfo) {
  66960. $(document).trigger("dx.viewchanged")
  66961. },
  66962. _enter: function(animationItems) {
  66963. var transitionExecutor = this.transitionExecutor;
  66964. $.each(animationItems, function(index, item) {
  66965. transitionExecutor.enter(item.$element, item.animation)
  66966. })
  66967. },
  66968. _leave: function(animationItems) {
  66969. var transitionExecutor = this.transitionExecutor;
  66970. $.each(animationItems, function(index, item) {
  66971. transitionExecutor.leave(item.$element, item.animation)
  66972. })
  66973. },
  66974. _doTransition: function(oldViewInfo, newViewInfo, direction) {
  66975. if (oldViewInfo)
  66976. this._leave(oldViewInfo.renderResult.animationItems);
  66977. this._enter(newViewInfo.renderResult.animationItems);
  66978. return this.transitionExecutor.start({direction: direction})
  66979. },
  66980. _showViewImpl: function(viewInfo, direction, previousViewTemplateId) {
  66981. var that = this,
  66982. result,
  66983. previousViewInfo = this._getPreviousViewInfo(viewInfo);
  66984. this._showView(viewInfo);
  66985. if (!previousViewInfo || previousViewInfo === viewInfo) {
  66986. that._changeView(viewInfo, previousViewTemplateId);
  66987. result = $.Deferred().resolve().promise()
  66988. }
  66989. else
  66990. result = that._doTransition(previousViewInfo, viewInfo, direction).done(function() {
  66991. that._changeView(viewInfo)
  66992. });
  66993. return result
  66994. },
  66995. _releaseView: function(viewInfo) {
  66996. this.viewReleased.fireWith(this, [viewInfo])
  66997. },
  66998. _changeView: function(viewInfo, previousViewTemplateId) {
  66999. var that = this;
  67000. if (previousViewTemplateId)
  67001. that._hideView(viewInfo, previousViewTemplateId);
  67002. else {
  67003. var previousViewInfo = that._getPreviousViewInfo(viewInfo);
  67004. if (previousViewInfo && previousViewInfo !== viewInfo) {
  67005. that._hideView(previousViewInfo);
  67006. that._releaseView(previousViewInfo)
  67007. }
  67008. this._visibleViews[this._getViewPaneName(viewInfo.viewTemplateInfo)] = viewInfo
  67009. }
  67010. this._applyViewCommands(viewInfo);
  67011. this._subscribeToDeferredItems(viewInfo);
  67012. this._renderDeferredItems(viewInfo.renderResult.$markup)
  67013. },
  67014. _subscribeToDeferredItems: function(viewInfo) {
  67015. var that = this,
  67016. $markup = viewInfo.renderResult.$markup;
  67017. $markup.find(".dx-pending-rendering").add($markup.filter(".dx-pending-rendering")).each(function() {
  67018. var $element = $(this),
  67019. promise = $element.data("dx-rendered-promise");
  67020. if (promise)
  67021. promise.done(function() {
  67022. that._renderCommands($element, viewInfo.commands)
  67023. })
  67024. })
  67025. },
  67026. _renderDeferredItems: function($items) {
  67027. var that = this,
  67028. $pendingItem = $items.find(".dx-pending-rendering-manual").add($items.filter(".dx-pending-rendering-manual")).first();
  67029. if ($pendingItem.length) {
  67030. var render = $pendingItem.data("dx-render-delegate");
  67031. setTimeout(function() {
  67032. render().done(function() {
  67033. that._renderDeferredItems($items)
  67034. })
  67035. })
  67036. }
  67037. },
  67038. _getViewPaneName: function(viewTemplateInfo) {
  67039. return this._defaultPaneName
  67040. },
  67041. _hideElements: function($elements) {
  67042. $elements.addClass("dx-hidden")
  67043. },
  67044. _showElements: function($elements) {
  67045. $elements.removeClass("dx-hidden");
  67046. DX.utils.triggerShownEvent($elements)
  67047. },
  67048. _hideViewElements: function($elements) {
  67049. DX.utils.triggerHidingEvent($elements);
  67050. this._patchIDs($elements);
  67051. this._disableInputs($elements);
  67052. $elements.removeClass("dx-active-view").addClass("dx-inactive-view")
  67053. },
  67054. _hideView: function(viewInfo, templateId) {
  67055. if (viewInfo.renderResult) {
  67056. var $markupToHide = templateId === undefined ? viewInfo.renderResult.$markup : viewInfo.renderResult.markupCache[templateId];
  67057. this._hideViewElements($markupToHide)
  67058. }
  67059. },
  67060. _showViewElements: function($elements) {
  67061. this._unpatchIDs($elements);
  67062. this._enableInputs($elements);
  67063. $elements.removeClass("dx-inactive-view").addClass("dx-active-view");
  67064. DX.utils.triggerShownEvent($elements)
  67065. },
  67066. _showView: function(viewInfo) {
  67067. if (viewInfo.renderResult)
  67068. this._showViewElements(viewInfo.renderResult.$markup)
  67069. },
  67070. _patchIDs: function($markup) {
  67071. this._processIDs($markup, function(id) {
  67072. var result = id;
  67073. if (id.indexOf(HIDDEN_BAG_ID) === -1)
  67074. result = HIDDEN_BAG_ID + "-" + id;
  67075. return result
  67076. })
  67077. },
  67078. _unpatchIDs: function($markup) {
  67079. this._processIDs($markup, function(id) {
  67080. var result = id;
  67081. if (id.indexOf(HIDDEN_BAG_ID) === 0)
  67082. result = id.substr(HIDDEN_BAG_ID.length + 1);
  67083. return result
  67084. })
  67085. },
  67086. _processIDs: function($markup, process) {
  67087. var elementsWithIds = $markup.find("[id]");
  67088. $.each(elementsWithIds, function(index, element) {
  67089. var $el = $(element),
  67090. id = $el.attr("id");
  67091. $el.attr("id", process(id))
  67092. })
  67093. },
  67094. _enableInputs: function($markup) {
  67095. var $inputs = $markup.find(":input[data-disabled=true]");
  67096. $.each($inputs, function(index, input) {
  67097. $(input).removeAttr("disabled").removeAttr("data-disabled")
  67098. })
  67099. },
  67100. _disableInputs: function($markup) {
  67101. var $inputs = $markup.find(":input:not([disabled], [disabled=true])");
  67102. $.each($inputs, function(index, input) {
  67103. $(input).attr({
  67104. disabled: true,
  67105. "data-disabled": true
  67106. })
  67107. })
  67108. }
  67109. }).include(DX.EventsMixin);
  67110. var layoutSets = DX.framework.html.layoutSets;
  67111. layoutSets["default"] = layoutSets["default"] || [];
  67112. layoutSets["default"].push({controller: new DX.framework.html.DefaultLayoutController})
  67113. })(jQuery, DevExpress);
  67114. /*! Module framework, file framework.viewEngine.js */
  67115. (function($, DX, undefined) {
  67116. var Class = DX.Class,
  67117. framework = DX.framework,
  67118. _VIEW_ROLE = "dxView",
  67119. _LAYOUT_ROLE = "dxLayout";
  67120. DX.registerComponent(_VIEW_ROLE, framework, DX.DOMComponent.inherit({
  67121. _setDefaultOptions: function() {
  67122. this.callBase();
  67123. this.option({
  67124. name: null,
  67125. title: null
  67126. })
  67127. },
  67128. ctor: function() {
  67129. this.callBase.apply(this, arguments);
  67130. this._id = DX.utils.uniqueId()
  67131. },
  67132. _render: function() {
  67133. this.callBase();
  67134. this.element().addClass("dx-view");
  67135. this.element().attr("dx-data-template-id", this._id)
  67136. },
  67137. getId: function() {
  67138. return this._id
  67139. }
  67140. }), framework);
  67141. DX.registerComponent(_LAYOUT_ROLE, framework, DX.DOMComponent.inherit({
  67142. _setDefaultOptions: function() {
  67143. this.callBase();
  67144. this.option({name: null})
  67145. },
  67146. _render: function() {
  67147. this.callBase();
  67148. this.element().addClass("dx-layout")
  67149. }
  67150. }));
  67151. DX.registerComponent("dxViewPlaceholder", framework, DX.DOMComponent.inherit({
  67152. _setDefaultOptions: function() {
  67153. this.callBase();
  67154. this.option({viewName: null})
  67155. },
  67156. _render: function() {
  67157. this.callBase();
  67158. this.element().addClass("dx-view-placeholder")
  67159. }
  67160. }));
  67161. var setupTransitionElement = function($element, transitionType, transitionName, contentCssPosition) {
  67162. if (contentCssPosition === "absolute")
  67163. $element.addClass("dx-transition-absolute");
  67164. else
  67165. $element.addClass("dx-transition-static");
  67166. $element.addClass("dx-transition").addClass("dx-transition-" + transitionName).addClass("dx-transition-" + transitionType).attr("data-dx-transition-type", transitionType).attr("data-dx-transition-name", transitionName)
  67167. };
  67168. var setupTransitionInnerElement = function($element) {
  67169. $element.addClass("dx-transition-inner-wrapper")
  67170. };
  67171. DX.registerComponent("dxTransition", framework, DX.DOMComponent.inherit({
  67172. _setDefaultOptions: function() {
  67173. this.callBase();
  67174. this.option({
  67175. name: null,
  67176. type: undefined,
  67177. animation: "slide"
  67178. })
  67179. },
  67180. _render: function() {
  67181. this.callBase();
  67182. var element = this.element();
  67183. setupTransitionElement(element, this.option("type") || this.option("animation"), this.option("name"), "absolute");
  67184. element.wrapInner("<div/>");
  67185. setupTransitionInnerElement(element.children());
  67186. if (this.option("type"))
  67187. DX.log("W0003", "dxTransition", "type", "15.1", "Use the 'animation' property instead")
  67188. },
  67189. _clean: function() {
  67190. this.callBase();
  67191. this.element().empty()
  67192. }
  67193. }));
  67194. DX.framework.prepareTransition = function($element, targetPlaceholderName) {
  67195. if ($element.children(".dx-content").length === 0) {
  67196. $element.wrapInner("<div>");
  67197. $element.children().dxContent({targetPlaceholder: targetPlaceholderName})
  67198. }
  67199. };
  67200. DX.registerComponent("dxContentPlaceholder", framework, DX.DOMComponent.inherit({
  67201. _setDefaultOptions: function() {
  67202. this.callBase();
  67203. this.option({
  67204. name: null,
  67205. transition: undefined,
  67206. animation: "none",
  67207. contentCssPosition: "absolute"
  67208. })
  67209. },
  67210. _render: function() {
  67211. this.callBase();
  67212. var $element = this.element();
  67213. $element.addClass("dx-content-placeholder").addClass("dx-content-placeholder-" + this.option("name"));
  67214. $element.attr("data-dx-content-placeholder-name", this.option("name"));
  67215. setupTransitionElement($element, this.option("transition") || this.option("animation"), this.option("name"), this.option("contentCssPosition"));
  67216. if (this.option("transition"))
  67217. DX.log("W0003", "dxContentPlaceholder", "transition", "15.1", "Use the 'animation' property instead")
  67218. },
  67219. prepareTransition: function() {
  67220. DX.framework.prepareTransition(this.element(), this.option("name"))
  67221. }
  67222. }));
  67223. DX.registerComponent("dxContent", framework, DX.DOMComponent.inherit({
  67224. _setDefaultOptions: function() {
  67225. this.callBase();
  67226. this.option({targetPlaceholder: null})
  67227. },
  67228. _optionChanged: function() {
  67229. this._refresh()
  67230. },
  67231. _clean: function() {
  67232. this.callBase();
  67233. this.element().removeClass(this._currentClass)
  67234. },
  67235. _render: function() {
  67236. this.callBase();
  67237. var element = this.element();
  67238. element.addClass("dx-content");
  67239. this._currentClass = "dx-content-" + this.option("targetPlaceholder");
  67240. element.attr("data-dx-target-placeholder-id", this.option("targetPlaceholder"));
  67241. element.addClass(this._currentClass);
  67242. setupTransitionInnerElement(element)
  67243. }
  67244. }));
  67245. framework.html.ViewEngine = Class.inherit({
  67246. ctor: function(options) {
  67247. options = options || {};
  67248. this.$root = options.$root;
  67249. this.device = options.device || {};
  67250. this.dataOptionsAttributeName = options.dataOptionsAttributeName || "data-options";
  67251. this._templateMap = {};
  67252. this._pendingViewContainer = null;
  67253. this.markupLoaded = $.Callbacks();
  67254. this._templateContext = options.templateContext
  67255. },
  67256. _enumerateTemplates: function(processFn) {
  67257. var that = this;
  67258. $.each(that._templateMap, function(name, templatesByRoleMap) {
  67259. $.each(templatesByRoleMap, function(role, templates) {
  67260. $.each(templates, function(index, template) {
  67261. processFn(template)
  67262. })
  67263. })
  67264. })
  67265. },
  67266. _findComponent: function(name, role) {
  67267. var components = (this._templateMap[name] || {})[role] || [],
  67268. filter = this._templateContext && this._templateContext.option() || {};
  67269. components = this._filterTemplates(filter, components);
  67270. this._checkMatchedTemplates(components);
  67271. return components[0]
  67272. },
  67273. _findTemplate: function(name, role) {
  67274. var component = this._findComponent(name, role);
  67275. if (!component)
  67276. throw DX.Error("E3013", role, name);
  67277. var $template = component.element(),
  67278. $result = $template.clone().removeClass("dx-hidden");
  67279. return $result
  67280. },
  67281. _extendModelFromViewData: function($view, model) {
  67282. DX.utils.extendFromObject(model, $view.data(_VIEW_ROLE).option())
  67283. },
  67284. _loadTemplatesFromMarkupCore: function($markup) {
  67285. var that = this;
  67286. if ($markup.find("[data-dx-role]").length)
  67287. throw DX.Error("E3019");
  67288. that.markupLoaded.fire({markup: $markup});
  67289. $markup.appendTo(that.$root);
  67290. var components = DX.utils.createComponents($markup, [_VIEW_ROLE, _LAYOUT_ROLE]);
  67291. $.each(components, function(index, component) {
  67292. var $element = component.element();
  67293. $element.addClass("dx-hidden");
  67294. DX.utils.createComponents($markup, ["dxContent", "dxContentPlaceholder", "dxTransition"]);
  67295. that._registerTemplateComponent(component);
  67296. component.element().detach()
  67297. })
  67298. },
  67299. _registerTemplateComponent: function(component) {
  67300. var role = component.NAME,
  67301. options = component.option(),
  67302. templateName = options.name,
  67303. componentsByRoleMap = this._templateMap[templateName] || {};
  67304. componentsByRoleMap[role] = componentsByRoleMap[role] || [];
  67305. componentsByRoleMap[role].push(component);
  67306. this._templateMap[templateName] = componentsByRoleMap
  67307. },
  67308. _applyPartialViews: function($render) {
  67309. var that = this;
  67310. DX.utils.createComponents($render, ["dxViewPlaceholder"]);
  67311. $.each($render.find(".dx-view-placeholder"), function() {
  67312. var $partialPlaceholder = $(this);
  67313. if ($partialPlaceholder.children().length)
  67314. return;
  67315. var viewName = $partialPlaceholder.data("dxViewPlaceholder").option("viewName"),
  67316. $view = that._findTemplate(viewName, _VIEW_ROLE);
  67317. that._applyPartialViews($view);
  67318. $partialPlaceholder.append($view);
  67319. $view.removeClass("dx-hidden")
  67320. })
  67321. },
  67322. _ajaxImpl: function() {
  67323. return $.ajax.apply($, arguments)
  67324. },
  67325. _loadTemplatesFromURL: function(url) {
  67326. var that = this,
  67327. options = this._getLoadOptions(),
  67328. deferred = $.Deferred();
  67329. url = options.winPhonePrefix + url;
  67330. this._ajaxImpl({
  67331. url: url,
  67332. isLocal: options.isLocal,
  67333. dataType: "html"
  67334. }).done(function(data) {
  67335. that._loadTemplatesFromMarkupCore(DX.utils.createMarkupFromString(data));
  67336. deferred.resolve()
  67337. }).fail(function(jqXHR, textStatus, errorThrown) {
  67338. var error = DX.Error("E3021", url, errorThrown);
  67339. deferred.reject(error)
  67340. });
  67341. return deferred.promise()
  67342. },
  67343. _getLoadOptions: function() {
  67344. if (location.protocol.indexOf("wmapp") >= 0)
  67345. return {
  67346. winPhonePrefix: location.protocol + "www/",
  67347. isLocal: true
  67348. };
  67349. return {
  67350. winPhonePrefix: "",
  67351. isLocal: undefined
  67352. }
  67353. },
  67354. _loadExternalTemplates: function() {
  67355. var tasks = [],
  67356. that = this;
  67357. $("head").find("link[rel='dx-template']").each(function(index, link) {
  67358. var task = that._loadTemplatesFromURL($(link).attr("href"));
  67359. tasks.push(task)
  67360. });
  67361. return $.when.apply($, tasks)
  67362. },
  67363. _processTemplates: function() {
  67364. var that = this;
  67365. $.each(that._templateMap, function(name, templatesByRoleMap) {
  67366. $.each(templatesByRoleMap, function(role, templates) {
  67367. that._filterTemplatesByDevice(templates)
  67368. })
  67369. });
  67370. that._enumerateTemplates(function(template) {
  67371. that._applyPartialViews(template.element())
  67372. })
  67373. },
  67374. _filterTemplatesByDevice: function(components) {
  67375. var filteredComponents = this._filterTemplates(this.device, components);
  67376. $.each(components, function(index, component) {
  67377. if ($.inArray(component, filteredComponents) < 0) {
  67378. component._dispose();
  67379. component.element().remove()
  67380. }
  67381. });
  67382. components.length = 0;
  67383. components.push.apply(components, filteredComponents)
  67384. },
  67385. _filterTemplates: function(filter, components) {
  67386. return DX.utils.findBestMatches(filter, components, function(component) {
  67387. return component.option()
  67388. })
  67389. },
  67390. _checkMatchedTemplates: function(bestMatches) {
  67391. if (bestMatches.length > 1) {
  67392. var message = "";
  67393. $.each(bestMatches, function(index, match) {
  67394. message += match.element().attr("data-options") + "\r\n"
  67395. });
  67396. throw DX.Error("E3020", message, JSON.stringify(this.device));
  67397. }
  67398. },
  67399. _extendModelFormViewTemplate: function($viewTemplate, model) {
  67400. this._extendModelFromViewData($viewTemplate, model)
  67401. },
  67402. _wrapViewDefaultContent: function($viewTemplate) {
  67403. $viewTemplate.wrapInner("<div class=\"dx-full-height\"></div>");
  67404. $viewTemplate.children().eq(0).dxContent({targetPlaceholder: 'content'})
  67405. },
  67406. _initDefaultLayout: function() {
  67407. this._$defaultLayoutTemplate = $("<div class=\"dx-full-height\" data-options=\"dxLayout : { name: 'default' } \"> \n" + " <div class=\"dx-full-height\" data-options=\"dxContentPlaceholder : { name: 'content' } \" ></div> \n" + "</div>");
  67408. DX.utils.createComponents(this._$defaultLayoutTemplate)
  67409. },
  67410. _getDefaultLayoutTemplate: function() {
  67411. var $result = this._$defaultLayoutTemplate.clone();
  67412. return $result
  67413. },
  67414. applyLayout: function($view, $layout) {
  67415. if ($layout === undefined || $layout.length === 0)
  67416. $layout = this._getDefaultLayoutTemplate();
  67417. if ($view.children(".dx-content").length === 0)
  67418. this._wrapViewDefaultContent($view);
  67419. var $toMerge = $().add($layout).add($view);
  67420. var $placeholderContents = $toMerge.find(".dx-content");
  67421. $.each($placeholderContents, function() {
  67422. var $placeholderContent = $(this);
  67423. var placeholderId = $placeholderContent.attr("data-dx-target-placeholder-id");
  67424. var $placeholder = $toMerge.find(".dx-content-placeholder-" + placeholderId);
  67425. $placeholder.empty();
  67426. $placeholder.append($placeholderContent)
  67427. });
  67428. $placeholderContents.filter(":not(.dx-content-placeholder .dx-content)").remove();
  67429. return $layout
  67430. },
  67431. init: function() {
  67432. var that = this;
  67433. this._initDefaultLayout();
  67434. return this._loadExternalTemplates().done(function() {
  67435. that._loadTemplatesFromMarkupCore(that.$root.children());
  67436. that._processTemplates()
  67437. })
  67438. },
  67439. getViewTemplate: function(viewName) {
  67440. return this._findTemplate(viewName, _VIEW_ROLE)
  67441. },
  67442. getViewTemplateInfo: function(name) {
  67443. return this._findComponent(name, _VIEW_ROLE)
  67444. },
  67445. getLayoutTemplate: function(layoutName) {
  67446. if (!layoutName)
  67447. return this._getDefaultLayoutTemplate();
  67448. return this._findTemplate(layoutName, _LAYOUT_ROLE)
  67449. },
  67450. getLayoutTemplateInfo: function(name) {
  67451. return this._findComponent(name, _LAYOUT_ROLE)
  67452. },
  67453. loadTemplates: function(source) {
  67454. var result;
  67455. if (typeof source === "string")
  67456. result = this._loadTemplatesFromURL(source);
  67457. else {
  67458. this._loadTemplatesFromMarkupCore(source);
  67459. result = $.Deferred().resolve().promise()
  67460. }
  67461. return result.done($.proxy(this._processTemplates, this))
  67462. }
  67463. })
  67464. })(jQuery, DevExpress);
  67465. /*! Module framework, file framework.htmlApplication.js */
  67466. (function($, DX, undefined) {
  67467. var frameworkNS = DX.framework,
  67468. htmlNS = frameworkNS.html;
  67469. var VIEW_PORT_CLASSNAME = "dx-viewport";
  67470. htmlNS.HtmlApplication = frameworkNS.Application.inherit({
  67471. ctor: function(options) {
  67472. options = options || {};
  67473. this.callBase(options);
  67474. this._$root = $(options.rootNode || document.body);
  67475. this._initViewport(options.viewPort);
  67476. if (this._applicationMode === "mobileApp")
  67477. DX.utils.initMobileViewport(options.viewPort);
  67478. this.device = options.device || DX.devices.current();
  67479. this.commandManager = options.commandManager || new DX.framework.html.CommandManager({commandMapping: this.commandMapping});
  67480. this._initTemplateContext();
  67481. this.viewEngine = options.viewEngine || new htmlNS.ViewEngine({
  67482. $root: this._$root,
  67483. device: this.device,
  67484. templateContext: this._templateContext
  67485. });
  67486. this.components.push(this.viewEngine);
  67487. this._initMarkupFilters(this.viewEngine);
  67488. this.viewRendered = $.Callbacks();
  67489. this._layoutSet = options.layoutSet || DX.framework.html.layoutSets["default"];
  67490. this._animationSet = options.animationSet || DX.framework.html.animationSets["default"];
  67491. this._availableLayoutControllers = [];
  67492. this._activeLayoutControllersStack = [];
  67493. this.resolveLayoutController = $.Callbacks();
  67494. this._callbacksToEvents("HtmlApplication", ["viewRendered", "resolveLayoutController"]);
  67495. this._initAnimations(this._animationSet)
  67496. },
  67497. _initAnimations: function(animationSet) {
  67498. if (!animationSet)
  67499. return;
  67500. $.each(animationSet, function(name, configs) {
  67501. $.each(configs, function(index, config) {
  67502. DX.animationPresets.registerPreset(name, config)
  67503. })
  67504. });
  67505. DX.animationPresets.applyChanges()
  67506. },
  67507. _localizeMarkup: function($markup) {
  67508. DX.localization.localizeNode($markup)
  67509. },
  67510. _notifyIfBadMarkup: function($markup) {
  67511. $markup.each(function() {
  67512. var html = $(this).html();
  67513. if (/href="#/.test(html))
  67514. DX.log("W3005", html)
  67515. })
  67516. },
  67517. _initMarkupFilters: function(viewEngine) {
  67518. var filters = [];
  67519. filters.push(this._localizeMarkup);
  67520. filters.push(this._notifyIfBadMarkup);
  67521. if (viewEngine.markupLoaded)
  67522. viewEngine.markupLoaded.add(function(args) {
  67523. $.each(filters, function(_, filter) {
  67524. filter(args.markup)
  67525. })
  67526. })
  67527. },
  67528. _createViewCache: function(options) {
  67529. var result = this.callBase(options);
  67530. if (!options.viewCache)
  67531. result = new DX.framework.ConditionalViewCacheDecorator({
  67532. filter: function(key, viewInfo) {
  67533. return !viewInfo.viewTemplateInfo.disableCache
  67534. },
  67535. viewCache: result
  67536. });
  67537. return result
  67538. },
  67539. _initViewport: function() {
  67540. this._$viewPort = this._getViewPort();
  67541. DX.viewPort(this._$viewPort)
  67542. },
  67543. _getViewPort: function() {
  67544. var $viewPort = $("." + VIEW_PORT_CLASSNAME);
  67545. if (!$viewPort.length)
  67546. $viewPort = $("<div>").addClass(VIEW_PORT_CLASSNAME).appendTo(this._$root);
  67547. return $viewPort
  67548. },
  67549. _initTemplateContext: function() {
  67550. this._templateContext = new DX.Component({orientation: DX.devices.orientation()});
  67551. DX.devices.on("orientationChanged", $.proxy(function(args) {
  67552. this._templateContext.option("orientation", args.orientation)
  67553. }, this))
  67554. },
  67555. _showViewImpl: function(viewInfo, direction) {
  67556. var that = this,
  67557. deferred = $.Deferred(),
  67558. result = deferred.promise(),
  67559. layoutController = viewInfo.layoutController;
  67560. that._obtainViewLink(viewInfo);
  67561. layoutController.showView(viewInfo, direction).done(function() {
  67562. that._activateLayoutController(layoutController, that._getTargetNode(viewInfo)).done(function() {
  67563. deferred.resolve()
  67564. })
  67565. });
  67566. DX.ui.events.lockFeedback(result);
  67567. return result
  67568. },
  67569. _resolveLayoutController: function(viewInfo) {
  67570. var args = {
  67571. viewInfo: viewInfo,
  67572. layoutController: null,
  67573. availableLayoutControllers: this._availableLayoutControllers
  67574. };
  67575. this._processEvent("resolveLayoutController", args, viewInfo.model);
  67576. return args.layoutController || this._resolveLayoutControllerImpl(viewInfo)
  67577. },
  67578. _ensureOneLayoutControllerFound: function(target, matches) {
  67579. var toJSONInterceptor = function(key, value) {
  67580. if (key === "controller")
  67581. return "[controller]: { name:" + value.name + " }";
  67582. return value
  67583. };
  67584. if (!matches.length) {
  67585. DX.log("W3003", JSON.stringify(target, null, 4), JSON.stringify(this._availableLayoutControllers, toJSONInterceptor, 4));
  67586. throw DX.Error("E3011");
  67587. }
  67588. if (matches.length > 1) {
  67589. DX.log("W3004", JSON.stringify(target, null, 4), JSON.stringify(matches, toJSONInterceptor, 4));
  67590. throw DX.Error("E3012");
  67591. }
  67592. },
  67593. _resolveLayoutControllerImpl: function(viewInfo) {
  67594. var templateInfo = viewInfo.viewTemplateInfo || {},
  67595. navigateOptions = viewInfo.navigateOptions || {},
  67596. target = $.extend({
  67597. root: !viewInfo.canBack,
  67598. customResolveRequired: false,
  67599. pane: templateInfo.pane,
  67600. modal: navigateOptions.modal !== undefined ? navigateOptions.modal : templateInfo.modal || false
  67601. }, DX.devices.current());
  67602. var matches = DX.utils.findBestMatches(target, this._availableLayoutControllers);
  67603. this._ensureOneLayoutControllerFound(target, matches);
  67604. return matches[0].controller
  67605. },
  67606. _onNavigatingBack: function(args) {
  67607. this.callBase.apply(this, arguments);
  67608. if (!args.cancel && !this.canBack() && this._activeLayoutControllersStack.length > 1) {
  67609. var previousActiveLayoutController = this._activeLayoutControllersStack[this._activeLayoutControllersStack.length - 2],
  67610. previousViewInfo = previousActiveLayoutController.activeViewInfo();
  67611. args.cancel = true;
  67612. this._activateLayoutController(previousActiveLayoutController);
  67613. this.navigationManager.currentItem(previousViewInfo.key)
  67614. }
  67615. },
  67616. _activeLayoutController: function() {
  67617. return this._activeLayoutControllersStack.length ? this._activeLayoutControllersStack[this._activeLayoutControllersStack.length - 1] : undefined
  67618. },
  67619. _getTargetNode: function(viewInfo) {
  67620. var jQueryEvent = (viewInfo.navigateOptions || {}).jQueryEvent;
  67621. return jQueryEvent ? $(jQueryEvent.target) : undefined
  67622. },
  67623. _activateLayoutController: function(layoutController, targetNode) {
  67624. var that = this,
  67625. result = $.Deferred(),
  67626. previousLayoutController = that._activeLayoutController();
  67627. if (previousLayoutController !== layoutController)
  67628. layoutController.activate(targetNode).done(function() {
  67629. var tasks = [];
  67630. if (!layoutController.isOverlay) {
  67631. var controllerToDeactivate;
  67632. while (that._activeLayoutControllersStack.length && controllerToDeactivate !== layoutController) {
  67633. controllerToDeactivate = that._activeLayoutController();
  67634. if (controllerToDeactivate !== layoutController) {
  67635. that._activeLayoutControllersStack.pop();
  67636. tasks.push(controllerToDeactivate.deactivate())
  67637. }
  67638. }
  67639. }
  67640. $.when.apply($, tasks).done(function() {
  67641. that._activeLayoutControllersStack.push(layoutController);
  67642. result.resolve()
  67643. })
  67644. });
  67645. else
  67646. result.resolve();
  67647. return result.promise()
  67648. },
  67649. init: function() {
  67650. var that = this,
  67651. result = this.callBase();
  67652. result.done(function() {
  67653. that._initLayoutControllers();
  67654. that.renderNavigation()
  67655. });
  67656. return result
  67657. },
  67658. _disposeView: function(viewInfo) {
  67659. if (viewInfo.layoutController.disposeView)
  67660. viewInfo.layoutController.disposeView(viewInfo);
  67661. this.callBase(viewInfo)
  67662. },
  67663. viewPort: function() {
  67664. return this._$viewPort
  67665. },
  67666. _createViewInfo: function(navigationItem, navigateOptions) {
  67667. var viewInfo = this.callBase.apply(this, arguments),
  67668. templateInfo = this.getViewTemplateInfo(viewInfo.viewName);
  67669. if (!templateInfo)
  67670. throw DX.Error("E3013", "dxView", viewInfo.viewName);
  67671. viewInfo.viewTemplateInfo = templateInfo;
  67672. viewInfo.layoutController = this._resolveLayoutController(viewInfo);
  67673. return viewInfo
  67674. },
  67675. _createViewModel: function(viewInfo) {
  67676. this.callBase(viewInfo);
  67677. var templateInfo = viewInfo.viewTemplateInfo,
  67678. model = viewInfo.model;
  67679. for (var name in templateInfo)
  67680. if (!(name in model))
  67681. model[name] = templateInfo[name]
  67682. },
  67683. _initLayoutControllers: function() {
  67684. var that = this;
  67685. $.each(that._layoutSet, function(index, controllerInfo) {
  67686. var controller = controllerInfo.controller,
  67687. target = DX.devices.current();
  67688. if (DX.utils.findBestMatches(target, [controllerInfo]).length) {
  67689. that._availableLayoutControllers.push(controllerInfo);
  67690. if (controller.init)
  67691. controller.init({
  67692. app: that,
  67693. $viewPort: that._$viewPort,
  67694. navigationManager: that.navigationManager,
  67695. viewEngine: that.viewEngine,
  67696. templateContext: that._templateContext,
  67697. commandManager: that.commandManager
  67698. });
  67699. if (controller.on) {
  67700. controller.on("viewReleased", function(viewInfo) {
  67701. that._onViewReleased(viewInfo)
  67702. });
  67703. controller.on("viewRendered", function(viewInfo) {
  67704. that._processEvent("viewRendered", {viewInfo: viewInfo}, viewInfo.model)
  67705. });
  67706. controller.on("viewShowing", function(viewInfo) {
  67707. that._processEvent("viewShowing", {viewInfo: viewInfo}, viewInfo.model)
  67708. })
  67709. }
  67710. }
  67711. })
  67712. },
  67713. _onViewReleased: function(viewInfo) {
  67714. this._onViewHidden(viewInfo);
  67715. this._releaseViewLink(viewInfo)
  67716. },
  67717. renderNavigation: function() {
  67718. var that = this;
  67719. $.each(that._availableLayoutControllers, function(index, controllerInfo) {
  67720. var controller = controllerInfo.controller;
  67721. if (controller.renderNavigation)
  67722. controller.renderNavigation(that.navigation)
  67723. })
  67724. },
  67725. getViewTemplate: function(viewName) {
  67726. return this.viewEngine.getViewTemplate(viewName)
  67727. },
  67728. getViewTemplateInfo: function(viewName) {
  67729. var viewComponent = this.viewEngine.getViewTemplateInfo(viewName);
  67730. return viewComponent && viewComponent.option()
  67731. },
  67732. loadTemplates: function(source) {
  67733. return this.viewEngine.loadTemplates(source)
  67734. },
  67735. templateContext: function() {
  67736. return this._templateContext
  67737. }
  67738. })
  67739. })(jQuery, DevExpress);
  67740. DevExpress.MOD_FRAMEWORK = true
  67741. }
  67742. if (!DevExpress.MOD_VIZ_CORE) {
  67743. if (!window.DevExpress)
  67744. throw Error('Required module is not referenced: core');
  67745. /*! Module viz-core, file namespaces.js */
  67746. (function(DevExpress) {
  67747. DevExpress.viz = {}
  67748. })(DevExpress);
  67749. /*! Module viz-core, file namespaces.js */
  67750. (function(DevExpress) {
  67751. DevExpress.viz.core = {}
  67752. })(DevExpress);
  67753. /*! Module viz-core, file errorsWarnings.js */
  67754. (function($, DX) {
  67755. $.extend(DX.ERROR_MESSAGES, {
  67756. E2001: "Invalid data source",
  67757. E2002: "Axis type and data type are incompatible",
  67758. E2003: "\"{0}\" data source field contains data of unsupported type",
  67759. E2004: "\"{0}\" data source field is inconsistent",
  67760. E2101: "Unknown series type was specified: {0}",
  67761. E2102: "Ambiguity occurred between two value axes with the same name",
  67762. E2103: "\"{0}\" option must be a function",
  67763. E2104: "Invalid logarithm base",
  67764. E2105: "Invalid value of a \"{0}\"",
  67765. E2106: "Invalid visible range",
  67766. E2202: "Invalid scale {0} value",
  67767. E2203: "The \"{0}\" field of the \"selectedRange\" configuration object is not valid",
  67768. W2001: "{0} cannot be drawn because its container is invisible",
  67769. W2002: "The {0} data field is absent",
  67770. W2003: "Tick interval is too small",
  67771. W2101: "\"{0}\" pane does not exist; \"{1}\" pane is used instead",
  67772. W2102: "Value axis with the \"{0}\" name was created automatically",
  67773. W2103: "Chart title was hidden due to container size",
  67774. W2104: "Legend was hidden due to container size",
  67775. W2105: "Title of \"{0}\" axis was hidden due to container size",
  67776. W2106: "Labels of \"{0}\" axis were hidden due to container size",
  67777. W2301: "Invalid value range"
  67778. })
  67779. })(jQuery, DevExpress);
  67780. /*! Module viz-core, file numericTickManager.js */
  67781. (function($, DX, undefined) {
  67782. var core = DX.viz.core,
  67783. utils = DX.utils,
  67784. _isDefined = utils.isDefined,
  67785. _adjustValue = utils.adjustValue,
  67786. _math = Math,
  67787. _abs = _math.abs,
  67788. _ceil = _math.ceil,
  67789. _floor = _math.floor,
  67790. _noop = $.noop,
  67791. MINOR_TICKS_COUNT_LIMIT = 200,
  67792. DEFAULT_MINOR_NUMBER_MULTIPLIERS = [2, 4, 5, 8, 10];
  67793. core.outOfScreen = {
  67794. x: -1000,
  67795. y: -1000
  67796. };
  67797. core.tickManager = {};
  67798. core.tickManager.continuous = {
  67799. _hasUnitBeginningTickCorrection: _noop,
  67800. _removeBoundedOverlappingDates: _noop,
  67801. _correctInterval: function(step) {
  67802. this._tickInterval *= step
  67803. },
  67804. _correctMax: function(tickInterval) {
  67805. this._max = this._adjustNumericTickValue(_ceil(this._max / tickInterval) * tickInterval, tickInterval, this._min)
  67806. },
  67807. _correctMin: function(tickInterval) {
  67808. this._min = this._adjustNumericTickValue(_floor(this._min / tickInterval) * tickInterval, tickInterval, this._min)
  67809. },
  67810. _findBusinessDelta: function(min, max) {
  67811. return _adjustValue(_abs(min - max))
  67812. },
  67813. _findTickIntervalForCustomTicks: function() {
  67814. return _abs(this._customTicks[1] - this._customTicks[0])
  67815. },
  67816. _getBoundInterval: function() {
  67817. var that = this,
  67818. boundCoef = that._options.boundCoef;
  67819. return _isDefined(boundCoef) && isFinite(boundCoef) ? that._tickInterval * _abs(boundCoef) : that._tickInterval / 2
  67820. },
  67821. _getInterval: function(deltaCoef, numberMultipliers) {
  67822. var interval = deltaCoef || this._getDeltaCoef(this._screenDelta, this._businessDelta, this._options.gridSpacingFactor),
  67823. multipliers = numberMultipliers || this._options.numberMultipliers,
  67824. factor,
  67825. result = 0,
  67826. newResult,
  67827. hasResult = false,
  67828. i;
  67829. if (interval > 1.0)
  67830. for (factor = 1; !hasResult; factor *= 10)
  67831. for (i = 0; i < multipliers.length; i++) {
  67832. result = multipliers[i] * factor;
  67833. if (interval <= result) {
  67834. hasResult = true;
  67835. break
  67836. }
  67837. }
  67838. else if (interval > 0) {
  67839. result = 1;
  67840. for (factor = 0.1; !hasResult; factor /= 10)
  67841. for (i = multipliers.length - 1; i >= 0; i--) {
  67842. newResult = multipliers[i] * factor;
  67843. if (interval > newResult) {
  67844. hasResult = true;
  67845. break
  67846. }
  67847. result = newResult
  67848. }
  67849. }
  67850. return _adjustValue(result)
  67851. },
  67852. _getMarginValue: function(min, max, margin) {
  67853. return utils.applyPrecisionByMinDelta(min, margin, _abs(max - min) * margin)
  67854. },
  67855. _getDefaultMinorInterval: function(screenDelta, businessDelta) {
  67856. var deltaCoef = this._getDeltaCoef(screenDelta, businessDelta, this._options.minorGridSpacingFactor),
  67857. multipliers = DEFAULT_MINOR_NUMBER_MULTIPLIERS,
  67858. i = multipliers.length - 1,
  67859. result;
  67860. for (i; i >= 0; i--) {
  67861. result = businessDelta / multipliers[i];
  67862. if (deltaCoef <= result)
  67863. return _adjustValue(result)
  67864. }
  67865. return 0
  67866. },
  67867. _getMinorInterval: function(screenDelta, businessDelta) {
  67868. var that = this,
  67869. options = that._options,
  67870. minorTickInterval = options.minorTickInterval,
  67871. minorTickCount = options.minorTickCount,
  67872. interval,
  67873. intervalsCount,
  67874. count;
  67875. if (isFinite(minorTickInterval) && that._isTickIntervalCorrect(minorTickInterval, MINOR_TICKS_COUNT_LIMIT, businessDelta)) {
  67876. interval = minorTickInterval;
  67877. count = interval < businessDelta ? _ceil(businessDelta / interval) - 1 : 0
  67878. }
  67879. else if (_isDefined(minorTickCount)) {
  67880. intervalsCount = _isDefined(minorTickCount) ? minorTickCount + 1 : _floor(screenDelta / options.minorGridSpacingFactor);
  67881. count = intervalsCount - 1;
  67882. interval = count > 0 ? businessDelta / intervalsCount : 0
  67883. }
  67884. else {
  67885. interval = that._getDefaultMinorInterval(screenDelta, businessDelta);
  67886. count = interval < businessDelta ? _floor(businessDelta / interval) - 1 : 0
  67887. }
  67888. that._minorTickInterval = interval;
  67889. that._minorTickCount = count
  67890. },
  67891. _getNextTickValue: function(value, tickInterval, isTickIntervalNegative) {
  67892. tickInterval = _isDefined(isTickIntervalNegative) && isTickIntervalNegative ? -tickInterval : tickInterval;
  67893. value += tickInterval;
  67894. return this._adjustNumericTickValue(value, tickInterval, this._min)
  67895. },
  67896. _isTickIntervalValid: function(tickInterval) {
  67897. return _isDefined(tickInterval) && isFinite(tickInterval) && tickInterval !== 0
  67898. }
  67899. }
  67900. })(jQuery, DevExpress);
  67901. /*! Module viz-core, file datetimeTickManager.js */
  67902. (function($, DX, undefined) {
  67903. var core = DX.viz.core,
  67904. utils = DX.utils,
  67905. _isDefined = utils.isDefined,
  67906. _convertDateUnitToMilliseconds = utils.convertDateUnitToMilliseconds,
  67907. _correctDateWithUnitBeginning = utils.correctDateWithUnitBeginning,
  67908. _dateToMilliseconds = utils.dateToMilliseconds,
  67909. _convertMillisecondsToDateUnits = utils.convertMillisecondsToDateUnits,
  67910. _math = Math,
  67911. _abs = _math.abs,
  67912. _ceil = _math.ceil,
  67913. _floor = _math.floor,
  67914. _round = _math.round,
  67915. MINOR_TICKS_COUNT_LIMIT = 50,
  67916. DEFAULT_DATETIME_MULTIPLIERS = {
  67917. millisecond: [1, 2, 5, 10, 25, 100, 250, 300, 500],
  67918. second: [1, 2, 3, 5, 10, 15, 20, 30],
  67919. minute: [1, 2, 3, 5, 10, 15, 20, 30],
  67920. hour: [1, 2, 3, 4, 6, 8, 12],
  67921. day: [1, 2, 3, 5, 7, 10, 14],
  67922. month: [1, 2, 3, 6]
  67923. };
  67924. core.tickManager.datetime = $.extend({}, core.tickManager.continuous, {
  67925. _correctInterval: function(step) {
  67926. var tickIntervalInMs = _dateToMilliseconds(this._tickInterval);
  67927. this._tickInterval = _convertMillisecondsToDateUnits(tickIntervalInMs * step)
  67928. },
  67929. _correctMax: function(tickInterval) {
  67930. var interval = _dateToMilliseconds(tickInterval);
  67931. this._max = new Date(_ceil(this._max / interval) * interval)
  67932. },
  67933. _correctMin: function(tickInterval) {
  67934. var interval = _dateToMilliseconds(tickInterval);
  67935. this._min = new Date(_floor(this._min / interval) * interval);
  67936. if (this._options.setTicksAtUnitBeginning)
  67937. _correctDateWithUnitBeginning(this._min, tickInterval)
  67938. },
  67939. _findTickIntervalForCustomTicks: function() {
  67940. return _convertMillisecondsToDateUnits(_abs(this._customTicks[1] - this._customTicks[0]))
  67941. },
  67942. _getBoundInterval: function() {
  67943. var that = this,
  67944. interval = that._tickInterval,
  67945. intervalInMs = _dateToMilliseconds(interval),
  67946. boundCoef = that._options.boundCoef,
  67947. boundIntervalInMs = _isDefined(boundCoef) && isFinite(boundCoef) ? intervalInMs * _abs(boundCoef) : intervalInMs / 2;
  67948. return _convertMillisecondsToDateUnits(boundIntervalInMs)
  67949. },
  67950. _getInterval: function(deltaCoef) {
  67951. var interval = deltaCoef || this._getDeltaCoef(this._screenDelta, this._businessDelta, this._options.gridSpacingFactor),
  67952. multipliers = this._options.numberMultipliers,
  67953. result = {},
  67954. factor,
  67955. i,
  67956. key,
  67957. specificMultipliers,
  67958. yearsCount;
  67959. if (interval > 0 && interval < 1.0)
  67960. return {milliseconds: 1};
  67961. if (interval === 0)
  67962. return 0;
  67963. for (key in DEFAULT_DATETIME_MULTIPLIERS)
  67964. if (DEFAULT_DATETIME_MULTIPLIERS.hasOwnProperty(key)) {
  67965. specificMultipliers = DEFAULT_DATETIME_MULTIPLIERS[key];
  67966. for (i = 0; i < specificMultipliers.length; i++)
  67967. if (interval <= _convertDateUnitToMilliseconds(key, specificMultipliers[i])) {
  67968. result[key + 's'] = specificMultipliers[i];
  67969. return result
  67970. }
  67971. }
  67972. for (factor = 1; ; factor *= 10)
  67973. for (i = 0; i < multipliers.length; i++) {
  67974. yearsCount = factor * multipliers[i];
  67975. if (interval <= _convertDateUnitToMilliseconds('year', yearsCount))
  67976. return {years: yearsCount}
  67977. }
  67978. return 0
  67979. },
  67980. _getMarginValue: function(min, max, margin) {
  67981. return _convertMillisecondsToDateUnits(_round(_abs(max - min) * margin))
  67982. },
  67983. _getMinorInterval: function(screenDelta, businessDelta) {
  67984. var that = this,
  67985. options = that._options,
  67986. interval,
  67987. intervalInMs,
  67988. intervalsCount,
  67989. count;
  67990. if (_isDefined(options.minorTickInterval) && that._isTickIntervalCorrect(options.minorTickInterval, MINOR_TICKS_COUNT_LIMIT, businessDelta)) {
  67991. interval = options.minorTickInterval;
  67992. intervalInMs = _dateToMilliseconds(interval);
  67993. count = intervalInMs < businessDelta ? _ceil(businessDelta / intervalInMs) - 1 : 0
  67994. }
  67995. else {
  67996. intervalsCount = _isDefined(options.minorTickCount) ? options.minorTickCount + 1 : _floor(screenDelta / options.minorGridSpacingFactor);
  67997. count = intervalsCount - 1;
  67998. interval = count > 0 ? _convertMillisecondsToDateUnits(businessDelta / intervalsCount) : 0
  67999. }
  68000. that._minorTickInterval = interval;
  68001. that._minorTickCount = count
  68002. },
  68003. _getNextTickValue: function(value, tickInterval, isTickIntervalNegative, isTickIntervalWithPow, withCorrection) {
  68004. var newValue = utils.addInterval(value, tickInterval, isTickIntervalNegative);
  68005. if (this._options.setTicksAtUnitBeginning && withCorrection !== false) {
  68006. _correctDateWithUnitBeginning(newValue, tickInterval, true);
  68007. this._correctDateWithUnitBeginningCalled = true
  68008. }
  68009. return newValue
  68010. },
  68011. _getUnitBeginningMinorTicks: function(minorTicks) {
  68012. var that = this,
  68013. ticks = that._ticks,
  68014. tickInterval = that._findMinorTickInterval(ticks[1], ticks[2]),
  68015. isTickIntervalNegative = true,
  68016. isTickIntervalWithPow = false,
  68017. needCorrectTick = false,
  68018. startTick = that._getNextTickValue(ticks[1], tickInterval, isTickIntervalNegative, isTickIntervalWithPow, needCorrectTick);
  68019. if (that._isTickIntervalValid(tickInterval))
  68020. minorTicks = that._createTicks(minorTicks, tickInterval, startTick, ticks[0], isTickIntervalNegative, isTickIntervalWithPow, needCorrectTick);
  68021. return minorTicks
  68022. },
  68023. _hasUnitBeginningTickCorrection: function() {
  68024. var ticks = this._ticks;
  68025. if (ticks.length < 3)
  68026. return false;
  68027. return ticks[1] - ticks[0] !== ticks[2] - ticks[1] && this._options.setTicksAtUnitBeginning && this._options.minorTickCount
  68028. },
  68029. _isTickIntervalValid: function(tickInterval) {
  68030. return _isDefined(tickInterval) && _dateToMilliseconds(tickInterval) !== 0
  68031. },
  68032. _removeBoundedOverlappingDates: function() {
  68033. var dates = this._ticks;
  68034. if (dates.length > 2 && this.getOverlappingBehavior().mode !== "stagger" && !this._areDisplayValuesValid(dates[0], dates[1]))
  68035. dates.splice(1, 1)
  68036. }
  68037. })
  68038. })(jQuery, DevExpress);
  68039. /*! Module viz-core, file logarithmicTickManager.js */
  68040. (function($, DX, undefined) {
  68041. var core = DX.viz.core,
  68042. utils = DX.utils,
  68043. _isDefined = utils.isDefined,
  68044. _addInterval = utils.addInterval,
  68045. _adjustValue = utils.adjustValue,
  68046. _getLog = utils.getLog,
  68047. _raiseTo = utils.raiseTo,
  68048. _math = Math,
  68049. _abs = _math.abs,
  68050. _ceil = _math.ceil,
  68051. _floor = _math.floor,
  68052. _round = _math.round;
  68053. core.tickManager.logarithmic = $.extend({}, core.tickManager.continuous, {
  68054. _correctMax: function() {
  68055. var base = this._options.base;
  68056. this._max = _adjustValue(_raiseTo(_ceil(_adjustValue(_getLog(this._max, base))), base))
  68057. },
  68058. _correctMin: function() {
  68059. var base = this._options.base;
  68060. this._min = _adjustValue(_raiseTo(_floor(_adjustValue(_getLog(this._min, base))), base))
  68061. },
  68062. _findBusinessDelta: function(min, max, isTickIntervalWithPow) {
  68063. var delta;
  68064. if (min <= 0 || max <= 0)
  68065. return 0;
  68066. if (isTickIntervalWithPow === false)
  68067. delta = core.tickManager.continuous._findBusinessDelta(min, max);
  68068. else
  68069. delta = _round(_abs(_getLog(min, this._options.base) - _getLog(max, this._options.base)));
  68070. return delta
  68071. },
  68072. _findTickIntervalForCustomTicks: function() {
  68073. return _adjustValue(_getLog(this._customTicks[1] / this._customTicks[0], this._options.base))
  68074. },
  68075. _getInterval: function(deltaCoef) {
  68076. var interval = deltaCoef || this._getDeltaCoef(this._screenDelta, this._businessDelta, this._options.gridSpacingFactor),
  68077. multipliers = this._options.numberMultipliers,
  68078. factor,
  68079. result = 0,
  68080. hasResult = false,
  68081. i;
  68082. if (interval !== 0)
  68083. for (factor = 1; !hasResult; factor *= 10)
  68084. for (i = 0; i < multipliers.length; i++) {
  68085. result = multipliers[i] * factor;
  68086. if (interval <= result) {
  68087. hasResult = true;
  68088. break
  68089. }
  68090. }
  68091. return _adjustValue(result)
  68092. },
  68093. _getMinorInterval: function(screenDelta, businessDelta) {
  68094. var that = this,
  68095. options = that._options,
  68096. minorTickCount = options.minorTickCount,
  68097. intervalsCount = _isDefined(minorTickCount) ? minorTickCount + 1 : _floor(screenDelta / options.minorGridSpacingFactor),
  68098. count = intervalsCount - 1,
  68099. interval = count > 0 ? businessDelta / intervalsCount : 0;
  68100. that._minorTickInterval = interval;
  68101. that._minorTickCount = count
  68102. },
  68103. _getMarginValue: function() {
  68104. return null
  68105. },
  68106. _getNextTickValue: function(value, tickInterval, isTickIntervalNegative, isTickIntervalWithPow) {
  68107. var that = this,
  68108. pow,
  68109. nextTickValue;
  68110. tickInterval = _isDefined(isTickIntervalNegative) && isTickIntervalNegative ? -tickInterval : tickInterval;
  68111. if (isTickIntervalWithPow === false)
  68112. nextTickValue = value + tickInterval;
  68113. else {
  68114. pow = _addInterval(_getLog(value, that._options.base), tickInterval, that._min > that._max);
  68115. nextTickValue = _adjustValue(_raiseTo(pow, that._options.base))
  68116. }
  68117. return nextTickValue
  68118. }
  68119. })
  68120. })(jQuery, DevExpress);
  68121. /*! Module viz-core, file tickOverlappingManager.js */
  68122. (function($, DX, undefined) {
  68123. var core = DX.viz.core,
  68124. coreTickManager = core.tickManager,
  68125. utils = DX.utils,
  68126. _isDefined = utils.isDefined,
  68127. _isNumber = utils.isNumber,
  68128. _math = Math,
  68129. _abs = _math.abs,
  68130. _ceil = _math.ceil,
  68131. _floor = _math.floor,
  68132. _atan = _math.atan,
  68133. _max = _math.max,
  68134. _each = $.each,
  68135. _map = $.map,
  68136. _noop = $.noop,
  68137. _isFunction = $.isFunction,
  68138. SCREEN_DELTA_KOEF = 4,
  68139. AXIS_STAGGER_OVERLAPPING_KOEF = 2,
  68140. STAGGER = "stagger",
  68141. ROTATE = "rotate",
  68142. MIN_ARRANGEMENT_TICKS_COUNT = 2;
  68143. function nextState(state) {
  68144. switch (state) {
  68145. case"overlap":
  68146. return STAGGER;
  68147. case STAGGER:
  68148. return ROTATE;
  68149. default:
  68150. return "end"
  68151. }
  68152. }
  68153. function defaultGetTextFunc(value) {
  68154. return value.toString()
  68155. }
  68156. coreTickManager.overlappingMethods = {};
  68157. coreTickManager.overlappingMethods.base = {
  68158. _applyOverlappingBehavior: function() {
  68159. var that = this,
  68160. options = that._options,
  68161. overlappingBehavior = options && options.overlappingBehavior;
  68162. if (overlappingBehavior && overlappingBehavior.mode !== "ignore") {
  68163. that._useAutoArrangement = true;
  68164. that._correctTicks();
  68165. if (overlappingBehavior.mode === "auto") {
  68166. that._applyAutoOverlappingBehavior();
  68167. that._useAutoArrangement = options.overlappingBehavior.isOverlapped
  68168. }
  68169. if (that._useAutoArrangement) {
  68170. if (overlappingBehavior.mode === STAGGER)
  68171. that._screenDelta *= AXIS_STAGGER_OVERLAPPING_KOEF;
  68172. that._applyAutoArrangement()
  68173. }
  68174. }
  68175. },
  68176. _checkBoundedTicksOverlapping: function() {
  68177. this._removeBoundedOverlappingDates();
  68178. this._applyStartEndTicksCorrection()
  68179. },
  68180. getMaxLabelParams: function(ticks) {
  68181. var that = this,
  68182. getText = that._options.getText || defaultGetTextFunc,
  68183. tickWithMaxLength,
  68184. tickTextWithMaxLength,
  68185. maxLength = 0,
  68186. bbox;
  68187. ticks = ticks || that._getMajorTicks();
  68188. if (!ticks.length)
  68189. return {
  68190. width: 0,
  68191. height: 0,
  68192. length: 0,
  68193. y: 0
  68194. };
  68195. _each(ticks, function(_, item) {
  68196. var text = getText(item, that._options.labelOptions),
  68197. length = text.length;
  68198. if (maxLength < length) {
  68199. maxLength = length;
  68200. tickWithMaxLength = item;
  68201. tickTextWithMaxLength = text
  68202. }
  68203. });
  68204. bbox = that._getTextElementBbox(tickWithMaxLength, tickTextWithMaxLength);
  68205. return {
  68206. width: bbox.width,
  68207. height: bbox.height,
  68208. y: bbox.y,
  68209. length: maxLength
  68210. }
  68211. },
  68212. _applyAutoArrangement: function() {
  68213. var that = this,
  68214. options = that._options,
  68215. arrangementStep,
  68216. maxDisplayValueSize;
  68217. if (that._useAutoArrangement) {
  68218. maxDisplayValueSize = that._getTicksSize();
  68219. arrangementStep = that._getAutoArrangementStep(maxDisplayValueSize);
  68220. if (arrangementStep > 1)
  68221. if (_isDefined(that._tickInterval) || _isDefined(that._customTicks))
  68222. that._ticks = that._getAutoArrangementTicks(arrangementStep);
  68223. else {
  68224. options.gridSpacingFactor = maxDisplayValueSize;
  68225. that._ticks = that._createTicks([], that._findTickInterval(), that._min, that._max)
  68226. }
  68227. }
  68228. },
  68229. _getAutoArrangementTicks: function(step) {
  68230. var that = this,
  68231. ticks = that._ticks,
  68232. ticksLength = ticks.length,
  68233. resultTicks = ticks,
  68234. decimatedTicks = that._decimatedTicks || [],
  68235. i;
  68236. if (step > 1) {
  68237. resultTicks = [];
  68238. for (i = 0; i < ticksLength; i++)
  68239. if (i % step === 0)
  68240. resultTicks.push(ticks[i]);
  68241. else
  68242. decimatedTicks.push(ticks[i]);
  68243. that._correctInterval(step)
  68244. }
  68245. return resultTicks
  68246. },
  68247. _isOverlappedTicks: function(screenDelta) {
  68248. return this._getAutoArrangementStep(this._getTicksSize(), screenDelta, -1) > 1
  68249. },
  68250. _areDisplayValuesValid: function(value1, value2) {
  68251. var that = this,
  68252. options = that._options,
  68253. getText = options.getText || defaultGetTextFunc,
  68254. rotationAngle = options.overlappingBehavior && _isNumber(options.overlappingBehavior.rotationAngle) ? options.overlappingBehavior.rotationAngle : 0,
  68255. bBox1 = that._getTextElementBbox(value1, getText(value1, options.labelOptions)),
  68256. bBox2 = that._getTextElementBbox(value2, getText(value2, options.labelOptions)),
  68257. horizontalInverted = bBox1.x > bBox2.x,
  68258. verticalInverted = bBox1.y > bBox2.y,
  68259. hasHorizontalOverlapping,
  68260. hasVerticalOverlapping,
  68261. result;
  68262. if (rotationAngle !== 0)
  68263. result = that._getDistanceByAngle(bBox1.height, rotationAngle) <= _abs(bBox2.x - bBox1.x);
  68264. else {
  68265. hasHorizontalOverlapping = !horizontalInverted ? bBox1.x + bBox1.width > bBox2.x : bBox2.x + bBox2.width > bBox1.x;
  68266. hasVerticalOverlapping = !verticalInverted ? bBox1.y + bBox1.height > bBox2.y : bBox2.y + bBox2.height > bBox1.y;
  68267. result = !(hasHorizontalOverlapping && hasVerticalOverlapping)
  68268. }
  68269. return result
  68270. }
  68271. };
  68272. coreTickManager.overlappingMethods.circular = $.extend({}, coreTickManager.overlappingMethods.base, {
  68273. _correctTicks: _noop,
  68274. _applyAutoOverlappingBehavior: function() {
  68275. this._options.overlappingBehavior.isOverlapped = true
  68276. },
  68277. _getTextElementBbox: function(value, text) {
  68278. var textOptions = $.extend({}, this._options.textOptions, {rotate: 0}),
  68279. delta = _isFunction(this._options.translate) ? this._options.translate(value) : {
  68280. x: 0,
  68281. y: 0
  68282. },
  68283. bbox;
  68284. text = this._options.renderText(text, delta.x, delta.y).css(this._options.textFontStyles).attr(textOptions);
  68285. bbox = text.getBBox();
  68286. text.remove();
  68287. return bbox
  68288. },
  68289. _getTicksSize: function() {
  68290. return this.getMaxLabelParams(this._ticks)
  68291. },
  68292. _applyStartEndTicksCorrection: function() {
  68293. var ticks = this._ticks,
  68294. lastTick = ticks[ticks.length - 1];
  68295. if (ticks.length > 1 && !this._areDisplayValuesValid(ticks[0], lastTick))
  68296. ticks.pop()
  68297. },
  68298. _getAutoArrangementStep: function(maxDisplayValueSize) {
  68299. var that = this,
  68300. options = that._options,
  68301. radius = options.circularRadius,
  68302. startAngle = options.circularStartAngle,
  68303. endAngle = options.circularEndAngle,
  68304. circleDelta = startAngle === endAngle ? 360 : _abs(startAngle - endAngle),
  68305. businessDelta = that._businessDelta || that._ticks.length,
  68306. degreesPerTick = that._tickInterval * circleDelta / businessDelta,
  68307. width = maxDisplayValueSize.width,
  68308. height = maxDisplayValueSize.height,
  68309. angle1 = _abs(2 * _atan(height / (2 * radius - width)) * 180 / _math.PI),
  68310. angle2 = _abs(2 * _atan(width / (2 * radius - height)) * 180 / _math.PI),
  68311. minAngleForTick = _max(angle1, angle2),
  68312. step = 1;
  68313. if (degreesPerTick < minAngleForTick)
  68314. step = _ceil(minAngleForTick / degreesPerTick);
  68315. return _max(1, step)
  68316. }
  68317. });
  68318. coreTickManager.overlappingMethods.linear = $.extend({}, coreTickManager.overlappingMethods.base, {
  68319. _correctTicks: function() {
  68320. var getIntervalFunc = coreTickManager.continuous._getInterval,
  68321. arrangementStep;
  68322. if (this._testingGetIntervalFunc)
  68323. getIntervalFunc = this._testingGetIntervalFunc;
  68324. arrangementStep = _ceil(getIntervalFunc.call(this, this._getDeltaCoef(this._screenDelta * SCREEN_DELTA_KOEF, this._ticks.length))) || this._ticks.length;
  68325. this._appliedArrangementStep = arrangementStep;
  68326. this._ticks = this._getAutoArrangementTicks(arrangementStep)
  68327. },
  68328. _getTextElementBbox: function(value, text) {
  68329. var textOptions = $.extend({}, this._options.textOptions, {rotate: 0}),
  68330. x = 0,
  68331. y = 0,
  68332. delta = _isFunction(this._options.translate) ? this._options.translate(value) : 0,
  68333. bbox;
  68334. if (this._options.isHorizontal)
  68335. x += delta;
  68336. else
  68337. y += delta;
  68338. text = this._options.renderText(text, x, y).css(this._options.textFontStyles).attr(textOptions);
  68339. bbox = text.getBBox();
  68340. text.remove();
  68341. return bbox
  68342. },
  68343. _applyStartEndTicksCorrection: _noop,
  68344. _getAutoArrangementStep: function(maxDisplayValueSize, screenDelta, minArrangementTicksStep) {
  68345. var that = this,
  68346. options = that._options,
  68347. requiredValuesCount,
  68348. textSpacing = options.textSpacing || 0,
  68349. addedSpacing = options.isHorizontal ? textSpacing : 0;
  68350. screenDelta = screenDelta || that._screenDelta;
  68351. minArrangementTicksStep = _isDefined(minArrangementTicksStep) ? minArrangementTicksStep : 1;
  68352. if (options.getCustomAutoArrangementStep)
  68353. return options.getCustomAutoArrangementStep(that._ticks, options);
  68354. if (maxDisplayValueSize > 0) {
  68355. requiredValuesCount = _floor((screenDelta + textSpacing) / (maxDisplayValueSize + addedSpacing));
  68356. requiredValuesCount = requiredValuesCount <= minArrangementTicksStep ? MIN_ARRANGEMENT_TICKS_COUNT : requiredValuesCount;
  68357. return _ceil((options.ticksCount || that._ticks.length) / requiredValuesCount)
  68358. }
  68359. return 1
  68360. },
  68361. _getOptimalRotationAngle: function() {
  68362. var that = this,
  68363. options = that._options,
  68364. tick1 = that._ticks[0],
  68365. tick2 = that._ticks[1],
  68366. outOfScreen = core.outOfScreen,
  68367. textOptions = that._textOptions,
  68368. getText = options.getText || defaultGetTextFunc,
  68369. textFontStyles = options.textFontStyles,
  68370. svgElement1 = options.renderText(getText(tick1, options.labelOptions), outOfScreen.x + options.translate(tick1, !options.isHorizontal), outOfScreen.y).css(textFontStyles).attr(textOptions),
  68371. svgElement2 = options.renderText(getText(tick2, options.labelOptions), outOfScreen.x + options.translate(tick2, !options.isHorizontal), outOfScreen.y).css(textFontStyles).attr(textOptions),
  68372. bBox1 = svgElement1.getBBox(),
  68373. bBox2 = svgElement2.getBBox(),
  68374. angle = _math.asin((bBox1.height + options.textSpacing) / (bBox2.x - bBox1.x)) * 180 / Math.PI;
  68375. svgElement1.remove();
  68376. svgElement2.remove();
  68377. return isNaN(angle) ? 90 : _ceil(angle)
  68378. },
  68379. _applyAutoOverlappingBehavior: function() {
  68380. var that = this,
  68381. overlappingBehavior = that._options.overlappingBehavior,
  68382. screenDelta = that._screenDelta,
  68383. isOverlapped = false,
  68384. rotationAngle = null,
  68385. mode = null,
  68386. state = "overlap";
  68387. while (state !== "end") {
  68388. isOverlapped = rotationAngle && rotationAngle !== 90 ? false : that._isOverlappedTicks(screenDelta);
  68389. state = nextState(isOverlapped ? state : null);
  68390. switch (state) {
  68391. case STAGGER:
  68392. screenDelta *= AXIS_STAGGER_OVERLAPPING_KOEF;
  68393. mode = state;
  68394. break;
  68395. case ROTATE:
  68396. rotationAngle = that._getOptimalRotationAngle();
  68397. screenDelta = that._screenDelta;
  68398. mode = state;
  68399. break
  68400. }
  68401. }
  68402. overlappingBehavior.isOverlapped = isOverlapped;
  68403. overlappingBehavior.mode = mode;
  68404. overlappingBehavior.rotationAngle = rotationAngle
  68405. },
  68406. _getDistanceByAngle: function(elementHeight, rotationAngle) {
  68407. return elementHeight / _abs(_math.sin(rotationAngle * (_math.PI / 180)))
  68408. },
  68409. _getTicksSize: function() {
  68410. var that = this,
  68411. options = that._options,
  68412. ticks = that._ticks,
  68413. ticksString,
  68414. rotationAngle = options.overlappingBehavior ? options.overlappingBehavior.rotationAngle : 0,
  68415. bBox,
  68416. result,
  68417. getText = options.getText || defaultGetTextFunc,
  68418. isRotate = _isNumber(rotationAngle) && rotationAngle !== 0,
  68419. joinNeeded = !isRotate && options.isHorizontal;
  68420. if (ticks.length === 0)
  68421. return 0;
  68422. ticksString = joinNeeded ? _map(ticks, function(tick) {
  68423. return getText(tick, options.labelOptions)
  68424. }).join("\n") : getText(ticks[0], options.labelOptions);
  68425. bBox = that._getTextElementBbox(ticksString, ticksString);
  68426. result = isRotate ? that._getDistanceByAngle(bBox.height, rotationAngle) : options.isHorizontal ? bBox.width : bBox.height;
  68427. return _ceil(result)
  68428. }
  68429. })
  68430. })(jQuery, DevExpress);
  68431. /*! Module viz-core, file baseTickManager.js */
  68432. (function($, DX, undefined) {
  68433. var core = DX.viz.core,
  68434. coreTickManager = core.tickManager,
  68435. utils = DX.utils,
  68436. _isDefined = utils.isDefined,
  68437. _isNumber = utils.isNumber,
  68438. _addInterval = utils.addInterval,
  68439. _adjustValue = utils.adjustValue,
  68440. _each = $.each,
  68441. _map = $.map,
  68442. _inArray = $.inArray,
  68443. _noop = $.noop,
  68444. DEFAULT_GRID_SPACING_FACTOR = 30,
  68445. DEFAULT_MINOR_GRID_SPACING_FACTOR = 15,
  68446. DEFAULT_NUMBER_MULTIPLIERS = [1, 2, 3, 5],
  68447. TICKS_COUNT_LIMIT = 2000,
  68448. MIN_ARRANGEMENT_TICKS_COUNT = 2;
  68449. function concatAndSort(array1, array2) {
  68450. var array = array1.concat(array2).sort(function(x, y) {
  68451. return _isDefined(x) && _isDefined(y) && x.valueOf() - y.valueOf()
  68452. }),
  68453. length = array.length,
  68454. i;
  68455. for (i = length - 1; i > 0; i--)
  68456. if (_isDefined(array[i]) && _isDefined(array[i - 1]) && array[i].valueOf() === array[i - 1].valueOf())
  68457. array.splice(i, 1);
  68458. return array
  68459. }
  68460. coreTickManager.discrete = $.extend({}, coreTickManager.continuous, {
  68461. _getMinorTicks: _noop,
  68462. _findTickInterval: _noop,
  68463. _createTicks: function() {
  68464. return []
  68465. },
  68466. _getMarginValue: _noop,
  68467. _generateBounds: _noop,
  68468. _correctMin: _noop,
  68469. _correctMax: _noop,
  68470. _findBusinessDelta: _noop,
  68471. _addBoundedTicks: _noop,
  68472. getFullTicks: function() {
  68473. return this._customTicks
  68474. },
  68475. getMinorTicks: function() {
  68476. return this._decimatedTicks || []
  68477. },
  68478. _findTickIntervalForCustomTicks: function() {
  68479. return 1
  68480. }
  68481. });
  68482. coreTickManager.TickManager = DX.Class.inherit({
  68483. ctor: function(types, data, options) {
  68484. options = options || {};
  68485. this.update(types || {}, data || {}, options);
  68486. this._initOverlappingMethods(options.overlappingBehaviorType)
  68487. },
  68488. dispose: function() {
  68489. this._ticks = null;
  68490. this._minorTicks = null;
  68491. this._decimatedTicks = null;
  68492. this._boundaryTicks = null;
  68493. this._options = null
  68494. },
  68495. update: function(types, data, options) {
  68496. this._updateOptions(options || {});
  68497. this._min = data.min;
  68498. this._updateTypes(types || {});
  68499. this._updateData(data || {})
  68500. },
  68501. _updateMinMax: function(data) {
  68502. var min = data.min || 0,
  68503. max = data.max || 0,
  68504. newMinMax = this._applyMinMaxMargins(min, max);
  68505. this._min = this._originalMin = newMinMax.min;
  68506. this._max = this._originalMax = newMinMax.max;
  68507. this._updateBusinessDelta()
  68508. },
  68509. _updateBusinessDelta: function() {
  68510. this._businessDelta = this._findBusinessDelta && this._findBusinessDelta(this._min, this._max)
  68511. },
  68512. _updateTypes: function(types) {
  68513. var that = this,
  68514. axisType = that._validateAxisType(types.axisType),
  68515. dataType = that._validateDataType(types.dataType);
  68516. that._resetMethods();
  68517. this._axisType = axisType;
  68518. this._dataType = dataType;
  68519. this._initMethods()
  68520. },
  68521. _updateData: function(data) {
  68522. data = $.extend({}, data);
  68523. data.min = _isDefined(data.min) ? data.min : this._originalMin;
  68524. data.max = _isDefined(data.max) ? data.max : this._originalMax;
  68525. this._updateMinMax(data);
  68526. this._customTicks = data.customTicks && data.customTicks.slice();
  68527. this._customMinorTicks = data.customMinorTicks;
  68528. this._screenDelta = data.screenDelta || 0
  68529. },
  68530. _updateOptions: function(options) {
  68531. var opt;
  68532. this._options = opt = options;
  68533. this._useAutoArrangement = !!this._options.useTicksAutoArrangement;
  68534. opt.gridSpacingFactor = opt.gridSpacingFactor || DEFAULT_GRID_SPACING_FACTOR;
  68535. opt.minorGridSpacingFactor = opt.minorGridSpacingFactor || DEFAULT_MINOR_GRID_SPACING_FACTOR;
  68536. opt.numberMultipliers = opt.numberMultipliers || DEFAULT_NUMBER_MULTIPLIERS
  68537. },
  68538. getTickBounds: function() {
  68539. return {
  68540. minVisible: this._minBound,
  68541. maxVisible: this._maxBound
  68542. }
  68543. },
  68544. getTicks: function(withoutOverlappingBehavior) {
  68545. var that = this,
  68546. options = that._options;
  68547. that._ticks = that._getMajorTicks();
  68548. that._checkLabelFormat();
  68549. that._decimatedTicks = [];
  68550. that._applyAutoArrangement();
  68551. !withoutOverlappingBehavior && that._applyOverlappingBehavior();
  68552. that._generateBounds();
  68553. if (options.showMinorTicks)
  68554. that._minorTicks = that._customMinorTicks || that._getMinorTicks();
  68555. that._addBoundedTicks();
  68556. !withoutOverlappingBehavior && that._checkBoundedTicksOverlapping();
  68557. return that._ticks
  68558. },
  68559. getMinorTicks: function() {
  68560. var that = this,
  68561. decimatedTicks = that._decimatedTicks || [],
  68562. options = that._options || {},
  68563. hasDecimatedTicks = decimatedTicks.length,
  68564. hasMinorTickOptions = _isDefined(options.minorTickInterval) || _isDefined(options.minorTickCount),
  68565. hasCustomMinorTicks = that._customMinorTicks && that._customMinorTicks.length,
  68566. hasMinorTicks = options.showMinorTicks && (hasMinorTickOptions || hasCustomMinorTicks),
  68567. ticks = hasDecimatedTicks && !hasMinorTicks ? decimatedTicks : that._minorTicks || [];
  68568. return concatAndSort(ticks, [])
  68569. },
  68570. getDecimatedTicks: function() {
  68571. return concatAndSort(this._decimatedTicks || [], [])
  68572. },
  68573. getFullTicks: function() {
  68574. return concatAndSort(this._ticks || [], this.getMinorTicks(), this._axisType)
  68575. },
  68576. getBoundaryTicks: function() {
  68577. return concatAndSort(this._boundaryTicks || [], [])
  68578. },
  68579. getTickInterval: function() {
  68580. return this._tickInterval
  68581. },
  68582. getMinorTickInterval: function() {
  68583. return this._minorTickInterval
  68584. },
  68585. getOverlappingBehavior: function() {
  68586. return this._options.overlappingBehavior
  68587. },
  68588. getOptions: function() {
  68589. return this._options
  68590. },
  68591. _getMajorTicks: function() {
  68592. var ticks;
  68593. if (this._customTicks) {
  68594. ticks = this._customTicks.slice();
  68595. this._tickInterval = ticks.length > 1 ? this._findTickIntervalForCustomTicks() : 0
  68596. }
  68597. else
  68598. ticks = this._createTicks([], this._findTickInterval(), this._min, this._max);
  68599. return ticks
  68600. },
  68601. _applyMargin: function(margin, min, max, isNegative) {
  68602. var coef,
  68603. value = min;
  68604. if (isFinite(margin)) {
  68605. coef = this._getMarginValue(min, max, margin);
  68606. if (coef)
  68607. value = this._getNextTickValue(min, coef, isNegative, false)
  68608. }
  68609. return value
  68610. },
  68611. _applyMinMaxMargins: function(min, max) {
  68612. var options = this._options,
  68613. newMin = min > max ? max : min,
  68614. newMax = max > min ? max : min;
  68615. this._minCorrectionEnabled = this._getCorrectionEnabled(min, "min");
  68616. this._maxCorrectionEnabled = this._getCorrectionEnabled(max, "max");
  68617. if (options && !options.stick) {
  68618. newMin = this._applyMargin(options.minValueMargin, min, max, true);
  68619. newMax = this._applyMargin(options.maxValueMargin, max, min, false)
  68620. }
  68621. return {
  68622. min: newMin,
  68623. max: newMax
  68624. }
  68625. },
  68626. _checkBoundedTickInArray: function(value, array) {
  68627. var arrayValues = _map(array || [], function(item) {
  68628. return item.valueOf()
  68629. }),
  68630. minorTicksIndex = _inArray(value.valueOf(), arrayValues);
  68631. if (minorTicksIndex !== -1)
  68632. array.splice(minorTicksIndex, 1)
  68633. },
  68634. _checkLabelFormat: function() {
  68635. var options = this._options;
  68636. if (this._dataType === "datetime" && !options.hasLabelFormat && this._ticks.length)
  68637. options.labelOptions.format = DX.formatHelper.getDateFormatByTicks(this._ticks)
  68638. },
  68639. _generateBounds: function() {
  68640. var that = this,
  68641. interval = that._getBoundInterval(),
  68642. stick = that._options.stick,
  68643. minStickValue = that._options.minStickValue,
  68644. maxStickValue = that._options.maxStickValue,
  68645. minBound = that._minCorrectionEnabled && !stick ? that._getNextTickValue(that._min, interval, true) : that._originalMin,
  68646. maxBound = that._maxCorrectionEnabled && !stick ? that._getNextTickValue(that._max, interval) : that._originalMax;
  68647. that._minBound = minBound < minStickValue ? minStickValue : minBound;
  68648. that._maxBound = maxBound > maxStickValue ? maxStickValue : maxBound
  68649. },
  68650. _initOverlappingMethods: function(type) {
  68651. this._initMethods(coreTickManager.overlappingMethods[type || "linear"])
  68652. },
  68653. _addBoundedTicks: function() {
  68654. var that = this,
  68655. tickValues = _map(that._ticks, function(tick) {
  68656. return tick.valueOf()
  68657. }),
  68658. min = that._originalMin,
  68659. max = that._originalMax,
  68660. addMinMax = that._options.addMinMax || {};
  68661. that._boundaryTicks = [];
  68662. if (addMinMax.min && _inArray(min.valueOf(), tickValues) === -1) {
  68663. that._ticks.splice(0, 0, min);
  68664. that._boundaryTicks.push(min);
  68665. that._checkBoundedTickInArray(min, that._minorTicks);
  68666. that._checkBoundedTickInArray(min, that._decimatedTicks)
  68667. }
  68668. if (addMinMax.max && _inArray(max.valueOf(), tickValues) === -1) {
  68669. that._ticks.push(max);
  68670. that._boundaryTicks.push(max);
  68671. that._checkBoundedTickInArray(max, that._minorTicks);
  68672. that._checkBoundedTickInArray(max, that._decimatedTicks)
  68673. }
  68674. },
  68675. _getCorrectionEnabled: function(value, marginSelector) {
  68676. var options = this._options || {},
  68677. hasPercentStick = options.percentStick && value === 1,
  68678. hasValueMargin = options[marginSelector + "ValueMargin"];
  68679. return !hasPercentStick && !hasValueMargin
  68680. },
  68681. _validateAxisType: function(type) {
  68682. var defaultType = "continuous",
  68683. allowedTypes = {
  68684. continuous: true,
  68685. discrete: true,
  68686. logarithmic: true
  68687. };
  68688. return allowedTypes[type] ? type : defaultType
  68689. },
  68690. _validateDataType: function(type) {
  68691. var allowedTypes = {
  68692. numeric: true,
  68693. datetime: true,
  68694. string: true
  68695. };
  68696. if (!allowedTypes[type])
  68697. type = _isDefined(this._min) ? this._getDataType(this._min) : "numeric";
  68698. return type
  68699. },
  68700. _getDataType: function(value) {
  68701. return utils.isDate(value) ? 'datetime' : 'numeric'
  68702. },
  68703. _getMethods: function() {
  68704. var methods;
  68705. if (this._axisType === "continuous")
  68706. methods = this._dataType === "datetime" ? coreTickManager.datetime : coreTickManager.continuous;
  68707. else
  68708. methods = coreTickManager[this._axisType] || coreTickManager.continuous;
  68709. return methods
  68710. },
  68711. _resetMethods: function() {
  68712. var that = this,
  68713. methods = that._getMethods();
  68714. _each(methods, function(name) {
  68715. if (that[name])
  68716. delete that[name]
  68717. })
  68718. },
  68719. _initMethods: function(methods) {
  68720. var that = this;
  68721. methods = methods || that._getMethods();
  68722. _each(methods, function(name, func) {
  68723. that[name] = func
  68724. })
  68725. },
  68726. _getDeltaCoef: function(screenDelta, businessDelta, gridSpacingFactor) {
  68727. var count;
  68728. gridSpacingFactor = gridSpacingFactor || this._options.gridSpacingFactor;
  68729. screenDelta = screenDelta || this._screenDelta;
  68730. businessDelta = businessDelta || this._businessDelta;
  68731. count = screenDelta / gridSpacingFactor;
  68732. count = count <= 1 ? MIN_ARRANGEMENT_TICKS_COUNT : count;
  68733. return businessDelta / count
  68734. },
  68735. _adjustNumericTickValue: function(value, interval, min) {
  68736. return utils.isExponential(value) ? _adjustValue(value) : utils.applyPrecisionByMinDelta(min, interval, value)
  68737. },
  68738. _isTickIntervalCorrect: function(tickInterval, tickCountLimit, businessDelta) {
  68739. var date;
  68740. businessDelta = businessDelta || this._businessDelta;
  68741. if (!_isNumber(tickInterval)) {
  68742. date = new Date;
  68743. tickInterval = _addInterval(date, tickInterval) - date;
  68744. if (!tickInterval)
  68745. return false
  68746. }
  68747. if (_isNumber(tickInterval))
  68748. if (tickInterval > 0 && businessDelta / tickInterval > tickCountLimit) {
  68749. if (this._options.incidentOccured)
  68750. this._options.incidentOccured('W2003')
  68751. }
  68752. else
  68753. return true;
  68754. return false
  68755. },
  68756. _correctValue: function(valueTypeSelector, tickInterval, correctionMethod) {
  68757. var that = this,
  68758. correctionEnabledSelector = "_" + valueTypeSelector + "CorrectionEnabled",
  68759. spaceCorrectionSelector = valueTypeSelector + "SpaceCorrection",
  68760. valueSelector = "_" + valueTypeSelector,
  68761. minStickValue = that._options.minStickValue,
  68762. maxStickValue = that._options.maxStickValue;
  68763. if (that[correctionEnabledSelector]) {
  68764. if (that._options[spaceCorrectionSelector])
  68765. that[valueSelector] = that._getNextTickValue(that[valueSelector], tickInterval, valueTypeSelector === "min");
  68766. correctionMethod.call(this, tickInterval)
  68767. }
  68768. if (valueTypeSelector === "min")
  68769. that[valueSelector] = that[valueSelector] < minStickValue ? minStickValue : that[valueSelector];
  68770. if (valueTypeSelector === "max")
  68771. that[valueSelector] = that[valueSelector] > maxStickValue ? maxStickValue : that[valueSelector]
  68772. },
  68773. _findTickInterval: function() {
  68774. var that = this,
  68775. options = that._options,
  68776. tickInterval;
  68777. tickInterval = that._isTickIntervalValid(options.tickInterval) && that._isTickIntervalCorrect(options.tickInterval, TICKS_COUNT_LIMIT) ? options.tickInterval : that._getInterval();
  68778. if (that._isTickIntervalValid(tickInterval)) {
  68779. that._correctValue("min", tickInterval, that._correctMin);
  68780. that._correctValue("max", tickInterval, that._correctMax);
  68781. that._updateBusinessDelta()
  68782. }
  68783. that._tickInterval = tickInterval;
  68784. return tickInterval
  68785. },
  68786. _findMinorTickInterval: function(firstTick, secondTick) {
  68787. var that = this,
  68788. ticks = that._ticks,
  68789. intervals = that._options.stick ? ticks.length - 1 : ticks.length;
  68790. if (intervals < 1)
  68791. intervals = 1;
  68792. that._getMinorInterval(that._screenDelta / intervals, that._findBusinessDelta(firstTick, secondTick, false));
  68793. return that._minorTickInterval
  68794. },
  68795. _createMinorTicks: function(ticks, firstTick, secondTick) {
  68796. var that = this,
  68797. tickInterval = that._findMinorTickInterval(firstTick, secondTick),
  68798. isTickIntervalNegative = false,
  68799. isTickIntervalWithPow = false,
  68800. needCorrectTick = false,
  68801. startTick = that._getNextTickValue(firstTick, tickInterval, isTickIntervalNegative, isTickIntervalWithPow, needCorrectTick);
  68802. if (that._isTickIntervalValid(tickInterval))
  68803. ticks = that._createCountedTicks(ticks, tickInterval, startTick, secondTick, that._minorTickCount, isTickIntervalNegative, isTickIntervalWithPow, needCorrectTick);
  68804. return ticks
  68805. },
  68806. _getMinorTicks: function() {
  68807. var that = this,
  68808. minorTicks = [],
  68809. ticks = that._ticks,
  68810. ticksLength = ticks.length,
  68811. hasUnitBeginningTick = that._hasUnitBeginningTickCorrection(),
  68812. i = hasUnitBeginningTick ? 1 : 0;
  68813. if (ticks.length) {
  68814. minorTicks = that._getBoundedMinorTicks(minorTicks, that._minBound, ticks[0], true);
  68815. if (hasUnitBeginningTick)
  68816. minorTicks = that._getUnitBeginningMinorTicks(minorTicks);
  68817. for (i; i < ticksLength - 1; i++)
  68818. minorTicks = that._createMinorTicks(minorTicks, ticks[i], ticks[i + 1]);
  68819. minorTicks = that._getBoundedMinorTicks(minorTicks, that._maxBound, ticks[ticksLength - 1])
  68820. }
  68821. else
  68822. minorTicks = that._createMinorTicks(minorTicks, that._minBound, that._maxBound);
  68823. return minorTicks
  68824. },
  68825. _createCountedTicks: function(ticks, tickInterval, min, max, count, isTickIntervalWithPow, needMax) {
  68826. var value = min,
  68827. i;
  68828. for (i = 0; i < count; i++) {
  68829. if (!(needMax === false && value.valueOf() === max.valueOf()))
  68830. ticks.push(value);
  68831. value = this._getNextTickValue(value, tickInterval, false, isTickIntervalWithPow, false)
  68832. }
  68833. return ticks
  68834. },
  68835. _createTicks: function(ticks, tickInterval, min, max, isTickIntervalNegative, isTickIntervalWithPow, withCorrection) {
  68836. var that = this,
  68837. value = min,
  68838. newValue = min,
  68839. leftBound,
  68840. rightBound,
  68841. boundedRule;
  68842. if (that._isTickIntervalValid(tickInterval)) {
  68843. boundedRule = min - max < 0;
  68844. do {
  68845. value = newValue;
  68846. if (that._options.stick) {
  68847. if (value >= that._originalMin && value <= that._originalMax)
  68848. ticks.push(value)
  68849. }
  68850. else
  68851. ticks.push(value);
  68852. newValue = that._getNextTickValue(value, tickInterval, isTickIntervalNegative, isTickIntervalWithPow, withCorrection);
  68853. if (value.valueOf() === newValue.valueOf())
  68854. break;
  68855. leftBound = newValue - min >= 0;
  68856. rightBound = max - newValue >= 0
  68857. } while (boundedRule === leftBound && boundedRule === rightBound)
  68858. }
  68859. else
  68860. ticks.push(value);
  68861. return ticks
  68862. },
  68863. _getBoundedMinorTicks: function(minorTicks, boundedTick, tick, isNegative) {
  68864. var that = this,
  68865. needCorrectTick = false,
  68866. nextTick = that._tickInterval ? this._getNextTickValue(tick, that._tickInterval, isNegative, true, needCorrectTick) : boundedTick,
  68867. tickInterval = that._findMinorTickInterval(tick, nextTick),
  68868. isTickIntervalCorrect = that._isTickIntervalCorrect(tickInterval, TICKS_COUNT_LIMIT, that._findBusinessDelta(tick, boundedTick, false)),
  68869. startTick,
  68870. endTick,
  68871. boundedTickValue = boundedTick.valueOf();
  68872. if (isTickIntervalCorrect && that._isTickIntervalValid(tickInterval) && that._minorTickCount > 0) {
  68873. if (isNegative) {
  68874. if (tick.valueOf() <= boundedTickValue)
  68875. return minorTicks;
  68876. while (nextTick.valueOf() < boundedTickValue)
  68877. nextTick = this._getNextTickValue(nextTick, tickInterval, false, false, needCorrectTick);
  68878. startTick = nextTick;
  68879. endTick = that._getNextTickValue(tick, tickInterval, true, false, false)
  68880. }
  68881. else {
  68882. startTick = that._getNextTickValue(tick, tickInterval, false, false, false);
  68883. endTick = boundedTick
  68884. }
  68885. minorTicks = that._createTicks(minorTicks, tickInterval, startTick, endTick, false, false, needCorrectTick)
  68886. }
  68887. return minorTicks
  68888. },
  68889. getTypes: function() {
  68890. return {
  68891. axisType: this._axisType,
  68892. dataType: this._dataType
  68893. }
  68894. },
  68895. getData: function() {
  68896. return {
  68897. min: this._min,
  68898. max: this._max,
  68899. customTicks: this._customTicks,
  68900. customMinorTicks: this._customMinorTicks,
  68901. screenDelta: this._screenDelta
  68902. }
  68903. }
  68904. })
  68905. })(jQuery, DevExpress);
  68906. /*! Module viz-core, file numericTranslator.js */
  68907. (function($, DX, undefined) {
  68908. var utils = DX.utils,
  68909. isDefined = utils.isDefined,
  68910. round = Math.round;
  68911. DX.viz.core.numericTranslatorFunctions = {
  68912. translate: function(bp) {
  68913. var that = this,
  68914. canvasOptions = that._canvasOptions,
  68915. doubleError = canvasOptions.rangeDoubleError,
  68916. specialValue = that.translateSpecialCase(bp);
  68917. if (isDefined(specialValue))
  68918. return specialValue;
  68919. if (isNaN(bp) || bp.valueOf() + doubleError < canvasOptions.rangeMin || bp.valueOf() - doubleError > canvasOptions.rangeMax)
  68920. return null;
  68921. return that._conversionValue(that._calculateProjection((bp - canvasOptions.rangeMinVisible) * canvasOptions.ratioOfCanvasRange))
  68922. },
  68923. untranslate: function(pos, _directionOffset, enableOutOfCanvas) {
  68924. var canvasOptions = this._canvasOptions,
  68925. startPoint = canvasOptions.startPoint;
  68926. if (!enableOutOfCanvas && (pos < startPoint || pos > canvasOptions.endPoint) || !isDefined(canvasOptions.rangeMin) || !isDefined(canvasOptions.rangeMax))
  68927. return null;
  68928. return this._calculateUnProjection((pos - startPoint) / canvasOptions.ratioOfCanvasRange)
  68929. },
  68930. getInterval: function() {
  68931. return round(this._canvasOptions.ratioOfCanvasRange * (this._businessRange.interval || Math.abs(this._canvasOptions.rangeMax - this._canvasOptions.rangeMin)))
  68932. },
  68933. _getValue: function(val) {
  68934. return val
  68935. },
  68936. zoom: function(translate, scale) {
  68937. var that = this,
  68938. canvasOptions = that._canvasOptions,
  68939. startPoint = canvasOptions.startPoint,
  68940. endPoint = canvasOptions.endPoint,
  68941. newStart = (startPoint + translate) / scale,
  68942. newEnd = (endPoint + translate) / scale,
  68943. minPoint = Math.min(that.translate(that._getValue(canvasOptions.rangeMin)), that.translate(that._getValue(canvasOptions.rangeMax))),
  68944. maxPoint = Math.max(that.translate(that._getValue(canvasOptions.rangeMin)), that.translate(that._getValue(canvasOptions.rangeMax)));
  68945. if (minPoint > newStart) {
  68946. newEnd -= newStart - minPoint;
  68947. newStart = minPoint
  68948. }
  68949. if (maxPoint < newEnd) {
  68950. newStart -= newEnd - maxPoint;
  68951. newEnd = maxPoint
  68952. }
  68953. if (maxPoint - minPoint < newEnd - newStart) {
  68954. newStart = minPoint;
  68955. newEnd = maxPoint
  68956. }
  68957. translate = (endPoint - startPoint) * newStart / (newEnd - newStart) - startPoint;
  68958. scale = (startPoint + translate) / newStart || 1;
  68959. return {
  68960. min: that.untranslate(newStart, undefined, true),
  68961. max: that.untranslate(newEnd, undefined, true),
  68962. translate: translate,
  68963. scale: scale
  68964. }
  68965. },
  68966. getMinScale: function(zoom) {
  68967. return zoom ? 1.1 : 0.9
  68968. },
  68969. getScale: function(val1, val2) {
  68970. var canvasOptions = this._canvasOptions;
  68971. val1 = isDefined(val1) ? val1 : canvasOptions.rangeMin;
  68972. val2 = isDefined(val2) ? val2 : canvasOptions.rangeMax;
  68973. return (canvasOptions.rangeMax - canvasOptions.rangeMin) / Math.abs(val1 - val2)
  68974. }
  68975. }
  68976. })(jQuery, DevExpress);
  68977. /*! Module viz-core, file datetimeTranslator.js */
  68978. (function($, DX, undefined) {
  68979. var core = DX.viz.core,
  68980. numericTranslator = core.numericTranslatorFunctions;
  68981. core.datetimeTranslatorFunctions = {
  68982. translate: numericTranslator.translate,
  68983. untranslate: function() {
  68984. var result = numericTranslator.untranslate.apply(this, arguments);
  68985. return result === null ? result : new Date(result)
  68986. },
  68987. _getValue: numericTranslator._getValue,
  68988. getInterval: numericTranslator.getInterval,
  68989. zoom: numericTranslator.zoom,
  68990. getMinScale: numericTranslator.getMinScale,
  68991. getScale: numericTranslator.getScale
  68992. }
  68993. })(jQuery, DevExpress);
  68994. /*! Module viz-core, file categoryTranslator.js */
  68995. (function($, DX, undefined) {
  68996. var isDefined = DX.utils.isDefined,
  68997. round = Math.round;
  68998. DX.viz.core.categoryTranslatorFunctions = {
  68999. translate: function(category, directionOffset) {
  69000. var that = this,
  69001. canvasOptions = that._canvasOptions,
  69002. categoryRecord = that._categoriesToPoints[category],
  69003. stickDelta,
  69004. specialValue = that.translateSpecialCase(category),
  69005. startPointIndex = canvasOptions.startPointIndex || 0,
  69006. stickInterval = that._businessRange.stick ? 0 : 0.5;
  69007. if (isDefined(specialValue))
  69008. return specialValue;
  69009. if (!categoryRecord)
  69010. return null;
  69011. directionOffset = directionOffset || 0;
  69012. directionOffset = canvasOptions.invert ? -directionOffset : directionOffset;
  69013. stickDelta = categoryRecord.index + stickInterval - startPointIndex + directionOffset * 0.5;
  69014. return round(canvasOptions.startPoint + canvasOptions.interval * stickDelta)
  69015. },
  69016. untranslate: function(pos, directionOffset, enableOutOfCanvas) {
  69017. var that = this,
  69018. canvasOptions = that._canvasOptions,
  69019. startPoint = canvasOptions.startPoint,
  69020. categories = that.visibleCategories || that._categories,
  69021. categoriesLength = categories.length,
  69022. result = 0,
  69023. stickInterval = that._businessRange.stick ? 0.5 : 0;
  69024. if (!enableOutOfCanvas && (pos < startPoint || pos > canvasOptions.endPoint))
  69025. return null;
  69026. directionOffset = directionOffset || 0;
  69027. result = round((pos - startPoint) / canvasOptions.interval + stickInterval - 0.5 - directionOffset * 0.5);
  69028. if (categoriesLength === result)
  69029. result--;
  69030. if (result === -1)
  69031. result = 0;
  69032. if (canvasOptions.invert)
  69033. result = categoriesLength - result - 1;
  69034. return categories[result]
  69035. },
  69036. getInterval: function() {
  69037. return this._canvasOptions.interval
  69038. },
  69039. zoom: function(translate, scale) {
  69040. var that = this,
  69041. canvasOptions = that._canvasOptions,
  69042. interval = canvasOptions.interval * scale,
  69043. translateCaltegories = translate / interval,
  69044. stick = that._businessRange.stick,
  69045. startCategoryIndex = parseInt((canvasOptions.startPointIndex || 0) + translateCaltegories + 0.5),
  69046. categoriesLength = parseInt(canvasOptions.canvasLength / interval + (stick ? 1 : 0)) || 1,
  69047. endCategoryIndex,
  69048. newVisibleCategories,
  69049. categories = that._categories,
  69050. newInterval;
  69051. canvasOptions.invert && (categories = categories.slice().reverse());
  69052. if (startCategoryIndex < 0)
  69053. startCategoryIndex = 0;
  69054. endCategoryIndex = startCategoryIndex + categoriesLength;
  69055. if (endCategoryIndex > categories.length) {
  69056. endCategoryIndex = categories.length;
  69057. startCategoryIndex = endCategoryIndex - categoriesLength;
  69058. if (startCategoryIndex < 0)
  69059. startCategoryIndex = 0
  69060. }
  69061. newVisibleCategories = categories.slice(parseInt(startCategoryIndex), parseInt(endCategoryIndex));
  69062. newInterval = that._getDiscreteInterval(newVisibleCategories.length, canvasOptions);
  69063. scale = newInterval / canvasOptions.interval;
  69064. translate = that.translate(newVisibleCategories[0]) * scale - (canvasOptions.startPoint + (stick ? 0 : newInterval / 2));
  69065. return {
  69066. min: !canvasOptions.invert ? newVisibleCategories[0] : newVisibleCategories[newVisibleCategories.length - 1],
  69067. max: !canvasOptions.invert ? newVisibleCategories[newVisibleCategories.length - 1] : newVisibleCategories[0],
  69068. translate: translate,
  69069. scale: scale
  69070. }
  69071. },
  69072. getMinScale: function(zoom) {
  69073. var that = this,
  69074. canvasOptions = that._canvasOptions,
  69075. categoriesLength = (that.visibleCategories || that._categories).length;
  69076. categoriesLength += (parseInt(categoriesLength * 0.1) || 1) * (zoom ? -2 : 2);
  69077. return canvasOptions.canvasLength / (Math.max(categoriesLength, 1) * canvasOptions.interval)
  69078. },
  69079. getScale: function(min, max) {
  69080. var that = this,
  69081. canvasOptions = that._canvasOptions,
  69082. visibleArea = that.getCanvasVisibleArea(),
  69083. stickOffset = !that._businessRange.stick && 1,
  69084. minPoint = that.translate(min, -stickOffset),
  69085. maxPoint = that.translate(max, +stickOffset);
  69086. if (!isDefined(minPoint))
  69087. minPoint = canvasOptions.invert ? visibleArea.max : visibleArea.min;
  69088. if (!isDefined(maxPoint))
  69089. maxPoint = canvasOptions.invert ? visibleArea.min : visibleArea.max;
  69090. return that.canvasLength / Math.abs(maxPoint - minPoint)
  69091. }
  69092. }
  69093. })(jQuery, DevExpress);
  69094. /*! Module viz-core, file logarithmicTranslator.js */
  69095. (function($, DX, undefined) {
  69096. var core = DX.viz.core,
  69097. numericTranslator = core.numericTranslatorFunctions,
  69098. utils = DX.utils,
  69099. raiseTo = utils.raiseTo,
  69100. getLog = utils.getLog;
  69101. core.logarithmicTranslatorFunctions = {
  69102. translate: function(bp) {
  69103. var that = this,
  69104. specialValue = that.translateSpecialCase(bp);
  69105. if (utils.isDefined(specialValue))
  69106. return specialValue;
  69107. return numericTranslator.translate.call(that, getLog(bp, that._businessRange.base))
  69108. },
  69109. untranslate: function() {
  69110. var result = numericTranslator.untranslate.apply(this, arguments);
  69111. return result === null ? result : raiseTo(result, this._businessRange.base)
  69112. },
  69113. getInterval: numericTranslator.getInterval,
  69114. _getValue: function(value) {
  69115. return Math.pow(this._canvasOptions.base, value)
  69116. },
  69117. zoom: numericTranslator.zoom,
  69118. getMinScale: numericTranslator.getMinScale,
  69119. getScale: function(val1, val2) {
  69120. var base = this._businessRange.base;
  69121. val1 = utils.isDefined(val1) ? getLog(val1, base) : undefined;
  69122. val2 = utils.isDefined(val2) ? getLog(val2, base) : undefined;
  69123. return numericTranslator.getScale.call(this, val1, val2)
  69124. }
  69125. }
  69126. })(jQuery, DevExpress);
  69127. /*! Module viz-core, file translator1D.js */
  69128. (function(DX, undefined) {
  69129. var _Number = Number;
  69130. function Translator1D() {
  69131. this.setDomain(arguments[0], arguments[1]).setCodomain(arguments[2], arguments[3])
  69132. }
  69133. Translator1D.prototype = {
  69134. constructor: Translator1D,
  69135. setDomain: function(domain1, domain2) {
  69136. var that = this;
  69137. that._domain1 = _Number(domain1);
  69138. that._domain2 = _Number(domain2);
  69139. that._domainDelta = that._domain2 - that._domain1;
  69140. return that
  69141. },
  69142. setCodomain: function(codomain1, codomain2) {
  69143. var that = this;
  69144. that._codomain1 = _Number(codomain1);
  69145. that._codomain2 = _Number(codomain2);
  69146. that._codomainDelta = that._codomain2 - that._codomain1;
  69147. return that
  69148. },
  69149. getDomain: function() {
  69150. return [this._domain1, this._domain2]
  69151. },
  69152. getCodomain: function() {
  69153. return [this._codomain1, this._codomain2]
  69154. },
  69155. getDomainStart: function() {
  69156. return this._domain1
  69157. },
  69158. getDomainEnd: function() {
  69159. return this._domain2
  69160. },
  69161. getCodomainStart: function() {
  69162. return this._codomain1
  69163. },
  69164. getCodomainEnd: function() {
  69165. return this._codomain2
  69166. },
  69167. getDomainRange: function() {
  69168. return this._domainDelta
  69169. },
  69170. getCodomainRange: function() {
  69171. return this._codomainDelta
  69172. },
  69173. translate: function(value) {
  69174. var ratio = (_Number(value) - this._domain1) / this._domainDelta;
  69175. return 0 <= ratio && ratio <= 1 ? this._codomain1 + ratio * this._codomainDelta : NaN
  69176. },
  69177. adjust: function(value) {
  69178. var ratio = (_Number(value) - this._domain1) / this._domainDelta,
  69179. result = NaN;
  69180. if (ratio < 0)
  69181. result = this._domain1;
  69182. else if (ratio > 1)
  69183. result = this._domain2;
  69184. else if (0 <= ratio && ratio <= 1)
  69185. result = _Number(value);
  69186. return result
  69187. }
  69188. };
  69189. DX.viz.core.Translator1D = Translator1D
  69190. })(DevExpress);
  69191. /*! Module viz-core, file translator2D.js */
  69192. (function($, DX, undefined) {
  69193. var core = DX.viz.core,
  69194. utils = DX.utils,
  69195. getLog = utils.getLog,
  69196. getPower = utils.getPower,
  69197. isDefined = utils.isDefined,
  69198. _abs = Math.abs,
  69199. CANVAS_PROP = ["width", "height", "left", "top", "bottom", "right"],
  69200. NUMBER_EQUALITY_CORRECTION = 1,
  69201. DATETIME_EQUALITY_CORRECTION = 60000,
  69202. _noop = $.noop,
  69203. _Translator2d;
  69204. var validateCanvas = function(canvas) {
  69205. $.each(CANVAS_PROP, function(_, prop) {
  69206. canvas[prop] = parseInt(canvas[prop]) || 0
  69207. });
  69208. return canvas
  69209. };
  69210. var makeCategoriesToPoints = function(categories, invert) {
  69211. var categoriesToPoints = {},
  69212. category,
  69213. length = categories.length,
  69214. i;
  69215. for (i = 0; i < length; i++) {
  69216. category = categories[i];
  69217. categoriesToPoints[category] = {
  69218. name: category,
  69219. index: invert ? length - 1 - i : i
  69220. }
  69221. }
  69222. return categoriesToPoints
  69223. };
  69224. var validateBusinessRange = function(businessRange) {
  69225. function validate(valueSelector, baseValueSeletor) {
  69226. if (!isDefined(businessRange[valueSelector]) && isDefined(businessRange[baseValueSeletor]))
  69227. businessRange[valueSelector] = businessRange[baseValueSeletor]
  69228. }
  69229. validate("minVisible", "min");
  69230. validate("maxVisible", "max");
  69231. return businessRange
  69232. };
  69233. _Translator2d = core.Translator2D = function(businessRange, canvas, options) {
  69234. this.update(businessRange, canvas, options)
  69235. };
  69236. _Translator2d.prototype = {
  69237. constructor: _Translator2d,
  69238. reinit: function() {
  69239. var that = this,
  69240. range = that._businessRange,
  69241. categories = range.categories || [],
  69242. script = {},
  69243. canvasOptions = that._prepareCanvasOptions(),
  69244. visibleCategories = utils.getCategoriesInfo(categories, range.minVisible, range.maxVisible).categories,
  69245. categoriesLength = (visibleCategories || categories).length;
  69246. switch (range.axisType) {
  69247. case"logarithmic":
  69248. script = core.logarithmicTranslatorFunctions;
  69249. break;
  69250. case"discrete":
  69251. script = core.categoryTranslatorFunctions;
  69252. that._categories = categories;
  69253. canvasOptions.interval = that._getDiscreteInterval(range.addSpiderCategory ? categoriesLength + 1 : categoriesLength, canvasOptions);
  69254. that._categoriesToPoints = makeCategoriesToPoints(categories, canvasOptions.invert);
  69255. if (visibleCategories && visibleCategories.length) {
  69256. canvasOptions.startPointIndex = that._categoriesToPoints[visibleCategories[canvasOptions.invert ? visibleCategories.length - 1 : 0]].index;
  69257. that.visibleCategories = visibleCategories
  69258. }
  69259. break;
  69260. default:
  69261. if (range.dataType === "datetime")
  69262. script = core.datetimeTranslatorFunctions;
  69263. else
  69264. script = core.numericTranslatorFunctions
  69265. }
  69266. that.translate = script.translate;
  69267. that.untranslate = script.untranslate;
  69268. that.getInterval = script.getInterval;
  69269. that.zoom = script.zoom;
  69270. that.getMinScale = script.getMinScale;
  69271. that._getValue = script._getValue;
  69272. that.getScale = script.getScale;
  69273. that._conversionValue = that._options.conversionValue ? function(value) {
  69274. return value
  69275. } : function(value) {
  69276. return Math.round(value)
  69277. }
  69278. },
  69279. _getDiscreteInterval: function(categoriesLength, canvasOptions) {
  69280. var correctedCategoriesCount = categoriesLength - (this._businessRange.stick ? 1 : 0);
  69281. return correctedCategoriesCount > 0 ? canvasOptions.canvasLength / correctedCategoriesCount : canvasOptions.canvasLength
  69282. },
  69283. _getCanvasBounds: function(range) {
  69284. var min = range.min,
  69285. max = range.max,
  69286. minVisible = range.minVisible,
  69287. maxVisible = range.maxVisible,
  69288. newMin,
  69289. newMax,
  69290. base = range.base,
  69291. isDateTime = utils.isDate(max) || utils.isDate(min),
  69292. correction = isDateTime ? DATETIME_EQUALITY_CORRECTION : NUMBER_EQUALITY_CORRECTION;
  69293. if (range.axisType === 'logarithmic') {
  69294. maxVisible = getLog(maxVisible, base);
  69295. minVisible = getLog(minVisible, base);
  69296. min = getLog(min, base);
  69297. max = getLog(max, base)
  69298. }
  69299. if (isDefined(min) && isDefined(max) && min.valueOf() === max.valueOf()) {
  69300. newMin = min.valueOf() - correction;
  69301. newMax = max.valueOf() + correction;
  69302. if (isDateTime) {
  69303. min = new Date(newMin);
  69304. max = new Date(newMax)
  69305. }
  69306. else {
  69307. min = min !== 0 ? newMin : 0;
  69308. max = newMax
  69309. }
  69310. }
  69311. if (isDefined(minVisible) && isDefined(maxVisible) && minVisible.valueOf() === maxVisible.valueOf()) {
  69312. newMin = minVisible.valueOf() - correction;
  69313. newMax = maxVisible.valueOf() + correction;
  69314. if (isDateTime) {
  69315. minVisible = newMin < min.valueOf() ? min : new Date(newMin);
  69316. maxVisible = newMax > max.valueOf() ? max : new Date(newMax)
  69317. }
  69318. else {
  69319. if (minVisible !== 0)
  69320. minVisible = newMin < min ? min : newMin;
  69321. maxVisible = newMax > max ? max : newMax
  69322. }
  69323. }
  69324. return {
  69325. base: base,
  69326. rangeMin: min,
  69327. rangeMax: max,
  69328. rangeMinVisible: minVisible,
  69329. rangeMaxVisible: maxVisible
  69330. }
  69331. },
  69332. _prepareCanvasOptions: function() {
  69333. var that = this,
  69334. businessRange = that._businessRange,
  69335. canvasOptions = that._canvasOptions = that._getCanvasBounds(businessRange),
  69336. length,
  69337. canvas = that._canvas;
  69338. if (that._options.direction === "horizontal") {
  69339. canvasOptions.startPoint = canvas.left;
  69340. length = canvas.width;
  69341. canvasOptions.endPoint = canvas.width - canvas.right;
  69342. canvasOptions.invert = businessRange.invert
  69343. }
  69344. else {
  69345. canvasOptions.startPoint = canvas.top;
  69346. length = canvas.height;
  69347. canvasOptions.endPoint = canvas.height - canvas.bottom;
  69348. canvasOptions.invert = !businessRange.invert
  69349. }
  69350. that.canvasLength = canvasOptions.canvasLength = canvasOptions.endPoint - canvasOptions.startPoint;
  69351. canvasOptions.rangeDoubleError = Math.pow(10, getPower(canvasOptions.rangeMax - canvasOptions.rangeMin) - getPower(length) - 2);
  69352. canvasOptions.ratioOfCanvasRange = canvasOptions.canvasLength / (canvasOptions.rangeMaxVisible - canvasOptions.rangeMinVisible);
  69353. return canvasOptions
  69354. },
  69355. updateBusinessRange: function(businessRange) {
  69356. this._businessRange = validateBusinessRange(businessRange);
  69357. this.reinit()
  69358. },
  69359. update: function(businessRange, canvas, options) {
  69360. var that = this;
  69361. that._options = $.extend(that._options || {}, options);
  69362. that._canvas = validateCanvas(canvas);
  69363. that.updateBusinessRange(businessRange)
  69364. },
  69365. getBusinessRange: function() {
  69366. return this._businessRange
  69367. },
  69368. getCanvasVisibleArea: function() {
  69369. return {
  69370. min: this._canvasOptions.startPoint,
  69371. max: this._canvasOptions.endPoint
  69372. }
  69373. },
  69374. translateSpecialCase: function(value) {
  69375. var that = this,
  69376. canvasOptions = that._canvasOptions,
  69377. startPoint = canvasOptions.startPoint,
  69378. endPoint = canvasOptions.endPoint,
  69379. range = that._businessRange,
  69380. minVisible = range.minVisible,
  69381. maxVisible = range.maxVisible,
  69382. invert,
  69383. result = null;
  69384. switch (value) {
  69385. case"canvas_position_default":
  69386. if (minVisible <= 0 && maxVisible >= 0)
  69387. result = that.translate(0);
  69388. else {
  69389. invert = range.invert ^ (minVisible <= 0 && maxVisible <= 0);
  69390. if (that._options.direction === "horizontal")
  69391. result = invert ? endPoint : startPoint;
  69392. else
  69393. result = invert ? startPoint : endPoint
  69394. }
  69395. break;
  69396. case"canvas_position_left":
  69397. case"canvas_position_top":
  69398. result = startPoint;
  69399. break;
  69400. case"canvas_position_center":
  69401. case"canvas_position_middle":
  69402. result = startPoint + canvasOptions.canvasLength / 2;
  69403. break;
  69404. case"canvas_position_right":
  69405. case"canvas_position_bottom":
  69406. result = endPoint;
  69407. break;
  69408. case"canvas_position_start":
  69409. result = canvasOptions.invert ? endPoint : startPoint;
  69410. break;
  69411. case"canvas_position_end":
  69412. result = canvasOptions.invert ? startPoint : endPoint;
  69413. break
  69414. }
  69415. return result
  69416. },
  69417. _calculateProjection: function(distance) {
  69418. var canvasOptions = this._canvasOptions;
  69419. return canvasOptions.invert ? canvasOptions.endPoint - distance : canvasOptions.startPoint + distance
  69420. },
  69421. _calculateUnProjection: function(distance) {
  69422. var canvasOptions = this._canvasOptions;
  69423. return canvasOptions.invert ? canvasOptions.rangeMaxVisible.valueOf() - distance : canvasOptions.rangeMinVisible.valueOf() + distance
  69424. },
  69425. getVisibleCategories: function() {
  69426. return this.visibleCategories
  69427. },
  69428. getMinBarSize: function(minBarSize) {
  69429. var visibleArea = this.getCanvasVisibleArea(),
  69430. minValue = this.untranslate(visibleArea.min + minBarSize);
  69431. return _abs(this.untranslate(visibleArea.min) - (!isDefined(minValue) ? this.untranslate(visibleArea.max) : minValue))
  69432. },
  69433. translate: _noop,
  69434. untranslate: _noop,
  69435. getInterval: _noop,
  69436. zoom: _noop,
  69437. getMinScale: _noop
  69438. }
  69439. })(jQuery, DevExpress);
  69440. /*! Module viz-core, file polarTranslator.js */
  69441. (function($, DX, undefined) {
  69442. var utils = DX.utils,
  69443. SHIFT_ANGLE = 90,
  69444. _round = Math.round;
  69445. function PolarTranslator(businessRange, canvas, options) {
  69446. var that = this;
  69447. that._argCanvas = {
  69448. left: 0,
  69449. right: 0,
  69450. width: this._getAngle()
  69451. };
  69452. that._valCanvas = {
  69453. left: 0,
  69454. right: 0
  69455. };
  69456. that.canvas = canvas;
  69457. that._init();
  69458. that._arg = new DX.viz.core.Translator2D(businessRange.arg, that._argCanvas, {
  69459. direction: "horizontal",
  69460. conversionValue: true
  69461. });
  69462. that._val = new DX.viz.core.Translator2D(businessRange.val, that._valCanvas, {direction: "horizontal"});
  69463. that._businessRange = businessRange;
  69464. that.startAngle = utils.isNumber(options.startAngle) ? options.startAngle : 0
  69465. }
  69466. PolarTranslator.prototype = {
  69467. constructor: PolarTranslator,
  69468. _init: function() {
  69469. var canvas = this.canvas;
  69470. this._setCoords({
  69471. x: canvas.left + (canvas.width - canvas.right - canvas.left) / 2,
  69472. y: canvas.top + (canvas.height - canvas.top - canvas.bottom) / 2,
  69473. r: Math.min(canvas.width - canvas.left - canvas.right, canvas.height - canvas.top - canvas.bottom) / 2
  69474. });
  69475. this._valCanvas.width = this._rad
  69476. },
  69477. reinit: function() {
  69478. this._init();
  69479. this._arg.reinit();
  69480. this._val.reinit()
  69481. },
  69482. _setCoords: function(coord) {
  69483. this._x0 = coord.x;
  69484. this._y0 = coord.y;
  69485. this._rad = coord.r < 0 ? 0 : coord.r
  69486. },
  69487. getBusinessRange: function() {
  69488. return this._businessRange
  69489. },
  69490. translate: function(arg, val, offsets) {
  69491. var that = this,
  69492. argTranslate = that._arg.translate(arg, offsets && offsets[0]),
  69493. radius = that._val.translate(val, offsets && offsets[1]),
  69494. angle = utils.isDefined(argTranslate) ? argTranslate + that.startAngle - SHIFT_ANGLE : null,
  69495. cossin = utils.getCosAndSin(angle),
  69496. x,
  69497. y;
  69498. y = _round(that._y0 + radius * cossin.sin);
  69499. x = _round(that._x0 + radius * cossin.cos);
  69500. return {
  69501. x: x,
  69502. y: y,
  69503. angle: angle,
  69504. radius: radius
  69505. }
  69506. },
  69507. getValLength: function() {
  69508. return this._rad
  69509. },
  69510. getCenter: function() {
  69511. return {
  69512. x: this._x0,
  69513. y: this._y0
  69514. }
  69515. },
  69516. getBaseAngle: function() {
  69517. return this.startAngle - SHIFT_ANGLE
  69518. },
  69519. getInterval: function() {
  69520. return this._arg.getInterval()
  69521. },
  69522. getValInterval: function() {
  69523. return this._val.getInterval()
  69524. },
  69525. _getAngle: function() {
  69526. return 360
  69527. },
  69528. getStartAngle: function() {
  69529. return this.startAngle
  69530. },
  69531. getComponent: function(type) {
  69532. var that = this,
  69533. translator = this["_" + type];
  69534. translator.getRadius = function() {
  69535. return that.getValLength()
  69536. };
  69537. translator.getCenter = function() {
  69538. return that.getCenter()
  69539. };
  69540. translator.getStartAngle = function() {
  69541. return that.getStartAngle()
  69542. };
  69543. return translator
  69544. },
  69545. _untranslate: function(x, y) {
  69546. var radius = utils.getDistance(this._x0, this._y0, x, y),
  69547. angle = Math.atan2(y - this._y0, x - this._x0);
  69548. return {
  69549. r: radius,
  69550. phi: angle
  69551. }
  69552. },
  69553. untranslate: function(x, y) {
  69554. var pos = this._untranslate(x, y);
  69555. pos.phi = _round(utils.normalizeAngle(pos.phi * 180 / Math.PI));
  69556. pos.r = _round(pos.r);
  69557. return pos
  69558. },
  69559. getVisibleCategories: $.noop,
  69560. getCanvasVisibleArea: function() {
  69561. return {}
  69562. },
  69563. getMinBarSize: function(minBarSize) {
  69564. return this._val.getMinBarSize(minBarSize)
  69565. }
  69566. };
  69567. DX.viz.core.PolarTranslator = PolarTranslator
  69568. })(jQuery, DevExpress);
  69569. /*! Module viz-core, file rectangle.js */
  69570. (function(DX, undefined) {
  69571. var isFinite = window.isFinite;
  69572. DX.viz.core.Rectangle = DX.Class.inherit({
  69573. ctor: function(options) {
  69574. var that = this;
  69575. options = options || {};
  69576. that.left = Number(options.left) || 0;
  69577. that.right = Number(options.right) || 0;
  69578. that.top = Number(options.top) || 0;
  69579. that.bottom = Number(options.bottom) || 0
  69580. },
  69581. width: function() {
  69582. return this.right - this.left
  69583. },
  69584. height: function() {
  69585. return this.bottom - this.top
  69586. },
  69587. horizontalMiddle: function() {
  69588. return (this.left + this.right) / 2
  69589. },
  69590. verticalMiddle: function() {
  69591. return (this.top + this.bottom) / 2
  69592. },
  69593. raw: function() {
  69594. var that = this;
  69595. return {
  69596. left: that.left,
  69597. top: that.top,
  69598. right: that.right,
  69599. bottom: that.bottom
  69600. }
  69601. },
  69602. clone: function() {
  69603. return new this.constructor(this.raw())
  69604. },
  69605. move: function(dx, dy) {
  69606. var result = this.clone();
  69607. if (isFinite(dx) && isFinite(dy)) {
  69608. result.left += Number(dx);
  69609. result.right += Number(dx);
  69610. result.top += Number(dy);
  69611. result.bottom += Number(dy)
  69612. }
  69613. return result
  69614. },
  69615. inflate: function(dx, dy) {
  69616. var result = this.clone();
  69617. if (isFinite(dx) && isFinite(dy)) {
  69618. result.left -= Number(dx);
  69619. result.right += Number(dx);
  69620. result.top -= Number(dy);
  69621. result.bottom += Number(dy)
  69622. }
  69623. return result
  69624. },
  69625. scale: function(factor) {
  69626. var that = this;
  69627. if (factor > 0)
  69628. return that.inflate(that.width() * (factor - 1) / 2, that.height() * (factor - 1) / 2);
  69629. return that.clone()
  69630. }
  69631. })
  69632. })(DevExpress);
  69633. /*! Module viz-core, file layoutElement.js */
  69634. (function($, DX, undefined) {
  69635. var core = DX.viz.core,
  69636. _round = Math.round;
  69637. var _splitPair = DX.utils.splitPair;
  69638. var defaultPosition = ["center", "center"],
  69639. defaultOffset = [0, 0];
  69640. var getAlignFactor = function(align) {
  69641. switch (align) {
  69642. case"center":
  69643. return 0.5;
  69644. case"right":
  69645. case"bottom":
  69646. return 1;
  69647. default:
  69648. return 0
  69649. }
  69650. };
  69651. function WrapperLayoutElement(renderElement, bbox) {
  69652. this._renderElement = renderElement;
  69653. this._cacheBBox = bbox
  69654. }
  69655. WrapperLayoutElement.prototype = {
  69656. position: function(options) {
  69657. var that = this,
  69658. ofBBox = options.of.getBBox ? options.of.getBBox() : options.of,
  69659. myBBox = this.getBBox(),
  69660. at = _splitPair(options.at) || defaultPosition,
  69661. my = _splitPair(options.my) || defaultPosition,
  69662. offset = _splitPair(options.offset) || defaultOffset,
  69663. shiftX = -getAlignFactor(my[0]) * myBBox.width + ofBBox.x - myBBox.x + getAlignFactor(at[0]) * ofBBox.width + parseInt(offset[0]),
  69664. shiftY = -getAlignFactor(my[1]) * myBBox.height + ofBBox.y - myBBox.y + getAlignFactor(at[1]) * ofBBox.height + parseInt(offset[1]);
  69665. that._renderElement.move(_round(shiftX), _round(shiftY))
  69666. },
  69667. getBBox: function() {
  69668. return this._cacheBBox || this._renderElement.getBBox()
  69669. },
  69670. draw: function(){}
  69671. };
  69672. core.WrapperLayoutElement = WrapperLayoutElement
  69673. })(jQuery, DevExpress);
  69674. /*! Module viz-core, file themes.js */
  69675. (function(DX, $, undefined) {
  69676. var themes = {},
  69677. themesMapping = {},
  69678. themesSchemeMapping = {},
  69679. _extend = $.extend,
  69680. _each = $.each,
  69681. currentThemeName = null,
  69682. nextCacheUid = 0,
  69683. widgetsCache = {};
  69684. function normalizeName(name) {
  69685. return name ? String(name).toLowerCase() : null
  69686. }
  69687. function findTheme(themeName) {
  69688. var name = normalizeName(themeName);
  69689. return themes[name] || themes[themesMapping[name] || currentThemeName]
  69690. }
  69691. function findThemeNameByName(name, scheme) {
  69692. return themesMapping[name + '.' + scheme] || themesSchemeMapping[name + '.' + scheme] || themesMapping[name]
  69693. }
  69694. function findThemeNameByPlatform(platform, version, scheme) {
  69695. return findThemeNameByName(platform + version, scheme) || findThemeNameByName(platform, scheme)
  69696. }
  69697. function currentTheme(themeName, colorScheme) {
  69698. if (!arguments.length)
  69699. return currentThemeName;
  69700. var scheme = normalizeName(colorScheme);
  69701. currentThemeName = (themeName && themeName.platform ? findThemeNameByPlatform(normalizeName(themeName.platform), themeName.version, scheme) : findThemeNameByName(normalizeName(themeName), scheme)) || currentThemeName;
  69702. return this
  69703. }
  69704. function getThemeInfo(themeName, splitter) {
  69705. var k = themeName.indexOf(splitter);
  69706. return k > 0 ? {
  69707. name: themeName.substring(0, k),
  69708. scheme: themeName.substring(k + 1)
  69709. } : null
  69710. }
  69711. function registerThemeName(themeName, targetThemeName) {
  69712. var themeInfo = getThemeInfo(themeName, '.') || getThemeInfo(themeName, '-') || {name: themeName},
  69713. name = themeInfo.name,
  69714. scheme = themeInfo.scheme;
  69715. if (scheme) {
  69716. themesMapping[name] = themesMapping[name] || targetThemeName;
  69717. themesMapping[name + '.' + scheme] = themesMapping[name + '-' + scheme] = targetThemeName
  69718. }
  69719. else
  69720. themesMapping[name] = targetThemeName
  69721. }
  69722. function registerTheme(theme, baseThemeName) {
  69723. var themeName = normalizeName(theme && theme.name);
  69724. if (themeName) {
  69725. registerThemeName(themeName, themeName);
  69726. themes[themeName] = _extend(true, {}, findTheme(baseThemeName), patchTheme(theme))
  69727. }
  69728. }
  69729. function registerThemeAlias(alias, theme) {
  69730. registerThemeName(normalizeName(alias), normalizeName(theme))
  69731. }
  69732. function registerThemeSchemeAlias(from, to) {
  69733. themesSchemeMapping[from] = to
  69734. }
  69735. function mergeScalar(target, field, source, sourceValue) {
  69736. var _value = source ? source[field] : sourceValue;
  69737. if (_value !== undefined && target[field] === undefined)
  69738. target[field] = _value
  69739. }
  69740. function mergeObject(target, field, source, sourceValue) {
  69741. var _value = source ? source[field] : sourceValue;
  69742. if (_value !== undefined)
  69743. target[field] = _extend(true, {}, _value, target[field])
  69744. }
  69745. function patchTheme(theme) {
  69746. theme = _extend(true, {
  69747. loadingIndicator: {font: {}},
  69748. legend: {
  69749. font: {},
  69750. border: {}
  69751. },
  69752. title: {font: {}},
  69753. tooltip: {font: {}},
  69754. "chart:common": {},
  69755. "chart:common:axis": {
  69756. grid: {},
  69757. minorGrid: {},
  69758. tick: {},
  69759. minorTick: {},
  69760. title: {font: {}},
  69761. label: {font: {}}
  69762. },
  69763. chart: {commonSeriesSettings: {candlestick: {}}},
  69764. pie: {},
  69765. polar: {},
  69766. gauge: {scale: {
  69767. majorTick: {},
  69768. minorTick: {},
  69769. label: {font: {}}
  69770. }},
  69771. barGauge: {},
  69772. map: {background: {}},
  69773. rangeSelector: {
  69774. scale: {label: {font: {}}},
  69775. chart: {}
  69776. },
  69777. sparkline: {},
  69778. bullet: {}
  69779. }, theme);
  69780. mergeScalar(theme.loadingIndicator, "backgroundColor", theme);
  69781. mergeScalar(theme.chart.commonSeriesSettings.candlestick, "innerColor", null, theme.backgroundColor);
  69782. mergeScalar(theme.map.background, "color", null, theme.backgroundColor);
  69783. mergeScalar(theme.title.font, "color", null, theme.primaryTitleColor);
  69784. mergeScalar(theme.legend.font, "color", null, theme.secondaryTitleColor);
  69785. mergeScalar(theme.legend.border, "color", null, theme.axisColor);
  69786. patchAxes(theme);
  69787. _each(["chart", "pie", "polar", "gauge", "barGauge", "map", "rangeSelector", "sparkline", "bullet"], function(_, section) {
  69788. mergeScalar(theme[section], "redrawOnResize", theme);
  69789. mergeScalar(theme[section], "containerBackgroundColor", null, theme.backgroundColor);
  69790. mergeObject(theme[section], "tooltip", theme)
  69791. });
  69792. _each(["chart", "pie", "polar", "gauge", "barGauge", "map", "rangeSelector"], function(_, section) {
  69793. mergeObject(theme[section], "loadingIndicator", theme);
  69794. mergeObject(theme[section], "legend", theme)
  69795. });
  69796. _each(["chart", "pie", "polar", "gauge", "barGauge"], function(_, section) {
  69797. mergeObject(theme[section], "title", theme)
  69798. });
  69799. _each(["gauge", "barGauge"], function(_, section) {
  69800. mergeObject(theme[section], "subtitle", null, theme.title)
  69801. });
  69802. _each(["chart", "pie", "polar"], function(_, section) {
  69803. mergeObject(theme, section, null, theme["chart:common"])
  69804. });
  69805. _each(["chart", "polar"], function(_, section) {
  69806. theme[section] = theme[section] || {};
  69807. mergeObject(theme[section], "commonAxisSettings", null, theme["chart:common:axis"])
  69808. });
  69809. mergeObject(theme.rangeSelector.chart, "commonSeriesSettings", theme.chart);
  69810. mergeObject(theme.rangeSelector.chart, "dataPrepareSettings", theme.chart);
  69811. mergeScalar(theme.map.legend, "backgroundColor", theme);
  69812. return theme
  69813. }
  69814. function patchAxes(theme) {
  69815. var commonAxisSettings = theme["chart:common:axis"],
  69816. colorFieldName = "color";
  69817. _each([commonAxisSettings, commonAxisSettings.grid, commonAxisSettings.minorGrid, commonAxisSettings.tick, commonAxisSettings.minorTick], function(_, obj) {
  69818. mergeScalar(obj, colorFieldName, null, theme.axisColor)
  69819. });
  69820. mergeScalar(commonAxisSettings.title.font, colorFieldName, null, theme.secondaryTitleColor);
  69821. mergeScalar(commonAxisSettings.label.font, colorFieldName, null, theme.axisLabelColor);
  69822. mergeScalar(theme.gauge.scale.label.font, colorFieldName, null, theme.axisLabelColor);
  69823. mergeScalar(theme.gauge.scale.majorTick, colorFieldName, null, theme.backgroundColor);
  69824. mergeScalar(theme.gauge.scale.minorTick, colorFieldName, null, theme.backgroundColor);
  69825. mergeScalar(theme.rangeSelector.scale.label.font, colorFieldName, null, theme.axisLabelColor)
  69826. }
  69827. function addCacheItem(target) {
  69828. var cacheUid = ++nextCacheUid;
  69829. target._cache = cacheUid;
  69830. widgetsCache[cacheUid] = target
  69831. }
  69832. function removeCacheItem(target) {
  69833. delete widgetsCache[target._cache]
  69834. }
  69835. function refreshAll() {
  69836. _each(widgetsCache, function() {
  69837. this.refresh()
  69838. });
  69839. return this
  69840. }
  69841. _extend(DX.viz.core, {
  69842. findTheme: findTheme,
  69843. currentTheme: currentTheme,
  69844. registerTheme: registerTheme,
  69845. registerThemeAlias: registerThemeAlias,
  69846. registerThemeSchemeAlias: registerThemeSchemeAlias,
  69847. refreshAll: refreshAll,
  69848. addCacheItem: addCacheItem,
  69849. removeCacheItem: removeCacheItem
  69850. });
  69851. _extend(DX.viz.core, {
  69852. themes: themes,
  69853. themesMapping: themesMapping,
  69854. themesSchemeMapping: themesSchemeMapping,
  69855. widgetsCache: widgetsCache
  69856. })
  69857. })(DevExpress, jQuery);
  69858. /*! Module viz-core, file palette.js */
  69859. (function(DX, $, undefined) {
  69860. var _String = window.String,
  69861. _floor = Math.floor,
  69862. _ceil = Math.ceil,
  69863. _Color = DX.Color,
  69864. _isArray = DX.utils.isArray,
  69865. _isString = DX.utils.isString,
  69866. _extend = $.extend;
  69867. var palettes = {
  69868. 'default': {
  69869. simpleSet: ['#5f8b95', '#ba4d51', '#af8a53', '#955f71', '#859666', '#7e688c'],
  69870. indicatingSet: ['#a3b97c', '#e1b676', '#ec7f83'],
  69871. gradientSet: ['#5f8b95', '#ba4d51']
  69872. },
  69873. 'harmony light': {
  69874. simpleSet: ['#fcb65e', '#679ec5', '#ad79ce', '#7abd5c', '#e18e92', '#b6d623', '#b7abea', '#85dbd5'],
  69875. indicatingSet: ['#b6d623', '#fcb65e', '#e18e92'],
  69876. gradientSet: ['#7abd5c', '#fcb65e']
  69877. },
  69878. 'soft pastel': {
  69879. simpleSet: ['#60a69f', '#78b6d9', '#6682bb', '#a37182', '#eeba69', '#90ba58', '#456c68', '#7565a4'],
  69880. indicatingSet: ['#90ba58', '#eeba69', '#a37182'],
  69881. gradientSet: ['#78b6d9', '#eeba69']
  69882. },
  69883. pastel: {
  69884. simpleSet: ['#bb7862', '#70b3a1', '#bb626a', '#057d85', '#ab394b', '#dac599', '#153459', '#b1d2c6'],
  69885. indicatingSet: ['#70b3a1', '#dac599', '#bb626a'],
  69886. gradientSet: ['#bb7862', '#70b3a1']
  69887. },
  69888. bright: {
  69889. simpleSet: ['#70c92f', '#f8ca00', '#bd1550', '#e97f02', '#9d419c', '#7e4452', '#9ab57e', '#36a3a6'],
  69890. indicatingSet: ['#70c92f', '#f8ca00', '#bd1550'],
  69891. gradientSet: ['#e97f02', '#f8ca00']
  69892. },
  69893. soft: {
  69894. simpleSet: ['#cbc87b', '#9ab57e', '#e55253', '#7e4452', '#e8c267', '#565077', '#6babac', '#ad6082'],
  69895. indicatingSet: ['#9ab57e', '#e8c267', '#e55253'],
  69896. gradientSet: ['#9ab57e', '#e8c267']
  69897. },
  69898. ocean: {
  69899. simpleSet: ['#75c099', '#acc371', '#378a8a', '#5fa26a', '#064970', '#38c5d2', '#00a7c6', '#6f84bb'],
  69900. indicatingSet: ['#c8e394', '#7bc59d', '#397c8b'],
  69901. gradientSet: ['#acc371', '#38c5d2']
  69902. },
  69903. vintage: {
  69904. simpleSet: ['#dea484', '#efc59c', '#cb715e', '#eb9692', '#a85c4c', '#f2c0b5', '#c96374', '#dd956c'],
  69905. indicatingSet: ['#ffe5c6', '#f4bb9d', '#e57660'],
  69906. gradientSet: ['#efc59c', '#cb715e']
  69907. },
  69908. violet: {
  69909. simpleSet: ['#d1a1d1', '#eeacc5', '#7b5685', '#7e7cad', '#a13d73', '#5b41ab', '#e287e2', '#689cc1'],
  69910. indicatingSet: ['#d8e2f6', '#d0b2da', '#d56a8a'],
  69911. gradientSet: ['#eeacc5', '#7b5685']
  69912. }
  69913. };
  69914. var currentPaletteName = 'default';
  69915. function currentPalette(name) {
  69916. if (name === undefined)
  69917. return currentPaletteName;
  69918. else {
  69919. name = String(name).toLowerCase();
  69920. currentPaletteName = name in palettes ? name : 'default'
  69921. }
  69922. }
  69923. function getPalette(palette, parameters) {
  69924. var result;
  69925. if (_isArray(palette))
  69926. result = palette;
  69927. else {
  69928. parameters = parameters || {};
  69929. var type = parameters.type || 'simpleSet';
  69930. if (_isString(palette)) {
  69931. var name = palette.toLowerCase(),
  69932. baseContainer = palettes[name],
  69933. themedContainer = parameters.theme && palettes[name + '_' + _String(parameters.theme).toLowerCase()];
  69934. result = themedContainer && themedContainer[type] || baseContainer && baseContainer[type]
  69935. }
  69936. if (!result)
  69937. result = palettes[currentPaletteName][type]
  69938. }
  69939. return result ? result.slice(0) : null
  69940. }
  69941. function registerPalette(name, palette, theme) {
  69942. var item = {};
  69943. if (_isArray(palette))
  69944. item.simpleSet = palette.slice(0);
  69945. else if (palette) {
  69946. item.simpleSet = _isArray(palette.simpleSet) ? palette.simpleSet.slice(0) : undefined;
  69947. item.indicatingSet = _isArray(palette.indicatingSet) ? palette.indicatingSet.slice(0) : undefined;
  69948. item.gradientSet = _isArray(palette.gradientSet) ? palette.gradientSet.slice(0) : undefined
  69949. }
  69950. if (item.simpleSet || item.indicatingSet || item.gradientSet) {
  69951. var paletteName = _String(name).toLowerCase();
  69952. if (theme)
  69953. paletteName = paletteName + '_' + _String(theme).toLowerCase();
  69954. _extend(palettes[paletteName] = palettes[paletteName] || {}, item)
  69955. }
  69956. }
  69957. function RingBuf(buf) {
  69958. var ind = 0;
  69959. this.next = function() {
  69960. var res = buf[ind++];
  69961. if (ind === buf.length)
  69962. this.reset();
  69963. return res
  69964. };
  69965. this.reset = function() {
  69966. ind = 0
  69967. }
  69968. }
  69969. function Palette(palette, parameters) {
  69970. parameters = parameters || {};
  69971. this._originalPalette = getPalette(palette, parameters);
  69972. var stepHighlight = parameters ? parameters.stepHighlight || 0 : 0;
  69973. this._paletteSteps = new RingBuf([0, stepHighlight, -stepHighlight]);
  69974. this._resetPalette()
  69975. }
  69976. _extend(Palette.prototype, {
  69977. dispose: function() {
  69978. this._originalPalette = this._palette = this._paletteSteps = null;
  69979. return this
  69980. },
  69981. getNextColor: function() {
  69982. var that = this;
  69983. if (that._currentColor >= that._palette.length)
  69984. that._resetPalette();
  69985. return that._palette[that._currentColor++]
  69986. },
  69987. _resetPalette: function() {
  69988. var that = this;
  69989. that._currentColor = 0;
  69990. var step = that._paletteSteps.next(),
  69991. originalPalette = that._originalPalette;
  69992. if (step) {
  69993. var palette = that._palette = [],
  69994. i = 0,
  69995. ii = originalPalette.length;
  69996. for (; i < ii; ++i)
  69997. palette[i] = getNewColor(originalPalette[i], step)
  69998. }
  69999. else
  70000. that._palette = originalPalette.slice(0)
  70001. },
  70002. reset: function() {
  70003. this._paletteSteps.reset();
  70004. this._resetPalette();
  70005. return this
  70006. }
  70007. });
  70008. function getNewColor(currentColor, step) {
  70009. var newColor = new _Color(currentColor).alter(step),
  70010. lightness = getLightness(newColor);
  70011. if (lightness > 200 || lightness < 55)
  70012. newColor = new _Color(currentColor).alter(-step / 2);
  70013. return newColor.toHex()
  70014. }
  70015. function getLightness(color) {
  70016. return color.r * 0.3 + color.g * 0.59 + color.b * 0.11
  70017. }
  70018. function GradientPalette(source, size) {
  70019. var palette = getPalette(source, {type: 'gradientSet'});
  70020. palette = size > 0 ? createGradientColors(palette, size) : [];
  70021. this.getColor = function(index) {
  70022. return palette[index] || null
  70023. };
  70024. this._DEBUG_source = source;
  70025. this._DEBUG_size = size
  70026. }
  70027. function createGradientColors(source, count) {
  70028. var ncolors = count - 1,
  70029. nsource = source.length - 1,
  70030. colors = [],
  70031. gradient = [],
  70032. i;
  70033. for (i = 0; i <= nsource; ++i)
  70034. colors.push(new _Color(source[i]));
  70035. if (ncolors > 0)
  70036. for (i = 0; i <= ncolors; ++i)
  70037. addColor(i / ncolors);
  70038. else
  70039. addColor(0.5);
  70040. return gradient;
  70041. function addColor(pos) {
  70042. var k = nsource * pos,
  70043. kl = _floor(k),
  70044. kr = _ceil(k);
  70045. gradient.push(colors[kl].blend(colors[kr], k - kl).toHex())
  70046. }
  70047. }
  70048. _extend(DX.viz.core, {
  70049. registerPalette: registerPalette,
  70050. getPalette: getPalette,
  70051. Palette: Palette,
  70052. GradientPalette: GradientPalette,
  70053. currentPalette: currentPalette
  70054. });
  70055. DX.viz.core._DEBUG_palettes = palettes
  70056. })(DevExpress, jQuery);
  70057. /*! Module viz-core, file utils.js */
  70058. (function(DX, $, undefined) {
  70059. var _ceil = Math.ceil,
  70060. _min = Math.min,
  70061. _round = Math.round;
  70062. function selectByKeys(object, keys) {
  70063. return $.map(keys, function(key) {
  70064. return object[key] ? object[key] : null
  70065. })
  70066. }
  70067. function decreaseFields(object, keys, eachDecrease, decrease) {
  70068. var dec = decrease;
  70069. $.each(keys, function(_, key) {
  70070. if (object[key]) {
  70071. object[key] -= eachDecrease;
  70072. dec -= eachDecrease
  70073. }
  70074. });
  70075. return dec
  70076. }
  70077. DX.viz.core.utils = {
  70078. decreaseGaps: function(object, keys, decrease) {
  70079. var arrayGaps;
  70080. do {
  70081. arrayGaps = selectByKeys(object, keys);
  70082. arrayGaps.push(_ceil(decrease / arrayGaps.length));
  70083. decrease = decreaseFields(object, keys, _min.apply(null, arrayGaps), decrease)
  70084. } while (decrease > 0 && arrayGaps.length > 1);
  70085. return decrease
  70086. },
  70087. parseScalar: function(value, defaultValue) {
  70088. return value !== undefined ? value : defaultValue
  70089. },
  70090. enumParser: function(values) {
  70091. var stored = {},
  70092. i,
  70093. ii;
  70094. for (i = 0, ii = values.length; i < ii; ++i)
  70095. stored[String(values[i]).toLowerCase()] = 1;
  70096. return function(value, defaultValue) {
  70097. var _value = String(value).toLowerCase();
  70098. return stored[_value] ? _value : defaultValue
  70099. }
  70100. },
  70101. patchFontOptions: function(options) {
  70102. var fontOptions = {};
  70103. $.each(options || {}, function(key, value) {
  70104. if (/^(cursor|opacity)$/i.test(key));
  70105. else if (key === "color")
  70106. key = "fill";
  70107. else
  70108. key = "font-" + key;
  70109. fontOptions[key] = value
  70110. });
  70111. return fontOptions
  70112. },
  70113. convertPolarToXY: function(centerCoords, startAngle, angle, radius) {
  70114. var shiftAngle = 90,
  70115. cossin;
  70116. angle = DX.utils.isDefined(angle) ? angle + startAngle - shiftAngle : 0;
  70117. cossin = DX.utils.getCosAndSin(angle);
  70118. return {
  70119. x: _round(centerCoords.x + radius * cossin.cos),
  70120. y: _round(centerCoords.y + radius * cossin.sin)
  70121. }
  70122. },
  70123. convertXYToPolar: function(centerCoords, x, y) {
  70124. var radius = DX.utils.getDistance(centerCoords.x, centerCoords.y, x, y),
  70125. angle = Math.atan2(y - centerCoords.y, x - centerCoords.x);
  70126. return {
  70127. phi: _round(DX.utils.normalizeAngle(angle * 180 / Math.PI)),
  70128. r: _round(radius)
  70129. }
  70130. }
  70131. }
  70132. })(DevExpress, jQuery);
  70133. /*! Module viz-core, file baseThemeManager.js */
  70134. (function(DX, $, undefined) {
  70135. var _isString = DX.utils.isString,
  70136. _parseScalar = DX.viz.core.utils.parseScalar,
  70137. _findTheme = DX.viz.core.findTheme,
  70138. _addCacheItem = DX.viz.core.addCacheItem,
  70139. _removeCacheItem = DX.viz.core.removeCacheItem,
  70140. _extend = $.extend,
  70141. _each = $.each;
  70142. function getThemePart(theme, path) {
  70143. var _theme = theme;
  70144. path && _each(path.split('.'), function(_, pathItem) {
  70145. return _theme = _theme[pathItem]
  70146. });
  70147. return _theme
  70148. }
  70149. DX.viz.core.BaseThemeManager = DX.Class.inherit({
  70150. ctor: function() {
  70151. _addCacheItem(this)
  70152. },
  70153. dispose: function() {
  70154. var that = this;
  70155. _removeCacheItem(that);
  70156. that._callback = that._theme = that._font = null;
  70157. return that
  70158. },
  70159. setCallback: function(callback) {
  70160. this._callback = callback;
  70161. return this
  70162. },
  70163. setTheme: function(theme, rtl) {
  70164. this._current = theme;
  70165. this._rtl = rtl;
  70166. return this.refresh()
  70167. },
  70168. refresh: function() {
  70169. var that = this,
  70170. current = that._current || {},
  70171. theme = _findTheme(current.name || current);
  70172. that._themeName = theme.name;
  70173. that._font = _extend({}, theme.font, current.font);
  70174. that._themeSection && _each(that._themeSection.split('.'), function(_, path) {
  70175. theme = _extend(true, {}, theme[path], that._IE8 ? theme[path + 'IE8'] : {})
  70176. });
  70177. that._theme = _extend(true, {}, theme, _isString(current) ? {} : current);
  70178. that._initializeTheme();
  70179. if (_parseScalar(that._rtl, that._theme.rtlEnabled))
  70180. _extend(true, that._theme, that._theme._rtl);
  70181. that._callback();
  70182. return that
  70183. },
  70184. theme: function(path) {
  70185. return getThemePart(this._theme, path)
  70186. },
  70187. themeName: function() {
  70188. return this._themeName
  70189. },
  70190. _initializeTheme: function() {
  70191. var that = this;
  70192. _each(that._fontFields || [], function(_, path) {
  70193. that._initializeFont(getThemePart(that._theme, path))
  70194. })
  70195. },
  70196. _initializeFont: function(font) {
  70197. _extend(font, this._font, _extend({}, font))
  70198. }
  70199. })
  70200. })(DevExpress, jQuery);
  70201. /*! Module viz-core, file parseUtils.js */
  70202. (function($, DX) {
  70203. var viz = DX.viz,
  70204. core = viz.core,
  70205. Class = DX.Class,
  70206. isDefined = DX.utils.isDefined;
  70207. var parseUtils = Class.inherit({
  70208. correctValueType: function(type) {
  70209. return type === 'numeric' || type === 'datetime' || type === 'string' ? type : ''
  70210. },
  70211. _parsers: {
  70212. string: function(val) {
  70213. return isDefined(val) ? '' + val : val
  70214. },
  70215. numeric: function(val) {
  70216. if (!isDefined(val))
  70217. return val;
  70218. var parsedVal = Number(val);
  70219. if (isNaN(parsedVal))
  70220. parsedVal = undefined;
  70221. return parsedVal
  70222. },
  70223. datetime: function(val) {
  70224. if (!isDefined(val))
  70225. return val;
  70226. var parsedVal,
  70227. numVal = Number(val);
  70228. if (!isNaN(numVal))
  70229. parsedVal = new Date(numVal);
  70230. else
  70231. parsedVal = new Date(val);
  70232. if (isNaN(Number(parsedVal)))
  70233. parsedVal = undefined;
  70234. return parsedVal
  70235. }
  70236. },
  70237. getParser: function(valueType) {
  70238. return this._parsers[this.correctValueType(valueType)] || $.noop
  70239. }
  70240. });
  70241. core.ParseUtils = parseUtils
  70242. })(jQuery, DevExpress);
  70243. /*! Module viz-core, file loadIndicator.js */
  70244. (function(DX, $, undefined) {
  70245. var _patchFontOptions = DX.viz.core.utils.patchFontOptions;
  70246. var STATE_HIDE = 0,
  70247. STATE_SHOW = 1,
  70248. STATE_ENDLOADING = 2;
  70249. function LoadIndicator(parameters) {
  70250. var that = this;
  70251. that._$widgetContainer = parameters.container;
  70252. that._$container = $("<div>", {css: {
  70253. position: "relative",
  70254. height: 0,
  70255. padding: 0,
  70256. margin: 0,
  70257. border: 0
  70258. }}).appendTo(that._$widgetContainer).hide();
  70259. that._renderer = new DX.viz.renderers.Renderer({animation: {
  70260. easing: "linear",
  70261. duration: 150
  70262. }});
  70263. that._renderer.draw(that._$container[0]);
  70264. that._rect = that._renderer.rect().attr({opacity: 0}).append(that._renderer.root);
  70265. that._text = that._renderer.text().attr({
  70266. align: "center",
  70267. visibility: "hidden"
  70268. }).append(that._renderer.root);
  70269. that._createStates(parameters.eventTrigger)
  70270. }
  70271. LoadIndicator.prototype = {
  70272. constructor: LoadIndicator,
  70273. _createStates: function(eventTrigger) {
  70274. var that = this;
  70275. that._states = {};
  70276. that._states[STATE_HIDE] = {
  70277. o: 0,
  70278. c: function() {
  70279. that._$container.hide();
  70280. eventTrigger("loadingIndicatorReady")
  70281. }
  70282. };
  70283. that._states[STATE_SHOW] = {
  70284. o: 0.85,
  70285. c: function() {
  70286. eventTrigger("loadingIndicatorReady")
  70287. }
  70288. };
  70289. that._states[STATE_ENDLOADING] = {
  70290. o: 1,
  70291. c: function() {
  70292. var onEndLoading = that._onEndLoading;
  70293. that._onEndLoading = null;
  70294. that._noHiding = true;
  70295. onEndLoading && onEndLoading();
  70296. that._noHiding = false;
  70297. that._onCompleteAction && that[that._onCompleteAction]()
  70298. }
  70299. }
  70300. },
  70301. applyCanvas: function(canvas) {
  70302. var width = canvas.width,
  70303. height = canvas.height;
  70304. this._renderer.resize(width, height);
  70305. this._rect.attr({
  70306. width: width,
  70307. height: height
  70308. });
  70309. this._text.attr({
  70310. x: width / 2,
  70311. y: height / 2
  70312. })
  70313. },
  70314. applyOptions: function(options) {
  70315. this._rect.attr({fill: options.backgroundColor});
  70316. this._text.css(_patchFontOptions(options.font)).attr({text: options.text})
  70317. },
  70318. dispose: function() {
  70319. var that = this;
  70320. that._$container.remove();
  70321. that._renderer.dispose();
  70322. that._$widgetContainer = that._$container = that._renderer = that._rect = that._text = that._states = null
  70323. },
  70324. toForeground: function() {
  70325. this._$container.appendTo(this._$widgetContainer)
  70326. },
  70327. forceShow: function() {
  70328. this._rect.stopAnimation(false).attr({opacity: 1})
  70329. },
  70330. _transit: function(stateId) {
  70331. var state = this._states[stateId];
  70332. this._rect.stopAnimation(true).animate({opacity: state.o}, {complete: state.c})
  70333. },
  70334. show: function() {
  70335. var that = this;
  70336. that._isHiding = false;
  70337. if (that._onEndLoading)
  70338. that._onCompleteAction = "show";
  70339. else {
  70340. that._onCompleteAction = null;
  70341. if (!that._visible) {
  70342. that._visible = true;
  70343. that._$container.show();
  70344. that._renderer.root.css({
  70345. position: "absolute",
  70346. left: 0,
  70347. top: that._$widgetContainer.offset().top - that._$container.offset().top
  70348. });
  70349. that._text.attr({visibility: "visible"})
  70350. }
  70351. that._transit(STATE_SHOW)
  70352. }
  70353. },
  70354. endLoading: function(complete) {
  70355. var that = this;
  70356. if (!that._onEndLoading)
  70357. if (that._visible) {
  70358. that._onEndLoading = complete;
  70359. that._transit(STATE_ENDLOADING)
  70360. }
  70361. else
  70362. complete && complete()
  70363. },
  70364. hide: function() {
  70365. var that = this;
  70366. that._isHiding = false;
  70367. if (that._onEndLoading)
  70368. that._onCompleteAction = "hide";
  70369. else {
  70370. that._onCompleteAction = null;
  70371. if (that._visible) {
  70372. that._visible = false;
  70373. that._text.attr({visibility: "hidden"});
  70374. that._transit(STATE_HIDE)
  70375. }
  70376. }
  70377. },
  70378. scheduleHiding: function() {
  70379. if (!this._noHiding) {
  70380. this._isHiding = true;
  70381. this._onCompleteAction = null
  70382. }
  70383. },
  70384. fulfillHiding: function() {
  70385. var isHiding = this._isHiding;
  70386. isHiding && this.hide();
  70387. return isHiding
  70388. }
  70389. };
  70390. DX.viz.core.LoadIndicator = LoadIndicator
  70391. })(DevExpress, jQuery);
  70392. /*! Module viz-core, file tooltip.js */
  70393. (function(DX, $, doc, undefined) {
  70394. var HALF_ARROW_WIDTH = 10,
  70395. FORMAT_PRECISION = {
  70396. argument: ["argumentFormat", "argumentPrecision"],
  70397. percent: ["percent", "percentPrecision"],
  70398. value: ["format", "precision"]
  70399. },
  70400. formatHelper = DX.formatHelper,
  70401. mathCeil = Math.ceil;
  70402. function hideElement($element) {
  70403. $element.css({left: "-9999px"}).detach()
  70404. }
  70405. function Tooltip(params) {
  70406. var that = this,
  70407. renderer,
  70408. root;
  70409. that._eventTrigger = params.eventTrigger;
  70410. that._wrapper = $("<div></div>").css({
  70411. position: "absolute",
  70412. overflow: "visible",
  70413. width: 0,
  70414. height: 0
  70415. }).addClass(params.cssClass);
  70416. that._renderer = renderer = new DX.viz.renderers.Renderer({});
  70417. root = renderer.root;
  70418. root.attr({"pointer-events": "none"});
  70419. renderer.draw(that._wrapper.get(0));
  70420. that._cloud = renderer.path([], "area").sharp().append(root);
  70421. that._shadow = renderer.shadowFilter();
  70422. that._textGroup = renderer.g().attr({align: "center"}).append(root);
  70423. that._text = renderer.text(undefined, 0, 0).append(that._textGroup);
  70424. that._textGroupHtml = $("<div></div>").css({
  70425. position: "absolute",
  70426. width: 0,
  70427. padding: 0,
  70428. margin: 0,
  70429. border: "0px solid transparent"
  70430. }).appendTo(that._wrapper);
  70431. that._textHtml = $("<div></div>").css({
  70432. position: "relative",
  70433. display: "inline-block",
  70434. padding: 0,
  70435. margin: 0,
  70436. border: "0px solid transparent"
  70437. }).appendTo(that._textGroupHtml)
  70438. }
  70439. Tooltip.prototype = {
  70440. constructor: Tooltip,
  70441. dispose: function() {
  70442. this._wrapper.remove();
  70443. this._renderer.dispose();
  70444. this._options = null
  70445. },
  70446. setOptions: function(options) {
  70447. options = options || {};
  70448. var that = this,
  70449. cloudSettings = that._cloudSettigns = {
  70450. opacity: options.opacity,
  70451. filter: that._shadow.ref,
  70452. "stroke-width": null,
  70453. stroke: null
  70454. },
  70455. borderOptions = options.border || {};
  70456. that._shadowSettigns = $.extend({
  70457. x: "-50%",
  70458. y: "-50%",
  70459. width: "200%",
  70460. height: "200%"
  70461. }, options.shadow);
  70462. that._options = options;
  70463. if (borderOptions.visible)
  70464. $.extend(cloudSettings, {
  70465. "stroke-width": borderOptions.width,
  70466. stroke: borderOptions.color,
  70467. "stroke-opacity": borderOptions.opacity,
  70468. dashStyle: borderOptions.dashStyle
  70469. });
  70470. that._textFontStyles = DX.viz.core.utils.patchFontOptions(options.font);
  70471. that._textFontStyles.color = options.font.color;
  70472. that._wrapper.css({"z-index": options.zIndex});
  70473. that._customizeTooltip = $.isFunction(options.customizeTooltip) ? options.customizeTooltip : null;
  70474. return that
  70475. },
  70476. setRendererOptions: function(options) {
  70477. this._renderer.setOptions(options);
  70478. this._textGroupHtml.css({direction: options.rtl ? "rtl" : "ltr"});
  70479. return this
  70480. },
  70481. render: function() {
  70482. var that = this;
  70483. hideElement(that._wrapper);
  70484. that._cloud.attr(that._cloudSettigns);
  70485. that._shadow.attr(that._shadowSettigns);
  70486. that._textGroupHtml.css(that._textFontStyles);
  70487. that._textGroup.css(that._textFontStyles);
  70488. that._text.css(that._textFontStyles);
  70489. that._eventData = null;
  70490. return that
  70491. },
  70492. update: function(options) {
  70493. return this.setOptions(options).render()
  70494. },
  70495. _prepare: function(formatObject, state) {
  70496. var options = this._options,
  70497. customize = {};
  70498. if (this._customizeTooltip) {
  70499. customize = this._customizeTooltip.call(formatObject, formatObject);
  70500. customize = $.isPlainObject(customize) ? customize : {};
  70501. if ("text" in customize)
  70502. state.text = DX.utils.isDefined(customize.text) ? String(customize.text) : "";
  70503. if ("html" in customize)
  70504. state.html = DX.utils.isDefined(customize.html) ? String(customize.html) : ""
  70505. }
  70506. if (!("text" in state) && !("html" in state))
  70507. state.text = formatObject.valueText || "";
  70508. state.color = customize.color || options.color;
  70509. state.borderColor = customize.borderColor || (options.border || {}).color;
  70510. state.textColor = customize.fontColor || (options.font || {}).color;
  70511. return !!state.text || !!state.html
  70512. },
  70513. show: function(formatObject, params, eventData) {
  70514. var that = this,
  70515. state = {},
  70516. options = that._options,
  70517. plr = options.paddingLeftRight,
  70518. ptb = options.paddingTopBottom,
  70519. textGroupHtml = that._textGroupHtml,
  70520. textHtml = that._textHtml,
  70521. bBox,
  70522. contentSize,
  70523. ss = that._shadowSettigns,
  70524. xOff = ss.offsetX,
  70525. yOff = ss.offsetY,
  70526. blur = ss.blur * 2 + 1;
  70527. if (!that._prepare(formatObject, state))
  70528. return false;
  70529. that._state = state;
  70530. state.tc = {};
  70531. that._wrapper.appendTo($("body"));
  70532. that._cloud.attr({
  70533. fill: state.color,
  70534. stroke: state.borderColor
  70535. });
  70536. if (state.html) {
  70537. that._text.attr({text: ""});
  70538. textGroupHtml.css({
  70539. color: state.textColor,
  70540. width: that._getCanvas().width
  70541. });
  70542. textHtml.html(state.html);
  70543. bBox = textHtml.get(0).getBoundingClientRect();
  70544. bBox = {
  70545. x: 0,
  70546. y: 0,
  70547. width: mathCeil(bBox.right - bBox.left),
  70548. height: mathCeil(bBox.bottom - bBox.top)
  70549. };
  70550. textGroupHtml.width(bBox.width);
  70551. textGroupHtml.height(bBox.height)
  70552. }
  70553. else {
  70554. textHtml.html("");
  70555. that._text.css({fill: state.textColor}).attr({text: state.text});
  70556. bBox = that._textGroup.css({fill: state.textColor}).getBBox()
  70557. }
  70558. contentSize = state.contentSize = {
  70559. x: bBox.x - plr,
  70560. y: bBox.y - ptb,
  70561. width: bBox.width + 2 * plr,
  70562. height: bBox.height + 2 * ptb,
  70563. lm: blur - xOff > 0 ? blur - xOff : 0,
  70564. rm: blur + xOff > 0 ? blur + xOff : 0,
  70565. tm: blur - yOff > 0 ? blur - yOff : 0,
  70566. bm: blur + yOff > 0 ? blur + yOff : 0
  70567. };
  70568. contentSize.fullWidth = contentSize.width + contentSize.lm + contentSize.rm;
  70569. contentSize.fullHeight = contentSize.height + contentSize.tm + contentSize.bm + options.arrowLength;
  70570. that.move(params.x, params.y, params.offset);
  70571. that._eventData && that._eventTrigger("tooltipHidden", that._eventData);
  70572. that._eventData = eventData;
  70573. that._eventTrigger("tooltipShown", that._eventData);
  70574. return true
  70575. },
  70576. hide: function() {
  70577. var that = this;
  70578. hideElement(that._wrapper);
  70579. that._eventData && that._eventTrigger("tooltipHidden", that._eventData);
  70580. that._eventData = null
  70581. },
  70582. move: function(x, y, offset) {
  70583. offset = offset || 0;
  70584. var that = this,
  70585. canvas = that._getCanvas(),
  70586. state = that._state,
  70587. coords = state.tc,
  70588. contentSize = state.contentSize;
  70589. if (that._calculatePosition(x, y, offset)) {
  70590. that._cloud.attr({points: coords.cloudPoints}).move(contentSize.lm, contentSize.tm);
  70591. if (state.html)
  70592. that._textGroupHtml.css({
  70593. left: -contentSize.x + contentSize.lm,
  70594. top: -contentSize.y + contentSize.tm + coords.correction
  70595. });
  70596. else
  70597. that._textGroup.move(-contentSize.x + contentSize.lm, -contentSize.y + contentSize.tm + coords.correction);
  70598. that._renderer.resize(coords.hp === "out" ? canvas.fullWidth - canvas.left : contentSize.fullWidth, coords.vp === "out" ? canvas.fullHeight - canvas.top : contentSize.fullHeight)
  70599. }
  70600. that._wrapper.css({
  70601. left: coords.x,
  70602. top: coords.y
  70603. })
  70604. },
  70605. formatValue: function(value, specialFormat) {
  70606. var formatObj = FORMAT_PRECISION[specialFormat || "value"],
  70607. format = formatObj[0] in this._options ? this._options[formatObj[0]] : specialFormat;
  70608. return formatHelper.format(value, format, this._options[formatObj[1]] || 0)
  70609. },
  70610. getLocation: function() {
  70611. return (this._options.location + "").toLowerCase()
  70612. },
  70613. isEnabled: function() {
  70614. return !!this._options.enabled
  70615. },
  70616. isShared: function() {
  70617. return !!this._options.shared
  70618. },
  70619. _calculatePosition: function(x, y, offset) {
  70620. var that = this,
  70621. canvas = that._getCanvas(),
  70622. options = that._options,
  70623. arrowLength = options.arrowLength,
  70624. state = that._state,
  70625. coords = state.tc,
  70626. contentSize = state.contentSize,
  70627. contentWidth = contentSize.width,
  70628. halfContentWidth = contentWidth / 2,
  70629. contentHeight = contentSize.height,
  70630. cTop = y - canvas.top,
  70631. cBottom = canvas.top + canvas.height - y,
  70632. cLeft = x - canvas.left,
  70633. cRight = canvas.width + canvas.left - x,
  70634. tTop = contentHeight + arrowLength + offset + contentSize.tm,
  70635. tBottom = contentHeight + arrowLength + offset + contentSize.bm,
  70636. tLeft = contentWidth + contentSize.lm,
  70637. tRight = contentWidth + contentSize.rm,
  70638. tHalfLeft = halfContentWidth + contentSize.lm,
  70639. tHalfRight = halfContentWidth + contentSize.rm,
  70640. correction = 0,
  70641. cloudPoints,
  70642. arrowPoints = [6, 0],
  70643. x1 = halfContentWidth + HALF_ARROW_WIDTH,
  70644. x2 = halfContentWidth,
  70645. x3 = halfContentWidth - HALF_ARROW_WIDTH,
  70646. y1,
  70647. y3,
  70648. y2 = contentHeight + arrowLength,
  70649. hp = "center",
  70650. vp = "bottom",
  70651. hasDeprecatedPosition;
  70652. y1 = y3 = contentHeight;
  70653. switch (options.verticalAlignment) {
  70654. case"top":
  70655. vp = "bottom";
  70656. hasDeprecatedPosition = true;
  70657. break;
  70658. case"bottom":
  70659. vp = "top";
  70660. hasDeprecatedPosition = true;
  70661. break
  70662. }
  70663. if (!hasDeprecatedPosition)
  70664. if (tTop > cTop && tBottom > cBottom)
  70665. vp = "out";
  70666. else if (tTop > cTop)
  70667. vp = "top";
  70668. hasDeprecatedPosition = false;
  70669. switch (options.horizontalAlignment) {
  70670. case"left":
  70671. hp = "right";
  70672. hasDeprecatedPosition = true;
  70673. break;
  70674. case"center":
  70675. hp = "center";
  70676. hasDeprecatedPosition = true;
  70677. break;
  70678. case"right":
  70679. hp = "left";
  70680. hasDeprecatedPosition = true;
  70681. break
  70682. }
  70683. if (!hasDeprecatedPosition)
  70684. if (tLeft > cLeft && tRight > cRight)
  70685. hp = "out";
  70686. else if (tHalfLeft > cLeft && tRight < cRight)
  70687. hp = "left";
  70688. else if (tHalfRight > cRight && tLeft < cLeft)
  70689. hp = "right";
  70690. if (hp === "out")
  70691. x = canvas.left;
  70692. else if (hp === "left") {
  70693. x1 = HALF_ARROW_WIDTH;
  70694. x2 = x3 = 0
  70695. }
  70696. else if (hp === "right") {
  70697. x1 = x2 = contentWidth;
  70698. x3 = contentWidth - HALF_ARROW_WIDTH;
  70699. x = x - contentWidth
  70700. }
  70701. else if (hp === "center")
  70702. x = x - halfContentWidth;
  70703. if (vp === "out")
  70704. y = canvas.top;
  70705. else if (vp === "top") {
  70706. hp !== "out" && (correction = arrowLength);
  70707. arrowPoints[0] = 2;
  70708. y1 = y3 = arrowLength;
  70709. y2 = x1;
  70710. x1 = x3;
  70711. x3 = y2;
  70712. y2 = 0;
  70713. y = y + offset
  70714. }
  70715. else
  70716. y = y - (contentHeight + arrowLength + offset);
  70717. coords.x = x - contentSize.lm;
  70718. coords.y = y - contentSize.tm;
  70719. coords.correction = correction;
  70720. if (hp === coords.hp && vp === coords.vp)
  70721. return false;
  70722. coords.hp = hp;
  70723. coords.vp = vp;
  70724. cloudPoints = [0, 0 + correction, contentWidth, 0 + correction, contentWidth, contentHeight + correction, 0, contentHeight + correction];
  70725. if (hp !== "out" && vp !== "out") {
  70726. arrowPoints.splice(2, 0, x1, y1, x2, y2, x3, y3);
  70727. cloudPoints.splice.apply(cloudPoints, arrowPoints)
  70728. }
  70729. coords.cloudPoints = cloudPoints;
  70730. return true
  70731. },
  70732. _getCanvas: function() {
  70733. var html = doc.documentElement,
  70734. body = doc.body,
  70735. win = window;
  70736. return {
  70737. left: win.pageXOffset || html.scrollLeft || 0,
  70738. top: win.pageYOffset || html.scrollTop || 0,
  70739. width: html.clientWidth || 0,
  70740. height: html.clientHeight || 0,
  70741. fullWidth: Math.max(body.scrollWidth, html.scrollWidth, body.offsetWidth, html.offsetWidth, body.clientWidth, html.clientWidth),
  70742. fullHeight: Math.max(body.scrollHeight, html.scrollHeight, body.offsetHeight, html.offsetHeight, body.clientHeight, html.clientHeight)
  70743. }
  70744. }
  70745. };
  70746. DX.viz.core.Tooltip = Tooltip
  70747. })(DevExpress, jQuery, document);
  70748. /*! Module viz-core, file legend.js */
  70749. (function(DX, $, undefined) {
  70750. var core = DX.viz.core,
  70751. coreUtils = core.utils,
  70752. WrapperLayoutElement = core.WrapperLayoutElement,
  70753. _Number = Number,
  70754. _String = String,
  70755. _math = Math,
  70756. _round = _math.round,
  70757. _max = _math.max,
  70758. _min = _math.min,
  70759. _ceil = _math.ceil,
  70760. utils = DX.utils,
  70761. _isDefined = utils.isDefined,
  70762. _isFunction = utils.isFunction,
  70763. _enumParser = coreUtils.enumParser,
  70764. _extend = $.extend,
  70765. _each = $.each,
  70766. _map = $.map,
  70767. DEFAULT_MARGIN = 10,
  70768. DEFAULT_MARKER_HATCHING_WIDTH = 2,
  70769. DEFAULT_MARKER_HATCHING_STEP = 5,
  70770. CENTER = "center",
  70771. RIGHT = "right",
  70772. LEFT = "left",
  70773. TOP = "top",
  70774. BOTTOM = "bottom",
  70775. HORIZONTAL = "horizontal",
  70776. VERTICAL = "vertical",
  70777. INSIDE = "inside",
  70778. OUTSIDE = "outside",
  70779. NONE = "none",
  70780. HEIGHT = "height",
  70781. WIDTH = "width",
  70782. parseHorizontalAlignment = _enumParser([LEFT, CENTER, RIGHT]),
  70783. parseVerticalAlignment = _enumParser([TOP, BOTTOM]),
  70784. parseOrientation = _enumParser([VERTICAL, HORIZONTAL]),
  70785. parseItemTextPosition = _enumParser([LEFT, RIGHT, TOP, BOTTOM]),
  70786. parsePosition = _enumParser([OUTSIDE, INSIDE]),
  70787. parseItemsAlignment = _enumParser([LEFT, CENTER, RIGHT]);
  70788. function getPattern(renderer, states, action, color) {
  70789. if (!states || !states[action])
  70790. return;
  70791. var direction = states[action].hatching.direction,
  70792. hatching,
  70793. colorFromAction = states[action].fill;
  70794. color = colorFromAction === NONE ? color : colorFromAction;
  70795. direction = !direction || direction === NONE ? RIGHT : direction;
  70796. hatching = _extend({}, states[action].hatching, {
  70797. direction: direction,
  70798. step: DEFAULT_MARKER_HATCHING_STEP,
  70799. width: DEFAULT_MARKER_HATCHING_WIDTH
  70800. });
  70801. return renderer.pattern(color, hatching)
  70802. }
  70803. function parseMargins(options) {
  70804. var margin = options.margin;
  70805. if (margin >= 0) {
  70806. margin = _Number(options.margin);
  70807. margin = {
  70808. top: margin,
  70809. bottom: margin,
  70810. left: margin,
  70811. right: margin
  70812. }
  70813. }
  70814. else
  70815. margin = {
  70816. top: margin.top >= 0 ? _Number(margin.top) : DEFAULT_MARGIN,
  70817. bottom: margin.bottom >= 0 ? _Number(margin.bottom) : DEFAULT_MARGIN,
  70818. left: margin.left >= 0 ? _Number(margin.left) : DEFAULT_MARGIN,
  70819. right: margin.right >= 0 ? _Number(margin.right) : DEFAULT_MARGIN
  70820. };
  70821. options.margin = margin
  70822. }
  70823. function getSizeItem(options, markerSize, labelBBox) {
  70824. var defaultXMargin = 7,
  70825. defaultTopMargin = 4,
  70826. width,
  70827. height;
  70828. switch (options.itemTextPosition) {
  70829. case LEFT:
  70830. case RIGHT:
  70831. width = markerSize + defaultXMargin + labelBBox.width;
  70832. height = _max(markerSize, labelBBox.height);
  70833. break;
  70834. case TOP:
  70835. case BOTTOM:
  70836. width = _max(markerSize, labelBBox.width);
  70837. height = markerSize + defaultTopMargin + labelBBox.height;
  70838. break
  70839. }
  70840. return {
  70841. width: width,
  70842. height: height
  70843. }
  70844. }
  70845. function calculateBboxLabelAndMarker(markerBBox, labelBBox) {
  70846. var bbox = {};
  70847. bbox.left = _min(markerBBox.x, labelBBox.x);
  70848. bbox.top = _min(markerBBox.y, labelBBox.y);
  70849. bbox.right = _max(markerBBox.x + markerBBox.width, labelBBox.x + labelBBox.width);
  70850. bbox.bottom = _max(markerBBox.y + markerBBox.height, labelBBox.y + labelBBox.height);
  70851. return bbox
  70852. }
  70853. function applyMarkerState(id, idToIndexMap, items, stateName) {
  70854. var item = idToIndexMap && items[idToIndexMap[id]];
  70855. if (item)
  70856. item.marker.attr(item.states[stateName])
  70857. }
  70858. function parseOptions(options, textField) {
  70859. if (!options)
  70860. return null;
  70861. DX.utils.debug.assertParam(options.visible, "Visibility was not passed");
  70862. DX.utils.debug.assertParam(options.markerSize, "markerSize was not passed");
  70863. DX.utils.debug.assertParam(options.font.color, "fontColor was not passed");
  70864. DX.utils.debug.assertParam(options.font.family, "fontFamily was not passed");
  70865. DX.utils.debug.assertParam(options.font.size, "fontSize was not passed");
  70866. DX.utils.debug.assertParam(options.paddingLeftRight, "paddingLeftRight was not passed");
  70867. DX.utils.debug.assertParam(options.paddingTopBottom, "paddingTopBottom was not passed");
  70868. DX.utils.debug.assertParam(options.columnItemSpacing, "columnItemSpacing was not passed");
  70869. DX.utils.debug.assertParam(options.rowItemSpacing, "rowItemSpacing was not passed");
  70870. parseMargins(options);
  70871. options.horizontalAlignment = parseHorizontalAlignment(options.horizontalAlignment, RIGHT);
  70872. options.verticalAlignment = parseVerticalAlignment(options.verticalAlignment, options.horizontalAlignment === CENTER ? BOTTOM : TOP);
  70873. options.orientation = parseOrientation(options.orientation, options.horizontalAlignment === CENTER ? HORIZONTAL : VERTICAL);
  70874. options.itemTextPosition = parseItemTextPosition(options.itemTextPosition, options.orientation === HORIZONTAL ? BOTTOM : RIGHT);
  70875. options.position = parsePosition(options.position, OUTSIDE);
  70876. options.itemsAlignment = parseItemsAlignment(options.itemsAlignment, null);
  70877. options.hoverMode = _String(options.hoverMode || "").toLowerCase();
  70878. options.customizeText = _isFunction(options.customizeText) ? options.customizeText : function() {
  70879. return this[textField]
  70880. };
  70881. options.customizeHint = _isFunction(options.customizeHint) ? options.customizeHint : $.noop;
  70882. return options
  70883. }
  70884. function createSquareMarker(renderer, size) {
  70885. return renderer.rect(0, 0, size, size)
  70886. }
  70887. function createCircleMarker(renderer, size) {
  70888. return renderer.circle(size / 2, size / 2, size / 2)
  70889. }
  70890. function isCircle(type) {
  70891. return _String(type).toLowerCase() === "circle"
  70892. }
  70893. function getMarkerCreator(type) {
  70894. return isCircle(type) ? createCircleMarker : createSquareMarker
  70895. }
  70896. function inRect(rect, x, y) {
  70897. return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom
  70898. }
  70899. function checkLinesSize(lines, layoutOptions, countItems) {
  70900. var position = {
  70901. x: 0,
  70902. y: 0
  70903. },
  70904. maxMeasureLength = 0,
  70905. maxOrtMeasureLength = 0;
  70906. $.each(lines, function(i, line) {
  70907. var firstItem = line[0];
  70908. $.each(line, function(_, item) {
  70909. var offset = item.offset || layoutOptions.spacing;
  70910. position[layoutOptions.direction] += item[layoutOptions.measure] + offset;
  70911. maxMeasureLength = _max(maxMeasureLength, position[layoutOptions.direction])
  70912. });
  70913. position[layoutOptions.direction] = 0;
  70914. position[layoutOptions.ortDirection] += firstItem[layoutOptions.ortMeasure] + firstItem.ortOffset || layoutOptions.ortSpacing;
  70915. maxOrtMeasureLength = _max(maxOrtMeasureLength, position[layoutOptions.ortDirection])
  70916. });
  70917. if (maxMeasureLength > layoutOptions.length) {
  70918. layoutOptions.countItem = decreaseItemCount(layoutOptions, countItems);
  70919. return true
  70920. }
  70921. }
  70922. function decreaseItemCount(layoutOptions, countItems) {
  70923. layoutOptions.ortCountItem++;
  70924. return _ceil(countItems / layoutOptions.ortCountItem)
  70925. }
  70926. function getLineLength(line, layoutOptions) {
  70927. var lineLength = 0;
  70928. $.each(line, function(_, item) {
  70929. var offset = item.offset || layoutOptions.spacing;
  70930. lineLength += item[layoutOptions.measure] + offset
  70931. });
  70932. return lineLength
  70933. }
  70934. function getMaxLineLength(lines, layoutOptions) {
  70935. var maxLineLength = 0;
  70936. $.each(lines, function(_, line) {
  70937. maxLineLength = _max(maxLineLength, getLineLength(line, layoutOptions))
  70938. });
  70939. return maxLineLength
  70940. }
  70941. function getInitPositionForDirection(line, layoutOptions, maxLineLength) {
  70942. var lineLength = getLineLength(line, layoutOptions),
  70943. initPosition;
  70944. switch (layoutOptions.itemsAlignment) {
  70945. case RIGHT:
  70946. initPosition = maxLineLength - lineLength;
  70947. break;
  70948. case CENTER:
  70949. initPosition = (maxLineLength - lineLength) / 2;
  70950. break;
  70951. default:
  70952. initPosition = 0
  70953. }
  70954. return initPosition
  70955. }
  70956. function getPos(layoutOptions) {
  70957. switch (layoutOptions.itemTextPosition) {
  70958. case BOTTOM:
  70959. return CENTER + " " + TOP;
  70960. case TOP:
  70961. return CENTER + " " + BOTTOM;
  70962. case LEFT:
  70963. return RIGHT + " " + CENTER;
  70964. case RIGHT:
  70965. return LEFT + " " + CENTER
  70966. }
  70967. }
  70968. function getLines(lines, layoutOptions, itemIndex) {
  70969. var tableLine = {};
  70970. if (itemIndex % layoutOptions.countItem === 0)
  70971. if (layoutOptions.markerOffset)
  70972. lines.push([], []);
  70973. else
  70974. lines.push([]);
  70975. if (layoutOptions.markerOffset) {
  70976. tableLine.firstLine = lines[lines.length - 1];
  70977. tableLine.secondLine = lines[lines.length - 2]
  70978. }
  70979. else
  70980. tableLine.firstLine = tableLine.secondLine = lines[lines.length - 1];
  70981. return tableLine
  70982. }
  70983. function setMaxInLine(line, mesuare) {
  70984. var maxLineSize = 0;
  70985. $.each(line, function(_, item) {
  70986. if (!item)
  70987. return;
  70988. maxLineSize = _max(maxLineSize, item[mesuare])
  70989. });
  70990. $.each(line, function(_, item) {
  70991. if (!item)
  70992. return;
  70993. item[mesuare] = maxLineSize
  70994. })
  70995. }
  70996. function transpose(array) {
  70997. var width = array.length,
  70998. height = array[0].length,
  70999. i,
  71000. j,
  71001. transposeArray = [];
  71002. for (i = 0; i < height; i++) {
  71003. transposeArray[i] = [];
  71004. for (j = 0; j < width; j++)
  71005. transposeArray[i][j] = array[j][i]
  71006. }
  71007. return transposeArray
  71008. }
  71009. function getAlign(position) {
  71010. switch (position) {
  71011. case TOP:
  71012. case BOTTOM:
  71013. return CENTER;
  71014. case LEFT:
  71015. return RIGHT;
  71016. case RIGHT:
  71017. return LEFT
  71018. }
  71019. }
  71020. var _Legend = DX.viz.core.Legend = function(settings) {
  71021. var that = this;
  71022. that._renderer = settings.renderer;
  71023. that._legendGroup = settings.group;
  71024. that._backgroundClass = settings.backgroundClass;
  71025. that._itemGroupClass = settings.itemGroupClass;
  71026. that._textField = settings.textField;
  71027. that._getCustomizeObject = settings.getFormatObject;
  71028. that._patterns = []
  71029. };
  71030. _Legend.prototype = {
  71031. constructor: _Legend,
  71032. update: function(data, options) {
  71033. var that = this;
  71034. that._data = data;
  71035. that._boundingRect = {
  71036. width: 0,
  71037. height: 0,
  71038. x: 0,
  71039. y: 0
  71040. };
  71041. that._options = parseOptions(options, that._textField);
  71042. return that
  71043. },
  71044. setSize: function(size) {
  71045. this._size = {
  71046. width: size.width,
  71047. height: size.height
  71048. };
  71049. return this
  71050. },
  71051. draw: function(size) {
  71052. var that = this,
  71053. options = that._options,
  71054. renderer = that._renderer,
  71055. items = that._data;
  71056. size && that.setSize(size);
  71057. that.erase();
  71058. if (!(options && options.visible && items && items.length))
  71059. return that;
  71060. that._insideLegendGroup = renderer.g().append(that._legendGroup);
  71061. that._createBackground();
  71062. that._createItems(that._getItemData());
  71063. that._locateElements(options);
  71064. that._finalUpdate(options);
  71065. return that
  71066. },
  71067. _createItems: function(items) {
  71068. var that = this,
  71069. options = that._options,
  71070. initMarkerSize = options.markerSize,
  71071. renderer = that._renderer,
  71072. markersOptions = [],
  71073. maxMarkerSize = 0,
  71074. i = 0,
  71075. bbox,
  71076. maxBboxWidth = 0,
  71077. maxBboxHeight = 0,
  71078. createMarker = getMarkerCreator(options.markerType);
  71079. _each(items, function(_i, item) {
  71080. maxMarkerSize = _max(maxMarkerSize, _Number(item.size > 0 ? item.size : initMarkerSize))
  71081. });
  71082. that._markersId = {};
  71083. for (; i < that._patterns.length; i++)
  71084. that._patterns[i].dispose();
  71085. that._patterns = [];
  71086. that._items = _map(items, function(dataItem, i) {
  71087. var group = that._insideLegendGroup,
  71088. markerSize = _Number(dataItem.size > 0 ? dataItem.size : initMarkerSize),
  71089. stateOfDataItem = dataItem.states,
  71090. normalState = stateOfDataItem.normal,
  71091. normalStateFill = normalState.fill,
  71092. marker = createMarker(renderer, markerSize).attr({
  71093. fill: normalStateFill || options.markerColor,
  71094. opacity: normalState.opacity
  71095. }).append(group),
  71096. label = that._createLabel(dataItem, group),
  71097. hoverPattern = getPattern(renderer, stateOfDataItem, "hover", normalStateFill),
  71098. selectionPattern = getPattern(renderer, stateOfDataItem, "selection", normalStateFill),
  71099. states = {normal: {fill: normalStateFill}},
  71100. labelBBox = label.getBBox();
  71101. if (hoverPattern) {
  71102. states.hovered = {fill: hoverPattern.id};
  71103. that._patterns.push(hoverPattern)
  71104. }
  71105. if (selectionPattern) {
  71106. states.selected = {fill: selectionPattern.id};
  71107. that._patterns.push(selectionPattern)
  71108. }
  71109. if (dataItem.id !== undefined)
  71110. that._markersId[dataItem.id] = i;
  71111. bbox = getSizeItem(options, markerSize, labelBBox);
  71112. maxBboxWidth = _max(maxBboxWidth, bbox.width);
  71113. maxBboxHeight = _max(maxBboxHeight, bbox.height);
  71114. markersOptions.push({
  71115. size: markerSize,
  71116. marker: marker
  71117. });
  71118. that._createHint(dataItem, label);
  71119. return {
  71120. label: label,
  71121. labelBBox: labelBBox,
  71122. group: group,
  71123. bbox: bbox,
  71124. marker: marker,
  71125. markerSize: markerSize,
  71126. tracker: {id: dataItem.id},
  71127. states: states,
  71128. itemTextPosition: options.itemTextPosition,
  71129. markerOffset: 0,
  71130. bboxs: []
  71131. }
  71132. });
  71133. if (options.equalRowHeight)
  71134. $.each(that._items, function(_, item) {
  71135. item.bbox.height = maxBboxHeight
  71136. })
  71137. },
  71138. _getItemData: function() {
  71139. var items = this._data;
  71140. if (this._options.inverted)
  71141. items = items.slice().reverse();
  71142. return items
  71143. },
  71144. _finalUpdate: function(options) {
  71145. this._adjustBackgroundSettings(options);
  71146. this._setBoundingRect(options.margin)
  71147. },
  71148. erase: function() {
  71149. var that = this,
  71150. insideLegendGroup = that._insideLegendGroup;
  71151. insideLegendGroup && insideLegendGroup.dispose();
  71152. that._insideLegendGroup = that._x1 = that._x2 = that._y2 = that._y2 = null;
  71153. return that
  71154. },
  71155. _locateElements: function(locationOptions) {
  71156. this._moveInInitialValues();
  71157. this._locateRowsColumns(locationOptions)
  71158. },
  71159. _moveInInitialValues: function() {
  71160. var that = this;
  71161. that._legendGroup && that._legendGroup.move(0, 0);
  71162. that._background && that._background.attr({
  71163. x: 0,
  71164. y: 0,
  71165. width: 0,
  71166. height: 0
  71167. })
  71168. },
  71169. applySelected: function(id) {
  71170. applyMarkerState(id, this._markersId, this._items, "selected");
  71171. return this
  71172. },
  71173. applyHover: function(id) {
  71174. applyMarkerState(id, this._markersId, this._items, "hovered");
  71175. return this
  71176. },
  71177. resetItem: function(id) {
  71178. applyMarkerState(id, this._markersId, this._items, "normal");
  71179. return this
  71180. },
  71181. _createLabel: function(data, group) {
  71182. var labelFormatObject = this._getCustomizeObject(data),
  71183. align = getAlign(this._options.itemTextPosition),
  71184. text = this._options.customizeText.call(labelFormatObject, labelFormatObject),
  71185. fontStyle = _isDefined(data.textOpacity) ? _extend({}, this._options.font, {opacity: data.textOpacity}) : this._options.font;
  71186. return this._renderer.text(text, 0, 0).css(coreUtils.patchFontOptions(fontStyle)).attr({align: align}).append(group)
  71187. },
  71188. _createHint: function(data, label) {
  71189. var labelFormatObject = this._getCustomizeObject(data),
  71190. text = this._options.customizeHint.call(labelFormatObject, labelFormatObject);
  71191. if (_isDefined(text) && text !== "")
  71192. label.setTitle(text)
  71193. },
  71194. _createBackground: function() {
  71195. var that = this,
  71196. isInside = that._options.position === INSIDE,
  71197. color = that._options.backgroundColor,
  71198. fill = color || (isInside ? that._options.containerBackgroundColor : NONE);
  71199. if (that._options.border.visible || (isInside || color) && color !== NONE)
  71200. that._background = that._renderer.rect(0, 0, 0, 0).attr({
  71201. fill: fill,
  71202. 'class': that._backgroundClass
  71203. }).append(that._insideLegendGroup)
  71204. },
  71205. _locateRowsColumns: function() {
  71206. var that = this,
  71207. iteration = 0,
  71208. layoutOptions = that._getItemsLayoutOptions(),
  71209. countItems = that._items.length,
  71210. lines;
  71211. do {
  71212. lines = [];
  71213. that._createLines(lines, layoutOptions);
  71214. that._alignLines(lines, layoutOptions);
  71215. iteration++
  71216. } while (checkLinesSize(lines, layoutOptions, countItems) && iteration < countItems);
  71217. that._applyItemPosition(lines, layoutOptions)
  71218. },
  71219. _createLines: function(lines, layoutOptions) {
  71220. $.each(this._items, function(i, item) {
  71221. var tableLine = getLines(lines, layoutOptions, i),
  71222. labelBox = {
  71223. width: item.labelBBox.width,
  71224. height: item.labelBBox.height,
  71225. element: item.label,
  71226. bbox: item.labelBBox,
  71227. pos: getPos(layoutOptions),
  71228. itemIndex: i
  71229. },
  71230. markerBox = {
  71231. width: item.markerSize,
  71232. height: item.markerSize,
  71233. element: item.marker,
  71234. bbox: {
  71235. width: item.markerSize,
  71236. height: item.markerSize,
  71237. x: 0,
  71238. y: 0
  71239. },
  71240. itemIndex: i
  71241. },
  71242. firstItem,
  71243. secondItem,
  71244. offsetDirection = layoutOptions.markerOffset ? "ortOffset" : "offset";
  71245. if (layoutOptions.inverseLabelPosition) {
  71246. firstItem = labelBox;
  71247. secondItem = markerBox
  71248. }
  71249. else {
  71250. firstItem = markerBox;
  71251. secondItem = labelBox
  71252. }
  71253. firstItem[offsetDirection] = layoutOptions.labelOffset;
  71254. tableLine.secondLine.push(firstItem);
  71255. tableLine.firstLine.push(secondItem)
  71256. })
  71257. },
  71258. _alignLines: function(lines, layoutOptions) {
  71259. var i,
  71260. measure = layoutOptions.ortMeasure;
  71261. _each(lines, processLine);
  71262. measure = layoutOptions.measure;
  71263. if (layoutOptions.itemsAlignment) {
  71264. if (layoutOptions.markerOffset)
  71265. for (i = 0; i < lines.length; )
  71266. _each(transpose([lines[i++], lines[i++]]), processLine)
  71267. }
  71268. else
  71269. _each(transpose(lines), processLine);
  71270. function processLine(_, line) {
  71271. setMaxInLine(line, measure)
  71272. }
  71273. },
  71274. _applyItemPosition: function(lines, layoutOptions) {
  71275. var that = this,
  71276. position = {
  71277. x: 0,
  71278. y: 0
  71279. },
  71280. maxLineLength = getMaxLineLength(lines, layoutOptions),
  71281. itemIndex = 0;
  71282. $.each(lines, function(i, line) {
  71283. var firstItem = line[0],
  71284. ortOffset = firstItem.ortOffset || layoutOptions.ortSpacing;
  71285. position[layoutOptions.direction] = getInitPositionForDirection(line, layoutOptions, maxLineLength);
  71286. $.each(line, function(_, item) {
  71287. var offset = item.offset || layoutOptions.spacing,
  71288. wrap = new WrapperLayoutElement(item.element, item.bbox),
  71289. itemBBox = {
  71290. x: position.x,
  71291. y: position.y,
  71292. width: item.width,
  71293. height: item.height
  71294. },
  71295. itemLegend = that._items[item.itemIndex];
  71296. wrap.position({
  71297. of: itemBBox,
  71298. my: item.pos,
  71299. at: item.pos
  71300. });
  71301. itemLegend.bboxs.push(itemBBox);
  71302. position[layoutOptions.direction] += item[layoutOptions.measure] + offset;
  71303. itemIndex++
  71304. });
  71305. position[layoutOptions.ortDirection] += firstItem[layoutOptions.ortMeasure] + ortOffset
  71306. });
  71307. $.each(this._items, function(_, item) {
  71308. var itemBBox = calculateBboxLabelAndMarker(item.bboxs[0], item.bboxs[1]),
  71309. horizontal = that._options.columnItemSpacing / 2,
  71310. vertical = that._options.rowItemSpacing / 2;
  71311. item.tracker.left = itemBBox.left - horizontal;
  71312. item.tracker.right = itemBBox.right + horizontal;
  71313. item.tracker.top = itemBBox.top - vertical;
  71314. item.tracker.bottom = itemBBox.bottom + vertical
  71315. })
  71316. },
  71317. _getItemsLayoutOptions: function() {
  71318. var that = this,
  71319. options = that._options,
  71320. border = options.border.visible,
  71321. orientation = options.orientation,
  71322. layoutOptions = {
  71323. itemsAlignment: options.itemsAlignment,
  71324. orientation: options.orientation
  71325. },
  71326. width = that._size.width - (border ? 2 * options.paddingLeftRight : 0),
  71327. height = that._size.height - (border ? 2 * options.paddingTopBottom : 0);
  71328. if (orientation === HORIZONTAL) {
  71329. layoutOptions.length = width;
  71330. layoutOptions.ortLength = height;
  71331. layoutOptions.spacing = options.columnItemSpacing;
  71332. layoutOptions.direction = "x";
  71333. layoutOptions.measure = WIDTH;
  71334. layoutOptions.ortMeasure = HEIGHT;
  71335. layoutOptions.ortDirection = "y";
  71336. layoutOptions.ortSpacing = options.rowItemSpacing;
  71337. layoutOptions.countItem = options.columnCount;
  71338. layoutOptions.ortCountItem = options.rowCount;
  71339. layoutOptions.marginTextLabel = 4;
  71340. layoutOptions.labelOffset = 7;
  71341. if (options.itemTextPosition === BOTTOM || options.itemTextPosition === TOP) {
  71342. layoutOptions.labelOffset = 4;
  71343. layoutOptions.markerOffset = true
  71344. }
  71345. }
  71346. else {
  71347. layoutOptions.length = height;
  71348. layoutOptions.ortLength = width;
  71349. layoutOptions.spacing = options.rowItemSpacing;
  71350. layoutOptions.direction = "y";
  71351. layoutOptions.measure = HEIGHT;
  71352. layoutOptions.ortMeasure = WIDTH;
  71353. layoutOptions.ortDirection = "x";
  71354. layoutOptions.ortSpacing = options.columnItemSpacing;
  71355. layoutOptions.countItem = options.rowCount;
  71356. layoutOptions.ortCountItem = options.columnCount;
  71357. layoutOptions.marginTextLabel = 7;
  71358. layoutOptions.labelOffset = 4;
  71359. if (options.itemTextPosition === RIGHT || options.itemTextPosition === LEFT) {
  71360. layoutOptions.labelOffset = 7;
  71361. layoutOptions.markerOffset = true
  71362. }
  71363. }
  71364. if (!layoutOptions.countItem)
  71365. if (layoutOptions.ortCountItem)
  71366. layoutOptions.countItem = _ceil(that._items.length / layoutOptions.ortCountItem);
  71367. else
  71368. layoutOptions.countItem = that._items.length;
  71369. if (options.itemTextPosition === TOP || options.itemTextPosition === LEFT)
  71370. layoutOptions.inverseLabelPosition = true;
  71371. layoutOptions.itemTextPosition = options.itemTextPosition;
  71372. layoutOptions.ortCountItem = layoutOptions.ortCountItem || _ceil(that._items.length / layoutOptions.countItem);
  71373. return layoutOptions
  71374. },
  71375. _adjustBackgroundSettings: function(locationOptions) {
  71376. if (!this._background)
  71377. return;
  71378. var border = locationOptions.border,
  71379. legendBox = this._insideLegendGroup.getBBox(),
  71380. backgroundSettings = {
  71381. x: _round(legendBox.x - locationOptions.paddingLeftRight),
  71382. y: _round(legendBox.y - locationOptions.paddingTopBottom),
  71383. width: _round(legendBox.width) + 2 * locationOptions.paddingLeftRight,
  71384. height: _round(legendBox.height) + 2 * locationOptions.paddingTopBottom,
  71385. opacity: locationOptions.backgroundOpacity
  71386. };
  71387. if (border.visible && border.width && border.color && border.color !== NONE) {
  71388. backgroundSettings["stroke-width"] = border.width;
  71389. backgroundSettings.stroke = border.color;
  71390. backgroundSettings["stroke-opacity"] = border.opacity;
  71391. backgroundSettings.dashStyle = border.dashStyle;
  71392. backgroundSettings.rx = border.cornerRadius || 0;
  71393. backgroundSettings.ry = border.cornerRadius || 0
  71394. }
  71395. this._background.attr(backgroundSettings)
  71396. },
  71397. _setBoundingRect: function(margin) {
  71398. if (!this._insideLegendGroup)
  71399. return;
  71400. var box = this._insideLegendGroup.getBBox();
  71401. box.height += margin.top + margin.bottom;
  71402. box.width += margin.left + margin.right;
  71403. box.x -= margin.left;
  71404. box.y -= margin.top;
  71405. this._boundingRect = box
  71406. },
  71407. changeSize: function() {
  71408. this.fit.apply(this, arguments)
  71409. },
  71410. fit: function(sizeForDecrease) {
  71411. var that = this,
  71412. beforeFit = that.getLayoutOptions(),
  71413. afterFit;
  71414. function fitLegendToDirection(direction) {
  71415. var size = $.extend({}, that._size);
  71416. size[direction] = beforeFit[direction] - sizeForDecrease[direction];
  71417. that.draw(size);
  71418. afterFit = that.getLayoutOptions();
  71419. if (that._insideLegendGroup)
  71420. if (beforeFit[direction] - sizeForDecrease[direction] < afterFit[direction]) {
  71421. that._options._incidentOccured("W2104");
  71422. that.erase()
  71423. }
  71424. }
  71425. if (sizeForDecrease.width > 0)
  71426. fitLegendToDirection(WIDTH);
  71427. if (sizeForDecrease.height > 0)
  71428. fitLegendToDirection(HEIGHT);
  71429. return this
  71430. },
  71431. getActionCallback: function(point) {
  71432. var that = this;
  71433. if (that._options.visible)
  71434. return function(act) {
  71435. var pointType = point.type,
  71436. seriesType = pointType || point.series.type;
  71437. if (pointType || seriesType === "pie" || seriesType === "doughnut" || seriesType === "donut")
  71438. that[act] && that[act](point.index)
  71439. };
  71440. else
  71441. return $.noop
  71442. },
  71443. getLayoutOptions: function() {
  71444. var options = this._options,
  71445. boundingRect = this._insideLegendGroup ? this._boundingRect : {
  71446. width: 0,
  71447. height: 0,
  71448. x: 0,
  71449. y: 0
  71450. };
  71451. if (options) {
  71452. boundingRect.verticalAlignment = options.verticalAlignment;
  71453. boundingRect.horizontalAlignment = options.horizontalAlignment;
  71454. if (options.orientation === HORIZONTAL)
  71455. boundingRect.cutLayoutSide = options.verticalAlignment;
  71456. else
  71457. boundingRect.cutLayoutSide = options.horizontalAlignment === CENTER ? options.verticalAlignment : options.horizontalAlignment;
  71458. return boundingRect
  71459. }
  71460. return null
  71461. },
  71462. shift: function(x, y) {
  71463. var that = this,
  71464. box = {};
  71465. if (that._insideLegendGroup) {
  71466. that._insideLegendGroup.attr({
  71467. translateX: x - that._boundingRect.x,
  71468. translateY: y - that._boundingRect.y
  71469. });
  71470. box = that._legendGroup.getBBox()
  71471. }
  71472. that._x1 = box.x;
  71473. that._y1 = box.y;
  71474. that._x2 = box.x + box.width;
  71475. that._y2 = box.y + box.height;
  71476. return that
  71477. },
  71478. getPosition: function() {
  71479. return this._options.position
  71480. },
  71481. coordsIn: function(x, y) {
  71482. return x >= this._x1 && x <= this._x2 && y >= this._y1 && y <= this._y2
  71483. },
  71484. getItemByCoord: function(x, y) {
  71485. var items = this._items,
  71486. legendGroup = this._insideLegendGroup;
  71487. x = x - legendGroup.attr("translateX");
  71488. y = y - legendGroup.attr("translateY");
  71489. for (var i = 0; i < items.length; i++)
  71490. if (inRect(items[i].tracker, x, y))
  71491. return items[i].tracker;
  71492. return null
  71493. },
  71494. dispose: function() {
  71495. var that = this;
  71496. that._legendGroup = that._insideLegendGroup = that._renderer = that._options = that._data = that._items = null;
  71497. return that
  71498. }
  71499. };
  71500. var __getMarkerCreator = getMarkerCreator;
  71501. DX.viz.core._DEBUG_stubMarkerCreator = function(callback) {
  71502. getMarkerCreator = function() {
  71503. return callback
  71504. }
  71505. };
  71506. DX.viz.core._DEBUG_restoreMarkerCreator = function() {
  71507. getMarkerCreator = __getMarkerCreator
  71508. }
  71509. })(DevExpress, jQuery);
  71510. /*! Module viz-core, file range.js */
  71511. (function($, DX, undefined) {
  71512. var core = DX.viz.core,
  71513. utils = DX.utils,
  71514. _isDefined = utils.isDefined,
  71515. _isDate = utils.isDate,
  71516. NUMBER_EQUALITY_CORRECTION = 1,
  71517. DATETIME_EQUALITY_CORRECTION = 60000,
  71518. minSelector = "min",
  71519. maxSelector = "max",
  71520. minVisibleSelector = "minVisible",
  71521. maxVisibleSelector = "maxVisible",
  71522. categoriesSelector = "categories",
  71523. baseSelector = "base",
  71524. axisTypeSelector = "axisType",
  71525. _Range;
  71526. function otherLessThan(thisValue, otherValue) {
  71527. return otherValue < thisValue
  71528. }
  71529. function otherGreaterThan(thisValue, otherValue) {
  71530. return otherValue > thisValue
  71531. }
  71532. function compareAndReplace(thisValue, otherValue, setValue, compare) {
  71533. var otherValueDefined = _isDefined(otherValue);
  71534. if (_isDefined(thisValue)) {
  71535. if (otherValueDefined && compare(thisValue, otherValue))
  71536. setValue(otherValue)
  71537. }
  71538. else if (otherValueDefined)
  71539. setValue(otherValue)
  71540. }
  71541. function returnValue(value) {
  71542. return value
  71543. }
  71544. function returnValueOf(value) {
  71545. return value.valueOf()
  71546. }
  71547. function getUniqueCategories(categories, otherCategories, dataType) {
  71548. var length = categories.length,
  71549. found,
  71550. i,
  71551. j,
  71552. valueOf = dataType === "datetime" ? returnValueOf : returnValue;
  71553. if (otherCategories && otherCategories.length)
  71554. for (i = 0; i < otherCategories.length; i++) {
  71555. for (j = 0, found = false; j < length; j++)
  71556. if (valueOf(categories[j]) === valueOf(otherCategories[i])) {
  71557. found = true;
  71558. break
  71559. }
  71560. !found && categories.push(otherCategories[i])
  71561. }
  71562. return categories
  71563. }
  71564. DX.viz.core.__NUMBER_EQUALITY_CORRECTION = NUMBER_EQUALITY_CORRECTION;
  71565. DX.viz.core.__DATETIME_EQUALITY_CORRECTION = DATETIME_EQUALITY_CORRECTION;
  71566. _Range = core.Range = function(range) {
  71567. range && $.extend(this, range)
  71568. };
  71569. _Range.prototype = {
  71570. constructor: _Range,
  71571. dispose: function() {
  71572. this[categoriesSelector] = null
  71573. },
  71574. addRange: function(otherRange) {
  71575. var that = this,
  71576. categories = that[categoriesSelector],
  71577. otherCategories = otherRange[categoriesSelector];
  71578. var compareAndReplaceByField = function(field, compare) {
  71579. compareAndReplace(that[field], otherRange[field], function(value) {
  71580. that[field] = value
  71581. }, compare)
  71582. };
  71583. var controlValuesByVisibleBounds = function(valueField, visibleValueField, compare) {
  71584. compareAndReplace(that[valueField], that[visibleValueField], function(value) {
  71585. _isDefined(that[valueField]) && (that[valueField] = value)
  71586. }, compare)
  71587. };
  71588. var checkField = function(field) {
  71589. that[field] = that[field] || otherRange[field]
  71590. };
  71591. if (utils.isDefined(otherRange.stick))
  71592. that.stick = otherRange.stick;
  71593. checkField("addSpiderCategory");
  71594. checkField("percentStick");
  71595. checkField("minSpaceCorrection");
  71596. checkField("maxSpaceCorrection");
  71597. checkField("invert");
  71598. checkField(axisTypeSelector);
  71599. checkField("dataType");
  71600. if (that[axisTypeSelector] === "logarithmic")
  71601. checkField(baseSelector);
  71602. else
  71603. that[baseSelector] = undefined;
  71604. compareAndReplaceByField(minSelector, otherLessThan);
  71605. compareAndReplaceByField(maxSelector, otherGreaterThan);
  71606. if (that[axisTypeSelector] === "discrete") {
  71607. checkField(minVisibleSelector);
  71608. checkField(maxVisibleSelector)
  71609. }
  71610. else {
  71611. compareAndReplaceByField(minVisibleSelector, otherLessThan);
  71612. compareAndReplaceByField(maxVisibleSelector, otherGreaterThan)
  71613. }
  71614. compareAndReplaceByField("interval", otherLessThan);
  71615. controlValuesByVisibleBounds(minSelector, minVisibleSelector, otherLessThan);
  71616. controlValuesByVisibleBounds(minSelector, maxVisibleSelector, otherLessThan);
  71617. controlValuesByVisibleBounds(maxSelector, maxVisibleSelector, otherGreaterThan);
  71618. controlValuesByVisibleBounds(maxSelector, minVisibleSelector, otherGreaterThan);
  71619. if (categories === undefined)
  71620. that[categoriesSelector] = otherCategories;
  71621. else
  71622. that[categoriesSelector] = getUniqueCategories(categories, otherCategories, that.dataType);
  71623. return this
  71624. },
  71625. isDefined: function() {
  71626. return _isDefined(this[minSelector]) && _isDefined(this[maxSelector]) || _isDefined(this[categoriesSelector])
  71627. },
  71628. setStubData: function(dataType) {
  71629. var that = this,
  71630. year = (new Date).getYear() - 1,
  71631. isDate = dataType === "datetime",
  71632. isCategories = that.axisType === "discrete";
  71633. if (isCategories)
  71634. that.categories = ["0", "1", "2"];
  71635. else {
  71636. that[minSelector] = isDate ? new Date(year, 0, 1) : 0;
  71637. that[maxSelector] = isDate ? new Date(year, 11, 31) : 10
  71638. }
  71639. that.stubData = true;
  71640. return that
  71641. },
  71642. correctValueZeroLevel: function() {
  71643. var that = this;
  71644. if (_isDate(that[maxSelector]) || _isDate(that[minSelector]))
  71645. return that;
  71646. function setZeroLevel(min, max) {
  71647. that[min] < 0 && that[max] < 0 && (that[max] = 0);
  71648. that[min] > 0 && that[max] > 0 && (that[min] = 0)
  71649. }
  71650. setZeroLevel(minSelector, maxSelector);
  71651. setZeroLevel(minVisibleSelector, maxVisibleSelector);
  71652. return that
  71653. },
  71654. checkZeroStick: function() {
  71655. var that = this;
  71656. if (that.min >= 0 && that.max >= 0)
  71657. that.minStickValue = 0;
  71658. else if (that.min <= 0 && that.max <= 0)
  71659. that.maxStickValue = 0;
  71660. return that
  71661. }
  71662. }
  71663. })(jQuery, DevExpress);
  71664. /*! Module viz-core, file svgRenderer.js */
  71665. (function($, DX, doc, undefined) {
  71666. var rendererNS = DX.viz.renderers = {},
  71667. math = Math,
  71668. mathMin = math.min,
  71669. mathMax = math.max,
  71670. mathCeil = math.ceil,
  71671. mathFloor = math.floor,
  71672. mathRound = math.round,
  71673. mathSin = math.sin,
  71674. mathCos = math.cos,
  71675. mathAbs = math.abs,
  71676. mathPI = math.PI,
  71677. PI_DIV_180 = mathPI / 180,
  71678. _parseInt = parseInt,
  71679. MAX_PIXEL_COUNT = 1E10,
  71680. SHARPING_CORRECTION = 0.5,
  71681. ARC_COORD_PREC = 5;
  71682. var pxAddingExceptions = {
  71683. "column-count": true,
  71684. "fill-opacity": true,
  71685. "flex-grow": true,
  71686. "flex-shrink": true,
  71687. "font-weight": true,
  71688. "line-height": true,
  71689. opacity: true,
  71690. order: true,
  71691. orphans: true,
  71692. widows: true,
  71693. "z-index": true,
  71694. zoom: true
  71695. };
  71696. var KEY_TEXT = "text",
  71697. KEY_STROKE = "stroke",
  71698. KEY_STROKE_WIDTH = "stroke-width",
  71699. KEY_STROKE_OPACITY = "stroke-opacity",
  71700. KEY_FONT_SIZE = "font-size",
  71701. KEY_FONT_STYLE = "font-style",
  71702. KEY_FONT_WEIGHT = "font-weight",
  71703. KEY_TEXT_DECORATION = "text-decoration",
  71704. NONE = "none";
  71705. var DEFAULTS = {
  71706. scaleX: 1,
  71707. scaleY: 1
  71708. };
  71709. var getNextDefsSvgId = function() {
  71710. var numDefsSvgElements = 1;
  71711. return function() {
  71712. return "DevExpress_" + numDefsSvgElements++
  71713. }
  71714. }();
  71715. function isObjectArgument(value) {
  71716. return typeof value !== "string"
  71717. }
  71718. function isDefined(value) {
  71719. return value !== null && value !== undefined
  71720. }
  71721. function isArray(value) {
  71722. return Object.prototype.toString.call(value) === "[object Array]"
  71723. }
  71724. function isObject(value) {
  71725. return Object.prototype.toString.call(value) === "[object Object]"
  71726. }
  71727. function createElement(tagName) {
  71728. return doc.createElementNS("http://www.w3.org/2000/svg", tagName)
  71729. }
  71730. function getPatternUrl(id, pathModified) {
  71731. return id !== null ? "url(" + (pathModified ? window.location.href : "") + "#" + id + ")" : ""
  71732. }
  71733. function extend(a, b, skipNonDefined) {
  71734. var value;
  71735. for (var key in b) {
  71736. value = b[key];
  71737. if (!skipNonDefined || skipNonDefined && value !== undefined && value !== null)
  71738. a[key] = value
  71739. }
  71740. return a
  71741. }
  71742. function rotateBBox(bbox, center, angle) {
  71743. var cos = Number(mathCos(angle * PI_DIV_180).toFixed(3)),
  71744. sin = Number(mathSin(angle * PI_DIV_180).toFixed(3)),
  71745. w2 = bbox.width / 2,
  71746. h2 = bbox.height / 2,
  71747. xc = bbox.x + w2,
  71748. yc = bbox.y + h2,
  71749. w2_ = mathAbs(w2 * cos) + mathAbs(h2 * sin),
  71750. h2_ = mathAbs(w2 * sin) + mathAbs(h2 * cos),
  71751. xc_ = center[0] + (xc - center[0]) * cos + (yc - center[1]) * sin,
  71752. yc_ = center[1] - (xc - center[0]) * sin + (yc - center[1]) * cos;
  71753. return normalizeBBox({
  71754. x: xc_ - w2_,
  71755. y: yc_ - h2_,
  71756. width: 2 * w2_,
  71757. height: 2 * h2_
  71758. })
  71759. }
  71760. function normalizeBBoxField(value) {
  71761. return -MAX_PIXEL_COUNT < value && value < +MAX_PIXEL_COUNT ? value : 0
  71762. }
  71763. function normalizeBBox(bbox) {
  71764. var rxl = normalizeBBoxField(mathFloor(bbox.x)),
  71765. ryt = normalizeBBoxField(mathFloor(bbox.y)),
  71766. rxr = normalizeBBoxField(mathCeil(bbox.width + bbox.x)),
  71767. ryb = normalizeBBoxField(mathCeil(bbox.height + bbox.y)),
  71768. result = {
  71769. x: rxl,
  71770. y: ryt,
  71771. width: rxr - rxl,
  71772. height: ryb - ryt
  71773. };
  71774. result.isEmpty = !result.x && !result.y && !result.width && !result.height;
  71775. return result
  71776. }
  71777. function getPreserveAspectRatio(location) {
  71778. return {
  71779. full: NONE,
  71780. lefttop: "xMinYMin",
  71781. leftcenter: "xMinYMid",
  71782. leftbottom: "xMinYMax",
  71783. centertop: "xMidYMin",
  71784. center: "xMidYMid",
  71785. centerbottom: "xMidYMax",
  71786. righttop: "xMaxYMin",
  71787. rightcenter: "xMaxYMid",
  71788. rightbottom: "xMaxYMax"
  71789. }[(location || "").toLowerCase()] || NONE
  71790. }
  71791. rendererNS._normalizeArcParams = function(x, y, innerR, outerR, startAngle, endAngle) {
  71792. var isCircle,
  71793. noArc = true;
  71794. if (mathRound(startAngle) !== mathRound(endAngle)) {
  71795. if (mathAbs(endAngle - startAngle) % 360 === 0) {
  71796. startAngle = 0;
  71797. endAngle = 360;
  71798. isCircle = true;
  71799. endAngle -= 0.01
  71800. }
  71801. if (startAngle > 360)
  71802. startAngle = startAngle % 360;
  71803. if (endAngle > 360)
  71804. endAngle = endAngle % 360;
  71805. if (startAngle > endAngle)
  71806. startAngle -= 360;
  71807. noArc = false
  71808. }
  71809. startAngle = startAngle * PI_DIV_180;
  71810. endAngle = endAngle * PI_DIV_180;
  71811. return [x, y, mathMin(outerR, innerR), mathMax(outerR, innerR), mathCos(startAngle), mathSin(startAngle), mathCos(endAngle), mathSin(endAngle), isCircle, mathFloor(mathAbs(endAngle - startAngle) / mathPI) % 2 ? "1" : "0", noArc]
  71812. };
  71813. var buildArcPath = function(x, y, innerR, outerR, startAngleCos, startAngleSin, endAngleCos, endAngleSin, isCircle, longFlag) {
  71814. return ["M", (x + outerR * startAngleCos).toFixed(ARC_COORD_PREC), (y - outerR * startAngleSin).toFixed(ARC_COORD_PREC), "A", outerR.toFixed(ARC_COORD_PREC), outerR.toFixed(ARC_COORD_PREC), 0, longFlag, 0, (x + outerR * endAngleCos).toFixed(ARC_COORD_PREC), (y - outerR * endAngleSin).toFixed(ARC_COORD_PREC), isCircle ? "M" : "L", (x + innerR * endAngleCos).toFixed(5), (y - innerR * endAngleSin).toFixed(ARC_COORD_PREC), "A", innerR.toFixed(ARC_COORD_PREC), innerR.toFixed(ARC_COORD_PREC), 0, longFlag, 1, (x + innerR * startAngleCos).toFixed(ARC_COORD_PREC), (y - innerR * startAngleSin).toFixed(ARC_COORD_PREC), "Z"].join(" ")
  71815. };
  71816. function buildPathSegments(points, type) {
  71817. var list = [["M", 0, 0]];
  71818. switch (type) {
  71819. case"line":
  71820. list = buildLineSegments(points);
  71821. break;
  71822. case"area":
  71823. list = buildLineSegments(points, true);
  71824. break;
  71825. case"bezier":
  71826. list = buildCurveSegments(points);
  71827. break;
  71828. case"bezierarea":
  71829. list = buildCurveSegments(points, true);
  71830. break
  71831. }
  71832. return list
  71833. }
  71834. function buildLineSegments(points, close) {
  71835. return buildSegments(points, buildSimpleLineSegment, close)
  71836. }
  71837. function buildCurveSegments(points, close) {
  71838. return buildSegments(points, buildSimpleCurveSegment, close)
  71839. }
  71840. function buildSegments(points, buildSimpleSegment, close) {
  71841. var i = 0,
  71842. ii = (points || []).length,
  71843. list = [];
  71844. if (isArray(points[0]))
  71845. for (; i < ii; )
  71846. buildSimpleSegment(points[i++], close, list);
  71847. else
  71848. buildSimpleSegment(points, close, list);
  71849. return list
  71850. }
  71851. function buildSimpleLineSegment(points, close, list) {
  71852. var i = 0,
  71853. ii = (points || []).length;
  71854. if (ii)
  71855. if (isObject(points[0]))
  71856. for (; i < ii; )
  71857. list.push([!i ? "M" : "L", points[i].x, points[i++].y]);
  71858. else
  71859. for (; i < ii; )
  71860. list.push([!i ? "M" : "L", points[i++], points[i++]]);
  71861. else
  71862. list.push(["M", 0, 0]);
  71863. close && list.push(["Z"]);
  71864. return list
  71865. }
  71866. function buildSimpleCurveSegment(points, close, list) {
  71867. var i = 2,
  71868. ii = (points || []).length;
  71869. if (ii)
  71870. if (isObject(points[0])) {
  71871. i = 1;
  71872. list.push(["M", points[0].x, points[0].y]);
  71873. for (; i < ii; )
  71874. list.push(["C", points[i].x, points[i++].y, points[i].x, points[i++].y, points[i].x, points[i++].y])
  71875. }
  71876. else {
  71877. list.push(["M", points[0], points[1]]);
  71878. for (; i < ii; )
  71879. list.push(["C", points[i++], points[i++], points[i++], points[i++], points[i++], points[i++]])
  71880. }
  71881. else
  71882. list.push(["M", 0, 0]);
  71883. close && list.push(["Z"]);
  71884. return list
  71885. }
  71886. function combinePathParam(segments) {
  71887. var d = [],
  71888. i = 0,
  71889. length = segments.length;
  71890. for (; i < length; i++)
  71891. d.push(segments[i].join(" "));
  71892. return d.join(" ")
  71893. }
  71894. function compensateSegments(oldSegments, newSegments, type) {
  71895. var oldLength = oldSegments.length,
  71896. newLength = newSegments.length,
  71897. i,
  71898. originalNewSegments,
  71899. makeEqualSegments = type.indexOf("area") !== -1 ? makeEqualAreaSegments : makeEqualLineSegments;
  71900. if (oldLength === 0)
  71901. for (i = 0; i < newLength; i++)
  71902. oldSegments.push(newSegments[i].slice(0));
  71903. else if (oldLength < newLength)
  71904. makeEqualSegments(oldSegments, newSegments, type);
  71905. else if (oldLength > newLength) {
  71906. originalNewSegments = newSegments.slice(0);
  71907. makeEqualSegments(newSegments, oldSegments, type)
  71908. }
  71909. return originalNewSegments
  71910. }
  71911. function prepareConstSegment(constSeg, type) {
  71912. var x = constSeg[constSeg.length - 2],
  71913. y = constSeg[constSeg.length - 1];
  71914. switch (type) {
  71915. case"line":
  71916. case"area":
  71917. constSeg[0] = "L";
  71918. break;
  71919. case"bezier":
  71920. case"bezierarea":
  71921. constSeg[0] = "C";
  71922. constSeg[1] = constSeg[3] = constSeg[5] = x;
  71923. constSeg[2] = constSeg[4] = constSeg[6] = y;
  71924. break
  71925. }
  71926. }
  71927. function makeEqualLineSegments(short, long, type) {
  71928. var constSeg = short[short.length - 1].slice(),
  71929. i = short.length;
  71930. prepareConstSegment(constSeg, type);
  71931. for (; i < long.length; i++)
  71932. short[i] = constSeg.slice(0)
  71933. }
  71934. function makeEqualAreaSegments(short, long, type) {
  71935. var i,
  71936. head,
  71937. shortLength = short.length,
  71938. longLength = long.length,
  71939. constsSeg1,
  71940. constsSeg2;
  71941. if ((shortLength - 1) % 2 === 0 && (longLength - 1) % 2 === 0) {
  71942. i = (shortLength - 1) / 2 - 1;
  71943. head = short.slice(0, i + 1);
  71944. constsSeg1 = head[head.length - 1].slice(0);
  71945. constsSeg2 = short.slice(i + 1)[0].slice(0);
  71946. prepareConstSegment(constsSeg1, type);
  71947. prepareConstSegment(constsSeg2, type);
  71948. for (var j = i; j < (longLength - 1) / 2 - 1; j++) {
  71949. short.splice(j + 1, 0, constsSeg1);
  71950. short.splice(j + 3, 0, constsSeg2)
  71951. }
  71952. }
  71953. }
  71954. function baseCss(styles) {
  71955. var elemStyles = this._styles,
  71956. str = "",
  71957. key,
  71958. value;
  71959. extend(elemStyles, styles || {}, true);
  71960. for (key in elemStyles) {
  71961. value = elemStyles[key];
  71962. if (value === "")
  71963. continue;
  71964. if (typeof value === "number" && !pxAddingExceptions[key])
  71965. value += "px";
  71966. str += key + ":" + value + ";"
  71967. }
  71968. str && this.element.setAttribute("style", str);
  71969. return this
  71970. }
  71971. function baseAttr(attrs) {
  71972. attrs = attrs || {};
  71973. var that = this,
  71974. settings = that._settings,
  71975. attributes = {},
  71976. key,
  71977. value,
  71978. elem = that.element,
  71979. renderer = that.renderer,
  71980. rtl = renderer.rtl,
  71981. hasTransformations,
  71982. recalculateDashStyle,
  71983. sw,
  71984. i;
  71985. if (!isObjectArgument(attrs)) {
  71986. if (attrs in settings)
  71987. return settings[attrs];
  71988. if (attrs in DEFAULTS)
  71989. return DEFAULTS[attrs];
  71990. return 0
  71991. }
  71992. extend(attributes, attrs);
  71993. for (key in attributes) {
  71994. value = attributes[key];
  71995. if (value === undefined)
  71996. continue;
  71997. settings[key] = value;
  71998. if (key === "align") {
  71999. key = "text-anchor";
  72000. value = {
  72001. left: rtl ? "end" : "start",
  72002. center: "middle",
  72003. right: rtl ? "start" : "end"
  72004. }[value] || ""
  72005. }
  72006. else if (key === "dashStyle") {
  72007. recalculateDashStyle = true;
  72008. continue
  72009. }
  72010. else if (key === KEY_STROKE_WIDTH)
  72011. recalculateDashStyle = true;
  72012. else if (key === "clipId") {
  72013. key = "clip-path";
  72014. value = getPatternUrl(value, renderer.pathModified)
  72015. }
  72016. else if (/^(translate(X|Y)|rotate[XY]?|scale(X|Y)|sharp)$/i.test(key)) {
  72017. hasTransformations = true;
  72018. continue
  72019. }
  72020. else if (/^(x|y|d)$/i.test(key))
  72021. hasTransformations = true;
  72022. if (value === null)
  72023. elem.removeAttribute(key);
  72024. else
  72025. elem.setAttribute(key, value)
  72026. }
  72027. if (recalculateDashStyle && "dashStyle" in settings) {
  72028. value = settings.dashStyle;
  72029. sw = ("_originalSW" in that ? that._originalSW : settings[KEY_STROKE_WIDTH]) || 1;
  72030. key = "stroke-dasharray";
  72031. value = value === null ? "" : value.toLowerCase();
  72032. if (value === "" || value === "solid" || value === NONE)
  72033. that.element.removeAttribute(key);
  72034. else {
  72035. value = value.replace(/longdash/g, "8,3,").replace(/dash/g, "4,3,").replace(/dot/g, "1,3,").replace(/,$/, "").split(",");
  72036. i = value.length;
  72037. while (i--)
  72038. value[i] = _parseInt(value[i]) * sw;
  72039. that.element.setAttribute(key, value.join(","))
  72040. }
  72041. }
  72042. if (hasTransformations)
  72043. that._applyTransformation();
  72044. return that
  72045. }
  72046. function createPathAttr(baseAttr) {
  72047. return function(attrs, inh) {
  72048. var that = this,
  72049. segments;
  72050. if (isObjectArgument(attrs)) {
  72051. attrs = extend({}, attrs);
  72052. segments = attrs.segments;
  72053. if ("points" in attrs) {
  72054. segments = buildPathSegments(attrs.points, that.type);
  72055. delete attrs.points
  72056. }
  72057. if (segments) {
  72058. attrs.d = combinePathParam(segments);
  72059. that.segments = segments;
  72060. delete attrs.segments
  72061. }
  72062. }
  72063. return baseAttr.call(that, attrs, inh)
  72064. }
  72065. }
  72066. function createArcAttr(baseAttr, buildArcPath) {
  72067. return function(attrs, inh) {
  72068. var settings = this._settings,
  72069. x,
  72070. y,
  72071. innerRadius,
  72072. outerRadius,
  72073. startAngle,
  72074. endAngle;
  72075. if (isObjectArgument(attrs)) {
  72076. attrs = extend({}, attrs);
  72077. if ("x" in attrs || "y" in attrs || "innerRadius" in attrs || "outerRadius" in attrs || "startAngle" in attrs || "endAngle" in attrs) {
  72078. settings.x = x = "x" in attrs ? attrs.x : settings.x;
  72079. delete attrs.x;
  72080. settings.y = y = "y" in attrs ? attrs.y : settings.y;
  72081. delete attrs.y;
  72082. settings.innerRadius = innerRadius = "innerRadius" in attrs ? attrs.innerRadius : settings.innerRadius;
  72083. delete attrs.innerRadius;
  72084. settings.outerRadius = outerRadius = "outerRadius" in attrs ? attrs.outerRadius : settings.outerRadius;
  72085. delete attrs.outerRadius;
  72086. settings.startAngle = startAngle = "startAngle" in attrs ? attrs.startAngle : settings.startAngle;
  72087. delete attrs.startAngle;
  72088. settings.endAngle = endAngle = "endAngle" in attrs ? attrs.endAngle : settings.endAngle;
  72089. delete attrs.endAngle;
  72090. attrs.d = buildArcPath.apply(this, rendererNS._normalizeArcParams(x, y, innerRadius, outerRadius, startAngle, endAngle))
  72091. }
  72092. }
  72093. return baseAttr.call(this, attrs, inh)
  72094. }
  72095. }
  72096. function createRectAttr(baseAttr) {
  72097. return function(attrs, inh) {
  72098. var that = this,
  72099. x,
  72100. y,
  72101. width,
  72102. height,
  72103. sw,
  72104. maxSW,
  72105. newSW;
  72106. if (isObjectArgument(attrs)) {
  72107. attrs = extend({}, attrs);
  72108. if (!inh && (attrs.x !== undefined || attrs.y !== undefined || attrs.width !== undefined || attrs.height !== undefined || attrs[KEY_STROKE_WIDTH] !== undefined)) {
  72109. attrs.x !== undefined ? x = that._originalX = attrs.x : x = that._originalX || 0;
  72110. attrs.y !== undefined ? y = that._originalY = attrs.y : y = that._originalY || 0;
  72111. attrs.width !== undefined ? width = that._originalWidth = attrs.width : width = that._originalWidth || 0;
  72112. attrs.height !== undefined ? height = that._originalHeight = attrs.height : height = that._originalHeight || 0;
  72113. attrs[KEY_STROKE_WIDTH] !== undefined ? sw = that._originalSW = attrs[KEY_STROKE_WIDTH] : sw = that._originalSW;
  72114. maxSW = ~~((width < height ? width : height) / 2);
  72115. newSW = (sw || 0) < maxSW ? sw || 0 : maxSW;
  72116. attrs.x = x + newSW / 2;
  72117. attrs.y = y + newSW / 2;
  72118. attrs.width = width - newSW;
  72119. attrs.height = height - newSW;
  72120. ((sw || 0) !== newSW || !(newSW === 0 && sw === undefined)) && (attrs[KEY_STROKE_WIDTH] = newSW)
  72121. }
  72122. if ("sharp" in attrs)
  72123. delete attrs.sharp
  72124. }
  72125. return baseAttr.call(that, attrs, inh)
  72126. }
  72127. }
  72128. var pathAttr = createPathAttr(baseAttr),
  72129. arcAttr = createArcAttr(baseAttr, buildArcPath),
  72130. rectAttr = createRectAttr(baseAttr);
  72131. function textAttr(attrs) {
  72132. var that = this,
  72133. settings,
  72134. isResetRequired,
  72135. wasStroked,
  72136. isStroked;
  72137. if (!isObjectArgument(attrs))
  72138. return baseAttr.call(that, attrs);
  72139. attrs = extend({}, attrs);
  72140. settings = that._settings;
  72141. wasStroked = isDefined(settings[KEY_STROKE]) && isDefined(settings[KEY_STROKE_WIDTH]);
  72142. if (attrs[KEY_TEXT] !== undefined) {
  72143. settings[KEY_TEXT] = attrs[KEY_TEXT];
  72144. delete attrs[KEY_TEXT];
  72145. isResetRequired = true
  72146. }
  72147. if (attrs[KEY_STROKE] !== undefined) {
  72148. settings[KEY_STROKE] = attrs[KEY_STROKE];
  72149. delete attrs[KEY_STROKE]
  72150. }
  72151. if (attrs[KEY_STROKE_WIDTH] !== undefined) {
  72152. settings[KEY_STROKE_WIDTH] = attrs[KEY_STROKE_WIDTH];
  72153. delete attrs[KEY_STROKE_WIDTH]
  72154. }
  72155. if (attrs[KEY_STROKE_OPACITY] !== undefined) {
  72156. settings[KEY_STROKE_OPACITY] = attrs[KEY_STROKE_OPACITY];
  72157. delete attrs[KEY_STROKE_OPACITY]
  72158. }
  72159. isStroked = isDefined(settings[KEY_STROKE]) && isDefined(settings[KEY_STROKE_WIDTH]);
  72160. baseAttr.call(that, attrs);
  72161. isResetRequired = isResetRequired || isStroked !== wasStroked && settings[KEY_TEXT];
  72162. if (isResetRequired)
  72163. createTextNodes(that, settings.text, isStroked);
  72164. if (isResetRequired || attrs["x"] !== undefined || attrs["y"] !== undefined)
  72165. locateTextNodes(that);
  72166. if (isStroked)
  72167. strokeTextNodes(that);
  72168. return that
  72169. }
  72170. function textCss(styles) {
  72171. styles = styles || {};
  72172. baseCss.call(this, styles);
  72173. if (KEY_FONT_SIZE in styles)
  72174. locateTextNodes(this);
  72175. return this
  72176. }
  72177. function orderHtmlTree(strCount, node, textArray) {
  72178. var nodeParams = node.params = node.params || {style: {}},
  72179. nodeStyle = nodeParams.style,
  72180. parentStyle = node.parentNode && node.parentNode.params && node.parentNode.params.style || {},
  72181. nativeElementStyle = node.style,
  72182. childCount = node.childNodes.length,
  72183. count = 0;
  72184. if (node.nodeName !== '#text')
  72185. extend(nodeStyle, parentStyle);
  72186. switch (node.tagName) {
  72187. case'B':
  72188. case'STRONG':
  72189. nodeStyle[KEY_FONT_WEIGHT] = 'bold';
  72190. break;
  72191. case'I':
  72192. case'EM':
  72193. nodeStyle[KEY_FONT_STYLE] = 'italic';
  72194. break;
  72195. case'U':
  72196. nodeStyle[KEY_TEXT_DECORATION] = 'underline';
  72197. break;
  72198. case'BR':
  72199. strCount++;
  72200. break
  72201. }
  72202. if (nativeElementStyle) {
  72203. if (nativeElementStyle.fontSize)
  72204. nodeStyle[KEY_FONT_SIZE] = (_parseInt(nativeElementStyle.fontSize, 10) || nodeStyle[KEY_FONT_SIZE]) + 'px';
  72205. nodeStyle.fill = nativeElementStyle.color || nodeStyle.fill;
  72206. nodeStyle[KEY_FONT_STYLE] = nativeElementStyle.fontStyle || nodeStyle[KEY_FONT_STYLE];
  72207. nodeStyle[KEY_FONT_WEIGHT] = nativeElementStyle.fontWeight || nodeStyle[KEY_FONT_WEIGHT];
  72208. nodeStyle[KEY_TEXT_DECORATION] = nativeElementStyle.textDecoration || nodeStyle[KEY_TEXT_DECORATION]
  72209. }
  72210. while (count !== childCount)
  72211. strCount = orderHtmlTree(strCount, node.childNodes[count++], textArray);
  72212. if (node.wholeText !== undefined) {
  72213. extend(nodeStyle, parentStyle);
  72214. textArray.push({
  72215. value: node.wholeText,
  72216. style: nodeStyle,
  72217. line: strCount,
  72218. height: _parseInt(nodeStyle[KEY_FONT_SIZE], 10) || 0
  72219. })
  72220. }
  72221. return strCount
  72222. }
  72223. function adjustLineHeights(items) {
  72224. var i,
  72225. ii,
  72226. currentItem = items[0],
  72227. item;
  72228. for (i = 1, ii = items.length; i < ii; ++i) {
  72229. item = items[i];
  72230. if (item.line === currentItem.line) {
  72231. currentItem.height = mathMax(currentItem.height, item.height);
  72232. currentItem.inherits = currentItem.inherits || item.height === 0;
  72233. item.height = NaN
  72234. }
  72235. else
  72236. currentItem = item
  72237. }
  72238. }
  72239. function parseHTML(text) {
  72240. var items = [],
  72241. div = doc.createElement("div");
  72242. div.innerHTML = text.replace(/\r/g, "").replace(/\n/g, "<br/>");
  72243. orderHtmlTree(0, div, items);
  72244. adjustLineHeights(items);
  72245. return items
  72246. }
  72247. function parseMultiline(text) {
  72248. var texts = text.replace(/\r/g, "").split("\n"),
  72249. i = 0,
  72250. items = [];
  72251. for (; i < texts.length; i++)
  72252. items.push({
  72253. value: texts[i],
  72254. height: 0
  72255. });
  72256. return items
  72257. }
  72258. function createTspans(items, element, fieldName) {
  72259. var i,
  72260. ii,
  72261. item;
  72262. for (i = 0, ii = items.length; i < ii; ++i) {
  72263. item = items[i];
  72264. item[fieldName] = createElement("tspan");
  72265. item[fieldName].appendChild(doc.createTextNode(item.value));
  72266. item.style && baseCss.call({
  72267. element: item[fieldName],
  72268. _styles: {}
  72269. }, item.style);
  72270. element.appendChild(item[fieldName])
  72271. }
  72272. }
  72273. function createTextNodes(wrapper, text, isStroked) {
  72274. var items;
  72275. wrapper._texts = null;
  72276. wrapper.clear();
  72277. if (text === null)
  72278. return;
  72279. text = "" + text;
  72280. if (!wrapper.renderer.encodeHtml && (text.indexOf("<") !== -1 || text.indexOf("&") !== -1))
  72281. items = parseHTML(text);
  72282. else if (text.indexOf("\n") !== -1)
  72283. items = parseMultiline(text);
  72284. else if (isStroked)
  72285. items = [{
  72286. value: text,
  72287. height: 0
  72288. }];
  72289. if (items) {
  72290. if (items.length) {
  72291. wrapper._texts = items;
  72292. if (isStroked)
  72293. createTspans(items, wrapper.element, KEY_STROKE);
  72294. createTspans(items, wrapper.element, "tspan")
  72295. }
  72296. }
  72297. else
  72298. wrapper.element.appendChild(doc.createTextNode(text))
  72299. }
  72300. function setTextNodeAttribute(item, name, value) {
  72301. item.tspan.setAttribute(name, value);
  72302. item.stroke && item.stroke.setAttribute(name, value)
  72303. }
  72304. function locateTextNodes(wrapper) {
  72305. if (!wrapper._texts)
  72306. return;
  72307. var items = wrapper._texts,
  72308. x = wrapper._settings.x,
  72309. lineHeight = wrapper._styles[KEY_FONT_SIZE] || 12,
  72310. i,
  72311. ii,
  72312. item = items[0];
  72313. setTextNodeAttribute(item, "x", x);
  72314. setTextNodeAttribute(item, "y", wrapper._settings.y);
  72315. for (i = 1, ii = items.length; i < ii; ++i) {
  72316. item = items[i];
  72317. if (item.height >= 0) {
  72318. setTextNodeAttribute(item, "x", x);
  72319. setTextNodeAttribute(item, "dy", item.inherits ? mathMax(item.height, lineHeight) : item.height || lineHeight)
  72320. }
  72321. }
  72322. }
  72323. function strokeTextNodes(wrapper) {
  72324. if (!wrapper._texts)
  72325. return;
  72326. var items = wrapper._texts,
  72327. stroke = wrapper._settings[KEY_STROKE],
  72328. strokeWidth = wrapper._settings[KEY_STROKE_WIDTH],
  72329. strokeOpacity = wrapper._settings[KEY_STROKE_OPACITY] || 1,
  72330. tspan,
  72331. i,
  72332. ii;
  72333. for (i = 0, ii = items.length; i < ii; ++i) {
  72334. tspan = items[i].stroke;
  72335. tspan.setAttribute(KEY_STROKE, stroke);
  72336. tspan.setAttribute(KEY_STROKE_WIDTH, strokeWidth);
  72337. tspan.setAttribute(KEY_STROKE_OPACITY, strokeOpacity);
  72338. tspan.setAttribute("stroke-linejoin", "round")
  72339. }
  72340. }
  72341. function baseAnimate(params, options, complete) {
  72342. options = options || {};
  72343. var that = this,
  72344. key,
  72345. value,
  72346. renderer = that.renderer,
  72347. settings = that._settings,
  72348. animationParams = {};
  72349. var defaults = {
  72350. translateX: 0,
  72351. translateY: 0,
  72352. scaleX: 1,
  72353. scaleY: 1,
  72354. rotate: 0,
  72355. rotateX: 0,
  72356. rotateY: 0
  72357. };
  72358. if (complete)
  72359. options.complete = complete;
  72360. if (renderer.animationEnabled()) {
  72361. for (key in params) {
  72362. value = params[key];
  72363. if (/^(translate(X|Y)|rotate[XY]?|scale(X|Y))$/i.test(key)) {
  72364. animationParams.transform = animationParams.transform || {
  72365. from: {},
  72366. to: {}
  72367. };
  72368. animationParams.transform.from[key] = key in settings ? settings[key] : defaults[key];
  72369. animationParams.transform.to[key] = value
  72370. }
  72371. else if (key === "arc" || key === "segments")
  72372. animationParams[key] = value;
  72373. else
  72374. animationParams[key] = {
  72375. from: key in settings ? settings[key] : parseFloat(that.element.getAttribute(key) || 0),
  72376. to: value
  72377. }
  72378. }
  72379. renderer.animateElement(that, animationParams, extend(extend({}, renderer._animation), options))
  72380. }
  72381. else {
  72382. options.step && options.step.call(that, 1, 1);
  72383. options.complete && options.complete.call(that);
  72384. that.attr(params)
  72385. }
  72386. return that
  72387. }
  72388. function pathAnimate(params, options, complete) {
  72389. var that = this,
  72390. curSegments = that.segments || [],
  72391. newSegments,
  72392. endSegments;
  72393. if (that.renderer.animationEnabled() && "points" in params) {
  72394. newSegments = buildPathSegments(params.points, that.type);
  72395. endSegments = compensateSegments(curSegments, newSegments, that.type);
  72396. params.segments = {
  72397. from: curSegments,
  72398. to: newSegments,
  72399. end: endSegments
  72400. };
  72401. delete params.points
  72402. }
  72403. return baseAnimate.call(that, params, options, complete)
  72404. }
  72405. function arcAnimate(params, options, complete) {
  72406. var that = this,
  72407. settings = that._settings,
  72408. arcParams = {
  72409. from: {},
  72410. to: {}
  72411. };
  72412. if (that.renderer.animationEnabled() && ("x" in params || "y" in params || "innerRadius" in params || "outerRadius" in params || "startAngle" in params || "endAngle" in params)) {
  72413. arcParams.from.x = settings.x || 0;
  72414. arcParams.from.y = settings.y || 0;
  72415. arcParams.from.innerRadius = settings.innerRadius || 0;
  72416. arcParams.from.outerRadius = settings.outerRadius || 0;
  72417. arcParams.from.startAngle = settings.startAngle || 0;
  72418. arcParams.from.endAngle = settings.endAngle || 0;
  72419. arcParams.to.x = "x" in params ? params.x : settings.x;
  72420. delete params.x;
  72421. arcParams.to.y = "y" in params ? params.y : settings.y;
  72422. delete params.y;
  72423. arcParams.to.innerRadius = "innerRadius" in params ? params.innerRadius : settings.innerRadius;
  72424. delete params.innerRadius;
  72425. arcParams.to.outerRadius = "outerRadius" in params ? params.outerRadius : settings.outerRadius;
  72426. delete params.outerRadius;
  72427. arcParams.to.startAngle = "startAngle" in params ? params.startAngle : settings.startAngle;
  72428. delete params.startAngle;
  72429. arcParams.to.endAngle = "endAngle" in params ? params.endAngle : settings.endAngle;
  72430. delete params.endAngle;
  72431. params.arc = arcParams
  72432. }
  72433. return baseAnimate.call(that, params, options, complete)
  72434. }
  72435. rendererNS.__mockPrivateFunctions = function(fs) {
  72436. fs = fs || {};
  72437. function mockFunction(mock, orig) {
  72438. if (!mock)
  72439. return orig;
  72440. var originalFunction = orig;
  72441. orig = mock;
  72442. orig._originalFunction = originalFunction;
  72443. return orig
  72444. }
  72445. createElement = mockFunction(fs.createElement, createElement);
  72446. baseAttr = mockFunction(fs.baseAttr, baseAttr);
  72447. baseAnimate = mockFunction(fs.baseAnimate, baseAnimate);
  72448. getNextDefsSvgId = mockFunction(fs.getNextDefsSvgId, getNextDefsSvgId);
  72449. compensateSegments = mockFunction(fs.compensateSegments, compensateSegments);
  72450. buildPathSegments = mockFunction(fs.buildPathSegments, buildPathSegments);
  72451. buildArcPath = mockFunction(fs.buildArcPath, buildArcPath);
  72452. pathAttr = createPathAttr(baseAttr);
  72453. arcAttr = createArcAttr(baseAttr, buildArcPath);
  72454. rectAttr = createRectAttr(baseAttr);
  72455. return {
  72456. createElement: createElement,
  72457. baseAttr: baseAttr,
  72458. baseAnimate: baseAnimate,
  72459. getNextDefsSvgId: getNextDefsSvgId,
  72460. compensateSegments: compensateSegments,
  72461. buildPathSegments: buildPathSegments,
  72462. buildArcPath: buildArcPath
  72463. }
  72464. };
  72465. rendererNS.__restoreMockPrivateFunctions = function() {
  72466. function restoreFunction(func) {
  72467. return func._originalFunction || func
  72468. }
  72469. createElement = restoreFunction(createElement);
  72470. baseAttr = restoreFunction(baseAttr);
  72471. baseAnimate = restoreFunction(baseAnimate);
  72472. getNextDefsSvgId = restoreFunction(getNextDefsSvgId);
  72473. compensateSegments = restoreFunction(compensateSegments);
  72474. buildPathSegments = restoreFunction(buildPathSegments);
  72475. buildArcPath = restoreFunction(buildArcPath);
  72476. pathAttr = createPathAttr(baseAttr);
  72477. arcAttr = createArcAttr(baseAttr, buildArcPath);
  72478. rectAttr = createRectAttr(baseAttr)
  72479. };
  72480. function SvgElement() {
  72481. this.ctor.apply(this, arguments)
  72482. }
  72483. rendererNS.SvgElement = SvgElement;
  72484. SvgElement.prototype = {
  72485. ctor: function(renderer, tagName, type) {
  72486. var that = this;
  72487. that.renderer = renderer;
  72488. that.element = createElement(tagName);
  72489. that._settings = {};
  72490. that._styles = {};
  72491. if (tagName === "path")
  72492. that.type = type || "line";
  72493. if (tagName === "text") {
  72494. that.attr = textAttr;
  72495. that.css = textCss
  72496. }
  72497. else if (tagName === "path")
  72498. if (that.type === "arc") {
  72499. that.attr = arcAttr;
  72500. that.animate = arcAnimate
  72501. }
  72502. else {
  72503. that.attr = pathAttr;
  72504. that.animate = pathAnimate
  72505. }
  72506. else if (tagName === "rect") {
  72507. that.attr = rectAttr;
  72508. that.sharp = function() {
  72509. return this
  72510. }
  72511. }
  72512. that._$element = $(that.element)
  72513. },
  72514. dispose: function() {
  72515. this._$element.remove();
  72516. return this
  72517. },
  72518. append: function(parent) {
  72519. parent = parent || this.renderer.root;
  72520. (parent.element || parent).appendChild(this.element);
  72521. return this
  72522. },
  72523. remove: function() {
  72524. var elem = this.element,
  72525. parent = elem.parentNode;
  72526. parent && parent.removeChild(elem);
  72527. return this
  72528. },
  72529. clear: function() {
  72530. this._$element.empty();
  72531. return this
  72532. },
  72533. toBackground: function() {
  72534. var elem = this.element,
  72535. parent = elem.parentNode;
  72536. parent && parent.insertBefore(elem, parent.firstChild);
  72537. return this
  72538. },
  72539. toForeground: function() {
  72540. var elem = this.element,
  72541. parent = elem.parentNode;
  72542. parent && parent.appendChild(elem);
  72543. return this
  72544. },
  72545. css: baseCss,
  72546. attr: baseAttr,
  72547. sharp: function(pos) {
  72548. return this.attr({sharp: pos || true})
  72549. },
  72550. _applyTransformation: function() {
  72551. var tr = this._settings,
  72552. scaleXDefined,
  72553. scaleYDefined,
  72554. transformations = [],
  72555. rotateX,
  72556. rotateY,
  72557. sharpMode = tr.sharp,
  72558. strokeOdd = tr[KEY_STROKE_WIDTH] % 2,
  72559. correctionX = strokeOdd && (sharpMode === "h" || sharpMode === true) ? SHARPING_CORRECTION : 0,
  72560. correctionY = strokeOdd && (sharpMode === "v" || sharpMode === true) ? SHARPING_CORRECTION : 0;
  72561. if (!("rotateX" in tr))
  72562. rotateX = tr.x;
  72563. else
  72564. rotateX = tr.rotateX;
  72565. if (!("rotateY" in tr))
  72566. rotateY = tr.y;
  72567. else
  72568. rotateY = tr.rotateY;
  72569. transformations.push("translate(" + ((tr.translateX || 0) + correctionX) + "," + ((tr.translateY || 0) + correctionY) + ")");
  72570. if (tr.rotate)
  72571. transformations.push("rotate(" + tr.rotate + "," + (rotateX || 0) + "," + (rotateY || 0) + ")");
  72572. scaleXDefined = isDefined(tr.scaleX);
  72573. scaleYDefined = isDefined(tr.scaleY);
  72574. if (scaleXDefined || scaleYDefined)
  72575. transformations.push("scale(" + (scaleXDefined ? tr.scaleX : 1) + "," + (scaleYDefined ? tr.scaleY : 1) + ")");
  72576. if (transformations.length)
  72577. this.element.setAttribute("transform", transformations.join(" "))
  72578. },
  72579. move: function(x, y, animate, animOptions) {
  72580. var obj = {};
  72581. isDefined(x) && (obj.translateX = x);
  72582. isDefined(y) && (obj.translateY = y);
  72583. if (!animate)
  72584. this.attr(obj);
  72585. else
  72586. this.animate(obj, animOptions);
  72587. return this
  72588. },
  72589. rotate: function(angle, x, y, animate, animOptions) {
  72590. var obj = {rotate: angle || 0};
  72591. isDefined(x) && (obj.rotateX = x);
  72592. isDefined(y) && (obj.rotateY = y);
  72593. if (!animate)
  72594. this.attr(obj);
  72595. else
  72596. this.animate(obj, animOptions);
  72597. return this
  72598. },
  72599. getBBox: function() {
  72600. var elem = this.element,
  72601. transformation = this._settings,
  72602. bBox;
  72603. try {
  72604. bBox = elem.getBBox && elem.getBBox()
  72605. }
  72606. catch(e) {}
  72607. bBox = bBox || {
  72608. x: 0,
  72609. y: 0,
  72610. width: elem.offsetWidth || 0,
  72611. height: elem.offsetHeight || 0
  72612. };
  72613. if (transformation.rotate)
  72614. bBox = rotateBBox(bBox, [("rotateX" in transformation ? transformation.rotateX : transformation.x) || 0, ("rotateY" in transformation ? transformation.rotateY : transformation.y) || 0], -transformation.rotate);
  72615. else
  72616. bBox = normalizeBBox(bBox);
  72617. return bBox
  72618. },
  72619. markup: function() {
  72620. var temp = doc.createElement('div'),
  72621. node = this.element.cloneNode(true);
  72622. temp.appendChild(node);
  72623. return temp.innerHTML
  72624. },
  72625. getOffset: function() {
  72626. return this._$element.offset()
  72627. },
  72628. animate: baseAnimate,
  72629. stopAnimation: function(disableComplete) {
  72630. var animation = this.animation;
  72631. animation && animation.stop(true, disableComplete);
  72632. return this
  72633. },
  72634. setTitle: function(text) {
  72635. var titleElem = createElement('title');
  72636. titleElem.textContent = text || '';
  72637. this.element.appendChild(titleElem)
  72638. },
  72639. on: function() {
  72640. $.fn.on.apply(this._$element, arguments);
  72641. return this
  72642. },
  72643. off: function() {
  72644. $.fn.off.apply(this._$element, arguments);
  72645. return this
  72646. },
  72647. trigger: function() {
  72648. $.fn.trigger.apply(this._$element, arguments);
  72649. return this
  72650. },
  72651. data: function() {
  72652. $.fn.data.apply(this._$element, arguments);
  72653. return this
  72654. }
  72655. };
  72656. function SvgRenderer(options) {
  72657. var that = this;
  72658. that.root = that._createElement("svg", {
  72659. xmlns: "http://www.w3.org/2000/svg",
  72660. "xmlns:xlink": "http://www.w3.org/1999/xlink",
  72661. version: "1.1",
  72662. fill: NONE,
  72663. stroke: NONE,
  72664. "stroke-width": 0,
  72665. "class": options.cssClass
  72666. }).css({
  72667. "line-height": "normal",
  72668. "-ms-user-select": NONE,
  72669. "-moz-user-select": NONE,
  72670. "-webkit-user-select": NONE,
  72671. "-webkit-tap-highlight-color": "rgba(0, 0, 0, 0)",
  72672. display: "block",
  72673. overflow: "hidden"
  72674. });
  72675. that._defs = that._createElement("defs");
  72676. that._animationController = new rendererNS.AnimationController(that.root.element);
  72677. that._animation = {
  72678. enabled: true,
  72679. duration: 1000,
  72680. easing: "easeOutCubic"
  72681. }
  72682. }
  72683. rendererNS.SvgRenderer = SvgRenderer;
  72684. SvgRenderer.prototype = {
  72685. constructor: SvgRenderer,
  72686. setOptions: function(options) {
  72687. var that = this;
  72688. that.pathModified = !!options.pathModified;
  72689. that.rtl = !!options.rtl;
  72690. that.encodeHtml = !!options.encodeHtml,
  72691. that.updateAnimationOptions(options.animation || {});
  72692. that.root.attr({direction: that.rtl ? "rtl" : "ltr"})
  72693. },
  72694. _createElement: function(tagName, attr, type) {
  72695. var elem = new rendererNS.SvgElement(this, tagName, type);
  72696. attr && elem.attr(attr);
  72697. return elem
  72698. },
  72699. draw: function(container) {
  72700. var that = this;
  72701. if (!container || that.drawn)
  72702. return that;
  72703. that.root.append(container);
  72704. that._defs.append(that.root);
  72705. that.drawn = true;
  72706. return that
  72707. },
  72708. resize: function(width, height) {
  72709. if (width >= 0 && height >= 0)
  72710. this.root.attr({
  72711. width: width,
  72712. height: height
  72713. });
  72714. return this
  72715. },
  72716. clear: function() {
  72717. var that = this;
  72718. that.root.remove();
  72719. that._defs.remove();
  72720. that.drawn = null;
  72721. return this
  72722. },
  72723. dispose: function() {
  72724. var that = this,
  72725. key;
  72726. that.root.dispose();
  72727. that._defs.dispose();
  72728. that._animationController.dispose();
  72729. for (key in that)
  72730. that[key] = null;
  72731. return null
  72732. },
  72733. animationEnabled: function() {
  72734. return !!this._animation.enabled
  72735. },
  72736. updateAnimationOptions: function(newOptions) {
  72737. extend(this._animation, newOptions);
  72738. return this
  72739. },
  72740. stopAllAnimations: function(lock) {
  72741. this._animationController[lock ? "lock" : "stop"]();
  72742. return this
  72743. },
  72744. animateElement: function(element, params, options) {
  72745. this._animationController.animateElement(element, params, options);
  72746. return this
  72747. },
  72748. svg: function() {
  72749. return this.root.markup()
  72750. },
  72751. getRootOffset: function() {
  72752. return this.root.getOffset()
  72753. },
  72754. onEndAnimation: function(endAnimation) {
  72755. this._animationController.onEndAnimation(endAnimation)
  72756. },
  72757. rect: function(x, y, width, height) {
  72758. return this._createElement("rect", {
  72759. x: x || 0,
  72760. y: y || 0,
  72761. width: width || 0,
  72762. height: height || 0
  72763. })
  72764. },
  72765. circle: function(x, y, r) {
  72766. return this._createElement("circle", {
  72767. cx: x || 0,
  72768. cy: y || 0,
  72769. r: r || 0
  72770. })
  72771. },
  72772. g: function() {
  72773. return this._createElement("g")
  72774. },
  72775. image: function(x, y, w, h, href, location) {
  72776. var image = this._createElement("image", {
  72777. x: x || 0,
  72778. y: y || 0,
  72779. width: w || 0,
  72780. height: h || 0,
  72781. preserveAspectRatio: getPreserveAspectRatio(location)
  72782. });
  72783. image.element.setAttributeNS("http://www.w3.org/1999/xlink", "href", href || "");
  72784. return image
  72785. },
  72786. path: function(points, type) {
  72787. return this._createElement("path", {points: points || []}, type)
  72788. },
  72789. arc: function(x, y, innerRadius, outerRadius, startAngle, endAngle) {
  72790. return this._createElement("path", {
  72791. x: x || 0,
  72792. y: y || 0,
  72793. innerRadius: innerRadius || 0,
  72794. outerRadius: outerRadius || 0,
  72795. startAngle: startAngle || 0,
  72796. endAngle: endAngle || 0
  72797. }, "arc")
  72798. },
  72799. text: function(text, x, y) {
  72800. return this._createElement("text", {
  72801. text: text,
  72802. x: x || 0,
  72803. y: y || 0
  72804. })
  72805. },
  72806. pattern: function(color, hatching) {
  72807. hatching = hatching || {};
  72808. var that = this,
  72809. id,
  72810. d,
  72811. pattern,
  72812. rect,
  72813. path,
  72814. step = hatching.step || 6,
  72815. stepTo2 = step / 2,
  72816. stepBy15 = step * 1.5,
  72817. direction = (hatching.direction || "").toLowerCase();
  72818. if (direction !== "right" && direction !== "left")
  72819. return {
  72820. id: color,
  72821. append: function() {
  72822. return this
  72823. },
  72824. clear: function(){},
  72825. dispose: function(){},
  72826. remove: function(){}
  72827. };
  72828. id = getNextDefsSvgId();
  72829. d = direction === "right" ? "M " + stepTo2 + " " + -stepTo2 + " L " + -stepTo2 + " " + stepTo2 + " M 0 " + step + " L " + step + " 0 M " + stepBy15 + " " + stepTo2 + " L " + stepTo2 + " " + stepBy15 : "M 0 0 L " + step + " " + step + " M " + -stepTo2 + " " + stepTo2 + " L " + stepTo2 + " " + stepBy15 + " M " + stepTo2 + " " + -stepTo2 + " L " + stepBy15 + " " + stepTo2;
  72830. pattern = that._createElement("pattern", {
  72831. id: id,
  72832. width: step,
  72833. height: step,
  72834. patternUnits: "userSpaceOnUse"
  72835. }).append(that._defs);
  72836. pattern.id = getPatternUrl(id, that.pathModified);
  72837. rect = that.rect(0, 0, step, step).attr({
  72838. fill: color,
  72839. opacity: hatching.opacity
  72840. }).append(pattern);
  72841. path = that._createElement("path", {
  72842. d: d,
  72843. "stroke-width": hatching.width || 1,
  72844. stroke: color
  72845. }).append(pattern);
  72846. pattern.rect = rect;
  72847. pattern.path = path;
  72848. return pattern
  72849. },
  72850. clipRect: function(x, y, width, height) {
  72851. var that = this,
  72852. id = getNextDefsSvgId(),
  72853. clipPath = that._createElement("clipPath", {id: id}).append(that._defs),
  72854. rect = that.rect(x, y, width, height).append(clipPath);
  72855. rect.id = id;
  72856. rect.clipPath = clipPath;
  72857. rect.remove = function() {
  72858. throw"Not implemented";
  72859. };
  72860. rect.dispose = function() {
  72861. clipPath.dispose();
  72862. clipPath = null;
  72863. return this
  72864. };
  72865. return rect
  72866. },
  72867. shadowFilter: function(x, y, width, height, offsetX, offsetY, blur, color, opacity) {
  72868. var that = this,
  72869. id = getNextDefsSvgId(),
  72870. filter = that._createElement("filter", {
  72871. id: id,
  72872. x: x || 0,
  72873. y: y || 0,
  72874. width: width || 0,
  72875. height: height || 0
  72876. }).append(that._defs),
  72877. gaussianBlur = that._createElement("feGaussianBlur", {
  72878. "in": "SourceGraphic",
  72879. result: "gaussianBlurResult",
  72880. stdDeviation: blur || 0
  72881. }).append(filter),
  72882. offset = that._createElement("feOffset", {
  72883. "in": "gaussianBlurResult",
  72884. result: "offsetResult",
  72885. dx: offsetX || 0,
  72886. dy: offsetY || 0
  72887. }).append(filter),
  72888. flood = that._createElement("feFlood", {
  72889. result: "floodResult",
  72890. "flood-color": color || "",
  72891. "flood-opacity": opacity
  72892. }).append(filter),
  72893. composite = that._createElement("feComposite", {
  72894. "in": "floodResult",
  72895. in2: "offsetResult",
  72896. operator: "in",
  72897. result: "compositeResult"
  72898. }).append(filter),
  72899. finalComposite = that._createElement("feComposite", {
  72900. "in": "SourceGraphic",
  72901. in2: "compositeResult",
  72902. operator: "over"
  72903. }).append(filter);
  72904. filter.ref = getPatternUrl(id, that.pathModified);
  72905. filter.gaussianBlur = gaussianBlur;
  72906. filter.offset = offset;
  72907. filter.flood = flood;
  72908. filter.composite = composite;
  72909. filter.finalComposite = finalComposite;
  72910. filter.attr = function(attrs) {
  72911. var that = this,
  72912. filterAttrs = {},
  72913. offsetAttrs = {},
  72914. floodAttrs = {};
  72915. "x" in attrs && (filterAttrs.x = attrs.x);
  72916. "y" in attrs && (filterAttrs.y = attrs.y);
  72917. "width" in attrs && (filterAttrs.width = attrs.width);
  72918. "height" in attrs && (filterAttrs.height = attrs.height);
  72919. baseAttr.call(that, filterAttrs);
  72920. "blur" in attrs && that.gaussianBlur.attr({stdDeviation: attrs.blur});
  72921. "offsetX" in attrs && (offsetAttrs.dx = attrs.offsetX);
  72922. "offsetY" in attrs && (offsetAttrs.dy = attrs.offsetY);
  72923. that.offset.attr(offsetAttrs);
  72924. "color" in attrs && (floodAttrs["flood-color"] = attrs.color);
  72925. "opacity" in attrs && (floodAttrs["flood-opacity"] = attrs.opacity);
  72926. that.flood.attr(floodAttrs);
  72927. return that
  72928. };
  72929. return filter
  72930. }
  72931. };
  72932. rendererNS.rotateBBox = rotateBBox;
  72933. rendererNS._createArcAttr = createArcAttr;
  72934. rendererNS._createPathAttr = createPathAttr;
  72935. rendererNS._createRectAttr = createRectAttr
  72936. })(jQuery, DevExpress, document);
  72937. /*! Module viz-core, file vmlRenderer.js */
  72938. (function($, DX, doc) {
  72939. DX.viz.renderers = DX.viz.renderers || {};
  72940. var rendererNS = DX.viz.renderers,
  72941. math = Math,
  72942. mathMin = math.min,
  72943. mathMax = math.max,
  72944. mathFloor = math.floor,
  72945. mathSin = math.sin,
  72946. mathCos = math.cos,
  72947. baseElementPrototype = rendererNS.SvgElement.prototype,
  72948. documentFragment = doc.createDocumentFragment(),
  72949. DEFAULT_STYLE = {
  72950. behavior: "url(#default#VML)",
  72951. display: "inline-block",
  72952. position: "absolute"
  72953. },
  72954. DEFAULT_ATTRS = {xmlns: 'urn:schemas-microsoft-com:vml'},
  72955. INHERITABLE_PROPERTIES = {
  72956. stroke: true,
  72957. fill: true,
  72958. opacity: true,
  72959. 'stroke-width': true,
  72960. align: true,
  72961. dashStyle: true,
  72962. "stroke-opacity": true,
  72963. 'fill-opacity': true,
  72964. rotate: true,
  72965. rotateX: true,
  72966. rotateY: true
  72967. },
  72968. stub = function(){},
  72969. stubReturnedThis = function() {
  72970. return this
  72971. },
  72972. svgToVmlConv = {
  72973. circle: "oval",
  72974. g: "div",
  72975. path: "shape",
  72976. text: "span"
  72977. },
  72978. FONT_HEIGHT_OFFSET_K = 0.55 + 0.45 / 2,
  72979. DEFAULTS = {
  72980. scaleX: 1,
  72981. scaleY: 1
  72982. },
  72983. pathAttr = rendererNS._createPathAttr(vmlAttr),
  72984. arcAttr = rendererNS._createArcAttr(vmlAttr, buildArcPath),
  72985. rectAttr = rendererNS._createRectAttr(vmlAttr);
  72986. function isDefined(value) {
  72987. return value !== null && value !== undefined
  72988. }
  72989. function extend(a, b) {
  72990. for (var key in b)
  72991. a[key] = b[key];
  72992. return a
  72993. }
  72994. function inArray(array, elem) {
  72995. var i = 0;
  72996. for (; i < array.length; i++)
  72997. if (elem === array[i])
  72998. return i;
  72999. return -1
  73000. }
  73001. function buildArcPath(x, y, innerR, outerR, startAngleCos, startAngleSin, endAngleCos, endAngleSin, isCircle, longFlag, noArc) {
  73002. var xOuterStart = x + outerR * startAngleCos,
  73003. yOuterStart = y - outerR * startAngleSin,
  73004. xOuterEnd = x + outerR * endAngleCos,
  73005. yOuterEnd = y - outerR * endAngleSin,
  73006. xInnerStart = x + innerR * endAngleCos,
  73007. yInnerStart = y - innerR * endAngleSin,
  73008. xInnerEnd = x + innerR * startAngleCos,
  73009. yInnerEnd = y - innerR * startAngleSin;
  73010. return !noArc ? ['wr', mathFloor(x - innerR), mathFloor(y - innerR), mathFloor(x + innerR), mathFloor(y + innerR), mathFloor(xInnerStart), mathFloor(yInnerStart), mathFloor(xInnerEnd), mathFloor(yInnerEnd), isCircle ? 'wr ' : 'at ', mathFloor(x - outerR), mathFloor(y - outerR), mathFloor(x + outerR), mathFloor(y + outerR), mathFloor(xOuterStart), mathFloor(yOuterStart), mathFloor(xOuterEnd), mathFloor(yOuterEnd), 'x e'].join(" ") : "m 0 0 x e"
  73011. }
  73012. function getInheritSettings(settings) {
  73013. var result = {},
  73014. prop,
  73015. value;
  73016. for (prop in INHERITABLE_PROPERTIES) {
  73017. value = settings[prop];
  73018. value !== undefined && (result[prop] = value)
  73019. }
  73020. return result
  73021. }
  73022. function correctBoundingRectWithStrokeWidth(rect, strokeWidth) {
  73023. strokeWidth = Math.ceil(parseInt(strokeWidth) / 2);
  73024. if (strokeWidth && strokeWidth > 1) {
  73025. rect.left -= strokeWidth;
  73026. rect.top -= strokeWidth;
  73027. rect.right += strokeWidth;
  73028. rect.bottom += strokeWidth
  73029. }
  73030. return rect
  73031. }
  73032. function shapeBBox() {
  73033. var points = (this._settings.d || "").match(/[-0-9]+/g),
  73034. i,
  73035. value,
  73036. resultRect = {};
  73037. for (i = 0; i < points.length; i++) {
  73038. value = parseInt(points[i]);
  73039. if (i % 2) {
  73040. resultRect.top = resultRect.top === undefined || value < resultRect.top ? value : resultRect.top;
  73041. resultRect.bottom = resultRect.bottom === undefined || value > resultRect.bottom ? value : resultRect.bottom
  73042. }
  73043. else {
  73044. resultRect.left = resultRect.left === undefined || value < resultRect.left ? value : resultRect.left;
  73045. resultRect.right = resultRect.right === undefined || value > resultRect.right ? value : resultRect.right
  73046. }
  73047. }
  73048. resultRect.left = resultRect.left || 0;
  73049. resultRect.top = resultRect.top || 0;
  73050. resultRect.right = resultRect.right || 0;
  73051. resultRect.bottom = resultRect.bottom || 0;
  73052. return correctBoundingRectWithStrokeWidth(resultRect, this._fullSettings["stroke-width"])
  73053. }
  73054. function baseAttr(attrs, inh) {
  73055. var element = this.element,
  73056. settings = this._settings,
  73057. fullSettings = this._fullSettings,
  73058. value,
  73059. key,
  73060. params = {style: {}},
  73061. appliedAttr,
  73062. elem;
  73063. if (typeof attrs === "string") {
  73064. if (attrs in settings)
  73065. return settings[attrs];
  73066. if (attrs in DEFAULTS)
  73067. return DEFAULTS[attrs];
  73068. return 0
  73069. }
  73070. for (key in attrs) {
  73071. value = attrs[key];
  73072. if (value === undefined)
  73073. continue;
  73074. appliedAttr = fullSettings[key];
  73075. !inh && (settings[key] = value);
  73076. fullSettings[key] = value;
  73077. if (INHERITABLE_PROPERTIES[key])
  73078. value = value === null ? this._parent && this._parent._fullSettings[key] || value : value;
  73079. appliedAttr !== value && this.processAttr(element, key, value, params)
  73080. }
  73081. this._applyTransformation(params);
  73082. this.css(params.style);
  73083. for (var i = 0; i < this._children.length; i++) {
  73084. elem = this._children[i];
  73085. elem !== this._clipRect && elem.attr(extend(getInheritSettings(this._fullSettings), elem._settings), true);
  73086. elem._applyStyleSheet()
  73087. }
  73088. !inh && this._applyStyleSheet();
  73089. return this
  73090. }
  73091. function vmlAttr() {
  73092. var elem = this.element,
  73093. result = baseAttr.apply(this, arguments);
  73094. for (var i = 0; i < elem.childNodes.length; i++) {
  73095. elem.childNodes[i].xmlns = 'urn:schemas-microsoft-com:vml';
  73096. elem.childNodes[i].style.behavior = "url(#default#VML)";
  73097. elem.childNodes[i].style.display = "inline-block"
  73098. }
  73099. return result
  73100. }
  73101. function processVmlAttr(element, attr, value, params) {
  73102. switch (attr) {
  73103. case"stroke":
  73104. value = value || "none";
  73105. element.stroked = value === 'none' ? 'f' : 't';
  73106. attr += "color";
  73107. break;
  73108. case"fill":
  73109. value = value || "none";
  73110. element.filled = value === 'none' ? 'f' : 't';
  73111. attr += "color";
  73112. break;
  73113. case"stroke-width":
  73114. attr = "strokeweight";
  73115. value = value + 'px';
  73116. break;
  73117. case"stroke-linejoin":
  73118. element.stroke.joinstyle = value;
  73119. return;
  73120. case"stroke-linecap":
  73121. element.stroke.endcap = value === "butt" ? "flat" : value;
  73122. return;
  73123. case"opacity":
  73124. value = adjustOpacityValue(value);
  73125. element.fill.opacity = value;
  73126. element.stroke.opacity = value;
  73127. return;
  73128. case"fill-opacity":
  73129. element.fill.opacity = adjustOpacityValue(value);
  73130. return;
  73131. case"stroke-opacity":
  73132. element.stroke.opacity = adjustOpacityValue(value);
  73133. return;
  73134. case"dashStyle":
  73135. if (value === null)
  73136. element.stroke[attr] = "";
  73137. else {
  73138. value = value.toLowerCase();
  73139. if (value === "solid" || value === "none")
  73140. value = "";
  73141. else
  73142. value = value.replace(/longdash/g, "8,3,").replace(/dash/g, "4,3,").replace(/dot/g, "1,3,").replace(/,$/, "");
  73143. element.stroke[attr] = value
  73144. }
  73145. return;
  73146. case"d":
  73147. attr = "path";
  73148. value = (value + '').toLowerCase().replace("z", "x e").replace(/([.]\d+)/g, "");
  73149. break;
  73150. case"href":
  73151. attr = "src";
  73152. break;
  73153. case"width":
  73154. case"height":
  73155. case"visibility":
  73156. params.style[attr] = value || "";
  73157. return;
  73158. case"class":
  73159. attr += "Name";
  73160. break;
  73161. case"translateX":
  73162. case"translateY":
  73163. case"rotate":
  73164. case"rotateX":
  73165. case"rotateY":
  73166. case"scale":
  73167. case"scaleX":
  73168. case"scaleY":
  73169. case"x":
  73170. case"y":
  73171. return
  73172. }
  73173. element[attr] = value
  73174. }
  73175. function adjustOpacityValue(value) {
  73176. return value >= 0.002 ? value : value === null ? 1 : 0.002
  73177. }
  73178. function createElement(tagName) {
  73179. var element = document.createElement(tagName);
  73180. return documentFragment.appendChild(element)
  73181. }
  73182. var VmlElement = function() {
  73183. this.ctor.apply(this, arguments)
  73184. };
  73185. function processAttr(element, attr, value, params) {
  73186. if (!INHERITABLE_PROPERTIES[attr])
  73187. if (attr === "visibility")
  73188. params.style[attr] = value || "";
  73189. else if (attr === "width" || attr === "height")
  73190. params.style[attr] = value;
  73191. else if (attr === "clipId")
  73192. this.applyClipID(value);
  73193. else if (attr === "translateX" || attr === "translateY" || attr === "x" || attr === "y")
  73194. return;
  73195. else if (attr === "class")
  73196. element.className = value;
  73197. else
  73198. element[attr] = value
  73199. }
  73200. var elementMixin = {
  73201. div: {
  73202. processAttr: processAttr,
  73203. attr: baseAttr,
  73204. _applyTransformation: function(params) {
  73205. var style = params.style,
  73206. settings = this._settings,
  73207. fullSettings = this._fullSettings;
  73208. if (fullSettings.rotate) {
  73209. fullSettings.rotateX = fullSettings.rotateX || 0;
  73210. fullSettings.rotateY = fullSettings.rotateY || 0
  73211. }
  73212. style.left = (settings.x || 0) + (settings.translateX || 0);
  73213. style.top = (settings.y || 0) + (settings.translateY || 0)
  73214. },
  73215. _getBBox: function() {
  73216. var left = Infinity,
  73217. top = Infinity,
  73218. right = -Infinity,
  73219. bottom = -Infinity,
  73220. i = 0,
  73221. child,
  73222. children = this._children,
  73223. translateX,
  73224. translateY,
  73225. childBBox,
  73226. childSettings;
  73227. if (!children.length)
  73228. left = top = bottom = right = 0;
  73229. else
  73230. for (; i < children.length; i++) {
  73231. child = children[i];
  73232. if (child === this._clipRect)
  73233. continue;
  73234. translateX = child._fullSettings.translateX || 0;
  73235. translateY = child._fullSettings.translateY || 0;
  73236. childSettings = child._fullSettings;
  73237. childBBox = child._getBBox();
  73238. left = mathMin(left, childBBox.left + translateX);
  73239. right = mathMax(right, childBBox.right + translateX);
  73240. top = mathMin(top, childBBox.top + translateY);
  73241. bottom = mathMax(bottom, childBBox.bottom + translateY)
  73242. }
  73243. return {
  73244. left: left,
  73245. right: right,
  73246. top: top,
  73247. bottom: bottom
  73248. }
  73249. },
  73250. defaultAttrs: {},
  73251. defaultStyle: {position: "absolute"}
  73252. },
  73253. shape: {
  73254. defaultAttrs: extend({
  73255. coordsize: "1,1",
  73256. "stroke-linejoin": "miter"
  73257. }, DEFAULT_ATTRS),
  73258. defaultStyle: extend({
  73259. width: 1,
  73260. height: 1
  73261. }, DEFAULT_STYLE),
  73262. _getBBox: shapeBBox
  73263. },
  73264. image: {processAttr: function(element, attr, value, params) {
  73265. if (attr === "fill" || attr === "stroke")
  73266. return;
  73267. processVmlAttr(element, attr, value, params)
  73268. }},
  73269. oval: {
  73270. processAttr: function(element, attr, value, params) {
  73271. if (attr === "cx" || attr === "cy")
  73272. attr = attr[1];
  73273. else if (attr === "r") {
  73274. value *= 2;
  73275. processVmlAttr(element, "width", value, params);
  73276. attr = "height"
  73277. }
  73278. else if (attr === "x" || attr === "y")
  73279. return;
  73280. processVmlAttr(element, attr, value, params)
  73281. },
  73282. _getBBox: function() {
  73283. var settings = this._fullSettings,
  73284. x = settings.cx || 0,
  73285. y = settings.cy || 0,
  73286. r = settings.r || 0;
  73287. return correctBoundingRectWithStrokeWidth({
  73288. left: x - r,
  73289. top: y - r,
  73290. right: x + r,
  73291. bottom: y + r
  73292. }, settings["stroke-width"] || 1)
  73293. }
  73294. },
  73295. span: {
  73296. defaultAttrs: {},
  73297. defaultStyle: {
  73298. position: 'absolute',
  73299. whiteSpace: 'nowrap'
  73300. },
  73301. processAttr: function(element, attr, value, params) {
  73302. if (attr === "text") {
  73303. value = isDefined(value) ? value.toString().replace(/\r/g, "") : "";
  73304. if (this.renderer.encodeHtml)
  73305. value = value.replace(/</g, "&lt;").replace(/>/g, "&gt;");
  73306. element.innerHTML = value.replace(/\n/g, "<br/>");
  73307. this.css({filter: ""});
  73308. this._bbox = null
  73309. }
  73310. else
  73311. processAttr(element, attr, value, params)
  73312. },
  73313. attr: baseAttr,
  73314. _applyTransformation: function(params) {
  73315. this.element.offsetHeight;
  73316. var that = this,
  73317. style = params.style,
  73318. settings = that._fullSettings,
  73319. x = isDefined(settings.x) ? settings.x : 0,
  73320. y = isDefined(settings.y) ? settings.y : 0,
  73321. bbox = that._bbox || that.element.getBoundingClientRect(),
  73322. textHeight = bbox.bottom - bbox.top,
  73323. textWidth = bbox.right - bbox.left,
  73324. rotateAngle = settings.rotate,
  73325. cos = 1,
  73326. sin = 0,
  73327. rotateX = isDefined(settings.rotateX) ? settings.rotateX : x,
  73328. rotateY = isDefined(settings.rotateY) ? settings.rotateY : y,
  73329. radianAngle,
  73330. marginLeft = 0,
  73331. marginTop = 0,
  73332. fontHeightOffset = textHeight * FONT_HEIGHT_OFFSET_K,
  73333. filter = "",
  73334. alignMultiplier = {
  73335. center: 0.5,
  73336. right: 1
  73337. }[settings.align],
  73338. opacity = this._styles.opacity || settings.opacity || settings["fill-opacity"];
  73339. if (textHeight && textWidth) {
  73340. if (rotateAngle) {
  73341. radianAngle = rotateAngle * Math.PI / 180.0;
  73342. cos = mathCos(radianAngle);
  73343. sin = mathSin(radianAngle);
  73344. marginLeft = (x - rotateX) * cos - (y - rotateY) * sin + rotateX - x;
  73345. marginTop = (x - rotateX) * sin + (y - rotateY) * cos + rotateY - y;
  73346. filter = 'progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand", M11 = ' + cos.toFixed(5) + ', M12 = ' + (-sin).toFixed(5) + ', M21 = ' + sin.toFixed(5) + ', M22 = ' + cos.toFixed(5) + ')'
  73347. }
  73348. if (rotateAngle < 90) {
  73349. marginTop -= fontHeightOffset * cos;
  73350. marginLeft -= (textHeight - fontHeightOffset) * sin
  73351. }
  73352. else if (rotateAngle < 180) {
  73353. marginTop += (textHeight - fontHeightOffset) * cos;
  73354. marginLeft += textWidth * cos - (textHeight - fontHeightOffset) * sin
  73355. }
  73356. else if (rotateAngle < 270) {
  73357. marginTop += (textHeight - fontHeightOffset) * cos + textWidth * sin;
  73358. marginLeft += textWidth * cos + fontHeightOffset * sin
  73359. }
  73360. else {
  73361. marginTop += textWidth * sin - fontHeightOffset * cos;
  73362. marginLeft += fontHeightOffset * sin
  73363. }
  73364. if (rotateAngle && this.renderer.rtl)
  73365. marginLeft -= textWidth - (textHeight * Math.abs(sin) + textWidth * Math.abs(cos));
  73366. if (alignMultiplier) {
  73367. marginLeft -= textWidth * alignMultiplier * cos;
  73368. marginTop -= textWidth * alignMultiplier * sin
  73369. }
  73370. if (isDefined(opacity))
  73371. filter += " progid:DXImageTransform.Microsoft.Alpha(Opacity=" + opacity * 100 + ")";
  73372. x += marginLeft;
  73373. y += marginTop;
  73374. this._bbox = bbox;
  73375. style.filter = (style.filter || "") + filter;
  73376. style.left = x + (settings.translateX || 0);
  73377. style.top = y + (settings.translateY || 0)
  73378. }
  73379. },
  73380. _getBBox: function textBBox() {
  73381. var element = this.element,
  73382. settings = this._fullSettings,
  73383. parentRect = (element.parentNode && element.parentNode.getBoundingClientRect ? element.parentNode : this.renderer.root.element).getBoundingClientRect(),
  73384. boundingRect = element.getBoundingClientRect(),
  73385. left = boundingRect.left - (settings.translateX || 0) - parentRect.left,
  73386. top = boundingRect.top - (settings.translateY || 0) - parentRect.top;
  73387. return {
  73388. left: left,
  73389. top: top,
  73390. right: left + element.offsetWidth,
  73391. bottom: top + element.offsetHeight
  73392. }
  73393. }
  73394. }
  73395. };
  73396. extend(VmlElement.prototype, baseElementPrototype);
  73397. extend(VmlElement.prototype, {
  73398. defaultStyle: DEFAULT_STYLE,
  73399. defaultAttrs: DEFAULT_ATTRS,
  73400. ctor: function(renderer, tagName, type) {
  73401. var that = this,
  73402. tagPrefix = '<';
  73403. that.renderer = renderer;
  73404. that.type = type;
  73405. that._children = [];
  73406. that._settings = {};
  73407. that._fullSettings = {};
  73408. that._styles = {};
  73409. if (tagName !== "div" && tagName !== "span")
  73410. tagPrefix = "<vml:";
  73411. if (tagName === "shape")
  73412. if (that.type === "arc")
  73413. that.attr = arcAttr;
  73414. else
  73415. that.attr = pathAttr;
  73416. else if (tagName === "rect")
  73417. that.attr = rectAttr;
  73418. extend(that, elementMixin[tagName]);
  73419. that.element = createElement(tagPrefix + tagName + "/>");
  73420. that.css(that.defaultStyle).attr(that.defaultAttrs);
  73421. that._$element = $(that.element)
  73422. },
  73423. dispose: function() {
  73424. this.remove();
  73425. this._$element.remove();
  73426. return this
  73427. },
  73428. attr: vmlAttr,
  73429. processAttr: processVmlAttr,
  73430. css: function(css) {
  73431. var elem = this.element,
  73432. value,
  73433. appliedValue,
  73434. key;
  73435. for (key in css) {
  73436. appliedValue = this._styles[key];
  73437. value = css[key];
  73438. if (!isDefined(value))
  73439. continue;
  73440. this._styles[key] = value;
  73441. if (appliedValue === value)
  73442. continue;
  73443. switch (key) {
  73444. case"fill":
  73445. key = "color";
  73446. break;
  73447. case"font-size":
  73448. key = "fontSize";
  73449. if (typeof value === "number")
  73450. value += "px";
  73451. break;
  73452. case"font-weight":
  73453. key = "fontWeight";
  73454. break;
  73455. case"z-index":
  73456. key = "zIndex";
  73457. break;
  73458. case"opacity":
  73459. continue
  73460. }
  73461. try {
  73462. elem.style[key] = value
  73463. }
  73464. catch(_) {
  73465. continue
  73466. }
  73467. }
  73468. return this
  73469. },
  73470. applyClipID: function(id) {
  73471. var clipRect,
  73472. cssValue,
  73473. renderer = this.renderer;
  73474. clipRect = renderer.getClipRect(id);
  73475. if (clipRect) {
  73476. cssValue = clipRect.getValue();
  73477. clipRect.addElement(this)
  73478. }
  73479. else
  73480. cssValue = "rect(-9999px 9999px 9999px -9999px)";
  73481. this._clipRect = this._clipRect || renderer.rect(0, 0, 0, 0).attr({
  73482. "class": "dxc-vml-clip",
  73483. fill: "none",
  73484. opacity: 0.001
  73485. });
  73486. this._clipRect.attr({
  73487. width: renderer.root.attr("width"),
  73488. height: renderer.root.attr("height")
  73489. });
  73490. this.css({
  73491. clip: cssValue,
  73492. width: renderer.root.attr("width"),
  73493. height: renderer.root.attr("height")
  73494. })
  73495. },
  73496. append: function(parent) {
  73497. parent = parent || this.renderer.root;
  73498. (parent.element || parent).appendChild(this.element);
  73499. if (parent._children) {
  73500. this._parent = parent;
  73501. if (inArray(parent._children, this) === -1)
  73502. parent._children.push(this);
  73503. this.attr(extend(getInheritSettings(parent._fullSettings), this._settings), true)
  73504. }
  73505. this._applyStyleSheet();
  73506. if (parent._clipRect && this !== parent._clipRect)
  73507. parent._clipRect.append(parent);
  73508. return this
  73509. },
  73510. _applyTransformation: function(params) {
  73511. var that = this,
  73512. style = params.style,
  73513. element = that.element,
  73514. settings = that._fullSettings,
  73515. x = that.type !== "arc" ? settings.x || settings.cx - settings.r || 0 : 0,
  73516. y = that.type !== "arc" ? settings.y || settings.cy - settings.r || 0 : 0;
  73517. if (settings.rotate) {
  73518. var radianAngle = settings.rotate * Math.PI / 180.0,
  73519. rotateX = isDefined(settings.rotateX) ? settings.rotateX : x,
  73520. rotateY = isDefined(settings.rotateY) ? settings.rotateY : y,
  73521. rx = x + (settings.width || 0 || parseInt(element.style.width || 0)) / 2,
  73522. ry = y + (settings.height || 0 || parseInt(element.style.height || 0)) / 2,
  73523. cos = mathCos(radianAngle),
  73524. sin = mathSin(radianAngle),
  73525. marginLeft = (rx - rotateX) * cos - (ry - rotateY) * sin + rotateX - rx,
  73526. marginTop = (rx - rotateX) * sin + (ry - rotateY) * cos + rotateY - ry;
  73527. x += marginLeft;
  73528. y += marginTop;
  73529. style.rotation = settings.rotate
  73530. }
  73531. style.left = x + (settings.translateX || 0);
  73532. style.top = y + (settings.translateY || 0)
  73533. },
  73534. remove: function() {
  73535. var that = this,
  73536. parent = that._parent;
  73537. if (parent)
  73538. parent._children.splice(inArray(parent._children, that), 1);
  73539. that._parent = null;
  73540. return baseElementPrototype.remove.call(that)
  73541. },
  73542. clear: function() {
  73543. this._children = [];
  73544. return baseElementPrototype.clear.call(this)
  73545. },
  73546. getBBox: function() {
  73547. var clientRect = this._getBBox(),
  73548. x = clientRect.left,
  73549. y = clientRect.top,
  73550. width = clientRect.right - x,
  73551. height = clientRect.bottom - y;
  73552. return {
  73553. x: x,
  73554. y: y,
  73555. width: width,
  73556. height: height,
  73557. isEmpty: !x && !y && !width && !height
  73558. }
  73559. },
  73560. _getBBox: function() {
  73561. var element = this.element,
  73562. settings = this._fullSettings,
  73563. x = settings.x || 0,
  73564. y = settings.y || 0,
  73565. width = parseInt(element.style.width || 0),
  73566. height = parseInt(element.style.height || 0);
  73567. return correctBoundingRectWithStrokeWidth({
  73568. left: x,
  73569. top: y,
  73570. right: x + width,
  73571. bottom: y + height
  73572. }, settings["stroke-width"] || 1)
  73573. },
  73574. _applyStyleSheet: function() {
  73575. if (this._useCSSTheme)
  73576. this.attr(getInheritSettings(this.element.currentStyle), true)
  73577. },
  73578. setTitle: function(text) {
  73579. this.element.setAttribute('title', text)
  73580. }
  73581. });
  73582. var ClipRect = function() {
  73583. this.ctor.apply(this, arguments)
  73584. };
  73585. extend(ClipRect.prototype, VmlElement.prototype);
  73586. extend(ClipRect.prototype, {
  73587. ctor: function(renderer, id) {
  73588. this._settings = this._fullSettings = {};
  73589. this.renderer = renderer;
  73590. this._children = [];
  73591. this._elements = [];
  73592. this.id = id
  73593. },
  73594. attr: function() {
  73595. var result = baseAttr.apply(this, arguments),
  73596. elements = this._elements.slice(),
  73597. element,
  73598. i;
  73599. if (result === this)
  73600. for (i = 0; i < elements.length; i++) {
  73601. element = elements[i];
  73602. if (element._fullSettings.clipId === this.id)
  73603. elements[i].applyClipID(this.id);
  73604. else
  73605. this.removeElement(element)
  73606. }
  73607. return result
  73608. },
  73609. processAttr: stub,
  73610. _applyTransformation: stub,
  73611. append: stubReturnedThis,
  73612. dispose: function() {
  73613. this._elements = null;
  73614. this.renderer.removeClipRect(this.id);
  73615. return this
  73616. },
  73617. addElement: function(element) {
  73618. var elements = this._elements;
  73619. if (inArray(elements, element) === -1)
  73620. elements.push(element)
  73621. },
  73622. removeElement: function(element) {
  73623. var index = inArray(this._elements, element);
  73624. index > -1 && this._elements.splice(index, 1)
  73625. },
  73626. getValue: function() {
  73627. var settings = this._settings,
  73628. left = (settings.x || 0) + (settings.translateX || 0),
  73629. top = (settings.y || 0) + (settings.translateY || 0);
  73630. return "rect(" + top + "px, " + (left + (settings.width || 0)) + "px, " + (top + (settings.height || 0)) + "px, " + left + "px)"
  73631. },
  73632. css: stubReturnedThis,
  73633. remove: stubReturnedThis
  73634. });
  73635. var VmlRenderer = function(options) {
  73636. var that = this;
  73637. that.root = that._createElement("div", {
  73638. fill: "none",
  73639. stroke: "none",
  73640. "stroke-width": 0
  73641. }).css({
  73642. position: "relative",
  73643. display: "inline-block",
  73644. overflow: "hidden"
  73645. });
  73646. that._clipRects = [];
  73647. that._animation = {enabled: false};
  73648. that._defs = {
  73649. clear: stubReturnedThis,
  73650. remove: stubReturnedThis,
  73651. append: stubReturnedThis,
  73652. dispose: stubReturnedThis
  73653. };
  73654. that.setOptions(options)
  73655. };
  73656. extend(VmlRenderer.prototype, rendererNS.SvgRenderer.prototype);
  73657. extend(VmlRenderer.prototype, {
  73658. constructor: VmlRenderer,
  73659. setOptions: function() {
  73660. rendererNS.SvgRenderer.prototype.setOptions.apply(this, arguments);
  73661. this.root.css({direction: this.rtl ? "rtl" : "ltr"})
  73662. },
  73663. _createElement: function(tagName, attr, type) {
  73664. tagName = svgToVmlConv[tagName] || tagName;
  73665. var elem = new rendererNS.VmlElement(this, tagName, type);
  73666. attr && elem.attr(attr);
  73667. return elem
  73668. },
  73669. dispose: function() {
  73670. this.root.dispose();
  73671. return null
  73672. },
  73673. shadowFilter: function() {
  73674. return {
  73675. ref: null,
  73676. append: stubReturnedThis,
  73677. dispose: stubReturnedThis,
  73678. attr: stubReturnedThis,
  73679. css: stubReturnedThis
  73680. }
  73681. },
  73682. clipRect: function(x, y, width, height) {
  73683. var clipRects = this._clipRects,
  73684. id = clipRects.length,
  73685. clipRect = new ClipRect(this, id).attr({
  73686. x: x || 0,
  73687. y: y || 0,
  73688. width: width || 0,
  73689. height: height || 0
  73690. });
  73691. clipRects.push(clipRect);
  73692. return clipRect
  73693. },
  73694. getClipRect: function(id) {
  73695. return this._clipRects[id]
  73696. },
  73697. removeClipRect: function(id) {
  73698. delete this._clipRects[id]
  73699. },
  73700. pattern: function(color) {
  73701. return {
  73702. id: color,
  73703. append: stubReturnedThis,
  73704. remove: stubReturnedThis,
  73705. dispose: stubReturnedThis
  73706. }
  73707. },
  73708. image: function(x, y, w, h, href, location) {
  73709. var image = this._createElement("image", {
  73710. x: x || 0,
  73711. y: y || 0,
  73712. width: w || 0,
  73713. height: h || 0,
  73714. location: location,
  73715. href: href
  73716. });
  73717. return image
  73718. },
  73719. updateAnimationOptions: stubReturnedThis,
  73720. stopAllAnimations: stubReturnedThis,
  73721. svg: function() {
  73722. return ""
  73723. },
  73724. onEndAnimation: function(callback) {
  73725. callback()
  73726. }
  73727. });
  73728. rendererNS.VmlRenderer = VmlRenderer;
  73729. rendererNS.VmlElement = VmlElement;
  73730. rendererNS._VmlClipRect = ClipRect
  73731. })(jQuery, DevExpress, document);
  73732. /*! Module viz-core, file animation.js */
  73733. (function(DX) {
  73734. var rendererNS = DX.viz.renderers,
  73735. noop = function(){},
  73736. easingFunctions = {
  73737. easeOutCubic: function(pos, start, end) {
  73738. return pos === 1 ? end : (1 - Math.pow(1 - pos, 3)) * (end - start) + +start
  73739. },
  73740. linear: function(pos, start, end) {
  73741. return pos === 1 ? end : pos * (end - start) + +start
  73742. }
  73743. };
  73744. rendererNS.easingFunctions = easingFunctions;
  73745. rendererNS.animationSvgStep = {
  73746. segments: function(elem, params, progress, easing, currentParams) {
  73747. var from = params.from,
  73748. to = params.to,
  73749. curSeg,
  73750. seg,
  73751. i,
  73752. j,
  73753. segments = [];
  73754. for (i = 0; i < from.length; i++) {
  73755. curSeg = from[i];
  73756. seg = [curSeg[0]];
  73757. if (curSeg.length > 1)
  73758. for (j = 1; j < curSeg.length; j++)
  73759. seg.push(easing(progress, curSeg[j], to[i][j]));
  73760. segments.push(seg)
  73761. }
  73762. currentParams.segments = params.end && progress === 1 ? params.end : segments;
  73763. elem.attr({segments: segments})
  73764. },
  73765. arc: function(elem, params, progress, easing) {
  73766. var from = params.from,
  73767. to = params.to,
  73768. current = {};
  73769. for (var i in from)
  73770. current[i] = easing(progress, from[i], to[i]);
  73771. elem.attr(current)
  73772. },
  73773. transform: function(elem, params, progress, easing, currentParams) {
  73774. var from = params.from,
  73775. to = params.to,
  73776. current = {};
  73777. for (var i in from)
  73778. current[i] = currentParams[i] = easing(progress, from[i], to[i]);
  73779. elem.attr(current)
  73780. },
  73781. base: function(elem, params, progress, easing, currentParams, attributeName) {
  73782. var obj = {};
  73783. obj[attributeName] = currentParams[attributeName] = easing(progress, params.from, params.to);
  73784. elem.attr(obj)
  73785. },
  73786. _: noop,
  73787. complete: function(element, currentSettings) {
  73788. element.attr(currentSettings)
  73789. }
  73790. };
  73791. function Animation(element, params, options) {
  73792. var that = this;
  73793. that._progress = 0;
  73794. that.element = element;
  73795. that.params = params;
  73796. that.options = options;
  73797. that.duration = options.partitionDuration ? options.duration * options.partitionDuration : options.duration;
  73798. that._animateStep = options.animateStep || rendererNS.animationSvgStep;
  73799. that._easing = easingFunctions[options.easing] || easingFunctions["easeOutCubic"];
  73800. that._currentParams = {};
  73801. that.tick = that._start
  73802. }
  73803. Animation.prototype = {
  73804. _calcProgress: function(now) {
  73805. return Math.min(1, (now - this._startTime) / this.duration)
  73806. },
  73807. _step: function(now) {
  73808. var that = this,
  73809. animateStep = that._animateStep,
  73810. attrName;
  73811. that._progress = that._calcProgress(now);
  73812. for (attrName in that.params) {
  73813. var anim = animateStep[attrName] || animateStep.base;
  73814. anim(that.element, that.params[attrName], that._progress, that._easing, that._currentParams, attrName)
  73815. }
  73816. that.options.step && that.options.step(that._easing(that._progress, 0, 1), that._progress);
  73817. if (that._progress === 1)
  73818. return that.stop();
  73819. return true
  73820. },
  73821. _start: function(now) {
  73822. this._startTime = now;
  73823. this.tick = this._step;
  73824. return true
  73825. },
  73826. _end: function(disableComplete) {
  73827. var that = this;
  73828. that.stop = noop;
  73829. that.tick = noop;
  73830. that._animateStep.complete && that._animateStep.complete(that.element, that._currentParams);
  73831. that.options.complete && !disableComplete && that.options.complete()
  73832. },
  73833. tick: function() {
  73834. return true
  73835. },
  73836. stop: function(breakAnimation, disableComplete) {
  73837. var that = this,
  73838. options = that.options;
  73839. if (!breakAnimation && options.repeatCount && --options.repeatCount > 0) {
  73840. that.tick = that._start;
  73841. return true
  73842. }
  73843. else
  73844. that._end(disableComplete)
  73845. }
  73846. };
  73847. function AnimationController(element) {
  73848. var that = this;
  73849. that._animationCount = 0;
  73850. that._timerId = null;
  73851. that._animations = {};
  73852. that.element = element
  73853. }
  73854. rendererNS.AnimationController = AnimationController;
  73855. AnimationController.prototype = {
  73856. _loop: function() {
  73857. var that = this,
  73858. animations = that._animations,
  73859. activeAnimation = 0,
  73860. now = (new Date).getTime(),
  73861. an,
  73862. endAnimation = that._endAnimation;
  73863. for (an in animations) {
  73864. if (!animations[an].tick(now))
  73865. delete animations[an];
  73866. activeAnimation++
  73867. }
  73868. if (activeAnimation === 0) {
  73869. that.stop();
  73870. that._endAnimationTimer = endAnimation && setTimeout(function() {
  73871. if (that._animationCount === 0) {
  73872. endAnimation();
  73873. that._endAnimation = null
  73874. }
  73875. });
  73876. return
  73877. }
  73878. that._timerId = DX.requestAnimationFrame.call(null, function() {
  73879. that._loop()
  73880. }, that.element)
  73881. },
  73882. addAnimation: function(animation) {
  73883. var that = this;
  73884. that._animations[that._animationCount++] = animation;
  73885. clearTimeout(that._endAnimationTimer);
  73886. if (!that._timerId) {
  73887. clearTimeout(that._startDelay);
  73888. that._startDelay = setTimeout(function() {
  73889. that._timerId = 1;
  73890. that._loop()
  73891. }, 0)
  73892. }
  73893. },
  73894. animateElement: function(elem, params, options) {
  73895. if (elem && params && options) {
  73896. elem.animation && elem.animation.stop(true);
  73897. this.addAnimation(elem.animation = new Animation(elem, params, options))
  73898. }
  73899. },
  73900. onEndAnimation: function(endAnimation) {
  73901. this._animationCount ? this._endAnimation = endAnimation : endAnimation()
  73902. },
  73903. dispose: function() {
  73904. this.stop();
  73905. this.element = null
  73906. },
  73907. stop: function() {
  73908. var that = this;
  73909. that._animations = {};
  73910. that._animationCount = 0;
  73911. DX.cancelAnimationFrame(that._timerId);
  73912. clearTimeout(that._startDelay);
  73913. clearTimeout(that._endAnimationTimer);
  73914. that._timerId = null
  73915. },
  73916. lock: function() {
  73917. var an,
  73918. animations = this._animations;
  73919. for (an in animations)
  73920. animations[an].stop(true, true);
  73921. this.stop()
  73922. }
  73923. };
  73924. rendererNS.Animation = Animation;
  73925. rendererNS.noop = noop
  73926. })(DevExpress);
  73927. /*! Module viz-core, file renderer.js */
  73928. (function($, DX, document) {
  73929. var renderers = DX.viz.renderers,
  73930. browser = DX.browser;
  73931. function isSvg() {
  73932. return !(browser.msie && browser.version < 9) || !!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', "svg").createSVGRect
  73933. }
  73934. if (!isSvg()) {
  73935. if (document.namespaces && !document.namespaces.vml) {
  73936. document.namespaces.add('vml', 'urn:schemas-microsoft-com:vml');
  73937. document.createStyleSheet().cssText = 'vml\\:* { behavior:url(#default#VML); display: inline-block; } '
  73938. }
  73939. renderers.Renderer = renderers.VmlRenderer
  73940. }
  73941. else
  73942. renderers.Renderer = renderers.SvgRenderer;
  73943. renderers.isSvg = isSvg
  73944. })(jQuery, DevExpress, document);
  73945. /*! Module viz-core, file seriesConsts.js */
  73946. (function(DX) {
  73947. DX.viz.core.series = DX.viz.core.series || {};
  73948. DX.viz.core.series.helpers = DX.viz.core.series.helpers || {};
  73949. DX.viz.core.series.helpers.consts = {
  73950. events: {
  73951. mouseover: "mouseover",
  73952. mouseout: "mouseout",
  73953. mousemove: "mousemove",
  73954. touchstart: "touchstart",
  73955. touchmove: "touchmove",
  73956. touchend: "touchend",
  73957. mousedown: "mousedown",
  73958. mouseup: "mouseup",
  73959. click: "click",
  73960. selectSeries: "selectseries",
  73961. deselectSeries: "deselectseries",
  73962. selectPoint: "selectpoint",
  73963. deselectPoint: "deselectpoint",
  73964. showPointTooltip: "showpointtooltip",
  73965. hidePointTooltip: "hidepointtooltip"
  73966. },
  73967. states: {
  73968. hover: "hover",
  73969. normal: "normal",
  73970. selected: "selected",
  73971. normalMark: 0,
  73972. hoverMark: 1,
  73973. selectedMark: 2
  73974. },
  73975. animations: {
  73976. showDuration: {duration: 400},
  73977. hideGroup: {opacity: 0.0001},
  73978. showGroup: {opacity: 1}
  73979. },
  73980. pieLabelIndent: 30
  73981. }
  73982. })(DevExpress);
  73983. /*! Module viz-core, file seriesFamily.js */
  73984. (function($, DX, undefined) {
  73985. var utils = DX.utils,
  73986. _math = Math,
  73987. _round = _math.round,
  73988. _abs = _math.abs,
  73989. _pow = _math.pow,
  73990. _each = $.each;
  73991. DX.viz.core.series.helpers.SeriesFamily = DX.Class.inherit(function() {
  73992. var ctor = function(options) {
  73993. var debug = DX.utils.debug;
  73994. debug.assert(options.type, "type was not passed or empty");
  73995. var that = this,
  73996. stubFunction = $.noop;
  73997. that.type = options.type.toLowerCase();
  73998. that.pane = options.pane;
  73999. that.series = [];
  74000. that.updateOptions(options);
  74001. switch (that.type) {
  74002. case"bar":
  74003. that.adjustSeriesDimensions = adjustBarSeriesDimensions;
  74004. that.adjustSeriesValues = stubFunction;
  74005. that.updateSeriesValues = updateBarSeriesValues;
  74006. break;
  74007. case"rangebar":
  74008. that.adjustSeriesDimensions = adjustBarSeriesDimensions;
  74009. that.adjustSeriesValues = stubFunction;
  74010. that.updateSeriesValues = stubFunction;
  74011. break;
  74012. case"fullstackedbar":
  74013. that.fullStacked = true;
  74014. that.adjustSeriesDimensions = adjustStackedBarSeriesDimensions;
  74015. that.adjustSeriesValues = adjustStackedSeriesValues;
  74016. that.updateSeriesValues = updateStackedSeriesValues;
  74017. break;
  74018. case"stackedbar":
  74019. that.adjustSeriesDimensions = adjustStackedBarSeriesDimensions;
  74020. that.adjustSeriesValues = adjustStackedSeriesValues;
  74021. that.updateSeriesValues = updateStackedSeriesValues;
  74022. break;
  74023. case"fullstackedarea":
  74024. case"fullstackedline":
  74025. case"fullstackedspline":
  74026. case"fullstackedsplinearea":
  74027. that.fullStacked = true;
  74028. that.adjustSeriesDimensions = stubFunction;
  74029. that.adjustSeriesValues = adjustStackedSeriesValues;
  74030. that.updateSeriesValues = stubFunction;
  74031. break;
  74032. case"stackedarea":
  74033. case"stackedsplinearea":
  74034. case"stackedline":
  74035. case"stackedspline":
  74036. that.adjustSeriesDimensions = stubFunction;
  74037. that.adjustSeriesValues = adjustStackedSeriesValues;
  74038. that.updateSeriesValues = stubFunction;
  74039. break;
  74040. case"candlestick":
  74041. case"stock":
  74042. that.adjustSeriesDimensions = adjustCandlestickSeriesDimensions;
  74043. that.adjustSeriesValues = stubFunction;
  74044. that.updateSeriesValues = stubFunction;
  74045. break;
  74046. case"bubble":
  74047. that.adjustSeriesDimensions = adjustBubbleSeriesDimensions;
  74048. that.adjustSeriesValues = stubFunction;
  74049. that.updateSeriesValues = stubFunction;
  74050. break;
  74051. default:
  74052. that.adjustSeriesDimensions = stubFunction;
  74053. that.adjustSeriesValues = stubFunction;
  74054. that.updateSeriesValues = stubFunction;
  74055. break
  74056. }
  74057. };
  74058. var updateOptions = function(options) {
  74059. this.equalBarWidth = options.equalBarWidth;
  74060. this.minBubbleSize = options.minBubbleSize;
  74061. this.maxBubbleSize = options.maxBubbleSize
  74062. };
  74063. var dispose = function() {
  74064. this.series = null;
  74065. this.translators = null
  74066. };
  74067. var add = function(series) {
  74068. var that = this,
  74069. singleSeries,
  74070. i;
  74071. if (!$.isArray(series))
  74072. series = [series];
  74073. for (i = 0; i < series.length; i++) {
  74074. singleSeries = series[i];
  74075. if (singleSeries.type.toLowerCase() === that.type)
  74076. that.series.push(singleSeries)
  74077. }
  74078. };
  74079. function correctPointCoordinates(points, width, offset) {
  74080. _each(points, function(_, point) {
  74081. point.correctCoordinates({
  74082. width: width,
  74083. offset: offset
  74084. })
  74085. })
  74086. }
  74087. function getStacksWithArgument(stackKeepers, argument) {
  74088. var stacksWithArgument = [];
  74089. _each(stackKeepers, function(stackName, seriesInStack) {
  74090. _each(seriesInStack, function(_, singleSeries) {
  74091. var points = singleSeries.getPointsByArg(argument),
  74092. pointsLength = points.length,
  74093. i;
  74094. for (i = 0; i < pointsLength; ++i)
  74095. if (points[i] && points[i].value) {
  74096. stacksWithArgument.push(stackName);
  74097. return false
  74098. }
  74099. })
  74100. });
  74101. return stacksWithArgument
  74102. }
  74103. function correctPointCoordinatesForStacks(stackKeepers, stacksWithArgument, argument, middleIndex, width, spacing) {
  74104. _each(stackKeepers, function(stackName, seriesInStack) {
  74105. var stackIndex = $.inArray(stackName, stacksWithArgument),
  74106. offset;
  74107. if (stackIndex === -1)
  74108. return;
  74109. offset = (stackIndex - middleIndex + 0.5) * width - (middleIndex - stackIndex - 0.5) * spacing;
  74110. _each(seriesInStack, function(_, singleSeries) {
  74111. _each(singleSeries.getPointsByArg(argument) || [], function(_, point) {
  74112. if (point && point.value)
  74113. point.correctCoordinates({
  74114. width: width,
  74115. offset: offset
  74116. })
  74117. })
  74118. })
  74119. })
  74120. }
  74121. var adjustBarSeriesDimensionsCore = function(series, interval, stackCount, equalBarWidth, seriesStackIndexCallback) {
  74122. var spacing,
  74123. width,
  74124. maxWidth,
  74125. middleIndex,
  74126. stackIndex,
  74127. i,
  74128. points,
  74129. seriesOffset,
  74130. stackName,
  74131. argumentsKeeper = {},
  74132. stackKeepers = {},
  74133. stacksWithArgument,
  74134. count;
  74135. if (equalBarWidth) {
  74136. width = equalBarWidth.width && equalBarWidth.width < 0 ? 0 : equalBarWidth.width;
  74137. spacing = equalBarWidth.spacing && equalBarWidth.spacing < 0 ? 0 : equalBarWidth.spacing;
  74138. if (!spacing)
  74139. if (stackCount > 1) {
  74140. spacing = width ? _round((interval * 0.7 - width * stackCount) / (stackCount - 1)) : _round(interval * 0.7 / stackCount * 0.2);
  74141. if (spacing < 1)
  74142. spacing = 1
  74143. }
  74144. else
  74145. spacing = 0;
  74146. if (!width) {
  74147. width = _round((interval * 0.7 - spacing * (stackCount - 1)) / stackCount);
  74148. if (width < 2)
  74149. width = 2
  74150. }
  74151. if (width * stackCount + spacing * (stackCount - 1) > interval) {
  74152. spacing = _round((interval * 0.7 - width * stackCount) / (stackCount - 1));
  74153. if (spacing < 1) {
  74154. spacing = 1;
  74155. maxWidth = _round((interval * 0.7 - spacing * (stackCount - 1)) / stackCount)
  74156. }
  74157. }
  74158. middleIndex = stackCount / 2;
  74159. for (i = 0; i < series.length; i++) {
  74160. stackIndex = seriesStackIndexCallback(i);
  74161. points = series[i].getPoints();
  74162. seriesOffset = (stackIndex - middleIndex + 0.5) * (maxWidth || width) - (middleIndex - stackIndex - 0.5) * spacing;
  74163. correctPointCoordinates(points, width, seriesOffset)
  74164. }
  74165. }
  74166. else {
  74167. _each(series, function(i, singleSeries) {
  74168. stackName = singleSeries.getStackName && singleSeries.getStackName();
  74169. stackName = stackName || i.toString();
  74170. if (!stackKeepers[stackName])
  74171. stackKeepers[stackName] = [];
  74172. stackKeepers[stackName].push(singleSeries)
  74173. });
  74174. _each(series, function(i, singleSeries) {
  74175. _each(singleSeries.getPoints(), function(_, point) {
  74176. var argument = point.argument;
  74177. if (!argumentsKeeper.hasOwnProperty(argument))
  74178. argumentsKeeper[argument.valueOf()] = 1
  74179. })
  74180. });
  74181. for (var argument in argumentsKeeper) {
  74182. if (!argumentsKeeper.hasOwnProperty(argument))
  74183. continue;
  74184. stacksWithArgument = getStacksWithArgument(stackKeepers, argument);
  74185. count = stacksWithArgument.length;
  74186. spacing = _round(interval * 0.7 / count * 0.2);
  74187. if (spacing < 1)
  74188. spacing = 1;
  74189. width = _round((interval * 0.7 - spacing * (count - 1)) / count);
  74190. if (width < 2)
  74191. width = 2;
  74192. middleIndex = count / 2;
  74193. correctPointCoordinatesForStacks(stackKeepers, stacksWithArgument, argument, middleIndex, width, spacing)
  74194. }
  74195. }
  74196. };
  74197. function checkMinBarSize(value, minShownValue) {
  74198. return _abs(value) < minShownValue ? value >= 0 ? minShownValue : -minShownValue : value
  74199. }
  74200. function getValueType(value) {
  74201. return value >= 0 ? "positive" : "negative"
  74202. }
  74203. function getVisibleSeries(that) {
  74204. return $.map(that.series, function(s) {
  74205. return s.isVisible() ? s : null
  74206. })
  74207. }
  74208. function getAbsStackSumByArg(stackKeepers, stackName, argument) {
  74209. var positiveStackValue = (stackKeepers.positive[stackName] || {})[argument] || 0,
  74210. negativeStackValue = -(stackKeepers.negative[stackName] || {})[argument] || 0;
  74211. return positiveStackValue + negativeStackValue
  74212. }
  74213. var adjustBarSeriesDimensions = function(translators) {
  74214. var debug = DX.utils.debug;
  74215. debug.assert(translators, "translator was not passed or empty");
  74216. var that = this,
  74217. equalBarWidth = that.equalBarWidth,
  74218. series = getVisibleSeries(that);
  74219. adjustBarSeriesDimensionsCore(series, getInterval(that, translators), series.length, equalBarWidth, function(seriesIndex) {
  74220. return seriesIndex
  74221. })
  74222. };
  74223. var adjustStackedBarSeriesDimensions = function(translators) {
  74224. var debug = DX.utils.debug;
  74225. debug.assert(translators, "translators was not passed or empty");
  74226. var that = this,
  74227. series = getVisibleSeries(that),
  74228. stackIndexes = {},
  74229. stackCount = 0,
  74230. equalBarWidth = that.equalBarWidth;
  74231. _each(series, function() {
  74232. var stackName = this.getStackName();
  74233. if (!stackIndexes.hasOwnProperty(stackName))
  74234. stackIndexes[stackName] = stackCount++
  74235. });
  74236. adjustBarSeriesDimensionsCore(series, getInterval(that, translators), stackCount, equalBarWidth, function(seriesIndex) {
  74237. return stackIndexes[series[seriesIndex].getStackName()]
  74238. })
  74239. };
  74240. var adjustStackedSeriesValues = function() {
  74241. var that = this,
  74242. series = getVisibleSeries(that),
  74243. stackKeepers = {
  74244. positive: {},
  74245. negative: {}
  74246. },
  74247. holesStack = {
  74248. left: {},
  74249. right: {}
  74250. };
  74251. _each(series, function(seriesIndex, singleSeries) {
  74252. var points = singleSeries.getPoints(),
  74253. hole = false;
  74254. singleSeries._prevSeries = series[seriesIndex - 1],
  74255. singleSeries.holes = $.extend(true, {}, holesStack);
  74256. _each(points, function(index, point) {
  74257. var value = point.initialValue,
  74258. argument = point.argument.valueOf(),
  74259. stackName = singleSeries.getStackName(),
  74260. stacks = value >= 0 ? stackKeepers.positive : stackKeepers.negative,
  74261. currentStack;
  74262. stacks[stackName] = stacks[stackName] || {};
  74263. currentStack = stacks[stackName];
  74264. if (currentStack[argument]) {
  74265. point.correctValue(currentStack[argument]);
  74266. currentStack[argument] += value
  74267. }
  74268. else {
  74269. currentStack[argument] = value;
  74270. point.resetCorrection()
  74271. }
  74272. if (!point.hasValue()) {
  74273. var prevPoint = points[index - 1];
  74274. if (!hole && prevPoint && prevPoint.hasValue()) {
  74275. argument = prevPoint.argument.valueOf();
  74276. prevPoint._skipSetRightHole = true;
  74277. holesStack.right[argument] = (holesStack.right[argument] || 0) + (prevPoint.value - (isFinite(prevPoint.minValue) ? prevPoint.minValue : 0))
  74278. }
  74279. hole = true
  74280. }
  74281. else if (hole) {
  74282. hole = false;
  74283. holesStack.left[argument] = (holesStack.left[argument] || 0) + (point.value - (isFinite(point.minValue) ? point.minValue : 0));
  74284. point._skipSetLeftHole = true
  74285. }
  74286. })
  74287. });
  74288. _each(series, function(seriesIndex, singleSeries) {
  74289. var points = singleSeries.getPoints(),
  74290. holes = singleSeries.holes;
  74291. _each(points, function(index, point) {
  74292. var argument = point.argument.valueOf();
  74293. point.resetHoles();
  74294. !point._skipSetLeftHole && point.setHole(holes.left[argument] || holesStack.left[argument] && 0, "left");
  74295. !point._skipSetRightHole && point.setHole(holes.right[argument] || holesStack.right[argument] && 0, "right");
  74296. point._skipSetLeftHole = null;
  74297. point._skipSetRightHole = null
  74298. })
  74299. });
  74300. that._stackKeepers = stackKeepers;
  74301. setPercentStackedValues(series, stackKeepers, that.fullStacked, holesStack)
  74302. };
  74303. var setPercentStackedValues = function(series, stackKeepers, fullStacked, holeStack) {
  74304. _each(series, function(_, singleSeries) {
  74305. _each(singleSeries.getPoints(), function(_, point) {
  74306. var argument = point.argument.valueOf();
  74307. point.setPercentValue(getAbsStackSumByArg(stackKeepers, singleSeries.getStackName(), argument), fullStacked, holeStack.left[argument], holeStack.right[argument])
  74308. })
  74309. })
  74310. };
  74311. var updateStackedSeriesValues = function(translators) {
  74312. var that = this,
  74313. series = getVisibleSeries(that),
  74314. stack = that._stackKeepers,
  74315. stackKeepers = {
  74316. positive: {},
  74317. negative: {}
  74318. };
  74319. _each(series, function(_, singleSeries) {
  74320. var minBarSize = singleSeries.getOptions().minBarSize,
  74321. minShownBusinessValue = minBarSize && translators.val.getMinBarSize(minBarSize),
  74322. stackName = singleSeries.getStackName();
  74323. _each(singleSeries.getPoints(), function(index, point) {
  74324. if (!point.hasValue())
  74325. return;
  74326. var value = point.initialValue,
  74327. argument = point.argument.valueOf(),
  74328. updateValue,
  74329. valueType,
  74330. currentStack;
  74331. if (that.fullStacked)
  74332. value = _abs(value) / getAbsStackSumByArg(stack, stackName, argument) || 0;
  74333. updateValue = checkMinBarSize(value, minShownBusinessValue);
  74334. valueType = getValueType(updateValue);
  74335. currentStack = stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {};
  74336. if (currentStack[argument]) {
  74337. point.minValue = currentStack[argument];
  74338. currentStack[argument] += updateValue
  74339. }
  74340. else
  74341. currentStack[argument] = updateValue;
  74342. point.value = currentStack[argument]
  74343. })
  74344. });
  74345. if (that.fullStacked)
  74346. updateFullStackedSeriesValues(series, stackKeepers)
  74347. };
  74348. var updateFullStackedSeriesValues = function(series, stackKeepers) {
  74349. _each(series, function(_, singleSeries) {
  74350. var stackName = singleSeries.getStackName ? singleSeries.getStackName() : "default";
  74351. _each(singleSeries.getPoints(), function(index, point) {
  74352. var value = _abs(point.value),
  74353. argument = point.argument.valueOf(),
  74354. valueType = getValueType(value),
  74355. currentStack;
  74356. stackKeepers[valueType][stackName] = stackKeepers[valueType][stackName] || {};
  74357. currentStack = stackKeepers[valueType][stackName];
  74358. point.value = point.value / currentStack[argument] || 0;
  74359. if (utils.isNumber(point.minValue))
  74360. point.minValue = point.minValue / currentStack[argument] || 0
  74361. })
  74362. })
  74363. };
  74364. var updateBarSeriesValues = function(translators) {
  74365. _each(this.series, function(_, singleSeries) {
  74366. var minBarSize = singleSeries.getOptions().minBarSize,
  74367. minShownBusinessValue = minBarSize && translators.val.getMinBarSize(minBarSize);
  74368. if (minShownBusinessValue)
  74369. _each(singleSeries.getPoints(), function(index, point) {
  74370. if (point.hasValue())
  74371. point.value = checkMinBarSize(point.initialValue, minShownBusinessValue)
  74372. })
  74373. })
  74374. };
  74375. var adjustCandlestickSeriesDimensions = function(translators) {
  74376. var debug = DX.utils.debug;
  74377. debug.assert(translators, "translator was not passed or empty");
  74378. var that = this,
  74379. series = getVisibleSeries(that);
  74380. adjustBarSeriesDimensionsCore(series, getInterval(that, translators), series.length, true, function(seriesIndex) {
  74381. return seriesIndex
  74382. })
  74383. };
  74384. var getInterval = function(that, translators) {
  74385. var argTranslator = translators.arg;
  74386. that.interval = argTranslator.getInterval();
  74387. return that.interval
  74388. };
  74389. var adjustBubbleSeriesDimensions = function(translators) {
  74390. var debug = DX.utils.debug;
  74391. debug.assert(translators, "translator was not passed or empty");
  74392. var that = this,
  74393. series = getVisibleSeries(that),
  74394. visibleAreaX = translators.arg.getCanvasVisibleArea(),
  74395. visibleAreaY = translators.val.getCanvasVisibleArea(),
  74396. min = Math.min(visibleAreaX.max - visibleAreaX.min, visibleAreaY.max - visibleAreaY.min),
  74397. minBubbleArea = _pow(that.minBubbleSize, 2),
  74398. maxBubbleArea = _pow(min * that.maxBubbleSize, 2),
  74399. equalBubbleSize = (min * that.maxBubbleSize + that.minBubbleSize) / 2,
  74400. minPointSize = Infinity,
  74401. maxPointSize = 0,
  74402. pointSize,
  74403. bubbleArea,
  74404. sizeProportion,
  74405. sizeDispersion,
  74406. areaDispersion;
  74407. _each(series, function(_, seriesItem) {
  74408. _each(seriesItem.getPoints(), function(_, point) {
  74409. maxPointSize = maxPointSize > point.size ? maxPointSize : point.size;
  74410. minPointSize = minPointSize < point.size ? minPointSize : point.size
  74411. })
  74412. });
  74413. sizeDispersion = maxPointSize - minPointSize;
  74414. areaDispersion = _abs(maxBubbleArea - minBubbleArea);
  74415. minPointSize = minPointSize < 0 ? 0 : minPointSize;
  74416. _each(series, function(_, seriesItem) {
  74417. _each(seriesItem.getPoints(), function(_, point) {
  74418. if (maxPointSize === minPointSize)
  74419. pointSize = _round(equalBubbleSize);
  74420. else {
  74421. sizeProportion = _abs(point.size - minPointSize) / sizeDispersion;
  74422. bubbleArea = areaDispersion * sizeProportion + minBubbleArea;
  74423. pointSize = _round(Math.sqrt(bubbleArea))
  74424. }
  74425. point.correctCoordinates(pointSize)
  74426. })
  74427. })
  74428. };
  74429. return {
  74430. ctor: ctor,
  74431. dispose: dispose,
  74432. add: add,
  74433. updateOptions: updateOptions
  74434. }
  74435. }())
  74436. })(jQuery, DevExpress);
  74437. /*! Module viz-core, file baseSeries.js */
  74438. (function($, DX) {
  74439. var viz = DX.viz,
  74440. core = viz.core,
  74441. seriesNS = core.series,
  74442. utils = DX.utils,
  74443. _isDefined = utils.isDefined,
  74444. _each = $.each,
  74445. _extend = $.extend,
  74446. _isEmptyObject = $.isEmptyObject,
  74447. _Event = $.Event,
  74448. _noop = $.noop,
  74449. SELECTED_STATE = 2,
  74450. HOVER_STATE = 1,
  74451. NONE_MODE = "none",
  74452. INCLUDE_POINTS = "includepoints",
  74453. EXLUDE_POINTS = "excludepoints",
  74454. NEAREST_POINT = "nearestpoint",
  74455. APPLY_SELECTED = "applySelected",
  74456. APPLY_HOVER = "applyHover",
  74457. SYMBOL_POINT = "symbolPoint",
  74458. POLAR_SYMBOL_POINT = "polarSymbolPoint",
  74459. BAR_POINT = "barPoint",
  74460. POLAR_BAR_POINT = "polarBarPoint",
  74461. PIE_POINT = "piePoint",
  74462. HOVER = "hover",
  74463. NORMAL = "normal",
  74464. SELECTION = "selection",
  74465. getEmptyBusinessRange = function() {
  74466. return {
  74467. arg: {},
  74468. val: {}
  74469. }
  74470. };
  74471. function triggerEvent(element, event, point) {
  74472. element && element.trigger(event, point)
  74473. }
  74474. seriesNS.mixins = {
  74475. chart: {pointTypes: {
  74476. scatter: SYMBOL_POINT,
  74477. line: SYMBOL_POINT,
  74478. spline: SYMBOL_POINT,
  74479. stepline: SYMBOL_POINT,
  74480. stackedline: SYMBOL_POINT,
  74481. fullstackedline: SYMBOL_POINT,
  74482. stackedspline: SYMBOL_POINT,
  74483. fullstackedspline: SYMBOL_POINT,
  74484. stackedsplinearea: SYMBOL_POINT,
  74485. fullstackedsplinearea: SYMBOL_POINT,
  74486. area: SYMBOL_POINT,
  74487. splinearea: SYMBOL_POINT,
  74488. steparea: SYMBOL_POINT,
  74489. stackedarea: SYMBOL_POINT,
  74490. fullstackedarea: SYMBOL_POINT,
  74491. rangearea: "rangeSymbolPoint",
  74492. bar: BAR_POINT,
  74493. stackedbar: BAR_POINT,
  74494. fullstackedbar: BAR_POINT,
  74495. rangebar: "rangeBarPoint",
  74496. bubble: "bubblePoint",
  74497. stock: "stockPoint",
  74498. candlestick: "candlestickPoint"
  74499. }},
  74500. pie: {pointTypes: {
  74501. pie: PIE_POINT,
  74502. doughnut: PIE_POINT,
  74503. donut: PIE_POINT
  74504. }},
  74505. polar: {pointTypes: {
  74506. scatter: POLAR_SYMBOL_POINT,
  74507. line: POLAR_SYMBOL_POINT,
  74508. area: POLAR_SYMBOL_POINT,
  74509. bar: POLAR_BAR_POINT,
  74510. stackedbar: POLAR_BAR_POINT
  74511. }}
  74512. };
  74513. function includePointsMode(mode) {
  74514. return mode === INCLUDE_POINTS || mode === "allseriespoints"
  74515. }
  74516. function Series() {
  74517. this.ctor.apply(this, arguments)
  74518. }
  74519. function applyPointStyle(point, styleName) {
  74520. !point.isSelected() && point.applyStyle(styleName)
  74521. }
  74522. seriesNS.Series = Series;
  74523. Series.prototype = {
  74524. ctor: function(renderSettings, options) {
  74525. var that = this;
  74526. that.fullState = 0;
  74527. that._extGroups = renderSettings;
  74528. that._renderer = renderSettings.renderer;
  74529. that._group = renderSettings.renderer.g().attr({"class": "dxc-series"});
  74530. that.updateOptions(options)
  74531. },
  74532. update: function(data, options) {
  74533. this.updateOptions(options);
  74534. this.updateData(data)
  74535. },
  74536. _createLegendState: _noop,
  74537. getLegendStyles: function() {
  74538. return this._styles.legendStyles
  74539. },
  74540. _createStyles: function(options) {
  74541. var that = this,
  74542. mainSeriesColor = options.mainSeriesColor,
  74543. specialMainColor = that._getSpecialColor(mainSeriesColor);
  74544. that._styles = {
  74545. normal: that._parseStyle(options, mainSeriesColor, mainSeriesColor),
  74546. hover: that._parseStyle(options.hoverStyle || {}, specialMainColor, mainSeriesColor),
  74547. selection: that._parseStyle(options.selectionStyle || {}, specialMainColor, mainSeriesColor),
  74548. legendStyles: {
  74549. normal: that._createLegendState(options, mainSeriesColor),
  74550. hover: that._createLegendState(options.hoverStyle || {}, specialMainColor),
  74551. selection: that._createLegendState(options.selectionStyle || {}, specialMainColor)
  74552. }
  74553. }
  74554. },
  74555. setAdjustSeriesLabels: function(adjustSeriesLabels) {
  74556. _each(this._points || [], function(_, point) {
  74557. point.setAdjustSeriesLabels(adjustSeriesLabels)
  74558. })
  74559. },
  74560. setClippingParams: function(baseId, wideId, forceClipping) {
  74561. this._paneClipRectID = baseId;
  74562. this._widePaneClipRectID = wideId;
  74563. this._forceClipping = forceClipping
  74564. },
  74565. applyClip: function() {
  74566. this._group.attr({clipId: this._paneClipRectID})
  74567. },
  74568. resetClip: function() {
  74569. this._group.attr({clipId: null})
  74570. },
  74571. getTagField: function() {
  74572. return this._options.tagField || "tag"
  74573. },
  74574. getValueFields: _noop,
  74575. getArgumentField: _noop,
  74576. getPoints: function() {
  74577. return this._points
  74578. },
  74579. _createPoint: function(data, pointsArray, index) {
  74580. data.index = index;
  74581. var that = this,
  74582. point = pointsArray[index],
  74583. pointsByArgument = that.pointsByArgument,
  74584. options;
  74585. if (that._checkData(data)) {
  74586. options = that._customizePoint(data) || that._getCreatingPointOptions();
  74587. if (point)
  74588. point.update(data, options);
  74589. else {
  74590. point = core.CoreFactory.createPoint(that, data, options);
  74591. pointsArray.push(point)
  74592. }
  74593. pointsByArgument[point.argument.valueOf()] = pointsByArgument[point.argument.valueOf()] || [];
  74594. pointsByArgument[point.argument.valueOf()].push(point);
  74595. return true
  74596. }
  74597. },
  74598. getRangeData: function(zoomArgs, calcIntervalFunction) {
  74599. return this._visible ? _extend(true, {}, this._getRangeData(zoomArgs, calcIntervalFunction)) : getEmptyBusinessRange()
  74600. },
  74601. _deleteGroup: function(groupName) {
  74602. var group = this[groupName];
  74603. if (group) {
  74604. group.dispose();
  74605. this[groupName] = null
  74606. }
  74607. },
  74608. _saveOldAnimationMethods: function() {
  74609. var that = this;
  74610. that._oldClearingAnimation = that._clearingAnimation;
  74611. that._oldUpdateElement = that._updateElement;
  74612. that._oldgetAffineCoordOptions = that._getAffineCoordOptions
  74613. },
  74614. _deleteOldAnimationMethods: function() {
  74615. this._oldClearingAnimation = null;
  74616. this._oldUpdateElement = null;
  74617. this._oldgetAffineCoordOptions = null
  74618. },
  74619. updateOptions: function(newOptions) {
  74620. var that = this,
  74621. widgetType = newOptions.widgetType,
  74622. oldType = that.type,
  74623. newType = newOptions.type;
  74624. that.type = newType && newType.toString().toLowerCase();
  74625. if (!that._checkType(widgetType) || that._checkPolarBarType(widgetType, newOptions)) {
  74626. that.dispose();
  74627. that.isUpdated = false;
  74628. return
  74629. }
  74630. if (oldType !== that.type) {
  74631. that._firstDrawing = true;
  74632. that._saveOldAnimationMethods();
  74633. that._resetType(oldType, widgetType);
  74634. that._setType(that.type, widgetType)
  74635. }
  74636. that._options = newOptions;
  74637. that._pointOptions = null;
  74638. that._deletePatterns();
  74639. that._patterns = [];
  74640. that.name = newOptions.name;
  74641. that.pane = newOptions.pane;
  74642. that.axis = newOptions.axis;
  74643. that.tag = newOptions.tag;
  74644. that._createStyles(newOptions);
  74645. that._updateOptions(newOptions);
  74646. that._visible = newOptions.visible;
  74647. that.isUpdated = true
  74648. },
  74649. _disposePoints: function(points) {
  74650. _each(points || [], function(_, p) {
  74651. p.dispose()
  74652. })
  74653. },
  74654. _correctPointsLength: function(length, points) {
  74655. this._disposePoints(this._oldPoints);
  74656. this._oldPoints = points.splice(length, points.length)
  74657. },
  74658. _getTicksForAggregation: function(min, max, screenDelta, pointSize) {
  74659. var types = {
  74660. axisType: "continuous",
  74661. dataType: utils.isDate(min) ? "datetime" : "numeric"
  74662. },
  74663. data = {
  74664. min: min,
  74665. max: max,
  74666. screenDelta: screenDelta
  74667. },
  74668. options = {
  74669. gridSpacingFactor: pointSize,
  74670. labelOptions: {},
  74671. stick: true
  74672. },
  74673. tickManager = new viz.core.tickManager.TickManager(types, data, options);
  74674. return {
  74675. ticks: tickManager.getTicks(true),
  74676. tickInterval: tickManager.getTickInterval()
  74677. }
  74678. },
  74679. _getRangeCorrector: _noop,
  74680. updateDataType: function(settings) {
  74681. var that = this;
  74682. that.argumentType = settings.argumentType;
  74683. that.valueType = settings.valueType;
  74684. that.argumentAxisType = settings.argumentAxisType;
  74685. that.valueAxisType = settings.valueAxisType;
  74686. that.showZero = settings.showZero;
  74687. return that
  74688. },
  74689. getOptions: function() {
  74690. return this._options
  74691. },
  74692. _resetRangeData: function() {
  74693. this._rangeData = getEmptyBusinessRange()
  74694. },
  74695. updateData: function(data) {
  74696. var that = this,
  74697. points = that._originalPoints || [],
  74698. lastPointIndex = 0,
  74699. options = that._options,
  74700. pointData,
  74701. rangeCorrector;
  74702. that._rangeErrorBarCorrector = rangeCorrector = that._getRangeCorrector();
  74703. that.pointsByArgument = {};
  74704. that._resetRangeData();
  74705. if (data && data.length)
  74706. that._canRenderCompleteHandle = true;
  74707. that._beginUpdateData(data);
  74708. _each(data, function(_, dataItem) {
  74709. pointData = that._getPointData(dataItem, options);
  74710. if (that._createPoint(pointData, points, lastPointIndex)) {
  74711. that._processRange(points[lastPointIndex], lastPointIndex > 0 ? points[lastPointIndex - 1] : null, rangeCorrector);
  74712. lastPointIndex++
  74713. }
  74714. });
  74715. that._disposePoints(that._aggregatedPoints);
  74716. that._aggregatedPoints = null;
  74717. that._points = that._originalPoints = points;
  74718. that._correctPointsLength(lastPointIndex, points);
  74719. that._endUpdateData()
  74720. },
  74721. getTeamplatedFields: function() {
  74722. var that = this,
  74723. fields = that.getValueFields(),
  74724. teampleteFields = [];
  74725. fields.push(that.getTagField());
  74726. _each(fields, function(_, field) {
  74727. var fieldsObject = {};
  74728. fieldsObject.teamplateField = field + that.name;
  74729. fieldsObject.originalField = field;
  74730. teampleteFields.push(fieldsObject)
  74731. });
  74732. return teampleteFields
  74733. },
  74734. resamplePoints: function(argTranslator, min, max) {
  74735. var that = this,
  74736. originalPoints = that.getAllPoints(),
  74737. minI,
  74738. maxI,
  74739. sizePoint,
  74740. tickObject,
  74741. ticks,
  74742. tickInterval;
  74743. if (originalPoints.length) {
  74744. _each(originalPoints, function(i, point) {
  74745. minI = point.argument - min <= 0 ? i : minI;
  74746. if (!maxI)
  74747. maxI = point.argument - max > 0 ? i : null
  74748. });
  74749. minI = minI ? minI : 1;
  74750. maxI = _isDefined(maxI) ? maxI : originalPoints.length - 1;
  74751. min = originalPoints[minI - 1].argument;
  74752. max = originalPoints[maxI].argument;
  74753. sizePoint = that._getPointSize();
  74754. if (that.argumentAxisType !== "discrete" && that.valueAxisType !== "discrete") {
  74755. tickObject = that._getTicksForAggregation(min, max, argTranslator.canvasLength, sizePoint);
  74756. ticks = tickObject.ticks;
  74757. tickInterval = tickObject.tickInterval;
  74758. if (ticks.length === 1) {
  74759. that._points = originalPoints;
  74760. return
  74761. }
  74762. }
  74763. else
  74764. ticks = argTranslator.canvasLength / sizePoint;
  74765. that._points = that._resample(ticks, tickInterval, argTranslator)
  74766. }
  74767. },
  74768. _removeOldSegments: function(startIndex) {
  74769. var that = this;
  74770. _each(that._graphics.splice(startIndex, that._graphics.length) || [], function(_, elem) {
  74771. that._removeElement(elem)
  74772. });
  74773. if (that._trackers)
  74774. _each(that._trackers.splice(startIndex, that._trackers.length) || [], function(_, elem) {
  74775. elem.remove()
  74776. })
  74777. },
  74778. draw: function(translators, animationEnabled, hideLayoutLabels, legendCallback) {
  74779. var that = this,
  74780. drawComplete;
  74781. if (that._oldClearingAnimation && animationEnabled && that._firstDrawing) {
  74782. drawComplete = function() {
  74783. that._draw(translators, true, hideLayoutLabels)
  74784. };
  74785. that._oldClearingAnimation(translators, drawComplete)
  74786. }
  74787. else
  74788. that._draw(translators, animationEnabled, hideLayoutLabels, legendCallback)
  74789. },
  74790. _clearSeries: function() {
  74791. var that = this;
  74792. that._deleteGroup("_elementsGroup");
  74793. that._deleteGroup("_bordersGroup");
  74794. that._deleteTrackers();
  74795. that._graphics = [];
  74796. that._trackers = []
  74797. },
  74798. _draw: function(translators, animationEnabled, hideLayoutLabels, legendCallback) {
  74799. var that = this,
  74800. points = that._points || [],
  74801. segment = [],
  74802. segmentCount = 0,
  74803. firstDrawing = that._firstDrawing,
  74804. closeSegment = points[0] && points[0].hasValue() && that._options.closed,
  74805. groupForPoint;
  74806. that._graphics = that._graphics || [];
  74807. that._prepareSeriesToDrawing();
  74808. if (!that._visible) {
  74809. animationEnabled = false;
  74810. that._group.remove();
  74811. return
  74812. }
  74813. that._group.append(that._extGroups.seriesGroup);
  74814. that.translators = translators;
  74815. that._createGroups(animationEnabled, undefined, firstDrawing);
  74816. that._segments = [];
  74817. that._drawedPoints = [];
  74818. that._firstDrawing = points.length ? false : true;
  74819. groupForPoint = {
  74820. markers: that._markersGroup,
  74821. labels: that._labelsGroup,
  74822. errorBars: that._errorBarGroup
  74823. };
  74824. _each(points, function(i, p) {
  74825. p.translate(translators);
  74826. if (p.hasValue()) {
  74827. that._drawPoint({
  74828. point: p,
  74829. groups: groupForPoint,
  74830. hasAnimation: animationEnabled,
  74831. firstDrawing: firstDrawing,
  74832. legendCallback: legendCallback
  74833. });
  74834. segment.push(p)
  74835. }
  74836. else if (segment.length) {
  74837. that._drawSegment(segment, animationEnabled, segmentCount++);
  74838. segment = []
  74839. }
  74840. });
  74841. segment.length && that._drawSegment(segment, animationEnabled, segmentCount++, closeSegment);
  74842. that._removeOldSegments(segmentCount);
  74843. that._defaultSegments = that._generateDefaultSegments();
  74844. hideLayoutLabels && that.hideLabels();
  74845. animationEnabled && that._animate(firstDrawing);
  74846. if (that.isSelected())
  74847. that._changeStyle(legendCallback, APPLY_SELECTED);
  74848. else if (that.isHovered())
  74849. that._changeStyle(legendCallback, APPLY_HOVER)
  74850. },
  74851. _checkType: function(widgetType) {
  74852. return !!seriesNS.mixins[widgetType][this.type]
  74853. },
  74854. _checkPolarBarType: function(widgetType, options) {
  74855. return widgetType === "polar" && options.spiderWidget && this.type.indexOf("bar") !== -1
  74856. },
  74857. _resetType: function(seriesType, widgetType) {
  74858. var that = this;
  74859. if (seriesType)
  74860. _each(seriesNS.mixins[widgetType][seriesType], function(methodName) {
  74861. delete that[methodName]
  74862. })
  74863. },
  74864. _setType: function(seriesType, widgetType) {
  74865. var that = this;
  74866. _each(seriesNS.mixins[widgetType][seriesType], function(methodName, method) {
  74867. that[methodName] = method
  74868. })
  74869. },
  74870. setSelectedState: function(state, mode, legendCallback) {
  74871. var that = this;
  74872. that.lastSelectionMode = (mode || that._options.selectionMode).toLowerCase();
  74873. if (state && !that.isSelected()) {
  74874. that.fullState = that.fullState | SELECTED_STATE;
  74875. that._nearestPoint && applyPointStyle(that._nearestPoint, "normal");
  74876. that._nearestPoint = null;
  74877. that._changeStyle(legendCallback, APPLY_SELECTED)
  74878. }
  74879. else if (!state && that.isSelected()) {
  74880. that.fullState = that.fullState & ~SELECTED_STATE;
  74881. if (that.isHovered())
  74882. that._changeStyle(legendCallback, APPLY_HOVER, SELECTION);
  74883. else
  74884. that._changeStyle(legendCallback, "resetItem")
  74885. }
  74886. },
  74887. setHoverState: function(state, mode, legendCallback) {
  74888. var that = this;
  74889. that.lastHoverMode = (mode || that._options.hoverMode).toLowerCase();
  74890. if (state && !that.isHovered()) {
  74891. that.fullState = that.fullState | HOVER_STATE;
  74892. !that.isSelected() && that._changeStyle(legendCallback, APPLY_HOVER)
  74893. }
  74894. else if (!state && that.isHovered()) {
  74895. that._nearestPoint = null;
  74896. that.fullState = that.fullState & ~HOVER_STATE;
  74897. !that.isSelected() && that._changeStyle(legendCallback, "resetItem")
  74898. }
  74899. },
  74900. isFullStackedSeries: function() {
  74901. return this.type.indexOf("fullstacked") === 0
  74902. },
  74903. isStackedSeries: function() {
  74904. return this.type.indexOf("stacked") === 0
  74905. },
  74906. isFinancialSeries: function() {
  74907. return this.type === "stock" || this.type === "candlestick"
  74908. },
  74909. _changeStyle: function(legendCallBack, legendAction, prevStyle) {
  74910. var that = this,
  74911. style = that._calcStyle(prevStyle),
  74912. pointStyle;
  74913. if (style.mode === NONE_MODE)
  74914. return;
  74915. legendCallBack && legendCallBack(legendAction);
  74916. if (includePointsMode(style.mode)) {
  74917. pointStyle = style.pointStyle;
  74918. _each(that._points || [], function(_, p) {
  74919. applyPointStyle(p, pointStyle)
  74920. })
  74921. }
  74922. that._applyStyle(style.series)
  74923. },
  74924. _calcStyle: function(prevStyle) {
  74925. var that = this,
  74926. styles = that._styles,
  74927. pointNormalState = false,
  74928. result;
  74929. switch (that.fullState & 3) {
  74930. case 0:
  74931. result = {
  74932. pointStyle: NORMAL,
  74933. mode: INCLUDE_POINTS,
  74934. series: styles.normal
  74935. };
  74936. break;
  74937. case 1:
  74938. pointNormalState = prevStyle === SELECTION && that.lastHoverMode === EXLUDE_POINTS || that.lastHoverMode === NEAREST_POINT && includePointsMode(that.lastSelectionMode);
  74939. result = {
  74940. pointStyle: pointNormalState ? NORMAL : HOVER,
  74941. mode: pointNormalState ? INCLUDE_POINTS : that.lastHoverMode,
  74942. series: styles.hover
  74943. };
  74944. break;
  74945. case 2:
  74946. result = {
  74947. pointStyle: SELECTION,
  74948. mode: that.lastSelectionMode,
  74949. series: styles.selection
  74950. };
  74951. break;
  74952. case 3:
  74953. pointNormalState = that.lastSelectionMode === EXLUDE_POINTS && includePointsMode(that.lastHoverMode);
  74954. result = {
  74955. pointStyle: pointNormalState ? NORMAL : SELECTION,
  74956. mode: pointNormalState ? INCLUDE_POINTS : that.lastSelectionMode,
  74957. series: styles.selection
  74958. }
  74959. }
  74960. return result
  74961. },
  74962. updateHover: function(x, y) {
  74963. var that = this,
  74964. currentNearestPoint = that._nearestPoint,
  74965. point = that.isHovered() && that.lastHoverMode === NEAREST_POINT && that.getNeighborPoint(x, y);
  74966. if (point !== currentNearestPoint && !that.isSelected()) {
  74967. currentNearestPoint && applyPointStyle(currentNearestPoint, "normal");
  74968. if (point) {
  74969. applyPointStyle(point, "hover");
  74970. that._nearestPoint = point
  74971. }
  74972. }
  74973. },
  74974. _getMainAxisName: function() {
  74975. return this._options.rotated ? "X" : "Y"
  74976. },
  74977. areLabelsVisible: function() {
  74978. return !_isDefined(this._options.maxLabelCount) || this._points.length <= this._options.maxLabelCount
  74979. },
  74980. getLabelVisibility: function() {
  74981. return this.areLabelsVisible() && this._options.label && this._options.label.visible
  74982. },
  74983. _customizePoint: function(pointData) {
  74984. var that = this,
  74985. options = that._options,
  74986. customizePoint = options.customizePoint,
  74987. customizeObject,
  74988. pointOptions,
  74989. customLabelOptions,
  74990. customOptions,
  74991. customizeLabel = options.customizeLabel,
  74992. useLabelCustomOptions,
  74993. usePointCustomOptions;
  74994. if (customizeLabel && customizeLabel.call) {
  74995. customizeObject = _extend({seriesName: that.name}, pointData);
  74996. customizeObject.series = that;
  74997. customLabelOptions = customizeLabel.call(customizeObject, customizeObject);
  74998. useLabelCustomOptions = customLabelOptions && !_isEmptyObject(customLabelOptions);
  74999. customLabelOptions = useLabelCustomOptions ? _extend(true, {}, options.label, customLabelOptions) : null
  75000. }
  75001. if (customizePoint && customizePoint.call) {
  75002. customizeObject = customizeObject || _extend({seriesName: that.name}, pointData);
  75003. customizeObject.series = that;
  75004. customOptions = customizePoint.call(customizeObject, customizeObject);
  75005. usePointCustomOptions = customOptions && !_isEmptyObject(customOptions)
  75006. }
  75007. if (useLabelCustomOptions || usePointCustomOptions) {
  75008. pointOptions = that._parsePointOptions(that._preparePointOptions(customOptions), customLabelOptions || options.label, true);
  75009. pointOptions.styles.useLabelCustomOptions = useLabelCustomOptions;
  75010. pointOptions.styles.usePointCustomOptions = usePointCustomOptions
  75011. }
  75012. return pointOptions
  75013. },
  75014. _getLabelOptions: function(labelOptions, defaultColor) {
  75015. var opt = labelOptions || {},
  75016. labelFont = opt.font || {},
  75017. labelBorder = opt.border || {},
  75018. labelConnector = opt.connector || {},
  75019. labelAttributes = {font: {
  75020. color: opt.backgroundColor === "none" && labelFont.color.toLowerCase() === "#ffffff" && opt.position !== "inside" ? defaultColor : labelFont.color,
  75021. family: labelFont.family,
  75022. weight: labelFont.weight,
  75023. size: labelFont.size,
  75024. opacity: labelFont.opacity
  75025. }},
  75026. backgroundAttr = {
  75027. fill: opt.backgroundColor || defaultColor,
  75028. "stroke-width": labelBorder.visible ? labelBorder.width || 0 : 0,
  75029. stroke: labelBorder.visible && labelBorder.width ? labelBorder.color : "none",
  75030. dashStyle: labelBorder.dashStyle
  75031. },
  75032. connectorAttr = {
  75033. stroke: labelConnector.visible && labelConnector.width ? labelConnector.color || defaultColor : "none",
  75034. "stroke-width": labelConnector.visible ? labelConnector.width || 0 : 0
  75035. };
  75036. return {
  75037. alignment: opt.alignment,
  75038. format: opt.format,
  75039. argumentFormat: opt.argumentFormat,
  75040. precision: opt.precision,
  75041. argumentPrecision: opt.argumentPrecision,
  75042. percentPrecision: opt.percentPrecision,
  75043. customizeText: $.isFunction(opt.customizeText) ? opt.customizeText : undefined,
  75044. attributes: labelAttributes,
  75045. visible: labelFont.size !== 0 ? opt.visible : false,
  75046. showForZeroValues: opt.showForZeroValues,
  75047. horizontalOffset: opt.horizontalOffset,
  75048. verticalOffset: opt.verticalOffset,
  75049. radialOffset: opt.radialOffset,
  75050. background: backgroundAttr,
  75051. position: opt.position,
  75052. connector: connectorAttr,
  75053. rotationAngle: opt.rotationAngle
  75054. }
  75055. },
  75056. show: function() {
  75057. if (!this._visible)
  75058. this._changeVisibility(true)
  75059. },
  75060. hide: function() {
  75061. if (this._visible)
  75062. this._changeVisibility(false)
  75063. },
  75064. _changeVisibility: function(visibility) {
  75065. var that = this;
  75066. that._visible = that._options.visible = visibility;
  75067. that._updatePointsVisibility();
  75068. that.hidePointTooltip();
  75069. that._options.visibilityChanged()
  75070. },
  75071. _updatePointsVisibility: $.noop,
  75072. hideLabels: function() {
  75073. _each(this._points, function(_, point) {
  75074. point._label.hide()
  75075. })
  75076. },
  75077. _parsePointOptions: function(pointOptions, labelOptions, isCustomPointOptions) {
  75078. var that = this,
  75079. options = that._options,
  75080. styles = that._createPointStyles(pointOptions, isCustomPointOptions),
  75081. parsedOptions = _extend(true, {}, pointOptions, {
  75082. type: options.type,
  75083. tag: that.tag,
  75084. rotated: options.rotated,
  75085. styles: styles,
  75086. widgetType: options.widgetType,
  75087. visibilityChanged: options.visibilityChanged
  75088. });
  75089. parsedOptions.label = that._getLabelOptions(labelOptions, styles.normal.fill);
  75090. parsedOptions.errorBars = options.valueErrorBar;
  75091. return parsedOptions
  75092. },
  75093. _resample: function(ticks, ticksInterval, argTranslator) {
  75094. var that = this,
  75095. fusPoints = [],
  75096. arrayFusPoints,
  75097. nowIndexTicks = 0,
  75098. lastPointIndex = 0,
  75099. originalPoints = that.getAllPoints(),
  75100. visibleArea;
  75101. if (that.argumentAxisType === "discrete" || that.valueAxisType === "discrete") {
  75102. visibleArea = argTranslator.getCanvasVisibleArea();
  75103. originalPoints = $.map(originalPoints, function(p) {
  75104. var pos = argTranslator.translate(p.argument),
  75105. result;
  75106. if (pos >= visibleArea.min && pos <= visibleArea.max)
  75107. result = p;
  75108. else {
  75109. p.setInvisibility();
  75110. result = null
  75111. }
  75112. return result
  75113. });
  75114. ticksInterval = originalPoints.length / ticks;
  75115. arrayFusPoints = $.map(originalPoints, function(point, index) {
  75116. if (Math.floor(nowIndexTicks) <= index) {
  75117. nowIndexTicks += ticksInterval;
  75118. return point
  75119. }
  75120. point.setInvisibility();
  75121. return null
  75122. });
  75123. return arrayFusPoints
  75124. }
  75125. that._aggregatedPoints = that._aggregatedPoints || [];
  75126. _each(originalPoints, function(_, point) {
  75127. point.setInvisibility();
  75128. switch (that._isInInterval(point.argument, ticks, nowIndexTicks, ticksInterval)) {
  75129. case true:
  75130. fusPoints.push(point);
  75131. break;
  75132. case"nextInterval":
  75133. var pointData = that._fusionPoints(fusPoints, ticks[nowIndexTicks], nowIndexTicks);
  75134. while (that._isInInterval(point.argument, ticks, nowIndexTicks, ticksInterval) === "nextInterval")
  75135. nowIndexTicks++;
  75136. fusPoints = [];
  75137. that._isInInterval(point.argument, ticks, nowIndexTicks, ticksInterval) === true && fusPoints.push(point);
  75138. if (that._createPoint(pointData, that._aggregatedPoints, lastPointIndex))
  75139. lastPointIndex++
  75140. }
  75141. });
  75142. if (fusPoints.length) {
  75143. var pointData = that._fusionPoints(fusPoints, ticks[nowIndexTicks], nowIndexTicks);
  75144. if (that._createPoint(pointData, that._aggregatedPoints, lastPointIndex))
  75145. lastPointIndex++
  75146. }
  75147. that._correctPointsLength(lastPointIndex, that._aggregatedPoints);
  75148. that._endUpdateData();
  75149. return that._aggregatedPoints
  75150. },
  75151. _isInInterval: function(argument, ticks, nowIndexTicks, ticksInterval) {
  75152. var minTick = ticks[nowIndexTicks],
  75153. maxTick = ticks[nowIndexTicks + 1],
  75154. sumMinTickTicksInterval;
  75155. ticksInterval = $.isNumeric(ticksInterval) ? ticksInterval : utils.dateToMilliseconds(ticksInterval);
  75156. sumMinTickTicksInterval = utils.isDate(minTick) ? new Date(minTick.getTime() + ticksInterval) : minTick + ticksInterval;
  75157. if (argument >= minTick && argument < sumMinTickTicksInterval)
  75158. return true;
  75159. if (argument < minTick || maxTick === undefined)
  75160. return false;
  75161. return "nextInterval"
  75162. },
  75163. canRenderCompleteHandle: function() {
  75164. var result = this._canRenderCompleteHandle;
  75165. delete this._canRenderCompleteHandle;
  75166. return !!result
  75167. },
  75168. isHovered: function() {
  75169. return !!(this.fullState & 1)
  75170. },
  75171. isSelected: function() {
  75172. return !!(this.fullState & 2)
  75173. },
  75174. isVisible: function() {
  75175. return this._visible
  75176. },
  75177. getAllPoints: function() {
  75178. return (this._originalPoints || []).slice()
  75179. },
  75180. getPointByPos: function(pos) {
  75181. return (this._points || [])[pos]
  75182. },
  75183. getVisiblePoints: function() {
  75184. return (this._drawedPoints || []).slice()
  75185. },
  75186. setPointHoverState: function(point, legendCallback) {
  75187. point.fullState = point.fullState | HOVER_STATE;
  75188. if (!(this.isSelected() && includePointsMode(this.lastSelectionMode)) && !point.isSelected()) {
  75189. point.applyStyle(HOVER);
  75190. legendCallback && legendCallback("applyHover")
  75191. }
  75192. },
  75193. releasePointHoverState: function(point, legendCallback) {
  75194. var that = this;
  75195. point.fullState = point.fullState & ~HOVER_STATE;
  75196. if (!(that.isSelected() && includePointsMode(that.lastSelectionMode)) && !point.isSelected())
  75197. if (!(that.isHovered() && includePointsMode(that.lastHoverMode)) || that.isSelected() && that.lastSelectionMode === EXLUDE_POINTS) {
  75198. point.applyStyle(NORMAL);
  75199. legendCallback && legendCallback("resetItem")
  75200. }
  75201. },
  75202. setPointSelectedState: function(point, legendCallback) {
  75203. point.fullState = point.fullState | SELECTED_STATE;
  75204. point.applyStyle(SELECTION);
  75205. legendCallback && legendCallback("applySelected")
  75206. },
  75207. releasePointSelectedState: function(point, legendCallback) {
  75208. var that = this;
  75209. point.fullState = point.fullState & ~SELECTED_STATE;
  75210. if (that.isHovered() && includePointsMode(that.lastHoverMode) || point.isHovered()) {
  75211. point.applyStyle(HOVER);
  75212. legendCallback && legendCallback("applyHover")
  75213. }
  75214. else if (that.isSelected() && includePointsMode(that.lastSelectionMode)) {
  75215. point.applyStyle(SELECTION);
  75216. legendCallback && legendCallback("applySelected")
  75217. }
  75218. else {
  75219. point.applyStyle(NORMAL);
  75220. legendCallback && legendCallback("resetItem")
  75221. }
  75222. },
  75223. selectPoint: function(point) {
  75224. triggerEvent(this._extGroups.seriesGroup, new _Event("selectpoint"), point)
  75225. },
  75226. deselectPoint: function(point) {
  75227. triggerEvent(this._extGroups.seriesGroup, new _Event("deselectpoint"), point)
  75228. },
  75229. showPointTooltip: function(point) {
  75230. triggerEvent(this._extGroups.seriesGroup, new _Event("showpointtooltip"), point)
  75231. },
  75232. hidePointTooltip: function(point) {
  75233. triggerEvent(this._extGroups.seriesGroup, new _Event("hidepointtooltip"), point)
  75234. },
  75235. select: function() {
  75236. var that = this;
  75237. triggerEvent(that._extGroups.seriesGroup, new _Event("selectseries", {target: that}), that._options.selectionMode);
  75238. that._group.toForeground()
  75239. },
  75240. clearSelection: function clearSelection() {
  75241. var that = this;
  75242. triggerEvent(that._extGroups.seriesGroup, new _Event("deselectseries", {target: that}), that._options.selectionMode)
  75243. },
  75244. getPointByArg: function(arg) {
  75245. return this.getPointsByArg(arg)[0] || null
  75246. },
  75247. getPointsByArg: function(arg) {
  75248. return this.pointsByArgument[arg.valueOf()] || []
  75249. },
  75250. _deletePoints: function() {
  75251. var that = this;
  75252. that._disposePoints(that._originalPoints);
  75253. that._disposePoints(that._aggregatedPoints);
  75254. that._disposePoints(that._oldPoints);
  75255. that._points = null;
  75256. that._oldPoints = null;
  75257. that._aggregatedPoints = null;
  75258. that._originalPoints = null;
  75259. that._drawedPoints = null
  75260. },
  75261. _deletePatterns: function() {
  75262. _each(this._patterns || [], function(_, pattern) {
  75263. pattern && pattern.dispose()
  75264. });
  75265. this._patterns = null
  75266. },
  75267. _deleteTrackers: function() {
  75268. var that = this;
  75269. _each(that._trackers || [], function(_, tracker) {
  75270. tracker.remove()
  75271. });
  75272. that._trackersGroup && that._trackersGroup.dispose();
  75273. that._trackers = that._trackersGroup = null
  75274. },
  75275. dispose: function() {
  75276. var that = this;
  75277. that._deletePoints();
  75278. that._group.dispose();
  75279. that._labelsGroup && that._labelsGroup.dispose();
  75280. that._errorBarGroup && that._errorBarGroup.dispose();
  75281. that._deletePatterns();
  75282. that._deleteTrackers();
  75283. that._group = that._extGroups = that._markersGroup = that._elementsGroup = that._bordersGroup = that._labelsGroup = that._errorBarGroup = that._graphics = that._rangeData = that._renderer = that.translators = that._styles = that._options = that._pointOptions = that._drawedPoints = that._aggregatedPoints = that.pointsByArgument = that._segments = that._prevSeries = null
  75284. },
  75285. correctPosition: _noop,
  75286. drawTrackers: _noop,
  75287. getNeighborPoint: _noop,
  75288. areErrorBarsVisible: _noop,
  75289. getColor: function() {
  75290. return this.getLegendStyles().normal.fill
  75291. },
  75292. getOpacity: function() {
  75293. return this._options.opacity
  75294. },
  75295. getStackName: function() {
  75296. return this.type === "stackedbar" || this.type === "fullstackedbar" ? this._stackName : null
  75297. },
  75298. getPointByCoord: function(x, y) {
  75299. var point = this.getNeighborPoint(x, y);
  75300. return point && point.coordsIn(x, y) ? point : null
  75301. }
  75302. }
  75303. })(jQuery, DevExpress);
  75304. /*! Module viz-core, file rangeDataCalculator.js */
  75305. (function($, DX, undefined) {
  75306. var _math = Math,
  75307. _abs = _math.abs,
  75308. _min = _math.min,
  75309. _max = _math.max,
  75310. _each = $.each,
  75311. _isEmptyObject = $.isEmptyObject,
  75312. _isDefined = DX.utils.isDefined,
  75313. _isFinite = isFinite,
  75314. MIN_VISIBLE = "minVisible",
  75315. MAX_VISIBLE = "maxVisible",
  75316. DISCRETE = "discrete";
  75317. function _truncateValue(data, value) {
  75318. var min = data.min,
  75319. max = data.max;
  75320. data.min = value < min || !_isDefined(min) ? value : min;
  75321. data.max = value > max || !_isDefined(max) ? value : max
  75322. }
  75323. function _processValue(series, type, value, prevValue, calcInterval) {
  75324. var axis = type === "arg" ? "argument" : "value",
  75325. data = series._rangeData[type],
  75326. minInterval = data.interval,
  75327. interval;
  75328. if (series[axis + "AxisType"] === DISCRETE) {
  75329. data.categories = data.categories || [];
  75330. data.categories.push(value)
  75331. }
  75332. else {
  75333. _truncateValue(data, value);
  75334. if (type === "arg") {
  75335. interval = (_isDefined(prevValue) ? _abs(calcInterval ? calcInterval(value, prevValue) : value - prevValue) : interval) || minInterval;
  75336. data.interval = _isDefined(interval) && (interval < minInterval || !_isDefined(minInterval)) ? interval : minInterval
  75337. }
  75338. }
  75339. }
  75340. function _addToVisibleRange(series, value) {
  75341. var data = series._rangeData.val,
  75342. isDiscrete = series.valueAxisType === DISCRETE;
  75343. if (!isDiscrete) {
  75344. if (value < data.minVisible || !_isDefined(data.minVisible))
  75345. data.minVisible = value;
  75346. if (value > data.maxVisible || !_isDefined(data.maxVisible))
  75347. data.maxVisible = value
  75348. }
  75349. }
  75350. function _processRangeValue(series, val, minVal) {
  75351. var data = series._rangeData.val;
  75352. if (series.valueAxisType === DISCRETE) {
  75353. data.categories = data.categories || [];
  75354. data.categories.push(val, minVal)
  75355. }
  75356. else {
  75357. _truncateValue(data, val);
  75358. _truncateValue(data, minVal)
  75359. }
  75360. }
  75361. function _unique(array) {
  75362. var values = {};
  75363. return $.map(array, function(item) {
  75364. var result = !values[item] ? item : null;
  75365. values[item] = true;
  75366. return result
  75367. })
  75368. }
  75369. function _processZoomArgument(series, zoomArgs, isDiscrete) {
  75370. var data = series._rangeData.arg,
  75371. minArg,
  75372. maxArg;
  75373. if (isDiscrete) {
  75374. data.minVisible = zoomArgs.minArg;
  75375. data.maxVisible = zoomArgs.maxArg;
  75376. return
  75377. }
  75378. minArg = zoomArgs.minArg < zoomArgs.maxArg ? zoomArgs.minArg : zoomArgs.maxArg;
  75379. maxArg = zoomArgs.maxArg > zoomArgs.minArg ? zoomArgs.maxArg : zoomArgs.minArg;
  75380. data.min = minArg < data.min ? minArg : data.min;
  75381. data.max = maxArg > data.max ? maxArg : data.max;
  75382. data.minVisible = minArg;
  75383. data.maxVisible = maxArg
  75384. }
  75385. function _correctZoomValue(series, zoomArgs) {
  75386. var minVal,
  75387. maxVal;
  75388. if (_isDefined(zoomArgs.minVal) && _isDefined(zoomArgs.maxVal)) {
  75389. minVal = zoomArgs.minVal < zoomArgs.maxVal ? zoomArgs.minVal : zoomArgs.maxVal;
  75390. maxVal = zoomArgs.maxVal > zoomArgs.minVal ? zoomArgs.maxVal : zoomArgs.minVal
  75391. }
  75392. if (_isDefined(zoomArgs.minVal)) {
  75393. series._rangeData.val.min = minVal < series._rangeData.val.min ? minVal : series._rangeData.val.min;
  75394. series._rangeData.val.minVisible = minVal
  75395. }
  75396. if (_isDefined(zoomArgs.maxVal)) {
  75397. series._rangeData.val.max = maxVal > series._rangeData.val.max ? maxVal : series._rangeData.val.max;
  75398. series._rangeData.val.maxVisible = maxVal
  75399. }
  75400. }
  75401. function _processZoomValue(series, zoomArgs) {
  75402. var adjustOnZoom = zoomArgs.adjustOnZoom,
  75403. points = series._points || [],
  75404. lastVisibleIndex,
  75405. prevPointAdded = false,
  75406. rangeData = series._rangeData,
  75407. errorBarCorrector = series._rangeErrorBarCorrector;
  75408. _each(points, function(index, point) {
  75409. var arg = point.argument,
  75410. prevPoint = index > 0 ? points[index - 1] : null;
  75411. if (adjustOnZoom && series.argumentAxisType !== DISCRETE && arg >= rangeData.arg.minVisible && arg <= rangeData.arg.maxVisible) {
  75412. if (!prevPointAdded) {
  75413. if (prevPoint && prevPoint.hasValue()) {
  75414. _addToVisibleRange(series, prevPoint.value);
  75415. _correctMinMaxByErrorBar(rangeData.val, prevPoint, errorBarCorrector, MIN_VISIBLE, MAX_VISIBLE)
  75416. }
  75417. prevPointAdded = true
  75418. }
  75419. if (point.hasValue()) {
  75420. _addToVisibleRange(series, point.value);
  75421. _correctMinMaxByErrorBar(rangeData.val, point, errorBarCorrector, MIN_VISIBLE, MAX_VISIBLE)
  75422. }
  75423. lastVisibleIndex = index
  75424. }
  75425. });
  75426. if (_isDefined(lastVisibleIndex) && lastVisibleIndex < points.length - 1 && points[lastVisibleIndex + 1].hasValue())
  75427. _addToVisibleRange(series, points[lastVisibleIndex + 1].value);
  75428. _correctZoomValue(series, zoomArgs)
  75429. }
  75430. function _processZoomRangeValue(series, zoomArgs, maxValueName, minValueName) {
  75431. var adjustOnZoom = zoomArgs.adjustOnZoom,
  75432. points = series._points || [],
  75433. argRangeData = series._rangeData.arg,
  75434. lastVisibleIndex,
  75435. prevPointAdded = false;
  75436. _each(points, function(index, point) {
  75437. var arg = point.argument,
  75438. prevPoint = index > 0 ? points[index - 1] : null;
  75439. if (adjustOnZoom && series.argumentAxisType !== DISCRETE && arg >= argRangeData.minVisible && arg <= argRangeData.maxVisible) {
  75440. if (!prevPointAdded) {
  75441. if (prevPoint && prevPoint.hasValue()) {
  75442. _addToVisibleRange(series, prevPoint[maxValueName]);
  75443. _addToVisibleRange(series, prevPoint[minValueName])
  75444. }
  75445. prevPointAdded = true
  75446. }
  75447. if (point.hasValue()) {
  75448. _addToVisibleRange(series, point[maxValueName]);
  75449. _addToVisibleRange(series, point[minValueName])
  75450. }
  75451. lastVisibleIndex = index
  75452. }
  75453. });
  75454. if (_isDefined(lastVisibleIndex) && lastVisibleIndex < points.length - 1 && points[lastVisibleIndex + 1].hasValue())
  75455. _addToVisibleRange(series, points[lastVisibleIndex + 1].value);
  75456. _correctZoomValue(series, zoomArgs)
  75457. }
  75458. function _processNewInterval(series, calcInterval) {
  75459. var data = series._rangeData,
  75460. points = series._points || [],
  75461. isArgumentAxisDiscrete = series.argumentAxisType === DISCRETE;
  75462. delete data.arg.interval;
  75463. _each(points, function(index, point) {
  75464. var arg = point.argument,
  75465. prevPoint = index > 0 ? points[index - 1] : null,
  75466. prevArg = prevPoint && prevPoint.argument;
  75467. !isArgumentAxisDiscrete && _processValue(series, "arg", arg, prevArg, calcInterval)
  75468. })
  75469. }
  75470. function _fillRangeData(series) {
  75471. var data = series._rangeData;
  75472. data.arg.categories && (data.arg.categories = _unique(data.arg.categories));
  75473. data.val.categories && (data.val.categories = _unique(data.val.categories));
  75474. data.arg.axisType = series.argumentAxisType;
  75475. data.arg.dataType = series.argumentType;
  75476. data.val.axisType = series.valueAxisType;
  75477. data.val.dataType = series.valueType;
  75478. data.val.isValueRange = true
  75479. }
  75480. function processTwoValues(series, point, prevPoint, highValueName, lowValueName) {
  75481. var val = point[highValueName],
  75482. minVal = point[lowValueName],
  75483. arg = point.argument,
  75484. prevVal = prevPoint && prevPoint[highValueName],
  75485. prevMinVal = prevPoint && prevPoint[lowValueName],
  75486. prevArg = prevPoint && prevPoint.argument;
  75487. point.hasValue() && _processRangeValue(series, val, minVal, prevVal, prevMinVal);
  75488. _processValue(series, "arg", arg, prevArg)
  75489. }
  75490. function calculateRangeMinValue(series, zoomArgs) {
  75491. var data = series._rangeData.val,
  75492. minVisible = data[MIN_VISIBLE],
  75493. maxVisible = data[MAX_VISIBLE];
  75494. zoomArgs = zoomArgs || {};
  75495. if (data)
  75496. if (series.valueAxisType !== "logarithmic" && series.valueType !== "datetime" && series.showZero !== false) {
  75497. data[MIN_VISIBLE] = minVisible > (zoomArgs.minVal || 0) ? zoomArgs.minVal || 0 : minVisible;
  75498. data[MAX_VISIBLE] = maxVisible < (zoomArgs.maxVal || 0) ? zoomArgs.maxVal || 0 : maxVisible;
  75499. data.min = data.min > 0 ? 0 : data.min;
  75500. data.max = data.max < 0 ? 0 : data.max
  75501. }
  75502. }
  75503. function processFullStackedRange(series) {
  75504. var data = series._rangeData.val,
  75505. isRangeEmpty = _isEmptyObject(data);
  75506. data.percentStick = true;
  75507. !isRangeEmpty && (data.min = 0)
  75508. }
  75509. function _correctMinMaxByErrorBar(data, point, getMinMaxCorrector, minSelector, maxSelector) {
  75510. if (!getMinMaxCorrector)
  75511. return;
  75512. var correctionData = getMinMaxCorrector(point),
  75513. minError = _min.apply(undefined, correctionData),
  75514. maxError = _max.apply(undefined, correctionData);
  75515. if (_isFinite(minError) && data[minSelector] > minError)
  75516. data[minSelector] = minError;
  75517. if (_isFinite(maxError) && data[maxSelector] < maxError)
  75518. data[maxSelector] = maxError
  75519. }
  75520. function processRange(series, point, prevPoint, getMinMaxCorrector) {
  75521. var val = point.value,
  75522. arg = point.argument,
  75523. prevVal = prevPoint && prevPoint.value,
  75524. prevArg = prevPoint && prevPoint.argument;
  75525. point.hasValue() && _processValue(series, "val", val, prevVal);
  75526. _processValue(series, "arg", arg, prevArg);
  75527. _correctMinMaxByErrorBar(series._rangeData.val, point, getMinMaxCorrector, "min", "max")
  75528. }
  75529. function addLabelPaddings(series) {
  75530. var labelOptions = series.getOptions().label,
  75531. valueData;
  75532. if (series.areLabelsVisible() && labelOptions && labelOptions.visible && labelOptions.position !== "inside") {
  75533. valueData = series._rangeData.val;
  75534. if (valueData.min < 0)
  75535. valueData.minSpaceCorrection = true;
  75536. if (valueData.max > 0)
  75537. valueData.maxSpaceCorrection = true
  75538. }
  75539. }
  75540. function addRangeSeriesLabelPaddings(series) {
  75541. var data = series._rangeData.val;
  75542. if (series.areLabelsVisible() && series._options.label.visible && series._options.label.position !== "inside")
  75543. data.minSpaceCorrection = data.maxSpaceCorrection = true
  75544. }
  75545. function calculateRangeData(series, zoomArgs, calcIntervalFunction, maxValueName, minValueName) {
  75546. var valueData = series._rangeData.val,
  75547. isRangeSeries = !!maxValueName && !!minValueName,
  75548. isDiscrete = series.argumentAxisType === DISCRETE;
  75549. if (zoomArgs && _isDefined(zoomArgs.minArg) && _isDefined(zoomArgs.maxArg)) {
  75550. if (!isDiscrete) {
  75551. valueData[MIN_VISIBLE] = zoomArgs.minVal;
  75552. valueData[MAX_VISIBLE] = zoomArgs.maxVal
  75553. }
  75554. _processZoomArgument(series, zoomArgs, isDiscrete);
  75555. if (isRangeSeries)
  75556. _processZoomRangeValue(series, zoomArgs, maxValueName, minValueName);
  75557. else
  75558. _processZoomValue(series, zoomArgs)
  75559. }
  75560. else if (!zoomArgs && calcIntervalFunction)
  75561. _processNewInterval(series, calcIntervalFunction);
  75562. _fillRangeData(series)
  75563. }
  75564. DX.viz.core.series.helpers.rangeDataCalculator = {
  75565. processRange: processRange,
  75566. calculateRangeData: calculateRangeData,
  75567. addLabelPaddings: addLabelPaddings,
  75568. addRangeSeriesLabelPaddings: addRangeSeriesLabelPaddings,
  75569. processFullStackedRange: processFullStackedRange,
  75570. calculateRangeMinValue: calculateRangeMinValue,
  75571. processTwoValues: processTwoValues
  75572. }
  75573. })(jQuery, DevExpress);
  75574. /*! Module viz-core, file scatterSeries.js */
  75575. (function($, DX) {
  75576. var series = DX.viz.core.series,
  75577. rangeCalculator = series.helpers.rangeDataCalculator,
  75578. chartSeries = series.mixins.chart,
  75579. _each = $.each,
  75580. _extend = $.extend,
  75581. _map = $.map,
  75582. _noop = $.noop,
  75583. _utils = DX.utils,
  75584. _isDefined = _utils.isDefined,
  75585. _isString = _utils.isString,
  75586. math = Math,
  75587. _floor = math.floor,
  75588. _abs = math.abs,
  75589. _sqrt = math.sqrt,
  75590. _min = math.min,
  75591. _max = math.max,
  75592. DEFAULT_SYMBOL_POINT_SIZE = 2,
  75593. DEFAULT_TRACKER_WIDTH = 20,
  75594. DEFAULT_DURATION = 400,
  75595. HIGH_ERROR = "highError",
  75596. LOW_ERROR = "lowError",
  75597. ORIGINAL = "original",
  75598. VARIANCE = "variance",
  75599. STANDARD_DEVIATION = "stddeviation",
  75600. STANDARD_ERROR = "stderror",
  75601. PERCENT = "percent",
  75602. FIXED = "fixed",
  75603. UNDEFINED = "undefined",
  75604. DISCRETE = "discrete",
  75605. LOGARITHMIC = "logarithmic",
  75606. DATETIME = "datetime";
  75607. function sum(array) {
  75608. var summa = 0;
  75609. _each(array, function(_, value) {
  75610. summa += value
  75611. });
  75612. return summa
  75613. }
  75614. function toLowerCase(value) {
  75615. return value.toLowerCase()
  75616. }
  75617. function isErrorBarTypeCorrect(type) {
  75618. return $.inArray(type, [FIXED, PERCENT, VARIANCE, STANDARD_DEVIATION, STANDARD_ERROR, UNDEFINED]) !== -1
  75619. }
  75620. function variance(array, expectedValue) {
  75621. return sum($.map(array, function(value) {
  75622. return (value - expectedValue) * (value - expectedValue)
  75623. })) / array.length
  75624. }
  75625. var baseScatterMethods = {
  75626. _defaultDuration: DEFAULT_DURATION,
  75627. _defaultTrackerWidth: DEFAULT_TRACKER_WIDTH,
  75628. _applyStyle: _noop,
  75629. _updateOptions: _noop,
  75630. _parseStyle: _noop,
  75631. _prepareSegment: _noop,
  75632. _drawSegment: _noop,
  75633. _generateDefaultSegments: _noop,
  75634. _prepareSeriesToDrawing: function() {
  75635. var that = this;
  75636. that._deleteOldAnimationMethods();
  75637. that._firstDrawing && that._clearSeries();
  75638. that._disposePoints(that._oldPoints);
  75639. that._oldPoints = null
  75640. },
  75641. _createLegendState: function(styleOptions, defaultColor) {
  75642. return {
  75643. fill: styleOptions.color || defaultColor,
  75644. hatching: styleOptions.hatching
  75645. }
  75646. },
  75647. updateTeamplateFieldNames: function() {
  75648. var that = this,
  75649. options = that._options;
  75650. options.valueField = that.getValueFields()[0] + that.name;
  75651. options.tagField = that.getTagField() + that.name
  75652. },
  75653. _applyElementsClipRect: function(settings) {
  75654. settings.clipId = this._paneClipRectID
  75655. },
  75656. _applyMarkerClipRect: function(settings) {
  75657. settings.clipId = this._forceClipping ? this._paneClipRectID : null
  75658. },
  75659. _createGroup: function(groupName, parent, target, settings) {
  75660. var group = parent[groupName] = parent[groupName] || this._renderer.g();
  75661. group.attr(settings).append(target)
  75662. },
  75663. _applyClearingSettings: function(settings) {
  75664. settings.opacity = null;
  75665. settings.scale = null;
  75666. if (this._options.rotated)
  75667. settings.translateX = null;
  75668. else
  75669. settings.translateY = null
  75670. },
  75671. _createMarkerGroup: function() {
  75672. var that = this,
  75673. settings = that._getPointOptions().styles.normal;
  75674. settings["class"] = "dxc-markers";
  75675. settings.opacity = 1;
  75676. that._applyMarkerClipRect(settings);
  75677. that._createGroup("_markersGroup", that, that._group, settings)
  75678. },
  75679. _createLabelGroup: function() {
  75680. var that = this,
  75681. settings = {
  75682. "class": "dxc-labels",
  75683. visibility: that.getLabelVisibility() ? "visible" : "hidden"
  75684. };
  75685. that._applyElementsClipRect(settings);
  75686. that._applyClearingSettings(settings);
  75687. that._createGroup("_labelsGroup", that, that._extGroups.labelsGroup, settings)
  75688. },
  75689. areErrorBarsVisible: function() {
  75690. var errorBarOptions = this._options.valueErrorBar || {};
  75691. return this._errorBarsEnabled() && errorBarOptions.displayMode !== "none" && (isErrorBarTypeCorrect(toLowerCase(errorBarOptions.type + "")) || _isDefined(errorBarOptions.lowValueField) || _isDefined(errorBarOptions.highValueField))
  75692. },
  75693. _createErrorBarGroup: function(animationEnabled) {
  75694. var that = this,
  75695. errorBarOptions = that._options.valueErrorBar || {},
  75696. settings;
  75697. if (that.areErrorBarsVisible()) {
  75698. settings = {
  75699. "class": "dxc-error-bars",
  75700. stroke: errorBarOptions.color,
  75701. 'stroke-width': errorBarOptions.lineWidth,
  75702. opacity: animationEnabled ? 0.001 : errorBarOptions.opacity || 1,
  75703. "stroke-linecap": "square",
  75704. sharp: true,
  75705. clipId: that._forceClipping ? that._paneClipRectID : that._widePaneClipRectID
  75706. };
  75707. that._createGroup("_errorBarGroup", that, that._group, settings)
  75708. }
  75709. },
  75710. _createGroups: function(animationEnabled) {
  75711. var that = this;
  75712. that._createMarkerGroup();
  75713. that._createLabelGroup();
  75714. that._createErrorBarGroup(animationEnabled);
  75715. animationEnabled && that._labelsGroup && that._labelsGroup.attr({opacity: 0.001})
  75716. },
  75717. _getCreatingPointOptions: function() {
  75718. var that = this,
  75719. defaultPointOptions,
  75720. creatingPointOptions = that._predefinedPointOptions,
  75721. normalStyle;
  75722. if (!creatingPointOptions) {
  75723. defaultPointOptions = that._getPointOptions();
  75724. that._predefinedPointOptions = creatingPointOptions = _extend(true, {styles: {}}, defaultPointOptions);
  75725. normalStyle = defaultPointOptions.styles && defaultPointOptions.styles.normal || {};
  75726. creatingPointOptions.styles = creatingPointOptions.styles || {};
  75727. creatingPointOptions.styles.normal = {
  75728. "stroke-width": normalStyle["stroke-width"],
  75729. r: normalStyle.r,
  75730. opacity: normalStyle.opacity
  75731. }
  75732. }
  75733. return creatingPointOptions
  75734. },
  75735. _getSpecialColor: function(mainSeriesColor) {
  75736. return mainSeriesColor
  75737. },
  75738. _getPointOptions: function() {
  75739. return this._parsePointOptions(this._preparePointOptions(), this._options.label)
  75740. },
  75741. _preparePointOptions: function(customOptions) {
  75742. var point = this._options.point;
  75743. return customOptions ? _extend(true, {}, point, customOptions) : point
  75744. },
  75745. _parsePointStyle: function(style, defaultColor, defaultBorderColor) {
  75746. var border = style.border || {};
  75747. return {
  75748. fill: style.color || defaultColor,
  75749. stroke: border.color || defaultBorderColor,
  75750. "stroke-width": border.visible ? border.width : 0,
  75751. r: style.size / 2 + (border.visible && style.size !== 0 ? ~~(border.width / 2) || 0 : 0)
  75752. }
  75753. },
  75754. _createPointStyles: function(pointOptions) {
  75755. var that = this,
  75756. mainPointColor = pointOptions.color || that._options.mainSeriesColor,
  75757. containerColor = that._options.containerBackgroundColor,
  75758. normalStyle = that._parsePointStyle(pointOptions, mainPointColor, mainPointColor);
  75759. normalStyle.visibility = pointOptions.visible ? "visible" : "hidden";
  75760. return {
  75761. normal: normalStyle,
  75762. hover: that._parsePointStyle(pointOptions.hoverStyle, containerColor, mainPointColor),
  75763. selection: that._parsePointStyle(pointOptions.selectionStyle, containerColor, mainPointColor)
  75764. }
  75765. },
  75766. _checkData: function(data) {
  75767. return _isDefined(data.argument) && data.value !== undefined
  75768. },
  75769. _getRangeCorrector: function() {
  75770. var errorBars = this.getOptions().valueErrorBar || {},
  75771. mode = toLowerCase(errorBars.displayMode + "");
  75772. return errorBars ? function(point) {
  75773. var lowError = point.lowError,
  75774. highError = point.highError;
  75775. switch (mode) {
  75776. case"low":
  75777. return [lowError];
  75778. case"high":
  75779. return [highError];
  75780. case"none":
  75781. return [];
  75782. default:
  75783. return [lowError, highError]
  75784. }
  75785. } : undefined
  75786. },
  75787. _processRange: function(point, prevPoint, errorBarCorrector) {
  75788. rangeCalculator.processRange(this, point, prevPoint, errorBarCorrector)
  75789. },
  75790. _getRangeData: function(zoomArgs, calcIntervalFunction) {
  75791. rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction);
  75792. rangeCalculator.addLabelPaddings(this);
  75793. return this._rangeData
  75794. },
  75795. _getPointData: function(data, options) {
  75796. var pointData = {
  75797. value: data[options.valueField || "val"],
  75798. argument: data[options.argumentField || "arg"],
  75799. tag: data[options.tagField || "tag"]
  75800. };
  75801. this._fillErrorBars(data, pointData, options);
  75802. return pointData
  75803. },
  75804. _errorBarsEnabled: function() {
  75805. return this.valueAxisType !== DISCRETE && this.valueAxisType !== LOGARITHMIC && this.valueType !== DATETIME
  75806. },
  75807. _fillErrorBars: function(data, pointData, options) {
  75808. var errorBars = options.valueErrorBar || {};
  75809. if (this._errorBarsEnabled()) {
  75810. pointData.lowError = data[errorBars.lowValueField || LOW_ERROR];
  75811. pointData.highError = data[errorBars.highValueField || HIGH_ERROR]
  75812. }
  75813. },
  75814. _drawPoint: function(options) {
  75815. var point = options.point;
  75816. if (point.isInVisibleArea()) {
  75817. point.clearVisibility();
  75818. point.draw(this._renderer, options.groups, options.hasAnimation, options.firstDrawing);
  75819. this._drawedPoints.push(point)
  75820. }
  75821. else
  75822. point.setInvisibility()
  75823. },
  75824. _clearingAnimation: function(translators, drawComplete) {
  75825. var that = this,
  75826. params = {opacity: 0.001},
  75827. options = {
  75828. duration: that._defaultDuration,
  75829. partitionDuration: 0.5
  75830. };
  75831. that._labelsGroup && that._labelsGroup.animate(params, options, function() {
  75832. that._markersGroup && that._markersGroup.animate(params, options, drawComplete)
  75833. })
  75834. },
  75835. _animateComplete: function() {
  75836. var that = this,
  75837. animationSettings = {duration: that._defaultDuration};
  75838. that._labelsGroup && that._labelsGroup.animate({opacity: 1}, animationSettings);
  75839. that._errorBarGroup && that._errorBarGroup.animate({opacity: (that._options.valueErrorBar || {}).opacity || 1}, animationSettings)
  75840. },
  75841. _animate: function() {
  75842. var that = this,
  75843. lastPointIndex = that._drawedPoints.length - 1;
  75844. _each(that._drawedPoints || [], function(i, p) {
  75845. p.animate(i === lastPointIndex ? function() {
  75846. that._animateComplete()
  75847. } : undefined, {
  75848. translateX: p.x,
  75849. translateY: p.y
  75850. })
  75851. })
  75852. },
  75853. _getPointSize: function() {
  75854. return this._options.point.visible ? this._options.point.size : DEFAULT_SYMBOL_POINT_SIZE
  75855. },
  75856. _calcMedianValue: function(fusionPoints, valueField) {
  75857. var result,
  75858. allValue = _map(fusionPoints, function(point) {
  75859. return point[valueField]
  75860. });
  75861. allValue.sort(function(a, b) {
  75862. return a - b
  75863. });
  75864. result = allValue[_floor(allValue.length / 2)];
  75865. return _isDefined(result) ? result : null
  75866. },
  75867. _calcErrorBarValues: function(fusionPoints) {
  75868. if (!fusionPoints.length)
  75869. return {};
  75870. var lowValue = fusionPoints[0].lowError,
  75871. highValue = fusionPoints[0].highError,
  75872. i = 1,
  75873. length = fusionPoints.length,
  75874. lowError,
  75875. highError;
  75876. for (i; i < length; i++) {
  75877. lowError = fusionPoints[i].lowError;
  75878. highError = fusionPoints[i].highError;
  75879. if (_isDefined(lowError) && _isDefined(highError)) {
  75880. lowValue = _min(lowError, lowValue);
  75881. highValue = _max(highError, highValue)
  75882. }
  75883. }
  75884. return {
  75885. low: lowValue,
  75886. high: highValue
  75887. }
  75888. },
  75889. _fusionPoints: function(fusionPoints, tick, index) {
  75890. var errorBarValues = this._calcErrorBarValues(fusionPoints);
  75891. return {
  75892. value: this._calcMedianValue(fusionPoints, "value"),
  75893. argument: tick,
  75894. tag: null,
  75895. index: index,
  75896. seriesName: this.name,
  75897. lowError: errorBarValues.low,
  75898. highError: errorBarValues.high
  75899. }
  75900. },
  75901. _endUpdateData: function() {
  75902. delete this._predefinedPointOptions
  75903. },
  75904. getArgumentField: function() {
  75905. return this._options.argumentField || "arg"
  75906. },
  75907. getValueFields: function() {
  75908. var options = this._options,
  75909. errorBarsOptions = options.valueErrorBar || {},
  75910. valueFields = [options.valueField || "val"],
  75911. lowValueField = errorBarsOptions.lowValueField,
  75912. highValueField = errorBarsOptions.highValueField;
  75913. _isString(lowValueField) && valueFields.push(lowValueField);
  75914. _isString(highValueField) && valueFields.push(highValueField);
  75915. return valueFields
  75916. },
  75917. _calculateErrorBars: function(data) {
  75918. var that = this,
  75919. options = that._options,
  75920. errorBarsOptions = options.valueErrorBar || {},
  75921. errorBarType = toLowerCase(errorBarsOptions.type + ""),
  75922. floatErrorValue = parseFloat(errorBarsOptions.value),
  75923. valueField = that.getValueFields()[0],
  75924. value,
  75925. lowValueField = errorBarsOptions.lowValueField || LOW_ERROR,
  75926. highValueField = errorBarsOptions.highValueField || HIGH_ERROR,
  75927. valueArray,
  75928. valueArrayLength,
  75929. meanValue,
  75930. processDataItem,
  75931. addSubError = function(_i, item) {
  75932. value = item[valueField];
  75933. item[lowValueField] = value - floatErrorValue;
  75934. item[highValueField] = value + floatErrorValue
  75935. };
  75936. if (!that._errorBarsEnabled() || !isErrorBarTypeCorrect(errorBarType))
  75937. return;
  75938. switch (errorBarType) {
  75939. case FIXED:
  75940. processDataItem = addSubError;
  75941. break;
  75942. case PERCENT:
  75943. processDataItem = function(_, item) {
  75944. value = item[valueField];
  75945. var error = value * floatErrorValue / 100;
  75946. item[lowValueField] = value - error;
  75947. item[highValueField] = value + error
  75948. };
  75949. break;
  75950. case UNDEFINED:
  75951. processDataItem = function(_, item) {
  75952. item[lowValueField] = item[ORIGINAL + lowValueField];
  75953. item[highValueField] = item[ORIGINAL + highValueField]
  75954. };
  75955. break;
  75956. default:
  75957. valueArray = $.map(data, function(item) {
  75958. return item[valueField]
  75959. });
  75960. valueArrayLength = valueArray.length;
  75961. floatErrorValue = floatErrorValue || 1;
  75962. switch (errorBarType) {
  75963. case VARIANCE:
  75964. floatErrorValue = variance(valueArray, sum(valueArray) / valueArrayLength) * floatErrorValue;
  75965. processDataItem = addSubError;
  75966. break;
  75967. case STANDARD_DEVIATION:
  75968. meanValue = sum(valueArray) / valueArrayLength;
  75969. floatErrorValue = _sqrt(variance(valueArray, meanValue)) * floatErrorValue;
  75970. processDataItem = function(_, item) {
  75971. item[lowValueField] = meanValue - floatErrorValue;
  75972. item[highValueField] = meanValue + floatErrorValue
  75973. };
  75974. break;
  75975. case STANDARD_ERROR:
  75976. floatErrorValue = _sqrt(variance(valueArray, sum(valueArray) / valueArrayLength) / valueArrayLength) * floatErrorValue;
  75977. processDataItem = addSubError;
  75978. break
  75979. }
  75980. }
  75981. processDataItem && _each(data, processDataItem)
  75982. },
  75983. _beginUpdateData: function(data) {
  75984. this._calculateErrorBars(data)
  75985. }
  75986. };
  75987. chartSeries.scatter = _extend({}, baseScatterMethods, {
  75988. drawTrackers: function() {
  75989. var that = this,
  75990. trackers,
  75991. trackersGroup,
  75992. segments = that._segments || [],
  75993. rotated = that._options.rotated,
  75994. cat = [];
  75995. if (!that.isVisible())
  75996. return;
  75997. if (segments.length) {
  75998. trackers = that._trackers = that._trackers || [];
  75999. trackersGroup = that._trackersGroup = (that._trackersGroup || that._renderer.g().attr({
  76000. fill: "gray",
  76001. opacity: 0.001,
  76002. stroke: "gray",
  76003. "class": "dxc-trackers"
  76004. })).attr({clipId: this._paneClipRectID || null}).append(that._group);
  76005. _each(segments, function(i, segment) {
  76006. if (!trackers[i])
  76007. trackers[i] = that._drawTrackerElement(segment).data({series: that}).append(trackersGroup);
  76008. else
  76009. that._updateTrackerElement(segment, trackers[i])
  76010. })
  76011. }
  76012. that._trackersTranslator = cat;
  76013. _each(that.getVisiblePoints(), function(_, p) {
  76014. var pointCoord = parseInt(rotated ? p.vy : p.vx);
  76015. if (!cat[pointCoord])
  76016. cat[pointCoord] = p;
  76017. else
  76018. $.isArray(cat[pointCoord]) ? cat[pointCoord].push(p) : cat[pointCoord] = [cat[pointCoord], p]
  76019. })
  76020. },
  76021. getNeighborPoint: function(x, y) {
  76022. var pCoord = this._options.rotated ? y : x,
  76023. nCoord = pCoord,
  76024. cat = this._trackersTranslator,
  76025. point = null,
  76026. minDistance,
  76027. oppositeCoord = this._options.rotated ? x : y,
  76028. opositeCoordName = this._options.rotated ? "vx" : "vy";
  76029. if (this.isVisible() && cat) {
  76030. point = cat[pCoord];
  76031. do {
  76032. point = cat[nCoord] || cat[pCoord];
  76033. pCoord--;
  76034. nCoord++
  76035. } while ((pCoord >= 0 || nCoord < cat.length) && !point);
  76036. if ($.isArray(point)) {
  76037. minDistance = _abs(point[0][opositeCoordName] - oppositeCoord);
  76038. _each(point, function(i, p) {
  76039. var distance = _abs(p[opositeCoordName] - oppositeCoord);
  76040. if (minDistance >= distance) {
  76041. minDistance = distance;
  76042. point = p
  76043. }
  76044. })
  76045. }
  76046. }
  76047. return point
  76048. }
  76049. });
  76050. series.mixins.polar.scatter = _extend({}, baseScatterMethods, {
  76051. drawTrackers: function() {
  76052. chartSeries.scatter.drawTrackers.call(this);
  76053. var cat = this._trackersTranslator,
  76054. index;
  76055. if (!this.isVisible())
  76056. return;
  76057. _each(cat, function(i, category) {
  76058. if (category) {
  76059. index = i;
  76060. return false
  76061. }
  76062. });
  76063. cat[index + 360] = cat[index]
  76064. },
  76065. getNeighborPoint: function(x, y) {
  76066. var pos = this.translators.untranslate(x, y);
  76067. return chartSeries.scatter.getNeighborPoint.call(this, pos.phi, pos.r)
  76068. }
  76069. })
  76070. })(jQuery, DevExpress);
  76071. /*! Module viz-core, file lineSeries.js */
  76072. (function($, DX) {
  76073. var core = DX.viz.core,
  76074. series = core.series,
  76075. chartSeries = series.mixins.chart,
  76076. polarSeries = series.mixins.polar,
  76077. utils = DX.utils,
  76078. scatterSeries = chartSeries.scatter,
  76079. rangeCalculator = core.series.helpers.rangeDataCalculator,
  76080. CANVAS_POSITION_START = "canvas_position_start",
  76081. CANVAS_POSITION_TOP = "canvas_position_top",
  76082. DISCRETE = "discrete",
  76083. _extend = $.extend,
  76084. _map = $.map,
  76085. _each = $.each;
  76086. function clonePoint(point, newX, newY, newAngle) {
  76087. var p = utils.clone(point);
  76088. p.x = newX;
  76089. p.y = newY;
  76090. p.angle = newAngle;
  76091. return p
  76092. }
  76093. function getTangentPoint(point, prevPoint, centerPoint, tan, nextStepAngle) {
  76094. var currectAngle = point.angle + nextStepAngle,
  76095. cossin = utils.getCosAndSin(currectAngle),
  76096. x = centerPoint.x + (point.radius + tan * nextStepAngle) * cossin.cos,
  76097. y = centerPoint.y - (point.radius + tan * nextStepAngle) * cossin.sin;
  76098. return clonePoint(prevPoint, x, y, currectAngle)
  76099. }
  76100. var lineMethods = {
  76101. _createElementsGroup: function(elementsStyle) {
  76102. var that = this,
  76103. settings = _extend({"class": "dxc-elements"}, elementsStyle);
  76104. that._applyElementsClipRect(settings);
  76105. that._createGroup("_elementsGroup", that, that._group, settings)
  76106. },
  76107. _createBordersGroup: function(borderStyle) {
  76108. var that = this,
  76109. settings = _extend({"class": "dxc-borders"}, borderStyle);
  76110. that._applyElementsClipRect(settings);
  76111. that._createGroup("_bordersGroup", that, that._group, settings)
  76112. },
  76113. _createGroups: function(animationEnabled, style) {
  76114. var that = this;
  76115. style = style || that._styles.normal;
  76116. that._createElementsGroup(style.elements);
  76117. that._areBordersVisible() && that._createBordersGroup(style.border);
  76118. scatterSeries._createGroups.call(that, animationEnabled, {});
  76119. animationEnabled && that._markersGroup && that._markersGroup.attr({opacity: 0.001})
  76120. },
  76121. _areBordersVisible: function() {
  76122. return false
  76123. },
  76124. _getDefaultSegment: function(segment) {
  76125. return {line: _map(segment.line || [], function(pt) {
  76126. return pt.getDefaultCoords()
  76127. })}
  76128. },
  76129. _prepareSegment: function(points) {
  76130. return {line: points}
  76131. },
  76132. _parseLineOptions: function(options, defaultColor) {
  76133. return {
  76134. stroke: options.color || defaultColor,
  76135. "stroke-width": options.width,
  76136. dashStyle: options.dashStyle || 'solid'
  76137. }
  76138. },
  76139. _parseStyle: function(options, defaultColor) {
  76140. return {elements: this._parseLineOptions(options, defaultColor)}
  76141. },
  76142. _applyStyle: function(style) {
  76143. var that = this;
  76144. that._elementsGroup && that._elementsGroup.attr(style.elements);
  76145. _each(that._graphics || [], function(_, graphic) {
  76146. graphic.line && graphic.line.attr({'stroke-width': style.elements["stroke-width"]}).sharp()
  76147. })
  76148. },
  76149. _drawElement: function(segment, group) {
  76150. return {line: this._createMainElement(segment.line, {"stroke-width": this._styles.normal.elements["stroke-width"]}).append(group)}
  76151. },
  76152. _removeElement: function(element) {
  76153. element.line.remove()
  76154. },
  76155. _generateDefaultSegments: function() {
  76156. var that = this;
  76157. return _map(that._segments || [], function(segment) {
  76158. return that._getDefaultSegment(segment)
  76159. })
  76160. },
  76161. _updateElement: function(element, segment, animate, animateParams, complete) {
  76162. var params = {points: segment.line},
  76163. lineElement = element.line;
  76164. animate ? lineElement.animate(params, animateParams, complete) : lineElement.attr(params)
  76165. },
  76166. _clearingAnimation: function(translator, drawComplete) {
  76167. var that = this,
  76168. lastIndex = that._graphics.length - 1,
  76169. settings = {opacity: 0.001},
  76170. options = {
  76171. duration: that._defaultDuration,
  76172. partitionDuration: 0.5
  76173. };
  76174. that._labelsGroup && that._labelsGroup.animate(settings, options, function() {
  76175. that._markersGroup && that._markersGroup.animate(settings, options, function() {
  76176. _each(that._defaultSegments || [], function(i, segment) {
  76177. that._oldUpdateElement(that._graphics[i], segment, true, {partitionDuration: 0.5}, i === lastIndex ? drawComplete : undefined)
  76178. })
  76179. })
  76180. })
  76181. },
  76182. _animateComplete: function() {
  76183. var that = this;
  76184. scatterSeries._animateComplete.call(this);
  76185. that._markersGroup && that._markersGroup.animate({opacity: 1}, {duration: that._defaultDuration})
  76186. },
  76187. _animate: function() {
  76188. var that = this,
  76189. lastIndex = that._graphics.length - 1;
  76190. _each(that._graphics || [], function(i, elem) {
  76191. that._updateElement(elem, that._segments[i], true, {complete: i === lastIndex ? function() {
  76192. that._animateComplete()
  76193. } : undefined})
  76194. })
  76195. },
  76196. _drawPoint: function(options) {
  76197. scatterSeries._drawPoint.call(this, {
  76198. point: options.point,
  76199. groups: options.groups
  76200. })
  76201. },
  76202. _createMainElement: function(points, settings) {
  76203. return this._renderer.path(points, "line").attr(settings).sharp()
  76204. },
  76205. _drawSegment: function(points, animationEnabled, segmentCount, lastSegment) {
  76206. var that = this,
  76207. segment = that._prepareSegment(points, that._options.rotated, lastSegment);
  76208. that._segments.push(segment);
  76209. if (!that._graphics[segmentCount])
  76210. that._graphics[segmentCount] = that._drawElement(animationEnabled ? that._getDefaultSegment(segment) : segment, that._elementsGroup);
  76211. else if (!animationEnabled)
  76212. that._updateElement(that._graphics[segmentCount], segment)
  76213. },
  76214. _getTrackerSettings: function() {
  76215. var that = this,
  76216. elements = that._styles.normal.elements;
  76217. return {
  76218. "stroke-width": elements["stroke-width"] > that._defaultTrackerWidth ? elements["stroke-width"] : that._defaultTrackerWidth,
  76219. fill: "none"
  76220. }
  76221. },
  76222. _getMainPointsFromSegment: function(segment) {
  76223. return segment.line
  76224. },
  76225. _drawTrackerElement: function(segment) {
  76226. return this._createMainElement(this._getMainPointsFromSegment(segment), this._getTrackerSettings(segment))
  76227. },
  76228. _updateTrackerElement: function(segment, element) {
  76229. var settings = this._getTrackerSettings(segment);
  76230. settings.points = this._getMainPointsFromSegment(segment);
  76231. element.attr(settings)
  76232. }
  76233. };
  76234. chartSeries.line = _extend({}, scatterSeries, lineMethods);
  76235. chartSeries.stepline = _extend({}, chartSeries.line, {
  76236. _calculateStepLinePoints: function(points) {
  76237. var segment = [];
  76238. _each(points, function(i, pt) {
  76239. var stepY,
  76240. point;
  76241. if (!i) {
  76242. segment.push(pt);
  76243. return
  76244. }
  76245. stepY = segment[segment.length - 1].y;
  76246. if (stepY !== pt.y) {
  76247. point = utils.clone(pt);
  76248. point.y = stepY;
  76249. segment.push(point)
  76250. }
  76251. segment.push(pt)
  76252. });
  76253. return segment
  76254. },
  76255. _prepareSegment: function(points) {
  76256. return chartSeries.line._prepareSegment(this._calculateStepLinePoints(points))
  76257. }
  76258. });
  76259. chartSeries.stackedline = _extend({}, chartSeries.line, {});
  76260. chartSeries.fullstackedline = _extend({}, chartSeries.line, {_getRangeData: function(zoomArgs, calcIntervalFunction) {
  76261. var that = this;
  76262. rangeCalculator.calculateRangeData(that, zoomArgs, calcIntervalFunction);
  76263. rangeCalculator.addLabelPaddings(that);
  76264. rangeCalculator.processFullStackedRange(that);
  76265. return that._rangeData
  76266. }});
  76267. chartSeries.spline = _extend({}, chartSeries.line, {
  76268. _calculateBezierPoints: function(src, rotated) {
  76269. var bezierPoints = [],
  76270. pointsCopy = src,
  76271. checkExtr = function(otherPointCoord, pointCoord, controlCoord) {
  76272. return otherPointCoord > pointCoord && controlCoord > otherPointCoord || otherPointCoord < pointCoord && controlCoord < otherPointCoord ? otherPointCoord : controlCoord
  76273. };
  76274. if (pointsCopy.length !== 1)
  76275. _each(pointsCopy, function(i, curPoint) {
  76276. var leftControlX,
  76277. leftControlY,
  76278. rightControlX,
  76279. rightControlY,
  76280. prevPoint,
  76281. nextPoint,
  76282. xCur,
  76283. yCur,
  76284. x1,
  76285. x2,
  76286. y1,
  76287. y2,
  76288. lambda = 0.5,
  76289. curIsExtremum,
  76290. leftPoint,
  76291. rightPoint,
  76292. a,
  76293. b,
  76294. c,
  76295. xc,
  76296. yc,
  76297. shift;
  76298. if (!i) {
  76299. bezierPoints.push(curPoint);
  76300. bezierPoints.push(curPoint);
  76301. return
  76302. }
  76303. prevPoint = pointsCopy[i - 1];
  76304. if (i < pointsCopy.length - 1) {
  76305. nextPoint = pointsCopy[i + 1];
  76306. xCur = curPoint.x;
  76307. yCur = curPoint.y;
  76308. x1 = prevPoint.x;
  76309. x2 = nextPoint.x;
  76310. y1 = prevPoint.y;
  76311. y2 = nextPoint.y;
  76312. curIsExtremum = !!(!rotated && (yCur <= prevPoint.y && yCur <= nextPoint.y || yCur >= prevPoint.y && yCur >= nextPoint.y) || rotated && (xCur <= prevPoint.x && xCur <= nextPoint.x || xCur >= prevPoint.x && xCur >= nextPoint.x));
  76313. if (curIsExtremum)
  76314. if (!rotated) {
  76315. rightControlY = leftControlY = yCur;
  76316. rightControlX = (xCur + nextPoint.x) / 2;
  76317. leftControlX = (xCur + prevPoint.x) / 2
  76318. }
  76319. else {
  76320. rightControlX = leftControlX = xCur;
  76321. rightControlY = (yCur + nextPoint.y) / 2;
  76322. leftControlY = (yCur + prevPoint.y) / 2
  76323. }
  76324. else {
  76325. a = y2 - y1;
  76326. b = x1 - x2;
  76327. c = y1 * x2 - x1 * y2;
  76328. if (!rotated) {
  76329. xc = xCur;
  76330. yc = -1 * (a * xc + c) / b;
  76331. shift = yc - yCur || 0;
  76332. y1 -= shift;
  76333. y2 -= shift
  76334. }
  76335. else {
  76336. yc = yCur;
  76337. xc = -1 * (b * yc + c) / a;
  76338. shift = xc - xCur || 0;
  76339. x1 -= shift;
  76340. x2 -= shift
  76341. }
  76342. rightControlX = (xCur + lambda * x2) / (1 + lambda);
  76343. rightControlY = (yCur + lambda * y2) / (1 + lambda);
  76344. leftControlX = (xCur + lambda * x1) / (1 + lambda);
  76345. leftControlY = (yCur + lambda * y1) / (1 + lambda)
  76346. }
  76347. if (!rotated) {
  76348. leftControlY = checkExtr(prevPoint.y, yCur, leftControlY);
  76349. rightControlY = checkExtr(nextPoint.y, yCur, rightControlY)
  76350. }
  76351. else {
  76352. leftControlX = checkExtr(prevPoint.x, xCur, leftControlX);
  76353. rightControlX = checkExtr(nextPoint.x, xCur, rightControlX)
  76354. }
  76355. leftPoint = clonePoint(curPoint, leftControlX, leftControlY);
  76356. rightPoint = clonePoint(curPoint, rightControlX, rightControlY);
  76357. bezierPoints.push(leftPoint, curPoint, rightPoint)
  76358. }
  76359. else {
  76360. bezierPoints.push(curPoint, curPoint);
  76361. return
  76362. }
  76363. });
  76364. else
  76365. bezierPoints.push(pointsCopy[0]);
  76366. return bezierPoints
  76367. },
  76368. _prepareSegment: function(points, rotated) {
  76369. return chartSeries.line._prepareSegment(this._calculateBezierPoints(points, rotated))
  76370. },
  76371. _createMainElement: function(points, settings) {
  76372. return this._renderer.path(points, "bezier").attr(settings).sharp()
  76373. }
  76374. });
  76375. polarSeries.line = _extend({}, polarSeries.scatter, lineMethods, {
  76376. _prepareSegment: function(points, rotated, lastSegment) {
  76377. var preparedPoints = [],
  76378. centerPoint = this.translators.translate(CANVAS_POSITION_START, CANVAS_POSITION_TOP),
  76379. i;
  76380. lastSegment && this._closeSegment(points);
  76381. if (this.argumentAxisType !== DISCRETE && this.valueAxisType !== DISCRETE) {
  76382. for (i = 1; i < points.length; i++)
  76383. preparedPoints = preparedPoints.concat(this._getTangentPoints(points[i], points[i - 1], centerPoint));
  76384. if (!preparedPoints.length)
  76385. preparedPoints = points
  76386. }
  76387. else
  76388. return chartSeries.line._prepareSegment.apply(this, arguments);
  76389. return {line: preparedPoints}
  76390. },
  76391. _getRemainingAngle: function(angle) {
  76392. var normAngle = utils.normalizeAngle(angle);
  76393. return angle >= 0 ? 360 - normAngle : -normAngle
  76394. },
  76395. _closeSegment: function(points) {
  76396. var point,
  76397. differenceAngle;
  76398. if (this._segments.length)
  76399. point = this._segments[0].line[0];
  76400. else
  76401. point = clonePoint(points[0], points[0].x, points[0].y, points[0].angle);
  76402. if (points[points.length - 1].angle !== point.angle) {
  76403. if (utils.normalizeAngle(Math.round(points[points.length - 1].angle)) === utils.normalizeAngle(Math.round(point.angle)))
  76404. point.angle = points[points.length - 1].angle;
  76405. else {
  76406. differenceAngle = points[points.length - 1].angle - point.angle;
  76407. point.angle = points[points.length - 1].angle + this._getRemainingAngle(differenceAngle)
  76408. }
  76409. points.push(point)
  76410. }
  76411. },
  76412. _getTangentPoints: function(point, prevPoint, centerPoint) {
  76413. var tangentPoints = [],
  76414. betweenAngle = Math.round(prevPoint.angle - point.angle),
  76415. tan = (prevPoint.radius - point.radius) / betweenAngle,
  76416. i;
  76417. if (betweenAngle === 0)
  76418. tangentPoints = [prevPoint, point];
  76419. else if (betweenAngle > 0)
  76420. for (i = betweenAngle; i >= 0; i--)
  76421. tangentPoints.push(getTangentPoint(point, prevPoint, centerPoint, tan, i));
  76422. else
  76423. for (i = 0; i >= betweenAngle; i--)
  76424. tangentPoints.push(getTangentPoint(point, prevPoint, centerPoint, tan, betweenAngle - i));
  76425. return tangentPoints
  76426. }
  76427. })
  76428. })(jQuery, DevExpress);
  76429. /*! Module viz-core, file areaSeries.js */
  76430. (function($, DX) {
  76431. var core = DX.viz.core,
  76432. utils = DX.utils,
  76433. series = core.series,
  76434. chartSeries = series.mixins.chart,
  76435. polarSeries = series.mixins.polar,
  76436. lineSeries = chartSeries.line,
  76437. rangeCalculator = core.series.helpers.rangeDataCalculator,
  76438. _map = $.map,
  76439. _extend = $.extend,
  76440. HOVER_COLOR_HIGHLIGHTING = 20;
  76441. var baseAreaMethods = {
  76442. _createBorderElement: lineSeries._createMainElement,
  76443. _createLegendState: function(styleOptions, defaultColor) {
  76444. var legendState = chartSeries.scatter._createLegendState.call(this, styleOptions, defaultColor);
  76445. legendState.opacity = styleOptions.opacity;
  76446. return legendState
  76447. },
  76448. _getSpecialColor: function(color) {
  76449. return this._options._IE8 ? new DX.Color(color).highlight(HOVER_COLOR_HIGHLIGHTING) : color
  76450. },
  76451. _getRangeData: function(zoomArgs, calcIntervalFunction) {
  76452. rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction);
  76453. rangeCalculator.addLabelPaddings(this);
  76454. rangeCalculator.calculateRangeMinValue(this, zoomArgs);
  76455. return this._rangeData
  76456. },
  76457. _getDefaultSegment: function(segment) {
  76458. var defaultSegment = lineSeries._getDefaultSegment(segment);
  76459. defaultSegment.area = defaultSegment.line.concat(defaultSegment.line.slice().reverse());
  76460. return defaultSegment
  76461. },
  76462. _updateElement: function(element, segment, animate, animateParams, complete) {
  76463. var lineParams = {points: segment.line},
  76464. areaParams = {points: segment.area},
  76465. borderElement = element.line;
  76466. if (animate) {
  76467. borderElement && borderElement.animate(lineParams, animateParams);
  76468. element.area.animate(areaParams, animateParams, complete)
  76469. }
  76470. else {
  76471. borderElement && borderElement.attr(lineParams);
  76472. element.area.attr(areaParams)
  76473. }
  76474. },
  76475. _removeElement: function(element) {
  76476. element.line && element.line.remove();
  76477. element.area.remove()
  76478. },
  76479. _drawElement: function(segment) {
  76480. return {
  76481. line: this._bordersGroup && this._createBorderElement(segment.line, {"stroke-width": this._styles.normal.border["stroke-width"]}).append(this._bordersGroup),
  76482. area: this._createMainElement(segment.area).append(this._elementsGroup)
  76483. }
  76484. },
  76485. _applyStyle: function(style) {
  76486. var that = this;
  76487. that._elementsGroup && that._elementsGroup.attr(style.elements);
  76488. that._bordersGroup && that._bordersGroup.attr(style.border);
  76489. $.each(that._graphics || [], function(_, graphic) {
  76490. graphic.line && graphic.line.attr({'stroke-width': style.border["stroke-width"]}).sharp()
  76491. })
  76492. },
  76493. _createPattern: function(color, hatching, custom) {
  76494. if (hatching && utils.isObject(hatching)) {
  76495. var pattern = this._renderer.pattern(color, hatching);
  76496. pattern._custom = custom;
  76497. this._patterns.push(pattern);
  76498. return pattern.id
  76499. }
  76500. return color
  76501. },
  76502. _parseStyle: function(options, defaultColor, defaultBorderColor) {
  76503. var borderOptions = options.border || {},
  76504. borderStyle = lineSeries._parseLineOptions(borderOptions, defaultBorderColor);
  76505. borderStyle["stroke-width"] = borderOptions.visible ? borderStyle["stroke-width"] : 0;
  76506. return {
  76507. border: borderStyle,
  76508. elements: {
  76509. stroke: "none",
  76510. fill: this._createPattern(options.color || defaultColor, options.hatching),
  76511. opacity: options.opacity
  76512. }
  76513. }
  76514. },
  76515. _areBordersVisible: function() {
  76516. var options = this._options;
  76517. return options.border.visible || options.hoverStyle.border.visible || options.selectionStyle.border.visible
  76518. },
  76519. _createMainElement: function(points, settings) {
  76520. return this._renderer.path(points, "area").attr(settings)
  76521. },
  76522. _getTrackerSettings: function(segment) {
  76523. return {"stroke-width": segment.singlePointSegment ? this._defaultTrackerWidth : 0}
  76524. },
  76525. _getMainPointsFromSegment: function(segment) {
  76526. return segment.area
  76527. }
  76528. };
  76529. chartSeries.area = _extend({}, lineSeries, baseAreaMethods, {
  76530. _prepareSegment: function(points, rotated) {
  76531. var processedPoints = this._processSinglePointsAreaSegment(points, rotated);
  76532. return {
  76533. line: processedPoints,
  76534. area: _map(processedPoints, function(pt) {
  76535. return pt.getCoords()
  76536. }).concat(_map(processedPoints.slice().reverse(), function(pt) {
  76537. return pt.getCoords(true)
  76538. })),
  76539. singlePointSegment: processedPoints !== points
  76540. }
  76541. },
  76542. _processSinglePointsAreaSegment: function(points, rotated) {
  76543. if (points.length === 1) {
  76544. var p = points[0],
  76545. p1 = utils.clone(p);
  76546. p1[rotated ? "y" : "x"] += 1;
  76547. p1.argument = null;
  76548. return [p, p1]
  76549. }
  76550. return points
  76551. }
  76552. });
  76553. polarSeries.area = _extend({}, polarSeries.line, baseAreaMethods, {
  76554. _prepareSegment: function(points, rotated, lastSegment) {
  76555. lastSegment && polarSeries.line._closeSegment.call(this, points);
  76556. var preparedPoints = chartSeries.area._prepareSegment.call(this, points);
  76557. return preparedPoints
  76558. },
  76559. _processSinglePointsAreaSegment: function(points) {
  76560. return polarSeries.line._prepareSegment.call(this, points).line
  76561. }
  76562. });
  76563. chartSeries.steparea = _extend({}, chartSeries.area, {_prepareSegment: function(points, rotated) {
  76564. points = chartSeries.area._processSinglePointsAreaSegment(points, rotated);
  76565. return chartSeries.area._prepareSegment.call(this, chartSeries.stepline._calculateStepLinePoints(points))
  76566. }});
  76567. chartSeries.splinearea = _extend({}, chartSeries.area, {
  76568. _areaPointsToSplineAreaPoints: function(areaPoints) {
  76569. var lastFwPoint = areaPoints[areaPoints.length / 2 - 1],
  76570. firstBwPoint = areaPoints[areaPoints.length / 2];
  76571. areaPoints.splice(areaPoints.length / 2, 0, {
  76572. x: lastFwPoint.x,
  76573. y: lastFwPoint.y
  76574. }, {
  76575. x: firstBwPoint.x,
  76576. y: firstBwPoint.y
  76577. });
  76578. if (lastFwPoint.defaultCoords)
  76579. areaPoints[areaPoints.length / 2].defaultCoords = true;
  76580. if (firstBwPoint.defaultCoords)
  76581. areaPoints[areaPoints.length / 2 - 1].defaultCoords = true
  76582. },
  76583. _prepareSegment: function(points, rotated) {
  76584. var areaSeries = chartSeries.area,
  76585. processedPoints = areaSeries._processSinglePointsAreaSegment(points, rotated),
  76586. areaSegment = areaSeries._prepareSegment.call(this, chartSeries.spline._calculateBezierPoints(processedPoints, rotated));
  76587. this._areaPointsToSplineAreaPoints(areaSegment.area);
  76588. areaSegment.singlePointSegment = processedPoints !== points;
  76589. return areaSegment
  76590. },
  76591. _getDefaultSegment: function(segment) {
  76592. var areaDefaultSegment = chartSeries.area._getDefaultSegment(segment);
  76593. this._areaPointsToSplineAreaPoints(areaDefaultSegment.area);
  76594. return areaDefaultSegment
  76595. },
  76596. _createMainElement: function(points, settings) {
  76597. return this._renderer.path(points, "bezierarea").attr(settings)
  76598. },
  76599. _createBorderElement: chartSeries.spline._createMainElement
  76600. })
  76601. })(jQuery, DevExpress);
  76602. /*! Module viz-core, file barSeries.js */
  76603. (function($, DX) {
  76604. var viz = DX.viz,
  76605. series = viz.core.series,
  76606. chartSeries = series.mixins.chart,
  76607. polarSeries = series.mixins.polar,
  76608. scatterSeries = chartSeries.scatter,
  76609. areaSeries = chartSeries.area,
  76610. _extend = $.extend,
  76611. _each = $.each,
  76612. DEFAULT_BAR_POINT_SIZE = 3;
  76613. var baseBarSeriesMethods = {
  76614. _getSpecialColor: areaSeries._getSpecialColor,
  76615. _createPattern: areaSeries._createPattern,
  76616. _updateOptions: function(options) {
  76617. this._stackName = "axis_" + (options.axis || "default") + "_stack_" + (options.stack || "default")
  76618. },
  76619. _parsePointStyle: function(style, defaultColor, defaultBorderColor, isCustomPointOptions) {
  76620. var color = this._createPattern(style.color || defaultColor, style.hatching, isCustomPointOptions),
  76621. base = scatterSeries._parsePointStyle.call(this, style, color, defaultBorderColor);
  76622. base.fill = color;
  76623. base.dashStyle = style.border && style.border.dashStyle || "solid";
  76624. delete base.r;
  76625. return base
  76626. },
  76627. _applyMarkerClipRect: function(settings) {
  76628. settings.clipId = null
  76629. },
  76630. _clearingAnimation: function(translators, drawComplete) {
  76631. var that = this,
  76632. settings = that._oldgetAffineCoordOptions(translators) || that._getAffineCoordOptions(translators);
  76633. that._labelsGroup && that._labelsGroup.animate({opacity: 0.001}, {
  76634. duration: that._defaultDuration,
  76635. partitionDuration: 0.5
  76636. }, function() {
  76637. that._markersGroup.animate(settings, {partitionDuration: 0.5}, function() {
  76638. that._markersGroup.attr({
  76639. scaleX: null,
  76640. scaleY: null,
  76641. translateX: 0,
  76642. translateY: 0
  76643. });
  76644. drawComplete()
  76645. })
  76646. })
  76647. },
  76648. _createGroups: function(animationEnabled, style, firstDrawing) {
  76649. var that = this,
  76650. settings = {};
  76651. scatterSeries._createGroups.apply(that, arguments);
  76652. if (animationEnabled && firstDrawing)
  76653. settings = this._getAffineCoordOptions(that.translators, true);
  76654. else if (!animationEnabled)
  76655. settings = {
  76656. scaleX: 1,
  76657. scaleY: 1,
  76658. translateX: 0,
  76659. translateY: 0
  76660. };
  76661. that._markersGroup.attr(settings)
  76662. },
  76663. _drawPoint: function(options) {
  76664. options.hasAnimation = options.hasAnimation && !options.firstDrawing;
  76665. options.firstDrawing = false;
  76666. scatterSeries._drawPoint.call(this, options)
  76667. },
  76668. _getMainColor: function() {
  76669. return this._options.mainSeriesColor
  76670. },
  76671. _createPointStyles: function(pointOptions, isCustomPointOptions) {
  76672. var that = this,
  76673. mainColor = pointOptions.color || that._getMainColor(),
  76674. specialMainColor = that._getSpecialColor(mainColor);
  76675. return {
  76676. normal: that._parsePointStyle(pointOptions, mainColor, mainColor, isCustomPointOptions),
  76677. hover: that._parsePointStyle(pointOptions.hoverStyle || {}, specialMainColor, mainColor, isCustomPointOptions),
  76678. selection: that._parsePointStyle(pointOptions.selectionStyle || {}, specialMainColor, mainColor, isCustomPointOptions)
  76679. }
  76680. },
  76681. _updatePointsVisibility: function() {
  76682. var visibility = this._options.visible;
  76683. $.each(this._points, function(_, point) {
  76684. point._options.visible = visibility
  76685. })
  76686. },
  76687. _preparePointOptions: function(customOptions) {
  76688. var options = this._options;
  76689. return customOptions ? _extend(true, {}, options, customOptions) : options
  76690. },
  76691. _animate: function(firstDrawing) {
  76692. var that = this,
  76693. complete = function() {
  76694. that._animateComplete()
  76695. },
  76696. animateFunc = function(drawedPoints, complete) {
  76697. var lastPointIndex = drawedPoints.length - 1;
  76698. _each(drawedPoints || [], function(i, point) {
  76699. point.animate(i === lastPointIndex ? complete : undefined, point.getMarkerCoords())
  76700. })
  76701. };
  76702. that._animatePoints(firstDrawing, complete, animateFunc)
  76703. },
  76704. _getPointSize: function() {
  76705. return DEFAULT_BAR_POINT_SIZE
  76706. },
  76707. _beginUpdateData: function(data) {
  76708. scatterSeries._beginUpdateData.call(this, data);
  76709. this._patterns = $.map(this._patterns, function(pattern) {
  76710. if (pattern._custom) {
  76711. pattern.remove();
  76712. return null
  76713. }
  76714. else
  76715. return pattern
  76716. })
  76717. }
  76718. };
  76719. chartSeries.bar = _extend({}, scatterSeries, baseBarSeriesMethods, {
  76720. _getAffineCoordOptions: function(translators) {
  76721. var rotated = this._options.rotated,
  76722. direction = rotated ? "x" : "y",
  76723. settings = {
  76724. scaleX: rotated ? 0.001 : 1,
  76725. scaleY: rotated ? 1 : 0.001
  76726. };
  76727. settings["translate" + direction.toUpperCase()] = translators[direction].translate("canvas_position_default");
  76728. return settings
  76729. },
  76730. _getRangeData: function() {
  76731. var rangeData = areaSeries._getRangeData.apply(this, arguments);
  76732. rangeData.arg.stick = false;
  76733. return rangeData
  76734. },
  76735. _animatePoints: function(firstDrawing, complete, animateFunc) {
  76736. var that = this;
  76737. that._markersGroup.animate({
  76738. scaleX: 1,
  76739. scaleY: 1,
  76740. translateY: 0,
  76741. translateX: 0
  76742. }, undefined, complete);
  76743. if (!firstDrawing)
  76744. animateFunc(that._drawedPoints, complete)
  76745. }
  76746. });
  76747. polarSeries.bar = _extend({}, polarSeries.scatter, baseBarSeriesMethods, {
  76748. _animatePoints: function(firstDrawing, complete, animateFunc) {
  76749. animateFunc(this._drawedPoints, complete)
  76750. },
  76751. _createGroups: function() {
  76752. scatterSeries._createGroups.apply(this, arguments)
  76753. },
  76754. _drawPoint: function(point, groups, animationEnabled) {
  76755. scatterSeries._drawPoint.call(this, point, groups, animationEnabled)
  76756. },
  76757. _parsePointStyle: function(style) {
  76758. var base = baseBarSeriesMethods._parsePointStyle.apply(this, arguments);
  76759. base.opacity = style.opacity;
  76760. return base
  76761. },
  76762. _createMarkerGroup: function() {
  76763. var that = this,
  76764. markersSettings = that._getPointOptions().styles.normal,
  76765. groupSettings;
  76766. markersSettings["class"] = "dxc-markers";
  76767. that._applyMarkerClipRect(markersSettings);
  76768. groupSettings = _extend({}, markersSettings);
  76769. delete groupSettings.opacity;
  76770. that._createGroup("_markersGroup", that, that._group, groupSettings)
  76771. },
  76772. _createLegendState: areaSeries._createLegendState,
  76773. _getRangeData: areaSeries._getRangeData
  76774. })
  76775. })(jQuery, DevExpress);
  76776. /*! Module viz-core, file rangeSeries.js */
  76777. (function($, DX) {
  76778. var core = DX.viz.core,
  76779. series = core.series.mixins.chart,
  76780. _extend = $.extend,
  76781. _isDefined = DX.utils.isDefined,
  76782. _noop = $.noop,
  76783. rangeCalculator = core.series.helpers.rangeDataCalculator,
  76784. areaSeries = series.area;
  76785. var baseRangeSeries = {
  76786. _beginUpdateData: _noop,
  76787. areErrorBarsVisible: _noop,
  76788. _createErrorBarGroup: _noop,
  76789. _checkData: function(data) {
  76790. return _isDefined(data.argument) && data.value !== undefined && data.minValue !== undefined
  76791. },
  76792. updateTeamplateFieldNames: function() {
  76793. var that = this,
  76794. options = that._options,
  76795. valueFields = that.getValueFields(),
  76796. name = that.name;
  76797. options.rangeValue1Field = valueFields[0] + name;
  76798. options.rangeValue2Field = valueFields[1] + name;
  76799. options.tagField = that.getTagField() + name
  76800. },
  76801. _processRange: function(point, prevPoint) {
  76802. rangeCalculator.processTwoValues(this, point, prevPoint, "value", "minValue")
  76803. },
  76804. _getRangeData: function(zoomArgs, calcIntervalFunction) {
  76805. rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction, "value", "minValue");
  76806. rangeCalculator.addRangeSeriesLabelPaddings(this);
  76807. return this._rangeData
  76808. },
  76809. _getPointData: function(data, options) {
  76810. return {
  76811. tag: data[options.tagField || "tag"],
  76812. minValue: data[options.rangeValue1Field || "val1"],
  76813. value: data[options.rangeValue2Field || "val2"],
  76814. argument: data[options.argumentField || "arg"]
  76815. }
  76816. },
  76817. _fusionPoints: function(fusionPoints, tick) {
  76818. var calcMedianValue = series.scatter._calcMedianValue,
  76819. value = calcMedianValue.call(this, fusionPoints, "value"),
  76820. minValue = calcMedianValue.call(this, fusionPoints, "minValue");
  76821. if (value === null || minValue === null)
  76822. value = minValue = null;
  76823. return {
  76824. minValue: minValue,
  76825. value: value,
  76826. argument: tick,
  76827. tag: null
  76828. }
  76829. },
  76830. getValueFields: function() {
  76831. return [this._options.rangeValue1Field || "val1", this._options.rangeValue2Field || "val2"]
  76832. }
  76833. };
  76834. series.rangebar = _extend({}, series.bar, baseRangeSeries);
  76835. series.rangearea = _extend({}, areaSeries, {
  76836. _drawPoint: function(options) {
  76837. var point = options.point;
  76838. if (point.isInVisibleArea()) {
  76839. point.clearVisibility();
  76840. point.draw(this._renderer, options.groups);
  76841. this._drawedPoints.push(point);
  76842. if (!point.visibleTopMarker)
  76843. point.hideMarker("top");
  76844. if (!point.visibleBottomMarker)
  76845. point.hideMarker("bottom")
  76846. }
  76847. else
  76848. point.setInvisibility()
  76849. },
  76850. _prepareSegment: function(points, rotated) {
  76851. var processedPoints = this._processSinglePointsAreaSegment(points, rotated),
  76852. processedMinPointsCoords = $.map(processedPoints, function(pt) {
  76853. return pt.getCoords(true)
  76854. });
  76855. return {
  76856. line: processedPoints,
  76857. bottomLine: processedMinPointsCoords,
  76858. area: $.map(processedPoints, function(pt) {
  76859. return pt.getCoords()
  76860. }).concat(processedMinPointsCoords.slice().reverse()),
  76861. singlePointSegment: processedPoints !== points
  76862. }
  76863. },
  76864. _getDefaultSegment: function(segment) {
  76865. var defaultSegment = areaSeries._getDefaultSegment.call(this, segment);
  76866. defaultSegment.bottomLine = defaultSegment.line;
  76867. return defaultSegment
  76868. },
  76869. _removeElement: function(element) {
  76870. areaSeries._removeElement.call(this, element);
  76871. element.bottomLine && element.bottomLine.remove()
  76872. },
  76873. _drawElement: function(segment, group) {
  76874. var that = this,
  76875. drawnElement = areaSeries._drawElement.call(that, segment, group);
  76876. drawnElement.bottomLine = that._bordersGroup && that._createBorderElement(segment.bottomLine, {"stroke-width": that._styles.normal.border["stroke-width"]}).append(that._bordersGroup);
  76877. return drawnElement
  76878. },
  76879. _applyStyle: function(style) {
  76880. var that = this,
  76881. elementsGroup = that._elementsGroup,
  76882. bordersGroup = that._bordersGroup;
  76883. elementsGroup && elementsGroup.attr(style.elements);
  76884. bordersGroup && bordersGroup.attr(style.border);
  76885. $.each(that._graphics || [], function(_, graphic) {
  76886. graphic.line && graphic.line.attr({"stroke-width": style.border["stroke-width"]});
  76887. graphic.bottomLine && graphic.bottomLine.attr({"stroke-width": style.border["stroke-width"]})
  76888. })
  76889. },
  76890. _updateElement: function(element, segment, animate, animateParams, complete) {
  76891. areaSeries._updateElement.call(this, element, segment, animate, animateParams, complete);
  76892. var bottomLineParams = {points: segment.bottomLine},
  76893. bottomBorderElement = element.bottomLine;
  76894. if (bottomBorderElement)
  76895. animate ? bottomBorderElement.animate(bottomLineParams, animateParams) : bottomBorderElement.attr(bottomLineParams)
  76896. }
  76897. }, baseRangeSeries)
  76898. })(jQuery, DevExpress);
  76899. /*! Module viz-core, file bubbleSeries.js */
  76900. (function($, DX) {
  76901. var mixins = DX.viz.core.series.mixins,
  76902. series = mixins.chart,
  76903. scatterSeries = series.scatter,
  76904. barSeries = series.bar,
  76905. _isDefined = DX.utils.isDefined,
  76906. _extend = $.extend,
  76907. _each = $.each,
  76908. _noop = $.noop;
  76909. series.bubble = _extend({}, scatterSeries, {
  76910. _fillErrorBars: _noop,
  76911. _getRangeCorrector: _noop,
  76912. _calculateErrorBars: _noop,
  76913. _getMainColor: barSeries._getMainColor,
  76914. _createPointStyles: barSeries._createPointStyles,
  76915. _createPattern: barSeries._createPattern,
  76916. _updatePointsVisibility: barSeries._updatePointsVisibility,
  76917. _preparePointOptions: barSeries._preparePointOptions,
  76918. _getSpecialColor: barSeries._getSpecialColor,
  76919. _applyMarkerClipRect: series.line._applyElementsClipRect,
  76920. _parsePointStyle: mixins.polar.bar._parsePointStyle,
  76921. _createLegendState: series.area._createLegendState,
  76922. _createMarkerGroup: mixins.polar.bar._createMarkerGroup,
  76923. areErrorBarsVisible: _noop,
  76924. _createErrorBarGroup: _noop,
  76925. _checkData: function(data) {
  76926. return _isDefined(data.argument) && _isDefined(data.size) && data.value !== undefined
  76927. },
  76928. _getPointData: function(data, options) {
  76929. var pointData = scatterSeries._getPointData.call(this, data, options);
  76930. pointData.size = data[options.sizeField || "size"];
  76931. return pointData
  76932. },
  76933. _fusionPoints: function(fusionPoints, tick) {
  76934. var calcMedianValue = scatterSeries._calcMedianValue;
  76935. return {
  76936. size: calcMedianValue.call(this, fusionPoints, "size"),
  76937. value: calcMedianValue.call(this, fusionPoints, "value"),
  76938. argument: tick,
  76939. tag: null
  76940. }
  76941. },
  76942. getValueFields: function() {
  76943. var options = this._options;
  76944. return [options.valueField || "val", options.sizeField || "size"]
  76945. },
  76946. updateTeamplateFieldNames: function() {
  76947. var that = this,
  76948. options = that._options,
  76949. valueFields = that.getValueFields(),
  76950. name = that.name;
  76951. options.valueField = valueFields[0] + name;
  76952. options.sizeField = valueFields[1] + name;
  76953. options.tagField = that.getTagField() + name
  76954. },
  76955. _clearingAnimation: function(translators, drawComplete) {
  76956. var that = this,
  76957. partitionDuration = 0.5,
  76958. lastPointIndex = that._drawedPoints.length - 1,
  76959. labelsGroup = that._labelsGroup;
  76960. labelsGroup && labelsGroup.animate({opacity: 0.001}, {
  76961. duration: that._defaultDuration,
  76962. partitionDuration: partitionDuration
  76963. }, function() {
  76964. _each(that._drawedPoints || [], function(i, p) {
  76965. p.animate(i === lastPointIndex ? drawComplete : undefined, {r: 0}, partitionDuration)
  76966. })
  76967. })
  76968. },
  76969. _animate: function() {
  76970. var that = this,
  76971. lastPointIndex = that._drawedPoints.length - 1,
  76972. labelsGroup = that._labelsGroup,
  76973. labelAnimFunc = function() {
  76974. labelsGroup && labelsGroup.animate({opacity: 1}, {duration: that._defaultDuration})
  76975. };
  76976. _each(that._drawedPoints || [], function(i, p) {
  76977. p.animate(i === lastPointIndex ? labelAnimFunc : undefined, {
  76978. r: p.bubbleSize,
  76979. translateX: p.x,
  76980. translateY: p.y
  76981. })
  76982. })
  76983. },
  76984. _beginUpdateData: barSeries._beginUpdateData
  76985. })
  76986. })(jQuery, DevExpress);
  76987. /*! Module viz-core, file pieSeries.js */
  76988. (function($, DX) {
  76989. var mixins = DX.viz.core.series.mixins,
  76990. pieSeries = mixins.pie,
  76991. _utils = DX.utils,
  76992. scatterSeries = mixins.chart.scatter,
  76993. barSeries = mixins.chart.bar,
  76994. _extend = $.extend,
  76995. _each = $.each,
  76996. _noop = $.noop,
  76997. _map = $.map,
  76998. _isFinite = isFinite,
  76999. _max = Math.max;
  77000. pieSeries.pie = _extend({}, barSeries, {
  77001. _createLabelGroup: scatterSeries._createLabelGroup,
  77002. _createGroups: scatterSeries._createGroups,
  77003. _createErrorBarGroup: _noop,
  77004. _drawPoint: function(options) {
  77005. var point = options.point,
  77006. legendCallback = options.legendCallback;
  77007. scatterSeries._drawPoint.call(this, options);
  77008. !point.isVisible() && point.setInvisibility();
  77009. legendCallback && point.isSelected() && legendCallback(point)("applySelected")
  77010. },
  77011. adjustLabels: function() {
  77012. var that = this,
  77013. points = that._points || [],
  77014. maxLabelLength,
  77015. labelsBBoxes = [];
  77016. _each(points, function(_, point) {
  77017. if (point._label.isVisible() && point._label.getLayoutOptions().position !== "inside") {
  77018. point.setLabelEllipsis();
  77019. labelsBBoxes.push(point._label.getBoundingRect().width)
  77020. }
  77021. });
  77022. if (labelsBBoxes.length)
  77023. maxLabelLength = _max.apply(null, labelsBBoxes);
  77024. _each(points, function(_, point) {
  77025. if (point._label.isVisible() && point._label.getLayoutOptions().position !== "inside") {
  77026. point._maxLabelLength = maxLabelLength;
  77027. point.updateLabelCoord()
  77028. }
  77029. })
  77030. },
  77031. _processRange: _noop,
  77032. _applyElementsClipRect: _noop,
  77033. getColor: _noop,
  77034. areErrorBarsVisible: _noop,
  77035. _prepareSeriesToDrawing: _noop,
  77036. _endUpdateData: scatterSeries._prepareSeriesToDrawing,
  77037. resetLabelSetups: function() {
  77038. _each(this._points || [], function(_, point) {
  77039. point._label.clearVisibility()
  77040. })
  77041. },
  77042. drawLabelsWOPoints: function(translators) {
  77043. var that = this,
  77044. options = that._options,
  77045. points = that._points || [],
  77046. labelsGroup;
  77047. if (options.label.position === "inside")
  77048. return false;
  77049. that._createGroups();
  77050. labelsGroup = that._labelsGroup;
  77051. _each(points, function(_, point) {
  77052. point.drawLabel(translators, that._renderer, labelsGroup)
  77053. });
  77054. return true
  77055. },
  77056. _getCreatingPointOptions: function() {
  77057. return this._getPointOptions()
  77058. },
  77059. _updateOptions: function(options) {
  77060. this.labelSpace = 0;
  77061. this.innerRadius = this.type === "pie" ? 0 : options.innerRadius
  77062. },
  77063. _checkData: function(data) {
  77064. var base = barSeries._checkData(data);
  77065. return this._options.paintNullPoints ? base : base && data.value !== null
  77066. },
  77067. _createMarkerGroup: function() {
  77068. var that = this;
  77069. if (!that._markersGroup)
  77070. that._markersGroup = that._renderer.g().attr({"class": "dxc-markers"}).append(that._group)
  77071. },
  77072. _getMainColor: function() {
  77073. return this._options.mainSeriesColor()
  77074. },
  77075. _getPointOptions: function() {
  77076. return this._parsePointOptions(this._preparePointOptions(), this._options.label)
  77077. },
  77078. _getRangeData: function() {
  77079. return this._rangeData
  77080. },
  77081. _getArrangeTotal: function(points) {
  77082. var total = 0;
  77083. _each(points, function(_, point) {
  77084. if (point.isVisible())
  77085. total += point.initialValue
  77086. });
  77087. return total
  77088. },
  77089. _createPointStyles: function(pointOptions) {
  77090. var that = this,
  77091. mainColor = pointOptions.color || that._getMainColor(),
  77092. specialMainColor = that._getSpecialColor(mainColor);
  77093. return {
  77094. normal: that._parsePointStyle(pointOptions, mainColor, mainColor),
  77095. hover: that._parsePointStyle(pointOptions.hoverStyle, specialMainColor, mainColor),
  77096. selection: that._parsePointStyle(pointOptions.selectionStyle, specialMainColor, mainColor),
  77097. legendStyles: {
  77098. normal: that._createLegendState(pointOptions, mainColor),
  77099. hover: that._createLegendState(pointOptions.hoverStyle, specialMainColor),
  77100. selection: that._createLegendState(pointOptions.selectionStyle, specialMainColor)
  77101. }
  77102. }
  77103. },
  77104. _getArrangeMinShownValue: function(points, total) {
  77105. var minSegmentSize = this._options.minSegmentSize,
  77106. totalMinSegmentSize = 0,
  77107. totalNotMinValues = 0;
  77108. total = total || points.length;
  77109. _each(points, function(_, point) {
  77110. if (point.isVisible())
  77111. if (point.initialValue < minSegmentSize * total / 360)
  77112. totalMinSegmentSize += minSegmentSize;
  77113. else
  77114. totalNotMinValues += point.initialValue
  77115. });
  77116. return totalMinSegmentSize < 360 ? minSegmentSize * totalNotMinValues / (360 - totalMinSegmentSize) : 0
  77117. },
  77118. _applyArrangeCorrection: function(points, minShownValue, total) {
  77119. var options = this._options,
  77120. isClockWise = options.segmentsDirection !== "anticlockwise",
  77121. shiftedAngle = _isFinite(options.startAngle) ? _utils.normalizeAngle(options.startAngle) : 0,
  77122. minSegmentSize = options.minSegmentSize,
  77123. percent,
  77124. correction = 0,
  77125. zeroTotalCorrection = 0;
  77126. if (total === 0) {
  77127. total = points.length;
  77128. zeroTotalCorrection = 1
  77129. }
  77130. _each(isClockWise ? points : points.concat([]).reverse(), function(_, point) {
  77131. var val = point.isVisible() ? zeroTotalCorrection || point.initialValue : 0,
  77132. updatedZeroValue;
  77133. if (minSegmentSize && point.isVisible() && val < minShownValue)
  77134. updatedZeroValue = minShownValue;
  77135. percent = val / total;
  77136. point.correctValue(correction, percent, zeroTotalCorrection + (updatedZeroValue || 0));
  77137. point.shiftedAngle = shiftedAngle;
  77138. correction = correction + (updatedZeroValue || val)
  77139. });
  77140. this._rangeData = {val: {
  77141. min: 0,
  77142. max: correction
  77143. }}
  77144. },
  77145. arrangePoints: function() {
  77146. var that = this,
  77147. originalPoints = that._originalPoints || [],
  77148. minSegmentSize = that._options.minSegmentSize,
  77149. minShownValue,
  77150. pointIndex = 0,
  77151. total,
  77152. isAllPointsNegative = _max.apply(null, _map(originalPoints, function(p) {
  77153. return p.value
  77154. })) <= 0,
  77155. points = that._originalPoints = that._points = _map(originalPoints, function(point) {
  77156. if (point.value === null || !isAllPointsNegative && point.value < 0 || point.value === 0 && !minSegmentSize) {
  77157. point.dispose();
  77158. return null
  77159. }
  77160. else {
  77161. point.index = pointIndex++;
  77162. return point
  77163. }
  77164. });
  77165. total = that._getArrangeTotal(points);
  77166. if (minSegmentSize)
  77167. minShownValue = this._getArrangeMinShownValue(points, total);
  77168. that._applyArrangeCorrection(points, minShownValue, total)
  77169. },
  77170. correctPosition: function(correction) {
  77171. var debug = DX.utils.debug;
  77172. debug.assert(correction, "correction was not passed");
  77173. debug.assertParam(correction.centerX, "correction.centerX was not passed");
  77174. debug.assertParam(correction.centerY, "correction.centerY was not passed");
  77175. debug.assertParam(correction.radiusInner, "correction.radiusInner was not passed");
  77176. debug.assertParam(correction.radiusOuter, "correction.radiusOuter was not passed");
  77177. _each(this._points, function(_, point) {
  77178. point.correctPosition(correction)
  77179. });
  77180. this._centerX = correction.centerX;
  77181. this._centerY = correction.centerY;
  77182. this._radiusOuter = correction.radiusOuter
  77183. },
  77184. _animate: function(firstDrawing) {
  77185. var that = this,
  77186. index = 0,
  77187. timeThreshold = 0.2,
  77188. points = that._points,
  77189. pointsCount = points && points.length,
  77190. duration = 1 / (timeThreshold * (pointsCount - 1) + 1),
  77191. completeFunc = function() {
  77192. that._animateComplete()
  77193. },
  77194. animateP = function() {
  77195. points[index] && points[index].animate(index === pointsCount - 1 ? completeFunc : undefined, duration, stepFunc);
  77196. index++
  77197. },
  77198. stepFunc = function(_, progress) {
  77199. if (progress >= timeThreshold) {
  77200. this.step = null;
  77201. animateP()
  77202. }
  77203. };
  77204. if (firstDrawing)
  77205. animateP();
  77206. else
  77207. $.each(points, function(i, p) {
  77208. p.animate(i === pointsCount - 1 ? completeFunc : undefined)
  77209. })
  77210. },
  77211. getVisiblePoints: function() {
  77212. return _map(this._points, function(p) {
  77213. return p.isVisible() ? p : null
  77214. })
  77215. },
  77216. getPointByCoord: function(x, y) {
  77217. var points = this._points;
  77218. for (var i = 0; i < points.length; i++)
  77219. if (points[i].coordsIn(x, y))
  77220. return points[i]
  77221. },
  77222. _beginUpdateData: function() {
  77223. this._deletePatterns();
  77224. this._patterns = []
  77225. },
  77226. getCenter: function() {
  77227. return {
  77228. x: this._centerX,
  77229. y: this._centerY
  77230. }
  77231. }
  77232. });
  77233. pieSeries.doughnut = pieSeries.donut = pieSeries.pie
  77234. })(jQuery, DevExpress);
  77235. /*! Module viz-core, file financialSeries.js */
  77236. (function($, DX) {
  77237. var viz = DX.viz,
  77238. seriesNS = viz.core.series,
  77239. series = seriesNS.mixins.chart,
  77240. scatterSeries = series.scatter,
  77241. barSeries = series.bar,
  77242. rangeCalculator = seriesNS.helpers.rangeDataCalculator,
  77243. _isDefined = DX.utils.isDefined,
  77244. _extend = $.extend,
  77245. _each = $.each,
  77246. _noop = $.noop,
  77247. DEFAULT_FINANCIAL_POINT_SIZE = 10;
  77248. series.stock = _extend({}, scatterSeries, {
  77249. _animate: _noop,
  77250. _applyMarkerClipRect: function(settings) {
  77251. settings.clipId = this._forceClipping ? this._paneClipRectID : this._widePaneClipRectID
  77252. },
  77253. _updatePointsVisibility: barSeries._updatePointsVisibility,
  77254. _preparePointOptions: barSeries._preparePointOptions,
  77255. _getRangeCorrector: _noop,
  77256. _createErrorBarGroup: _noop,
  77257. areErrorBarsVisible: _noop,
  77258. _createMarkerGroup: function() {
  77259. var that = this,
  77260. markersGroup,
  77261. styles = that._getPointOptions().styles,
  77262. defaultStyle = styles.normal,
  77263. defaultPositiveStyle = styles.positive.normal,
  77264. reductionStyle = styles.reduction.normal,
  77265. reductionPositiveStyle = styles.reductionPositive.normal,
  77266. markerSettings = {"class": "dxc-markers"};
  77267. that._applyMarkerClipRect(markerSettings);
  77268. defaultStyle["class"] = "default-markers";
  77269. defaultPositiveStyle["class"] = "default-positive-markers";
  77270. reductionStyle["class"] = "reduction-markers";
  77271. reductionPositiveStyle["class"] = "reduction-positive-markers";
  77272. that._createGroup("_markersGroup", that, that._group, markerSettings);
  77273. markersGroup = that._markersGroup;
  77274. that._createGroup("defaultMarkersGroup", markersGroup, markersGroup, defaultStyle);
  77275. that._createGroup("reductionMarkersGroup", markersGroup, markersGroup, reductionStyle);
  77276. that._createGroup("defaultPositiveMarkersGroup", markersGroup, markersGroup, defaultPositiveStyle);
  77277. that._createGroup("reductionPositiveMarkersGroup", markersGroup, markersGroup, reductionPositiveStyle)
  77278. },
  77279. _createGroups: function() {
  77280. scatterSeries._createGroups.call(this, false)
  77281. },
  77282. _clearingAnimation: function(translators, drawComplete) {
  77283. drawComplete()
  77284. },
  77285. _getCreatingPointOptions: function() {
  77286. var that = this,
  77287. defaultPointOptions,
  77288. creatingPointOptions = that._predefinedPointOptions;
  77289. if (!creatingPointOptions) {
  77290. defaultPointOptions = this._getPointOptions();
  77291. that._predefinedPointOptions = creatingPointOptions = _extend(true, {styles: {}}, defaultPointOptions);
  77292. creatingPointOptions.styles.normal = creatingPointOptions.styles.positive.normal = creatingPointOptions.styles.reduction.normal = creatingPointOptions.styles.reductionPositive.normal = {"stroke-width": defaultPointOptions.styles && defaultPointOptions.styles.normal && defaultPointOptions.styles.normal["stroke-width"]}
  77293. }
  77294. return creatingPointOptions
  77295. },
  77296. _checkData: function(data) {
  77297. return _isDefined(data.argument) && data.highValue !== undefined && data.lowValue !== undefined && data.openValue !== undefined && data.closeValue !== undefined
  77298. },
  77299. _processRange: function(point, prevPoint) {
  77300. rangeCalculator.processTwoValues(this, point, prevPoint, "highValue", "lowValue")
  77301. },
  77302. _getRangeData: function(zoomArgs, calcIntervalFunction) {
  77303. rangeCalculator.calculateRangeData(this, zoomArgs, calcIntervalFunction, "highValue", "lowValue");
  77304. rangeCalculator.addRangeSeriesLabelPaddings(this);
  77305. return this._rangeData
  77306. },
  77307. _getPointData: function(data, options) {
  77308. var that = this,
  77309. level,
  77310. openValueField = options.openValueField || "open",
  77311. closeValueField = options.closeValueField || "close",
  77312. highValueField = options.highValueField || "high",
  77313. lowValueField = options.lowValueField || "low",
  77314. reductionValue;
  77315. that.level = options.reduction.level;
  77316. switch ((that.level || "").toLowerCase()) {
  77317. case"open":
  77318. level = openValueField;
  77319. break;
  77320. case"high":
  77321. level = highValueField;
  77322. break;
  77323. case"low":
  77324. level = lowValueField;
  77325. break;
  77326. default:
  77327. level = closeValueField;
  77328. that.level = "close";
  77329. break
  77330. }
  77331. reductionValue = data[level];
  77332. return {
  77333. argument: data[options.argumentField || "date"],
  77334. highValue: data[highValueField],
  77335. lowValue: data[lowValueField],
  77336. closeValue: data[closeValueField],
  77337. openValue: data[openValueField],
  77338. reductionValue: reductionValue,
  77339. tag: data[options.tagField || "tag"],
  77340. isReduction: that._checkReduction(reductionValue)
  77341. }
  77342. },
  77343. _parsePointStyle: function(style, defaultColor, innerColor) {
  77344. return {
  77345. stroke: style.color || defaultColor,
  77346. "stroke-width": style.width,
  77347. fill: style.color || innerColor
  77348. }
  77349. },
  77350. updateTeamplateFieldNames: function() {
  77351. var that = this,
  77352. options = that._options,
  77353. valueFields = that.getValueFields(),
  77354. name = that.name;
  77355. options.openValueField = valueFields[0] + name;
  77356. options.highValueField = valueFields[1] + name;
  77357. options.lowValueField = valueFields[2] + name;
  77358. options.closeValueField = valueFields[3] + name;
  77359. options.tagField = that.getTagField() + name
  77360. },
  77361. _getDefaultStyle: function(options, isCustomPointOptions) {
  77362. var that = this,
  77363. mainPointColor = options.color || that._options.mainSeriesColor;
  77364. return {
  77365. normal: that._parsePointStyle(options, mainPointColor, mainPointColor, isCustomPointOptions),
  77366. hover: that._parsePointStyle(options.hoverStyle, mainPointColor, mainPointColor, isCustomPointOptions),
  77367. selection: that._parsePointStyle(options.selectionStyle, mainPointColor, mainPointColor, isCustomPointOptions)
  77368. }
  77369. },
  77370. _getReductionStyle: function(options, isCustomPointOptions) {
  77371. var that = this,
  77372. reductionColor = options.reduction.color;
  77373. return {
  77374. normal: that._parsePointStyle({
  77375. color: reductionColor,
  77376. width: options.width,
  77377. hatching: options.hatching
  77378. }, reductionColor, reductionColor, isCustomPointOptions),
  77379. hover: that._parsePointStyle(options.hoverStyle, reductionColor, reductionColor, isCustomPointOptions),
  77380. selection: that._parsePointStyle(options.selectionStyle, reductionColor, reductionColor, isCustomPointOptions)
  77381. }
  77382. },
  77383. _createPointStyles: function(pointOptions, isCustomPointOptions) {
  77384. var that = this,
  77385. innerColor = that._options.innerColor,
  77386. styles = that._getDefaultStyle(pointOptions, isCustomPointOptions),
  77387. positiveStyle,
  77388. reductionStyle,
  77389. reductionPositiveStyle;
  77390. positiveStyle = _extend(true, {}, styles);
  77391. reductionStyle = that._getReductionStyle(pointOptions, isCustomPointOptions);
  77392. reductionPositiveStyle = _extend(true, {}, reductionStyle);
  77393. positiveStyle.normal.fill = positiveStyle.hover.fill = positiveStyle.selection.fill = innerColor;
  77394. reductionPositiveStyle.normal.fill = reductionPositiveStyle.hover.fill = reductionPositiveStyle.selection.fill = innerColor;
  77395. styles.positive = positiveStyle;
  77396. styles.reduction = reductionStyle;
  77397. styles.reductionPositive = reductionPositiveStyle;
  77398. return styles
  77399. },
  77400. _endUpdateData: function() {
  77401. delete this.prevLevelValue;
  77402. delete this._predefinedPointOptions
  77403. },
  77404. _checkReduction: function(value) {
  77405. var that = this,
  77406. result = false;
  77407. if (value !== null) {
  77408. if (_isDefined(that.prevLevelValue))
  77409. result = value < that.prevLevelValue;
  77410. that.prevLevelValue = value
  77411. }
  77412. return result
  77413. },
  77414. _fusionPoints: function(fusionPoints, tick) {
  77415. var fusedPointData = {},
  77416. reductionLevel,
  77417. highValue = -Infinity,
  77418. lowValue = +Infinity,
  77419. openValue,
  77420. closeValue;
  77421. if (!fusionPoints.length)
  77422. return {};
  77423. _each(fusionPoints, function(_, point) {
  77424. if (!point.hasValue())
  77425. return;
  77426. highValue = Math.max(highValue, point.highValue);
  77427. lowValue = Math.min(lowValue, point.lowValue);
  77428. openValue = openValue !== undefined ? openValue : point.openValue;
  77429. closeValue = point.closeValue !== undefined ? point.closeValue : closeValue
  77430. });
  77431. fusedPointData.argument = tick;
  77432. fusedPointData.openValue = openValue;
  77433. fusedPointData.closeValue = closeValue;
  77434. fusedPointData.highValue = highValue;
  77435. fusedPointData.lowValue = lowValue;
  77436. fusedPointData.tag = null;
  77437. switch ((this.level || "").toLowerCase()) {
  77438. case"open":
  77439. reductionLevel = openValue;
  77440. break;
  77441. case"high":
  77442. reductionLevel = highValue;
  77443. break;
  77444. case"low":
  77445. reductionLevel = lowValue;
  77446. break;
  77447. default:
  77448. reductionLevel = closeValue;
  77449. break
  77450. }
  77451. fusedPointData.reductionValue = reductionLevel;
  77452. fusedPointData.isReduction = this._checkReduction(reductionLevel);
  77453. return fusedPointData
  77454. },
  77455. _getPointSize: function() {
  77456. return DEFAULT_FINANCIAL_POINT_SIZE
  77457. },
  77458. getValueFields: function() {
  77459. var options = this._options;
  77460. return [options.openValueField || "open", options.highValueField || "high", options.lowValueField || "low", options.closeValueField || "close"]
  77461. },
  77462. getArgumentField: function() {
  77463. return this._options.argumentField || "date"
  77464. },
  77465. _beginUpdateData: _noop
  77466. });
  77467. series.candlestick = _extend({}, series.stock, {
  77468. _createPattern: barSeries._createPattern,
  77469. _beginUpdateData: barSeries._beginUpdateData,
  77470. _parsePointStyle: function(style, defaultColor, innerColor, isCustomPointOptions) {
  77471. var color = this._createPattern(style.color || innerColor, style.hatching, isCustomPointOptions),
  77472. base = series.stock._parsePointStyle.call(this, style, defaultColor, color);
  77473. base.fill = color;
  77474. return base
  77475. }
  77476. })
  77477. })(jQuery, DevExpress);
  77478. /*! Module viz-core, file stackedSeries.js */
  77479. (function($, DX) {
  77480. var core = DX.viz.core,
  77481. series = core.series,
  77482. chartSeries = series.mixins.chart,
  77483. polarSeries = series.mixins.polar,
  77484. areaSeries = chartSeries.area,
  77485. barSeries = chartSeries.bar,
  77486. lineSeries = chartSeries.line,
  77487. rangeCalculator = core.series.helpers.rangeDataCalculator,
  77488. _extend = $.extend,
  77489. utils = DX.utils,
  77490. _noop = $.noop,
  77491. baseStackedSeries = {
  77492. _processRange: _noop,
  77493. _getRangeCorrector: _noop,
  77494. _fillErrorBars: _noop,
  77495. _calculateErrorBars: _noop,
  77496. _processStackedRange: function() {
  77497. var that = this,
  77498. prevPoint;
  77499. that._resetRangeData();
  77500. $.each(that.getAllPoints(), function(i, p) {
  77501. rangeCalculator.processRange(that, p, prevPoint);
  77502. prevPoint = p
  77503. })
  77504. },
  77505. _getRangeData: function() {
  77506. this._processStackedRange();
  77507. return areaSeries._getRangeData.apply(this, arguments)
  77508. }
  77509. },
  77510. baseFullStackedSeries = _extend({}, baseStackedSeries, {
  77511. _getRangeData: function(zoomArgs, calcIntervalFunction) {
  77512. var that = this;
  77513. that._processStackedRange();
  77514. rangeCalculator.calculateRangeData(that, zoomArgs, calcIntervalFunction);
  77515. rangeCalculator.addLabelPaddings(that);
  77516. rangeCalculator.processFullStackedRange(that);
  77517. rangeCalculator.calculateRangeMinValue(that, zoomArgs);
  77518. return that._rangeData
  77519. },
  77520. isFullStackedSeries: function() {
  77521. return true
  77522. }
  77523. });
  77524. chartSeries.stackedline = _extend({}, lineSeries, baseStackedSeries, {_getRangeData: function() {
  77525. this._processStackedRange();
  77526. return lineSeries._getRangeData.apply(this, arguments)
  77527. }});
  77528. chartSeries.stackedspline = _extend({}, chartSeries.spline, baseStackedSeries, {_getRangeData: chartSeries.stackedline._getRangeData});
  77529. chartSeries.fullstackedline = _extend({}, lineSeries, baseFullStackedSeries, {_getRangeData: function(zoomArgs, calcIntervalFunction) {
  77530. var that = this;
  77531. that._processStackedRange();
  77532. rangeCalculator.calculateRangeData(that, zoomArgs, calcIntervalFunction);
  77533. rangeCalculator.addLabelPaddings(that);
  77534. rangeCalculator.processFullStackedRange(that);
  77535. return that._rangeData
  77536. }});
  77537. chartSeries.fullstackedspline = _extend({}, chartSeries.spline, baseFullStackedSeries, {_getRangeData: chartSeries.fullstackedline._getRangeData});
  77538. chartSeries.stackedbar = _extend({}, barSeries, baseStackedSeries, {_getRangeData: function() {
  77539. this._processStackedRange();
  77540. return barSeries._getRangeData.apply(this, arguments)
  77541. }});
  77542. chartSeries.fullstackedbar = _extend({}, barSeries, baseFullStackedSeries, {_getRangeData: function() {
  77543. var rangeData = baseFullStackedSeries._getRangeData.apply(this, arguments);
  77544. rangeData.arg.stick = false;
  77545. return rangeData
  77546. }});
  77547. function clonePoint(point, value, minValue, position) {
  77548. point = utils.clone(point);
  77549. point.value = value;
  77550. point.minValue = minValue;
  77551. point.translate();
  77552. point.argument = point.argument + position;
  77553. return point
  77554. }
  77555. function preparePointsForStackedAreaSegment(points) {
  77556. points = $.map(points, function(p) {
  77557. var result = [p];
  77558. if (p.leftHole)
  77559. result = [clonePoint(p, p.leftHole, p.minLeftHole, "left"), p];
  77560. if (p.rightHole)
  77561. result.push(clonePoint(p, p.rightHole, p.minRightHole, "right"));
  77562. return result
  77563. });
  77564. return points
  77565. }
  77566. chartSeries.stackedarea = _extend({}, areaSeries, baseStackedSeries, {_prepareSegment: function(points, rotated) {
  77567. return areaSeries._prepareSegment.call(this, preparePointsForStackedAreaSegment(points, this._prevSeries), rotated)
  77568. }});
  77569. function getPointsByArgFromPrevSeries(prevSeries, argument) {
  77570. var result;
  77571. while (prevSeries) {
  77572. result = prevSeries._segmentByArg[argument];
  77573. if (result)
  77574. break;
  77575. prevSeries = prevSeries._prevSeries
  77576. }
  77577. return result
  77578. }
  77579. chartSeries.stackedsplinearea = _extend({}, chartSeries.splinearea, baseStackedSeries, {_prepareSegment: function(points, rotated) {
  77580. var that = this,
  77581. areaSegment;
  77582. points = preparePointsForStackedAreaSegment(points, that._prevSeries);
  77583. if (!this._prevSeries || points.length === 1)
  77584. areaSegment = chartSeries.splinearea._prepareSegment.call(this, points, rotated);
  77585. else {
  77586. var fwPoints = chartSeries.spline._calculateBezierPoints(points, rotated),
  77587. bwPoints = $.map(points, function(p) {
  77588. var point = p.getCoords(true);
  77589. point.argument = p.argument;
  77590. return point
  77591. }),
  77592. prevSeriesFwPoints = $.map(that._prevSeries._segments, function(seg) {
  77593. return seg.line
  77594. }),
  77595. pointByArg = {};
  77596. $.each(prevSeriesFwPoints, function(_, p) {
  77597. if (p.argument !== null) {
  77598. var argument = p.argument.valueOf();
  77599. if (!pointByArg[argument])
  77600. pointByArg[argument] = [p];
  77601. else
  77602. pointByArg[argument].push(p)
  77603. }
  77604. });
  77605. that._prevSeries._segmentByArg = pointByArg;
  77606. bwPoints = chartSeries.spline._calculateBezierPoints(bwPoints, rotated);
  77607. $.each(bwPoints, function(i, p) {
  77608. var argument = p.argument.valueOf(),
  77609. prevSeriesPoints;
  77610. if (i % 3 === 0) {
  77611. prevSeriesPoints = pointByArg[argument] || getPointsByArgFromPrevSeries(that._prevSeries, argument);
  77612. if (prevSeriesPoints) {
  77613. bwPoints[i - 1] && prevSeriesPoints[0] && (bwPoints[i - 1] = prevSeriesPoints[0]);
  77614. bwPoints[i + 1] && (bwPoints[i + 1] = prevSeriesPoints[2] || p)
  77615. }
  77616. }
  77617. });
  77618. areaSegment = {
  77619. line: fwPoints,
  77620. area: fwPoints.concat(bwPoints.reverse())
  77621. };
  77622. that._areaPointsToSplineAreaPoints(areaSegment.area)
  77623. }
  77624. return areaSegment
  77625. }});
  77626. chartSeries.fullstackedarea = _extend({}, areaSeries, baseFullStackedSeries, {_prepareSegment: chartSeries.stackedarea._prepareSegment});
  77627. chartSeries.fullstackedsplinearea = _extend({}, chartSeries.splinearea, baseFullStackedSeries, {_prepareSegment: chartSeries.stackedsplinearea._prepareSegment});
  77628. polarSeries.stackedbar = _extend({}, polarSeries.bar, baseStackedSeries, {_getRangeData: function() {
  77629. this._processStackedRange();
  77630. return polarSeries.bar._getRangeData.apply(this, arguments)
  77631. }})
  77632. })(jQuery, DevExpress);
  77633. /*! Module viz-core, file basePoint.js */
  77634. (function($, DX) {
  77635. var seriesNS = DX.viz.core.series,
  77636. statesConsts = seriesNS.helpers.consts.states,
  77637. _each = $.each,
  77638. _extend = $.extend,
  77639. _isDefined = DX.utils.isDefined,
  77640. seiresMixins = seriesNS.mixins,
  77641. _noop = $.noop;
  77642. function Point() {
  77643. this.ctor.apply(this, arguments)
  77644. }
  77645. seriesNS.points = {Point: Point};
  77646. Point.prototype = {
  77647. ctor: function(series, dataItem, options) {
  77648. this.series = series;
  77649. this.update(dataItem, options);
  77650. this._emptySettings = {
  77651. fill: null,
  77652. stroke: null,
  77653. dashStyle: null
  77654. }
  77655. },
  77656. getColor: function() {
  77657. return this._styles.normal.fill || this.series.getColor()
  77658. },
  77659. _getStyle: function() {
  77660. var that = this,
  77661. styles = that._styles,
  77662. style;
  77663. if (that.isSelected())
  77664. style = styles.selection;
  77665. else if (that.isHovered())
  77666. style = styles.hover;
  77667. else {
  77668. that.fullState = statesConsts.normalMark;
  77669. style = styles.normal
  77670. }
  77671. that._currentStyle = style;
  77672. return style
  77673. },
  77674. update: function(dataItem, options) {
  77675. this.updateOptions(options);
  77676. this.updateData(dataItem)
  77677. },
  77678. updateData: function(dataItem) {
  77679. var that = this;
  77680. that.argument = that.initialArgument = that.originalArgument = dataItem.argument;
  77681. that.tag = dataItem.tag;
  77682. that.index = dataItem.index;
  77683. that.lowError = dataItem.lowError;
  77684. that.highError = dataItem.highError;
  77685. that._updateData(dataItem);
  77686. !that.hasValue() && that.setInvisibility();
  77687. that._fillStyle();
  77688. that._updateLabelData()
  77689. },
  77690. deleteMarker: function() {
  77691. var that = this;
  77692. if (that.graphic)
  77693. that.graphic.dispose();
  77694. that.graphic = null
  77695. },
  77696. _drawErrorBar: _noop,
  77697. draw: function(renderer, groups, animationEnabled, firstDrawing) {
  77698. var that = this;
  77699. if (that._needDeletingOnDraw) {
  77700. that.deleteMarker();
  77701. that._needDeletingOnDraw = false
  77702. }
  77703. if (that._needClearingOnDraw) {
  77704. that.clearMarker();
  77705. that._needClearingOnDraw = false
  77706. }
  77707. if (!that._hasGraphic())
  77708. that._getMarkerVisibility() && that._drawMarker(renderer, groups.markers, animationEnabled, firstDrawing);
  77709. else
  77710. that._updateMarker(animationEnabled, undefined, groups.markers);
  77711. that._drawLabel(renderer, groups.labels);
  77712. that._drawErrorBar(renderer, groups.errorBars, animationEnabled)
  77713. },
  77714. applyStyle: function(style) {
  77715. var that = this;
  77716. if (that.graphic) {
  77717. if (style === "normal") {
  77718. if (that.isHovered()) {
  77719. that.applyStyle("hover");
  77720. return
  77721. }
  77722. that.clearMarker()
  77723. }
  77724. else
  77725. that.graphic.toForeground();
  77726. that._currentStyle = that._styles[style];
  77727. that._updateMarker(true, that._currentStyle)
  77728. }
  77729. },
  77730. setHoverState: function() {
  77731. this.series.setPointHoverState(this)
  77732. },
  77733. releaseHoverState: function(callback) {
  77734. var that = this;
  77735. that.series.releasePointHoverState(that, callback);
  77736. if (that.graphic)
  77737. !that.isSelected() && that.graphic.toBackground()
  77738. },
  77739. setSelectedState: function() {
  77740. this.series.setPointSelectedState(this)
  77741. },
  77742. releaseSelectedState: function() {
  77743. this.series.releasePointSelectedState(this)
  77744. },
  77745. select: function() {
  77746. this.series.selectPoint(this)
  77747. },
  77748. clearSelection: function() {
  77749. this.series.deselectPoint(this)
  77750. },
  77751. showTooltip: function() {
  77752. this.series.showPointTooltip(this)
  77753. },
  77754. hideTooltip: function() {
  77755. this.series.hidePointTooltip(this)
  77756. },
  77757. _checkLabelsChanging: function(oldType, newType) {
  77758. if (oldType) {
  77759. var isNewRange = ~newType.indexOf("range"),
  77760. isOldRange = ~oldType.indexOf("range");
  77761. return isOldRange && !isNewRange || !isOldRange && isNewRange
  77762. }
  77763. else
  77764. return false
  77765. },
  77766. updateOptions: function(newOptions) {
  77767. if (!_isDefined(newOptions))
  77768. return;
  77769. var that = this,
  77770. oldOptions = that._options,
  77771. widgetType = newOptions.widgetType,
  77772. oldType = oldOptions && oldOptions.type,
  77773. newType = newOptions.type;
  77774. if (seiresMixins[widgetType].pointTypes[oldType] !== seiresMixins[widgetType].pointTypes[newType]) {
  77775. that._needDeletingOnDraw = true;
  77776. that._needClearingOnDraw = false;
  77777. that._checkLabelsChanging(oldType, newType) && that.deleteLabel();
  77778. that._resetType(oldType, widgetType);
  77779. that._setType(newType, widgetType)
  77780. }
  77781. else {
  77782. that._needDeletingOnDraw = that._checkSymbol(oldOptions, newOptions);
  77783. that._needClearingOnDraw = that._checkCustomize(oldOptions, newOptions)
  77784. }
  77785. that._options = newOptions;
  77786. that._fillStyle();
  77787. that._updateLabelOptions(seiresMixins[widgetType].pointTypes[newType])
  77788. },
  77789. translate: function(translators) {
  77790. var that = this;
  77791. that.translators = translators || that.translators;
  77792. that.translators && that.hasValue() && that._translate(that.translators)
  77793. },
  77794. _checkCustomize: function(oldOptions, newOptions) {
  77795. return oldOptions.styles.usePointCustomOptions && !newOptions.styles.usePointCustomOptions
  77796. },
  77797. _getCustomLabelVisibility: function() {
  77798. return this._styles.useLabelCustomOptions ? !!this._options.label.visible : null
  77799. },
  77800. getBoundingRect: function() {
  77801. return this._getGraphicBbox()
  77802. },
  77803. _resetType: function(type, widgetType) {
  77804. var that = this;
  77805. if (type)
  77806. _each(seriesNS.points.mixins[seiresMixins[widgetType].pointTypes[type]], function(methodName) {
  77807. delete that[methodName]
  77808. })
  77809. },
  77810. _setType: function(type, widgetType) {
  77811. var that = this;
  77812. _each(seriesNS.points.mixins[seiresMixins[widgetType].pointTypes[type]], function(methodName, method) {
  77813. that[methodName] = method
  77814. })
  77815. },
  77816. isInVisibleArea: function() {
  77817. return this.inVisibleArea
  77818. },
  77819. isSelected: function() {
  77820. return !!(this.fullState & statesConsts.selectedMark)
  77821. },
  77822. isHovered: function() {
  77823. return !!(this.fullState & statesConsts.hoverMark)
  77824. },
  77825. getOptions: function() {
  77826. return this._options
  77827. },
  77828. animate: function(complete, settings, partitionDuration) {
  77829. if (!this.graphic) {
  77830. complete && complete();
  77831. return
  77832. }
  77833. this.graphic.animate(settings, {partitionDuration: partitionDuration}, complete)
  77834. },
  77835. getCoords: function(min) {
  77836. var that = this;
  77837. if (!min)
  77838. return {
  77839. x: that.x,
  77840. y: that.y
  77841. };
  77842. if (!that._options.rotated)
  77843. return {
  77844. x: that.x,
  77845. y: that.minY
  77846. };
  77847. return {
  77848. x: that.minX,
  77849. y: that.y
  77850. }
  77851. },
  77852. getDefaultCoords: function() {
  77853. var that = this;
  77854. return !that._options.rotated ? {
  77855. x: that.x,
  77856. y: that.defaultY
  77857. } : {
  77858. x: that.defaultX,
  77859. y: that.y
  77860. }
  77861. },
  77862. _calculateVisibility: function(x, y, width, height) {
  77863. var that = this,
  77864. visibleAreaX,
  77865. visibleAreaY,
  77866. rotated = that._options.rotated;
  77867. if (that.translators) {
  77868. visibleAreaX = that.translators.x.getCanvasVisibleArea();
  77869. visibleAreaY = that.translators.y.getCanvasVisibleArea();
  77870. if (visibleAreaX.min > x + (width || 0) || visibleAreaX.max < x || visibleAreaY.min > y + (height || 0) || visibleAreaY.max < y || rotated && _isDefined(width) && width !== 0 && (visibleAreaX.min === x + width || visibleAreaX.max === x) || !rotated && _isDefined(height) && height !== 0 && (visibleAreaY.min === y + height || visibleAreaY.max === y))
  77871. that.inVisibleArea = false;
  77872. else
  77873. that.inVisibleArea = true
  77874. }
  77875. },
  77876. correctPosition: _noop,
  77877. hasValue: function() {
  77878. return this.value !== null && this.minValue !== null
  77879. },
  77880. getBoundaryCoords: function() {
  77881. return this.getBoundingRect()
  77882. },
  77883. getCrosshairCoords: _noop,
  77884. getPointRadius: _noop,
  77885. _populatePointShape: _noop,
  77886. _checkSymbol: _noop,
  77887. getMarkerCoords: _noop,
  77888. hide: _noop,
  77889. show: _noop,
  77890. hideMarker: _noop,
  77891. setInvisibility: _noop,
  77892. clearVisibility: _noop,
  77893. isVisible: _noop,
  77894. resetCorrection: _noop,
  77895. correctValue: _noop,
  77896. setPercentValue: _noop,
  77897. correctCoordinates: _noop,
  77898. coordsIn: _noop,
  77899. getTooltipParams: _noop,
  77900. setLabelEllipsis: _noop,
  77901. updateLabelCoord: _noop,
  77902. drawLabel: _noop,
  77903. dispose: function() {
  77904. var that = this;
  77905. that.deleteMarker();
  77906. that.deleteLabel();
  77907. that._errorBar && this._errorBar.dispose();
  77908. that._options = that._styles = that.series = that.translators = that._errorBar = null
  77909. },
  77910. getTooltipFormatObject: function(tooltip) {
  77911. var that = this,
  77912. tooltipFormatObject = that._getFormatObject(tooltip),
  77913. sharedTooltipValuesArray = [],
  77914. tooltipStackPointsFormatObject = [];
  77915. if (that.stackPoints) {
  77916. _each(that.stackPoints, function(_, point) {
  77917. if (!point.isVisible())
  77918. return;
  77919. var formatObject = point._getFormatObject(tooltip);
  77920. tooltipStackPointsFormatObject.push(formatObject);
  77921. sharedTooltipValuesArray.push(formatObject.seriesName + ": " + formatObject.valueText)
  77922. });
  77923. _extend(tooltipFormatObject, {
  77924. points: tooltipStackPointsFormatObject,
  77925. valueText: sharedTooltipValuesArray.join("\n"),
  77926. stackName: that.stackPoints.stackName
  77927. })
  77928. }
  77929. return tooltipFormatObject
  77930. },
  77931. setHole: function(holeValue, position) {
  77932. var that = this,
  77933. minValue = isFinite(that.minValue) ? that.minValue : 0;
  77934. if (_isDefined(holeValue))
  77935. if (position === "left") {
  77936. that.leftHole = that.value - holeValue;
  77937. that.minLeftHole = minValue - holeValue
  77938. }
  77939. else {
  77940. that.rightHole = that.value - holeValue;
  77941. that.minRightHole = minValue - holeValue
  77942. }
  77943. },
  77944. resetHoles: function() {
  77945. this.leftHole = null;
  77946. this.minLeftHole = null;
  77947. this.rightHole = null;
  77948. this.minRightHole = null
  77949. },
  77950. getLabel: function() {
  77951. return this._label
  77952. }
  77953. }
  77954. })(jQuery, DevExpress);
  77955. /*! Module viz-core, file label.js */
  77956. (function(DX, $, undefined) {
  77957. var _degreesToRadians = DX.utils.degreesToRadians,
  77958. _patchFontOptions = DX.viz.core.utils.patchFontOptions,
  77959. _round = Math.round,
  77960. _abs = Math.abs,
  77961. _min = Math.min,
  77962. _max = Math.max,
  77963. _ceil = Math.ceil,
  77964. _getCosAndSin = DX.utils.getCosAndSin,
  77965. _rotateBBox = DX.viz.renderers.rotateBBox,
  77966. LABEL_BACKGROUND_PADDING_X = 8,
  77967. LABEL_BACKGROUND_PADDING_Y = 4;
  77968. function getClosestCoord(point, coords) {
  77969. var closestDistase = Infinity,
  77970. closestCoord;
  77971. $.each(coords, function(_, coord) {
  77972. var x = point[0] - coord[0],
  77973. y = point[1] - coord[1],
  77974. distance = x * x + y * y;
  77975. if (distance < closestDistase) {
  77976. closestDistase = distance;
  77977. closestCoord = coord
  77978. }
  77979. });
  77980. return closestCoord
  77981. }
  77982. var barPointStrategy = {
  77983. isLabelInside: function(labelPoint, figure) {
  77984. return labelPoint.x >= figure.x && labelPoint.x <= figure.x + figure.width && labelPoint.y >= figure.y && labelPoint.y <= figure.y + figure.height
  77985. },
  77986. prepareLabelPoints: function(points, center, angle, hasBackground) {
  77987. return !hasBackground ? points : [center]
  77988. },
  77989. getFigureCenter: function(figure) {
  77990. return [figure.x + figure.width / 2, figure.y + figure.height / 2]
  77991. },
  77992. findFigurePoint: function(figure, labelPoint) {
  77993. var figureCenter = barPointStrategy.getFigureCenter(figure),
  77994. point = getClosestCoord(labelPoint, [[figure.x, figureCenter[1]], [figureCenter[0], figure.y + figure.height], [figure.x + figure.width, figureCenter[1]], [figureCenter[0], figure.y]]);
  77995. return [_round(point[0]), _round(point[1])]
  77996. }
  77997. };
  77998. var symbolPointStrategy = {
  77999. isLabelInside: function() {
  78000. return false
  78001. },
  78002. prepareLabelPoints: barPointStrategy.prepareLabelPoints,
  78003. getFigureCenter: function(figure) {
  78004. return [figure.x, figure.y]
  78005. },
  78006. findFigurePoint: function(figure, labelPoint) {
  78007. var angle = Math.atan2(figure.y - labelPoint[1], labelPoint[0] - figure.x);
  78008. return [_round(figure.x + figure.r * Math.cos(angle)), _round(figure.y - figure.r * Math.sin(angle))]
  78009. }
  78010. };
  78011. var piePointStrategy = {
  78012. isLabelInside: function(_0, _1, isOutside) {
  78013. return !isOutside
  78014. },
  78015. prepareLabelPoints: function(points, center, angle) {
  78016. var rotatedPoints = [],
  78017. x0 = center[0],
  78018. y0 = center[1],
  78019. cossin = _getCosAndSin(angle || 0);
  78020. $.each(points, function(_, point) {
  78021. rotatedPoints.push([_round((point[0] - x0) * cossin.cos + (point[1] - y0) * cossin.sin + x0), _round(-(point[0] - x0) * cossin.sin + (point[1] - y0) * cossin.cos + y0)])
  78022. });
  78023. return rotatedPoints
  78024. },
  78025. getFigureCenter: symbolPointStrategy.getFigureCenter,
  78026. findFigurePoint: function(figure, labelPoint) {
  78027. var x = figure.x + (figure.y - labelPoint[1]) / Math.tan(_degreesToRadians(figure.angle)),
  78028. point = [figure.x, figure.y];
  78029. if (figure.x <= x && x <= labelPoint[0] || figure.x >= x && x >= labelPoint[0])
  78030. point.push(_round(x), labelPoint[1]);
  78031. return point
  78032. }
  78033. };
  78034. function selectStrategy(figure) {
  78035. return figure.angle !== undefined && piePointStrategy || figure.r !== undefined && symbolPointStrategy || barPointStrategy
  78036. }
  78037. function disposeItem(obj, field) {
  78038. obj[field] && obj[field].dispose();
  78039. obj[field] = null
  78040. }
  78041. function checkBackground(background) {
  78042. return background && (background.fill && background.fill !== "none" || background["stroke-width"] > 0 && background.stroke && background.stroke !== "none")
  78043. }
  78044. function checkConnector(connector) {
  78045. return connector && connector["stroke-width"] > 0 && connector.stroke && connector.stroke !== "none"
  78046. }
  78047. function formatValue(value, format, precision) {
  78048. return DX.formatHelper.format(value, format, precision)
  78049. }
  78050. function formatText(data, options) {
  78051. var format = options.format,
  78052. precision = options.precision;
  78053. data.valueText = formatValue(data.value, format, precision);
  78054. data.argumentText = formatValue(data.argument, options.argumentFormat, options.argumentPrecision);
  78055. if (data.percent !== undefined)
  78056. data.percentText = formatValue(data.percent, "percent", options.percentPrecision);
  78057. if (data.total !== undefined)
  78058. data.totalText = formatValue(data.total, format, precision);
  78059. if (data.openValue !== undefined)
  78060. data.openValueText = formatValue(data.openValue, format, precision);
  78061. if (data.closeValue !== undefined)
  78062. data.closeValueText = formatValue(data.closeValue, format, precision);
  78063. if (data.lowValue !== undefined)
  78064. data.lowValueText = formatValue(data.lowValue, format, precision);
  78065. if (data.highValue !== undefined)
  78066. data.highValueText = formatValue(data.highValue, format, precision);
  78067. if (data.reductionValue !== undefined)
  78068. data.reductionValueText = formatValue(data.reductionValue, format, precision);
  78069. return options.customizeText ? options.customizeText.call(data, data) : data.valueText
  78070. }
  78071. function Label(){}
  78072. Label.prototype = {
  78073. constructor: Label,
  78074. _setVisibility: function(value, state) {
  78075. this._group && this._group.attr({visibility: value});
  78076. this._visible = state
  78077. },
  78078. clearVisibility: function() {
  78079. this._setVisibility(null, true)
  78080. },
  78081. hide: function() {
  78082. this._setVisibility("hidden", false)
  78083. },
  78084. show: function() {
  78085. this._setVisibility("visible", true)
  78086. },
  78087. isVisible: function() {
  78088. return this._visible
  78089. },
  78090. setColor: function(color) {
  78091. this._color = color
  78092. },
  78093. setOptions: function(options) {
  78094. this._options = options
  78095. },
  78096. setData: function(data) {
  78097. this._data = data
  78098. },
  78099. setDataField: function(fieldName, fieldValue) {
  78100. this._data = this._data || {};
  78101. this._data[fieldName] = fieldValue
  78102. },
  78103. getData: function() {
  78104. return this._data
  78105. },
  78106. setFigureToDrawConnector: function(figure) {
  78107. this._figure = figure
  78108. },
  78109. dispose: function() {
  78110. var that = this;
  78111. disposeItem(that, "_group");
  78112. that._data = that._options = that._textContent = that._visible = that._insideGroup = that._text = that._background = that._connector = that._figure = null
  78113. },
  78114. draw: function(renderer, container, customVisibility) {
  78115. var that = this,
  78116. options = that._options || {},
  78117. text = that._textContent = formatText(that._data, that._options) || null;
  78118. that.clearVisibility();
  78119. if (text) {
  78120. if (!that._group) {
  78121. that._group = renderer.g().append(container);
  78122. that._insideGroup = renderer.g().append(that._group);
  78123. that._text = renderer.text("", 0, 0).append(that._insideGroup)
  78124. }
  78125. that._text.css(options.attributes ? _patchFontOptions(options.attributes.font) : {});
  78126. if (checkBackground(options.background)) {
  78127. that._background = that._background || renderer.rect().append(that._insideGroup).toBackground();
  78128. that._background.attr(options.background);
  78129. that._color && that._background.attr({fill: that._color})
  78130. }
  78131. else
  78132. disposeItem(that, "_background");
  78133. if (checkConnector(options.connector)) {
  78134. that._connector = that._connector || renderer.path([], "line").sharp().append(that._group).toBackground();
  78135. that._connector.attr(options.connector);
  78136. that._color && that._connector.attr({stroke: that._color})
  78137. }
  78138. else
  78139. disposeItem(that, "_connector");
  78140. that._updateText(text);
  78141. if (customVisibility !== null)
  78142. customVisibility ? that.show() : that.hide()
  78143. }
  78144. else
  78145. that.hide();
  78146. return that
  78147. },
  78148. _updateText: function(text) {
  78149. var that = this,
  78150. bbox = that._text.attr({text: text}).getBBox();
  78151. that._textSize = [bbox.width, bbox.height];
  78152. if (that._background) {
  78153. bbox.x -= LABEL_BACKGROUND_PADDING_X;
  78154. bbox.y -= LABEL_BACKGROUND_PADDING_Y;
  78155. bbox.width += 2 * LABEL_BACKGROUND_PADDING_X;
  78156. bbox.height += 2 * LABEL_BACKGROUND_PADDING_Y;
  78157. that._background.attr(bbox)
  78158. }
  78159. that._labelSize = [bbox.width / 2, bbox.height / 2];
  78160. if (that._options.rotationAngle) {
  78161. that._insideGroup.rotate(that._options.rotationAngle, bbox.x + bbox.width / 2, bbox.y + bbox.height / 2);
  78162. bbox = _rotateBBox(bbox, [bbox.x + bbox.width / 2, bbox.y + bbox.height / 2], -that._options.rotationAngle)
  78163. }
  78164. that._bbox = bbox
  78165. },
  78166. _getConnectorPoints: function() {
  78167. var that = this,
  78168. figure = that._figure,
  78169. strategy = selectStrategy(figure),
  78170. bbox = that.getBoundingRect(),
  78171. labelPoint,
  78172. figurePoint,
  78173. xc,
  78174. yc,
  78175. points = [];
  78176. if (!strategy.isLabelInside(bbox, figure, that._options.position !== "inside")) {
  78177. xc = bbox.x + bbox.width / 2;
  78178. yc = bbox.y + bbox.height / 2;
  78179. points = strategy.prepareLabelPoints([[xc, yc - that._labelSize[1]], [xc + that._labelSize[0], yc], [xc, yc + that._labelSize[1]], [xc - that._labelSize[0], yc]], [xc, yc], -that._options.rotationAngle || 0, !!that._background);
  78180. labelPoint = getClosestCoord(strategy.getFigureCenter(figure), points);
  78181. labelPoint = [_round(labelPoint[0]), _round(labelPoint[1])];
  78182. figurePoint = strategy.findFigurePoint(figure, labelPoint);
  78183. points = figurePoint.concat(labelPoint)
  78184. }
  78185. return points
  78186. },
  78187. fit: function(size) {
  78188. var that = this;
  78189. if (!that._textContent)
  78190. return that;
  78191. var cossin = _getCosAndSin(-that._options.rotationAngle || 0),
  78192. textSize = _min(_abs(that._textSize[0] / cossin.cos), _abs(that._textSize[1] / cossin.sin)),
  78193. requiredTextSize = _min(_abs(size.width / cossin.cos), _abs(size.height / cossin.sin)),
  78194. text = that._textContent,
  78195. i,
  78196. ii,
  78197. line,
  78198. lines,
  78199. lineLength,
  78200. requiredLineLength;
  78201. if (textSize > requiredTextSize) {
  78202. lines = text.split("<br/>");
  78203. for (i = 0, ii = lines.length, lineLength = 0; i < ii; ++i) {
  78204. line = lines[i] = lines[i].replace(/<[^>]+>/g, '');
  78205. lineLength = _max(lineLength, line.length)
  78206. }
  78207. requiredLineLength = _ceil(lineLength * requiredTextSize / textSize);
  78208. for (i = 0; i < ii; ++i)
  78209. lines[i] = (line = lines[i]).length > requiredLineLength ? line.substr(0, requiredLineLength - 4) + "..." : line;
  78210. text = lines.join("<br/>")
  78211. }
  78212. that._updateText(text);
  78213. return that
  78214. },
  78215. shift: function(x, y) {
  78216. var that = this;
  78217. if (that._textContent) {
  78218. that._insideGroup.attr({
  78219. translateX: that._x = _round(x - that._bbox.x),
  78220. translateY: that._y = _round(y - that._bbox.y)
  78221. });
  78222. if (that._connector)
  78223. that._connector.attr({points: that._getConnectorPoints()})
  78224. }
  78225. return that
  78226. },
  78227. getBoundingRect: function() {
  78228. var bbox = this._bbox;
  78229. return this._textContent ? {
  78230. x: bbox.x + this._x,
  78231. y: bbox.y + this._y,
  78232. width: bbox.width,
  78233. height: bbox.height
  78234. } : {}
  78235. },
  78236. getLayoutOptions: function() {
  78237. var options = this._options;
  78238. return {
  78239. alignment: options.alignment,
  78240. background: checkBackground(options.background),
  78241. horizontalOffset: options.horizontalOffset,
  78242. verticalOffset: options.verticalOffset,
  78243. radialOffset: options.radialOffset,
  78244. position: options.position
  78245. }
  78246. }
  78247. };
  78248. DX.viz.core.series.points.Label = Label;
  78249. Label._DEBUG_formatText = formatText
  78250. })(DevExpress, jQuery);
  78251. /*! Module viz-core, file symbolPoint.js */
  78252. (function($, DX) {
  78253. var core = DX.viz.core,
  78254. seriesNS = core.series,
  78255. _extend = $.extend,
  78256. _isDefined = DX.utils.isDefined,
  78257. _math = Math,
  78258. _round = _math.round,
  78259. _floor = _math.floor,
  78260. _ceil = _math.ceil,
  78261. _abs = _math.abs,
  78262. DEFAULT_IMAGE_WIDTH = 20,
  78263. DEFAULT_IMAGE_HEIGHT = 20,
  78264. LABEL_OFFSET = 10,
  78265. CANVAS_POSITION_DEFAULT = "canvas_position_default";
  78266. function getSquareMarkerCoords(radius) {
  78267. return [-radius, -radius, radius, -radius, radius, radius, -radius, radius, -radius, -radius]
  78268. }
  78269. function getPolygonMarkerCoords(radius) {
  78270. var r = _ceil(radius);
  78271. return [-r, 0, 0, -r, r, 0, 0, r, -r, 0]
  78272. }
  78273. function getCrossMarkerCoords(radius) {
  78274. var r = _ceil(radius),
  78275. floorHalfRadius = _floor(r / 2),
  78276. ceilHalfRadius = _ceil(r / 2);
  78277. return [-r, -floorHalfRadius, -floorHalfRadius, -r, 0, -ceilHalfRadius, floorHalfRadius, -r, r, -floorHalfRadius, ceilHalfRadius, 0, r, floorHalfRadius, floorHalfRadius, r, 0, ceilHalfRadius, -floorHalfRadius, r, -r, floorHalfRadius, -ceilHalfRadius, 0]
  78278. }
  78279. function getTriangleDownMarkerCoords(radius) {
  78280. return [-radius, -radius, radius, -radius, 0, radius, -radius, -radius]
  78281. }
  78282. function getTriangleUpMarkerCoords(radius) {
  78283. return [-radius, radius, radius, radius, 0, -radius, -radius, radius]
  78284. }
  78285. seriesNS.points.mixins = seriesNS.points.mixins || {};
  78286. seriesNS.points.mixins.symbolPoint = {
  78287. deleteLabel: function() {
  78288. this._label.dispose();
  78289. this._label = null
  78290. },
  78291. _hasGraphic: function() {
  78292. return this.graphic
  78293. },
  78294. clearVisibility: function() {
  78295. var that = this,
  78296. graphic = that.graphic;
  78297. if (graphic && graphic.attr("visibility"))
  78298. graphic.attr({visibility: null});
  78299. that._label.clearVisibility()
  78300. },
  78301. isVisible: function() {
  78302. return this.inVisibleArea && this.series.isVisible()
  78303. },
  78304. setInvisibility: function() {
  78305. var that = this,
  78306. graphic = that.graphic;
  78307. if (graphic && graphic.attr("visibility") !== "hidden")
  78308. graphic.attr({visibility: "hidden"});
  78309. that._errorBar && that._errorBar.attr({visibility: "hidden"});
  78310. that._label.hide()
  78311. },
  78312. clearMarker: function() {
  78313. var graphic = this.graphic;
  78314. graphic && graphic.attr(this._emptySettings)
  78315. },
  78316. setAdjustSeriesLabels: function(adjustSeriesLabels) {
  78317. this.adjustSeriesLabels = adjustSeriesLabels
  78318. },
  78319. _createLabel: function() {
  78320. this._label = core.CoreFactory.createLabel()
  78321. },
  78322. _updateLabelData: function() {
  78323. this._label.setData(this._getLabelFormatObject())
  78324. },
  78325. _updateLabelOptions: function() {
  78326. !this._label && this._createLabel();
  78327. this._label.setOptions(this._options.label)
  78328. },
  78329. _checkImage: function(image) {
  78330. return _isDefined(image) && (typeof image === "string" || _isDefined(image.url))
  78331. },
  78332. _fillStyle: function() {
  78333. this._styles = this._options.styles
  78334. },
  78335. _checkSymbol: function(oldOptions, newOptions) {
  78336. var oldSymbol = oldOptions.symbol,
  78337. newSymbol = newOptions.symbol,
  78338. symbolChanged = oldSymbol === "circle" && newSymbol !== "circle" || oldSymbol !== "circle" && newSymbol === "circle",
  78339. imageChanged = this._checkImage(oldOptions.image) !== this._checkImage(newOptions.image);
  78340. return !!(symbolChanged || imageChanged)
  78341. },
  78342. _populatePointShape: function(symbol, radius) {
  78343. switch (symbol) {
  78344. case"square":
  78345. return getSquareMarkerCoords(radius);
  78346. case"polygon":
  78347. return getPolygonMarkerCoords(radius);
  78348. case"triangle":
  78349. case"triangleDown":
  78350. return getTriangleDownMarkerCoords(radius);
  78351. case"triangleUp":
  78352. return getTriangleUpMarkerCoords(radius);
  78353. case"cross":
  78354. return getCrossMarkerCoords(radius)
  78355. }
  78356. },
  78357. correctValue: function(correction) {
  78358. var that = this;
  78359. if (that.hasValue()) {
  78360. that.value = that.initialValue + correction;
  78361. that.minValue = correction;
  78362. that.translate()
  78363. }
  78364. },
  78365. resetCorrection: function() {
  78366. this.value = this.initialValue;
  78367. this.minValue = CANVAS_POSITION_DEFAULT
  78368. },
  78369. _getTranslates: function(animationEnabled) {
  78370. var translateX = this.x,
  78371. translateY = this.y;
  78372. if (animationEnabled)
  78373. if (this._options.rotated)
  78374. translateX = this.defaultX;
  78375. else
  78376. translateY = this.defaultY;
  78377. return {
  78378. x: translateX,
  78379. y: translateY
  78380. }
  78381. },
  78382. _createImageMarker: function(renderer, settings, options) {
  78383. var width = options.width || DEFAULT_IMAGE_WIDTH,
  78384. height = options.height || DEFAULT_IMAGE_HEIGHT;
  78385. return renderer.image(-_round(width * 0.5), -_round(height * 0.5), width, height, options.url ? options.url.toString() : options.toString(), "center").attr({
  78386. translateX: settings.translateX,
  78387. translateY: settings.translateY,
  78388. visibility: settings.visibility
  78389. })
  78390. },
  78391. _createSymbolMarker: function(renderer, pointSettings) {
  78392. var marker,
  78393. options = this._options;
  78394. switch (options.symbol) {
  78395. case"circle":
  78396. delete pointSettings.points;
  78397. marker = renderer.circle().attr(pointSettings);
  78398. break;
  78399. case"square":
  78400. case"polygon":
  78401. case"triangle":
  78402. case"triangleDown":
  78403. case"triangleUp":
  78404. case"cross":
  78405. marker = renderer.path([], "area").attr(pointSettings).sharp();
  78406. break
  78407. }
  78408. return marker
  78409. },
  78410. _createMarker: function(renderer, group, image, settings, animationEnabled) {
  78411. var that = this,
  78412. marker = that._checkImage(image) ? that._createImageMarker(renderer, settings, image) : that._createSymbolMarker(renderer, settings, animationEnabled);
  78413. if (marker)
  78414. marker.data({point: that}).append(group);
  78415. return marker
  78416. },
  78417. _getSymbolBbox: function(x, y, r) {
  78418. return {
  78419. x: x - r,
  78420. y: y - r,
  78421. width: r * 2,
  78422. height: r * 2
  78423. }
  78424. },
  78425. _getImageBbox: function(x, y) {
  78426. var image = this._options.image,
  78427. width = image.width || DEFAULT_IMAGE_WIDTH,
  78428. height = image.height || DEFAULT_IMAGE_HEIGHT;
  78429. return {
  78430. x: x - _round(width / 2),
  78431. y: y - _round(height / 2),
  78432. width: width,
  78433. height: height
  78434. }
  78435. },
  78436. _getGraphicBbox: function() {
  78437. var that = this,
  78438. options = that._options,
  78439. x = that.x,
  78440. y = that.y,
  78441. bbox;
  78442. if (options.visible)
  78443. bbox = that._checkImage(options.image) ? that._getImageBbox(x, y) : that._getSymbolBbox(x, y, options.styles.normal.r);
  78444. else
  78445. bbox = {
  78446. x: x,
  78447. y: y,
  78448. width: 0,
  78449. height: 0
  78450. };
  78451. return bbox
  78452. },
  78453. _getVisibleArea: function() {
  78454. var translators = this.translators,
  78455. visibleX,
  78456. visibleY;
  78457. if (translators) {
  78458. visibleX = translators.x.getCanvasVisibleArea();
  78459. visibleY = translators.y.getCanvasVisibleArea();
  78460. return {
  78461. minX: visibleX.min,
  78462. maxX: visibleX.max,
  78463. minY: visibleY.min,
  78464. maxY: visibleY.max
  78465. }
  78466. }
  78467. },
  78468. _isLabelInsidePoint: $.noop,
  78469. _getShiftLabelCoords: function(label) {
  78470. var coord = this._addLabelAlignmentAndOffset(label, this._getLabelCoords(label));
  78471. return this._checkLabelPosition(label, coord)
  78472. },
  78473. _drawLabel: function(renderer, group) {
  78474. var that = this,
  78475. customVisibility = that._getCustomLabelVisibility(),
  78476. coord,
  78477. label = that._label;
  78478. if ((that.series.getLabelVisibility() || customVisibility !== null) && that.hasValue() && that._showForZeroValues()) {
  78479. label.draw(renderer, group, customVisibility);
  78480. if (!that._isLabelInsidePoint(label)) {
  78481. coord = that._getShiftLabelCoords(label);
  78482. label.setFigureToDrawConnector(that._getLabelConnector());
  78483. label.shift(_round(coord.x), _round(coord.y))
  78484. }
  78485. }
  78486. else
  78487. label.hide()
  78488. },
  78489. _showForZeroValues: function() {
  78490. return true
  78491. },
  78492. _getLabelConnector: function() {
  78493. var bbox = this._getGraphicBbox(),
  78494. w2 = bbox.width / 2,
  78495. h2 = bbox.height / 2;
  78496. return {
  78497. x: bbox.x + w2,
  78498. y: bbox.y + h2,
  78499. r: this._options.visible ? Math.max(w2, h2) : 0
  78500. }
  78501. },
  78502. _getPositionFromLocation: function() {
  78503. return {
  78504. x: this.x,
  78505. y: this.y
  78506. }
  78507. },
  78508. _isPointInVisibleArea: function(visibleArea, graphicBbox) {
  78509. return visibleArea.minX <= graphicBbox.x + graphicBbox.width && visibleArea.maxX >= graphicBbox.x && visibleArea.minY <= graphicBbox.y + graphicBbox.height && visibleArea.maxY >= graphicBbox.y
  78510. },
  78511. _checkLabelPosition: function(label, coord, pointPosition) {
  78512. var that = this,
  78513. visibleArea = that._getVisibleArea(),
  78514. labelBbox = label.getBoundingRect(),
  78515. graphicBbox = that._getGraphicBbox(pointPosition),
  78516. offset = LABEL_OFFSET;
  78517. if (that._isPointInVisibleArea(visibleArea, graphicBbox))
  78518. if (!that._options.rotated) {
  78519. if (visibleArea.minX > coord.x && that.adjustSeriesLabels)
  78520. coord.x = visibleArea.minX;
  78521. if (visibleArea.maxX < coord.x + labelBbox.width && that.adjustSeriesLabels)
  78522. coord.x = visibleArea.maxX - labelBbox.width;
  78523. if (visibleArea.minY > coord.y)
  78524. coord.y = graphicBbox.y + graphicBbox.height + offset;
  78525. if (visibleArea.maxY < coord.y + labelBbox.height)
  78526. coord.y = graphicBbox.y - labelBbox.height - offset
  78527. }
  78528. else {
  78529. if (visibleArea.minX > coord.x)
  78530. coord.x = graphicBbox.x + graphicBbox.width + offset;
  78531. if (visibleArea.maxX < coord.x + labelBbox.width)
  78532. coord.x = graphicBbox.x - offset - labelBbox.width;
  78533. if (visibleArea.minY > coord.y && that.adjustSeriesLabels)
  78534. coord.y = visibleArea.minY;
  78535. if (visibleArea.maxY < coord.y + labelBbox.height && that.adjustSeriesLabels)
  78536. coord.y = visibleArea.maxY - labelBbox.height
  78537. }
  78538. return coord
  78539. },
  78540. _addLabelAlignmentAndOffset: function(label, coord) {
  78541. var labelBBox = label.getBoundingRect(),
  78542. labelOptions = label.getLayoutOptions();
  78543. if (!this._options.rotated)
  78544. if (labelOptions.alignment === "left")
  78545. coord.x += labelBBox.width / 2;
  78546. else if (labelOptions.alignment === "right")
  78547. coord.x -= labelBBox.width / 2;
  78548. coord.x += labelOptions.horizontalOffset;
  78549. coord.y += labelOptions.verticalOffset;
  78550. return coord
  78551. },
  78552. _getLabelCoords: function(label, pointPosition) {
  78553. return this._getLabelCoordOfPosition(label, this._getLabelPosition(pointPosition), pointPosition)
  78554. },
  78555. _getLabelCoordOfPosition: function(label, position, pointPosition) {
  78556. var that = this,
  78557. labelBBox = label.getBoundingRect(),
  78558. graphicBbox = that._getGraphicBbox(pointPosition),
  78559. offset = LABEL_OFFSET,
  78560. centerY = graphicBbox.height / 2 - labelBBox.height / 2,
  78561. centerX = graphicBbox.width / 2 - labelBBox.width / 2,
  78562. x = graphicBbox.x,
  78563. y = graphicBbox.y;
  78564. switch (position) {
  78565. case"left":
  78566. x -= labelBBox.width + offset;
  78567. y += centerY;
  78568. break;
  78569. case"right":
  78570. x += graphicBbox.width + offset;
  78571. y += centerY;
  78572. break;
  78573. case"top":
  78574. x += centerX;
  78575. y -= labelBBox.height + offset;
  78576. break;
  78577. case"bottom":
  78578. x += centerX;
  78579. y += graphicBbox.height + offset;
  78580. break;
  78581. case"inside":
  78582. x += centerX;
  78583. y += centerY;
  78584. break
  78585. }
  78586. return {
  78587. x: x,
  78588. y: y
  78589. }
  78590. },
  78591. _drawMarker: function(renderer, group, animationEnabled) {
  78592. var that = this,
  78593. options = that._options,
  78594. translates = that._getTranslates(animationEnabled),
  78595. style = that._getStyle();
  78596. that.graphic = that._createMarker(renderer, group, options.image, _extend({
  78597. translateX: translates.x,
  78598. translateY: translates.y,
  78599. points: that._populatePointShape(options.symbol, style.r)
  78600. }, style), animationEnabled)
  78601. },
  78602. _getErrorBarSettings: function() {
  78603. return {visibility: "visible"}
  78604. },
  78605. _drawErrorBar: function(renderer, group) {
  78606. var that = this,
  78607. errorBarOptions = that._options.errorBars || {},
  78608. points = [],
  78609. settings,
  78610. pos = that._errorBarPos,
  78611. high = that._highErrorCoord,
  78612. low = that._lowErrorCoord,
  78613. displayMode = (errorBarOptions.displayMode + "").toLowerCase(),
  78614. isHighDisplayMode = displayMode === "high",
  78615. isLowDisplayMode = displayMode === "low",
  78616. edgeLength = _floor(parseInt(errorBarOptions.edgeLength) / 2),
  78617. highErrorOnly = (isHighDisplayMode || !_isDefined(low)) && _isDefined(high) && !isLowDisplayMode,
  78618. lowErrorOnly = (isLowDisplayMode || !_isDefined(high)) && _isDefined(low) && !isHighDisplayMode;
  78619. highErrorOnly && (low = that._baseErrorBarPos);
  78620. lowErrorOnly && (high = that._baseErrorBarPos);
  78621. if (displayMode !== "none" && _isDefined(high) && _isDefined(low) && _isDefined(pos)) {
  78622. !lowErrorOnly && points.push([pos - edgeLength, high, pos + edgeLength, high]);
  78623. points.push([pos, high, pos, low]);
  78624. !highErrorOnly && points.push([pos + edgeLength, low, pos - edgeLength, low]);
  78625. that._options.rotated && $.each(points, function(_, p) {
  78626. p.reverse()
  78627. });
  78628. settings = that._getErrorBarSettings(errorBarOptions);
  78629. if (!that._errorBar)
  78630. that._errorBar = renderer.path(points, "line").attr(settings).append(group);
  78631. else {
  78632. settings.points = points;
  78633. that._errorBar.attr(settings)
  78634. }
  78635. }
  78636. else
  78637. that._errorBar && that._errorBar.attr({visibility: "hidden"})
  78638. },
  78639. getTooltipParams: function() {
  78640. var that = this,
  78641. graphic = that.graphic;
  78642. return {
  78643. x: that.x,
  78644. y: that.y,
  78645. offset: graphic ? graphic.getBBox().height / 2 : 0
  78646. }
  78647. },
  78648. hasValue: function() {
  78649. return this.value !== null && this.minValue !== null
  78650. },
  78651. setPercentValue: function(total, fullStacked, leftHoleTotal, rightHoleTotal) {
  78652. var that = this,
  78653. valuePercent = _abs(that.value / total || 0),
  78654. minValuePercent = _abs(that.minValue / total || 0),
  78655. percent = valuePercent - minValuePercent;
  78656. that._label.setDataField("percent", percent);
  78657. that._label.setDataField("total", total);
  78658. if (that.series.isFullStackedSeries() && that.hasValue()) {
  78659. if (that.leftHole) {
  78660. that.leftHole /= total - leftHoleTotal;
  78661. that.minLeftHole /= total - leftHoleTotal
  78662. }
  78663. if (that.rightHole) {
  78664. that.rightHole /= total - rightHoleTotal;
  78665. that.minRightHole /= total - rightHoleTotal
  78666. }
  78667. that.value = valuePercent;
  78668. that.minValue = !minValuePercent ? that.minValue : minValuePercent;
  78669. that.translate()
  78670. }
  78671. },
  78672. _storeTrackerR: function() {
  78673. var that = this,
  78674. navigator = window.navigator,
  78675. r = that._options.styles.normal.r,
  78676. minTrackerSize;
  78677. navigator = that.__debug_navigator || navigator;
  78678. that.__debug_browserNavigator = navigator;
  78679. minTrackerSize = "ontouchstart" in window || navigator.msPointerEnabled && navigator.msMaxTouchPoints || navigator.pointerEnabled && navigator.maxTouchPoints ? 20 : 6;
  78680. that._options.trackerR = r < minTrackerSize ? minTrackerSize : r;
  78681. return that._options.trackerR
  78682. },
  78683. _translateErrorBars: function(valueTranslator) {
  78684. var that = this,
  78685. options = that._options,
  78686. errorBars = options.errorBars || {};
  78687. _isDefined(that.lowError) && (that._lowErrorCoord = valueTranslator.translate(that.lowError));
  78688. _isDefined(that.highError) && (that._highErrorCoord = valueTranslator.translate(that.highError));
  78689. that._errorBarPos = _floor(that._options.rotated ? that.vy : that.vx);
  78690. that._baseErrorBarPos = errorBars.type === "stdDeviation" ? that._lowErrorCoord + (that._highErrorCoord - that._lowErrorCoord) / 2 : that._options.rotated ? that.vx : that.vy
  78691. },
  78692. _translate: function(translators) {
  78693. var that = this,
  78694. valueAxis = that._options.rotated ? "x" : "y",
  78695. upperValueAxis = valueAxis.toUpperCase(),
  78696. valueTranslator = translators[valueAxis],
  78697. argumentAxis = that._options.rotated ? "y" : "x";
  78698. that["v" + valueAxis] = that[valueAxis] = valueTranslator.translate(that.value);
  78699. that["v" + argumentAxis] = that[argumentAxis] = translators[argumentAxis].translate(that.argument);
  78700. that["min" + upperValueAxis] = valueTranslator.translate(that.minValue);
  78701. that["default" + upperValueAxis] = valueTranslator.translate(CANVAS_POSITION_DEFAULT);
  78702. that._translateErrorBars(valueTranslator);
  78703. that._calculateVisibility(that.x, that.y)
  78704. },
  78705. _updateData: function(data) {
  78706. var that = this;
  78707. that.value = that.initialValue = that.originalValue = data.value;
  78708. that.minValue = that.initialMinValue = that.originalMinValue = _isDefined(data.minValue) ? data.minValue : CANVAS_POSITION_DEFAULT
  78709. },
  78710. _getImageSettings: function(image) {
  78711. return {
  78712. href: image.url || image.toString(),
  78713. width: image.width || DEFAULT_IMAGE_WIDTH,
  78714. height: image.height || DEFAULT_IMAGE_HEIGHT
  78715. }
  78716. },
  78717. getCrosshairCoords: function() {
  78718. return {
  78719. x: this.vx,
  78720. y: this.vy
  78721. }
  78722. },
  78723. getPointRadius: function() {
  78724. var style = this._currentStyle || this._getStyle(),
  78725. options = this._options,
  78726. r = style.r,
  78727. extraSpace,
  78728. symbol = options.symbol,
  78729. isSquare = symbol === "square",
  78730. isTriangle = symbol === "triangle" || symbol === "triangleDown" || symbol === "triangleUp";
  78731. if (options.visible && !options.image && r) {
  78732. extraSpace = style["stroke-width"] / 2;
  78733. return (isSquare || isTriangle ? 1.4 * r : r) + extraSpace
  78734. }
  78735. return 0
  78736. },
  78737. _updateMarker: function(animationEnabled, style) {
  78738. var that = this,
  78739. options = that._options,
  78740. settings,
  78741. image = options.image,
  78742. visibility = !that.isVisible() ? {visibility: "hidden"} : {};
  78743. style = style || that._getStyle();
  78744. if (that._checkImage(image))
  78745. settings = _extend({}, {visibility: style.visibility}, visibility, that._getImageSettings(image));
  78746. else
  78747. settings = _extend({}, style, visibility, {points: that._populatePointShape(options.symbol, style.r)});
  78748. if (!animationEnabled) {
  78749. settings.translateX = that.x;
  78750. settings.translateY = that.y
  78751. }
  78752. that.graphic.attr(settings).sharp()
  78753. },
  78754. _getLabelFormatObject: function() {
  78755. var that = this;
  78756. return {
  78757. argument: that.initialArgument,
  78758. value: that.initialValue,
  78759. originalArgument: that.originalArgument,
  78760. originalValue: that.originalValue,
  78761. seriesName: that.series.name,
  78762. lowErrorValue: that.lowError,
  78763. highErrorValue: that.highError,
  78764. point: that
  78765. }
  78766. },
  78767. _getLabelPosition: function() {
  78768. var rotated = this._options.rotated;
  78769. if (this.series.isFullStackedSeries() || this.initialValue > 0)
  78770. return rotated ? "right" : "top";
  78771. else
  78772. return rotated ? "left" : "bottom"
  78773. },
  78774. _getFormatObject: function(tooltip) {
  78775. var that = this,
  78776. labelFormatObject = that._label.getData();
  78777. return _extend({}, labelFormatObject, {
  78778. argumentText: tooltip.formatValue(that.initialArgument, "argument"),
  78779. valueText: tooltip.formatValue(that.initialValue)
  78780. }, _isDefined(labelFormatObject.percent) ? {percentText: tooltip.formatValue(labelFormatObject.percent, "percent")} : {}, _isDefined(labelFormatObject.total) ? {totalText: tooltip.formatValue(labelFormatObject.total)} : {})
  78781. },
  78782. _getMarkerVisibility: function() {
  78783. return this._options.visible
  78784. },
  78785. coordsIn: function(x, y) {
  78786. var trackerRadius = this._storeTrackerR();
  78787. return x >= this.x - trackerRadius && x <= this.x + trackerRadius && y >= this.y - trackerRadius && y <= this.y + trackerRadius
  78788. }
  78789. }
  78790. })(jQuery, DevExpress);
  78791. /*! Module viz-core, file barPoint.js */
  78792. (function($, DX) {
  78793. var points = DX.viz.core.series.points.mixins,
  78794. _extend = $.extend,
  78795. _math = Math,
  78796. _floor = _math.floor,
  78797. _abs = _math.abs,
  78798. _min = _math.min,
  78799. CANVAS_POSITION_DEFAULT = "canvas_position_default",
  78800. DEFAULT_BAR_TRACKER_SIZE = 9,
  78801. CORRECTING_BAR_TRACKER_VALUE = 4,
  78802. RIGHT = "right",
  78803. LEFT = "left",
  78804. TOP = "top",
  78805. BOTTOM = "bottom";
  78806. points.barPoint = _extend({}, points.symbolPoint, {
  78807. correctCoordinates: function(correctOptions) {
  78808. var correction = _floor(correctOptions.offset - correctOptions.width / 2),
  78809. rotated = this._options.rotated,
  78810. valueSelector = rotated ? "height" : "width",
  78811. correctionSelector = (rotated ? "y" : "x") + "Correction";
  78812. this[valueSelector] = correctOptions.width;
  78813. this[correctionSelector] = correction
  78814. },
  78815. _getGraphicBbox: function() {
  78816. var that = this,
  78817. bbox = {};
  78818. bbox.x = that.x;
  78819. bbox.y = that.y;
  78820. bbox.width = that.width;
  78821. bbox.height = that.height;
  78822. return bbox
  78823. },
  78824. _getLabelConnector: function() {
  78825. return this._getGraphicBbox()
  78826. },
  78827. _getLabelPosition: function() {
  78828. var that = this,
  78829. position,
  78830. translators = that.translators,
  78831. initialValue = that.initialValue,
  78832. invertX = translators.x.getBusinessRange().invert,
  78833. invertY = translators.y.getBusinessRange().invert,
  78834. isDiscreteValue = that.series.valueAxisType === "discrete",
  78835. isFullStacked = that.series.isFullStackedSeries(),
  78836. notVerticalInverted = !isDiscreteValue && (initialValue >= 0 && !invertY || initialValue < 0 && invertY) || isDiscreteValue && !invertY || isFullStacked,
  78837. notHorizontalInverted = !isDiscreteValue && (initialValue >= 0 && !invertX || initialValue < 0 && invertX) || isDiscreteValue && !invertX || isFullStacked;
  78838. if (!that._options.rotated)
  78839. position = notVerticalInverted ? TOP : BOTTOM;
  78840. else
  78841. position = notHorizontalInverted ? RIGHT : LEFT;
  78842. return position
  78843. },
  78844. _getLabelCoords: function(label) {
  78845. var that = this,
  78846. coords;
  78847. if (that.initialValue === 0 && that.series.isFullStackedSeries())
  78848. if (!this._options.rotated)
  78849. coords = that._getLabelCoordOfPosition(label, TOP);
  78850. else
  78851. coords = that._getLabelCoordOfPosition(label, RIGHT);
  78852. else if (label.getLayoutOptions().position === "inside")
  78853. coords = that._getLabelCoordOfPosition(label, "inside");
  78854. else
  78855. coords = points.symbolPoint._getLabelCoords.call(this, label);
  78856. return coords
  78857. },
  78858. _checkLabelPosition: function(label, coord) {
  78859. var that = this,
  78860. visibleArea = that._getVisibleArea(),
  78861. rotated = that._options.rotated,
  78862. graphicBbox = that._getGraphicBbox(),
  78863. labelBbox = label.getBoundingRect();
  78864. if (that._isPointInVisibleArea(visibleArea, graphicBbox))
  78865. return that._moveLabelOnCanvas(coord, visibleArea, labelBbox, that.adjustSeriesLabels || rotated, that.adjustSeriesLabels || !rotated);
  78866. return coord
  78867. },
  78868. _isLabelInsidePoint: function(label) {
  78869. var that = this,
  78870. graphicBbox = that._getGraphicBbox(),
  78871. labelBbox = label.getBoundingRect();
  78872. if (that._options.resolveLabelsOverlapping && label.getLayoutOptions().position === "inside")
  78873. if (labelBbox.width > graphicBbox.width || labelBbox.height > graphicBbox.height) {
  78874. label.hide();
  78875. return true
  78876. }
  78877. return false
  78878. },
  78879. _moveLabelOnCanvas: function(coord, visibleArea, labelBbox, horizontalAdjust, verticalAdjust) {
  78880. var x = coord.x,
  78881. y = coord.y;
  78882. if (visibleArea.minX > x && horizontalAdjust)
  78883. x = visibleArea.minX;
  78884. if (visibleArea.maxX < x + labelBbox.width && horizontalAdjust)
  78885. x = visibleArea.maxX - labelBbox.width;
  78886. if (visibleArea.minY > y && verticalAdjust)
  78887. y = visibleArea.minY;
  78888. if (visibleArea.maxY < y + labelBbox.height && verticalAdjust)
  78889. y = visibleArea.maxY - labelBbox.height;
  78890. return {
  78891. x: x,
  78892. y: y
  78893. }
  78894. },
  78895. _showForZeroValues: function() {
  78896. return this._options.label.showForZeroValues || this.initialValue
  78897. },
  78898. _drawMarker: function(renderer, group, animationEnabled) {
  78899. var that = this,
  78900. style = that._getStyle(),
  78901. x = that.x,
  78902. y = that.y,
  78903. width = that.width,
  78904. height = that.height,
  78905. r = that._options.cornerRadius;
  78906. if (animationEnabled)
  78907. if (that._options.rotated) {
  78908. width = 0;
  78909. x = that.defaultX
  78910. }
  78911. else {
  78912. height = 0;
  78913. y = that.defaultY
  78914. }
  78915. that.graphic = renderer.rect(x, y, width, height).attr({
  78916. rx: r,
  78917. ry: r
  78918. }).attr(style).data({point: that}).append(group)
  78919. },
  78920. _getSettingsForTracker: function() {
  78921. var that = this,
  78922. y = that.y,
  78923. height = that.height,
  78924. x = that.x,
  78925. width = that.width;
  78926. if (that._options.rotated) {
  78927. if (width === 1) {
  78928. width = DEFAULT_BAR_TRACKER_SIZE;
  78929. x -= CORRECTING_BAR_TRACKER_VALUE
  78930. }
  78931. }
  78932. else if (height === 1) {
  78933. height = DEFAULT_BAR_TRACKER_SIZE;
  78934. y -= CORRECTING_BAR_TRACKER_VALUE
  78935. }
  78936. return {
  78937. x: x,
  78938. y: y,
  78939. width: width,
  78940. height: height
  78941. }
  78942. },
  78943. getGraphicSettings: function() {
  78944. var graphic = this.graphic;
  78945. return {
  78946. x: graphic.attr("x"),
  78947. y: graphic.attr("y"),
  78948. height: graphic.attr("height"),
  78949. width: graphic.attr("width")
  78950. }
  78951. },
  78952. _getEdgeTooltipParams: function(x, y, width, height) {
  78953. var isPositive = this.value >= 0,
  78954. invertedY = this.translators.y.getBusinessRange().invert,
  78955. invertedX = this.translators.x.getBusinessRange().invert,
  78956. xCoord,
  78957. yCoord;
  78958. if (this._options.rotated) {
  78959. yCoord = y + height / 2;
  78960. if (invertedX)
  78961. xCoord = isPositive ? x : x + width;
  78962. else
  78963. xCoord = isPositive ? x + width : x
  78964. }
  78965. else {
  78966. xCoord = x + width / 2;
  78967. if (invertedY)
  78968. yCoord = isPositive ? y + height : y;
  78969. else
  78970. yCoord = isPositive ? y : y + height
  78971. }
  78972. return {
  78973. x: xCoord,
  78974. y: yCoord,
  78975. offset: 0
  78976. }
  78977. },
  78978. getTooltipParams: function(location) {
  78979. var x = this.x,
  78980. y = this.y,
  78981. width = this.width,
  78982. height = this.height;
  78983. return location === 'edge' ? this._getEdgeTooltipParams(x, y, width, height) : {
  78984. x: x + width / 2,
  78985. y: y + height / 2,
  78986. offset: 0
  78987. }
  78988. },
  78989. _truncateCoord: function(coord, minBounce, maxBounce) {
  78990. if (coord < minBounce)
  78991. return minBounce;
  78992. if (coord > maxBounce)
  78993. return maxBounce;
  78994. return coord
  78995. },
  78996. _translateErrorBars: function(valueTranslator, argVisibleArea) {
  78997. points.symbolPoint._translateErrorBars.call(this, valueTranslator);
  78998. if (this._errorBarPos < argVisibleArea.min || this._errorBarPos > argVisibleArea.max)
  78999. this._errorBarPos = undefined
  79000. },
  79001. _translate: function(translators) {
  79002. var that = this,
  79003. rotated = that._options.rotated,
  79004. valAxis = rotated ? "x" : "y",
  79005. argAxis = rotated ? "y" : "x",
  79006. valIntervalName = rotated ? "width" : "height",
  79007. argIntervalName = rotated ? "height" : "width",
  79008. argTranslator = translators[argAxis],
  79009. valTranslator = translators[valAxis],
  79010. argVisibleArea = argTranslator.getCanvasVisibleArea(),
  79011. valVisibleArea = valTranslator.getCanvasVisibleArea(),
  79012. arg,
  79013. minArg,
  79014. val,
  79015. minVal;
  79016. arg = minArg = argTranslator.translate(that.argument) + (that[argAxis + "Correction"] || 0);
  79017. val = valTranslator.translate(that.value);
  79018. minVal = valTranslator.translate(that.minValue);
  79019. that["v" + valAxis] = val;
  79020. that["v" + argAxis] = arg + that[argIntervalName] / 2;
  79021. that[valIntervalName] = _abs(val - minVal);
  79022. that._calculateVisibility(rotated ? _min(val, minVal) : _min(arg, minArg), rotated ? _min(arg, minArg) : _min(val, minVal), that.width, that.height);
  79023. val = that._truncateCoord(val, valVisibleArea.min, valVisibleArea.max);
  79024. minVal = that._truncateCoord(minVal, valVisibleArea.min, valVisibleArea.max);
  79025. that[argAxis] = arg;
  79026. that["min" + argAxis.toUpperCase()] = minArg;
  79027. that[valIntervalName] = _abs(val - minVal);
  79028. that[valAxis] = _min(val, minVal) + (that[valAxis + "Correction"] || 0);
  79029. that["min" + valAxis.toUpperCase()] = minVal + (that[valAxis + "Correction"] || 0);
  79030. that["default" + valAxis.toUpperCase()] = valTranslator.translate(CANVAS_POSITION_DEFAULT);
  79031. that._translateErrorBars(valTranslator, argVisibleArea);
  79032. if (that.inVisibleArea) {
  79033. if (that[argAxis] < argVisibleArea.min) {
  79034. that[argIntervalName] = that[argIntervalName] - (argVisibleArea.min - that[argAxis]);
  79035. that[argAxis] = argVisibleArea.min;
  79036. that["min" + argAxis.toUpperCase()] = argVisibleArea.min
  79037. }
  79038. if (that[argAxis] + that[argIntervalName] > argVisibleArea.max)
  79039. that[argIntervalName] = argVisibleArea.max - that[argAxis]
  79040. }
  79041. },
  79042. _updateMarker: function(animationEnabled, style) {
  79043. this.graphic.attr(_extend({}, style || this._getStyle(), !animationEnabled ? this.getMarkerCoords() : {}))
  79044. },
  79045. getMarkerCoords: function() {
  79046. return {
  79047. x: this.x,
  79048. y: this.y,
  79049. width: this.width,
  79050. height: this.height
  79051. }
  79052. },
  79053. coordsIn: function(x, y) {
  79054. var that = this;
  79055. return x >= that.x && x <= that.x + that.width && y >= that.y && y <= that.y + that.height
  79056. }
  79057. })
  79058. })(jQuery, DevExpress);
  79059. /*! Module viz-core, file bubblePoint.js */
  79060. (function($, DX) {
  79061. var points = DX.viz.core.series.points.mixins,
  79062. _extend = $.extend,
  79063. MIN_BUBBLE_HEIGHT = 20;
  79064. points.bubblePoint = _extend({}, points.symbolPoint, {
  79065. correctCoordinates: function(diameter) {
  79066. this.bubbleSize = diameter / 2
  79067. },
  79068. _drawMarker: function(renderer, group, animationEnabled) {
  79069. var that = this,
  79070. attr = _extend({
  79071. translateX: that.x,
  79072. translateY: that.y
  79073. }, that._getStyle());
  79074. that.graphic = renderer.circle(0, 0, animationEnabled ? 0 : that.bubbleSize).attr(attr).data({point: that}).append(group)
  79075. },
  79076. getTooltipParams: function(location) {
  79077. var that = this,
  79078. graphic = that.graphic,
  79079. height;
  79080. if (!graphic)
  79081. return;
  79082. height = graphic.getBBox().height;
  79083. return {
  79084. x: that.x,
  79085. y: height < MIN_BUBBLE_HEIGHT || location === 'edge' ? this.y - height / 2 : this.y,
  79086. offset: 0
  79087. }
  79088. },
  79089. _getLabelFormatObject: function() {
  79090. var formatObject = points.symbolPoint._getLabelFormatObject.call(this);
  79091. formatObject.size = this.initialSize;
  79092. return formatObject
  79093. },
  79094. _updateData: function(data) {
  79095. points.symbolPoint._updateData.call(this, data);
  79096. this.size = this.initialSize = data.size
  79097. },
  79098. _getGraphicBbox: function() {
  79099. var that = this;
  79100. return that._getSymbolBbox(that.x, that.y, that.bubbleSize)
  79101. },
  79102. _updateMarker: function(animationEnabled, style) {
  79103. var that = this;
  79104. style = style || that._getStyle();
  79105. if (!animationEnabled)
  79106. style = $.extend({
  79107. r: that.bubbleSize,
  79108. translateX: that.x,
  79109. translateY: that.y
  79110. }, style);
  79111. that.graphic.attr(style)
  79112. },
  79113. _getFormatObject: function(tooltip) {
  79114. var formatObject = points.symbolPoint._getFormatObject.call(this, tooltip);
  79115. formatObject.sizeText = tooltip.formatValue(this.initialSize);
  79116. return formatObject
  79117. },
  79118. _storeTrackerR: function() {
  79119. return this.bubbleSize
  79120. },
  79121. _getLabelCoords: function(label) {
  79122. var coords;
  79123. if (label.getLayoutOptions().position === "inside")
  79124. coords = this._getLabelCoordOfPosition(label, "inside");
  79125. else
  79126. coords = points.symbolPoint._getLabelCoords.call(this, label);
  79127. return coords
  79128. }
  79129. })
  79130. })(jQuery, DevExpress);
  79131. /*! Module viz-core, file piePoint.js */
  79132. (function($, DX) {
  79133. var CONNECTOR_LENGTH = 20,
  79134. series = DX.viz.core.series,
  79135. points = series.points.mixins,
  79136. _extend = $.extend,
  79137. _round = Math.round,
  79138. _sqrt = Math.sqrt,
  79139. _acos = Math.acos,
  79140. DEG = 180 / Math.PI,
  79141. _abs = Math.abs,
  79142. _normalizeAngle = DX.utils.normalizeAngle,
  79143. _getCosAndSin = DX.utils.getCosAndSin,
  79144. _isDefined = DX.utils.isDefined,
  79145. INDENT_FROM_PIE = series.helpers.consts.pieLabelIndent;
  79146. function getVerticallyShiftedAngularCoords(bbox, dy, center) {
  79147. var isPositive = bbox.x + bbox.width / 2 >= center.x,
  79148. dx1 = (isPositive ? bbox.x : bbox.x + bbox.width) - center.x,
  79149. dy1 = bbox.y - center.y,
  79150. dy2 = dy1 + dy,
  79151. dx2 = _round(_sqrt(dx1 * dx1 + dy1 * dy1 - dy2 * dy2)),
  79152. dx = (isPositive ? +dx2 : -dx2) || dx1;
  79153. return {
  79154. x: center.x + (isPositive ? dx : dx - bbox.width),
  79155. y: bbox.y + dy
  79156. }
  79157. }
  79158. DX.viz.core.utils.getVerticallyShiftedAngularCoords = getVerticallyShiftedAngularCoords;
  79159. points.piePoint = _extend({}, points.symbolPoint, {
  79160. _updateData: function(data) {
  79161. var that = this;
  79162. points.symbolPoint._updateData.call(this, data);
  79163. that._visible = true;
  79164. that.minValue = that.initialMinValue = that.originalMinValue = _isDefined(data.minValue) ? data.minValue : 0
  79165. },
  79166. animate: function(complete, duration, step) {
  79167. var that = this;
  79168. that.graphic.animate({
  79169. x: that.centerX,
  79170. y: that.centerY,
  79171. outerRadius: that.radiusOuter,
  79172. innerRadius: that.radiusInner,
  79173. startAngle: that.toAngle,
  79174. endAngle: that.fromAngle
  79175. }, {
  79176. partitionDuration: duration,
  79177. step: step
  79178. }, complete)
  79179. },
  79180. correctPosition: function(correction) {
  79181. var that = this;
  79182. that.radiusInner = correction.radiusInner;
  79183. that.radiusOuter = correction.radiusOuter;
  79184. that.centerX = correction.centerX;
  79185. that.centerY = correction.centerY
  79186. },
  79187. correctValue: function(correction, percent, base) {
  79188. var that = this;
  79189. that.value = (base || that.initialValue) + correction;
  79190. that.minValue = correction;
  79191. that.percent = percent;
  79192. that._label.setDataField("percent", percent)
  79193. },
  79194. _updateLabelData: function() {
  79195. this._label.setData(this._getLabelFormatObject())
  79196. },
  79197. _updateLabelOptions: function() {
  79198. var that = this;
  79199. !that._label && that._createLabel();
  79200. that._label.setOptions(that._options.label)
  79201. },
  79202. _getShiftLabelCoords: function() {
  79203. var that = this,
  79204. bbox = that._label.getBoundingRect(),
  79205. coord = that._getLabelCoords(that._label),
  79206. visibleArea = that._getVisibleArea();
  79207. if (that._isLabelDrawingWithoutPoints)
  79208. return that._checkLabelPosition(coord, bbox, visibleArea);
  79209. else
  79210. return that._getLabelExtraCoord(coord, that._checkVerticalLabelPosition(coord, bbox, visibleArea), bbox)
  79211. },
  79212. _getLabelPosition: function(options) {
  79213. return options.position
  79214. },
  79215. _getLabelCoords: function(label) {
  79216. var that = this,
  79217. bbox = label.getBoundingRect(),
  79218. options = label.getLayoutOptions(),
  79219. angleFunctions = _getCosAndSin(that.middleAngle),
  79220. position = that._getLabelPosition(options),
  79221. radiusInner = that.radiusInner,
  79222. radiusOuter = that.radiusOuter,
  79223. rad,
  79224. x;
  79225. if (position === 'inside') {
  79226. rad = radiusInner + (radiusOuter - radiusInner) / 2 + options.radialOffset;
  79227. x = that.centerX + rad * angleFunctions.cos - bbox.width / 2
  79228. }
  79229. else {
  79230. rad = radiusOuter + options.radialOffset + INDENT_FROM_PIE;
  79231. if (angleFunctions.cos > 0.1)
  79232. x = that.centerX + rad * angleFunctions.cos;
  79233. else if (angleFunctions.cos < -0.1)
  79234. x = that.centerX + rad * angleFunctions.cos - bbox.width;
  79235. else
  79236. x = that.centerX + rad * angleFunctions.cos - bbox.width / 2
  79237. }
  79238. return {
  79239. x: x,
  79240. y: _round(that.centerY - rad * angleFunctions.sin - bbox.height / 2)
  79241. }
  79242. },
  79243. _getColumnsCoord: function(coord) {
  79244. var that = this,
  79245. label = that._label,
  79246. bbox = label.getBoundingRect(),
  79247. options = label.getLayoutOptions(),
  79248. rad = that.radiusOuter + options.radialOffset,
  79249. canvas = that.series.canvas,
  79250. rightBorderX = canvas.width - canvas.right - bbox.width,
  79251. leftBorderX = canvas.left,
  79252. angleOfPoint = _normalizeAngle(that.middleAngle),
  79253. x;
  79254. if (options.position !== 'columns')
  79255. return coord;
  79256. rad += CONNECTOR_LENGTH;
  79257. if (angleOfPoint < 90 || angleOfPoint >= 270) {
  79258. x = that._maxLabelLength ? that.centerX + rad + that._maxLabelLength - bbox.width : rightBorderX;
  79259. x = x > rightBorderX ? rightBorderX : x
  79260. }
  79261. else {
  79262. x = that._maxLabelLength ? that.centerX - rad - that._maxLabelLength : leftBorderX;
  79263. x = x < leftBorderX ? leftBorderX : x
  79264. }
  79265. coord.x = x;
  79266. return coord
  79267. },
  79268. drawLabel: function(translators, renderer, group) {
  79269. this.translate(translators);
  79270. this._isLabelDrawingWithoutPoints = true;
  79271. this._drawLabel(renderer, group);
  79272. this._isLabelDrawingWithoutPoints = false
  79273. },
  79274. updateLabelCoord: function() {
  79275. var that = this,
  79276. bbox = that._label.getBoundingRect(),
  79277. coord = that._getColumnsCoord(bbox);
  79278. coord = that._checkHorizontalLabelPosition(coord, bbox, that._getVisibleArea());
  79279. that._label.shift(_round(coord.x), _round(bbox.y))
  79280. },
  79281. _checkVerticalLabelPosition: function(coord, box, visibleArea) {
  79282. var x = coord.x,
  79283. y = coord.y;
  79284. if (coord.y + box.height > visibleArea.maxY)
  79285. y = visibleArea.maxY - box.height;
  79286. else if (coord.y < visibleArea.minY)
  79287. y = visibleArea.minY;
  79288. return {
  79289. x: x,
  79290. y: y
  79291. }
  79292. },
  79293. _getLabelExtraCoord: function(coord, shiftCoord, box) {
  79294. return coord.y !== shiftCoord.y ? getVerticallyShiftedAngularCoords({
  79295. x: coord.x,
  79296. y: coord.y,
  79297. width: box.width,
  79298. height: box.height
  79299. }, shiftCoord.y - coord.y, {
  79300. x: this.centerX,
  79301. y: this.centerY
  79302. }) : coord
  79303. },
  79304. _checkHorizontalLabelPosition: function(coord, box, visibleArea) {
  79305. var x = coord.x,
  79306. y = coord.y;
  79307. if (coord.x + box.width > visibleArea.maxX)
  79308. x = visibleArea.maxX - box.width;
  79309. else if (coord.x < visibleArea.minX)
  79310. x = visibleArea.minX;
  79311. return {
  79312. x: x,
  79313. y: y
  79314. }
  79315. },
  79316. setLabelEllipsis: function() {
  79317. var that = this,
  79318. bbox = that._label.getBoundingRect(),
  79319. coord = that._checkHorizontalLabelPosition(bbox, bbox, that._getVisibleArea());
  79320. that._label.fit({
  79321. width: bbox.width - _abs(coord.x - bbox.x),
  79322. height: bbox.height - _abs(coord.y - bbox.y)
  79323. })
  79324. },
  79325. _getVisibleArea: function() {
  79326. var canvas = this.series.canvas;
  79327. return {
  79328. minX: canvas.left,
  79329. maxX: canvas.width - canvas.right,
  79330. minY: canvas.top,
  79331. maxY: canvas.height - canvas.bottom
  79332. }
  79333. },
  79334. _checkLabelPosition: function(coord, bbox, visibleArea) {
  79335. coord = this._checkHorizontalLabelPosition(coord, bbox, visibleArea);
  79336. return this._checkVerticalLabelPosition(coord, bbox, visibleArea)
  79337. },
  79338. getBoundaryCoords: function() {
  79339. var that = this,
  79340. rad = that.radiusOuter,
  79341. seriesStyle = that._options.styles.normal,
  79342. strokeWidthBy2 = seriesStyle["stroke-width"] / 2,
  79343. borderWidth = that.series.getOptions().containerBackgroundColor === seriesStyle.stroke ? _round(strokeWidthBy2) : _round(-strokeWidthBy2),
  79344. angleFunctions = _getCosAndSin(_round(that.middleAngle));
  79345. return {
  79346. x: _round(that.centerX + (rad - borderWidth) * angleFunctions.cos),
  79347. y: _round(that.centerY - (rad - borderWidth) * angleFunctions.sin)
  79348. }
  79349. },
  79350. _getLabelConnector: function() {
  79351. var coords = this.getBoundaryCoords();
  79352. coords.angle = this.middleAngle;
  79353. return coords
  79354. },
  79355. _drawMarker: function(renderer, group, animationEnabled, firstDrawing) {
  79356. var that = this,
  79357. radiusOuter = that.radiusOuter,
  79358. radiusInner = that.radiusInner,
  79359. fromAngle = that.fromAngle,
  79360. toAngle = that.toAngle;
  79361. if (animationEnabled) {
  79362. radiusInner = radiusOuter = 0;
  79363. if (!firstDrawing)
  79364. fromAngle = toAngle = that.shiftedAngle
  79365. }
  79366. that.graphic = renderer.arc(that.centerX, that.centerY, radiusInner, radiusOuter, toAngle, fromAngle).attr({"stroke-linejoin": "round"}).attr(that._getStyle()).data({point: that}).sharp().append(group)
  79367. },
  79368. getTooltipParams: function() {
  79369. var that = this,
  79370. angleFunctions = _getCosAndSin(that.middleAngle),
  79371. radiusInner = that.radiusInner,
  79372. radiusOuter = that.radiusOuter;
  79373. return {
  79374. x: that.centerX + (radiusInner + (radiusOuter - radiusInner) / 2) * angleFunctions.cos,
  79375. y: that.centerY - (radiusInner + (radiusOuter - radiusInner) / 2) * angleFunctions.sin,
  79376. offset: 0
  79377. }
  79378. },
  79379. _translate: function(translator) {
  79380. var that = this,
  79381. angle = that.shiftedAngle || 0,
  79382. value = that.value,
  79383. minValue = that.minValue;
  79384. that.fromAngle = translator.translate(minValue) + angle;
  79385. that.toAngle = translator.translate(value) + angle;
  79386. that.middleAngle = translator.translate((value - minValue) / 2 + minValue) + angle;
  79387. if (!that.isVisible())
  79388. that.middleAngle = that.toAngle = that.fromAngle = that.fromAngle || angle
  79389. },
  79390. _getMarkerVisibility: function() {
  79391. return true
  79392. },
  79393. _updateMarker: function(animationEnabled, style) {
  79394. var that = this;
  79395. style = style || that._getStyle();
  79396. if (!animationEnabled)
  79397. style = _extend({
  79398. x: that.centerX,
  79399. y: that.centerY,
  79400. outerRadius: that.radiusOuter,
  79401. innerRadius: that.radiusInner,
  79402. startAngle: that.toAngle,
  79403. endAngle: that.fromAngle
  79404. }, style);
  79405. that.graphic.attr(style).sharp()
  79406. },
  79407. getLegendStyles: function() {
  79408. return this._styles.legendStyles
  79409. },
  79410. isInVisibleArea: function() {
  79411. return true
  79412. },
  79413. hide: function() {
  79414. var that = this;
  79415. if (that._visible) {
  79416. that._visible = false;
  79417. that.hideTooltip();
  79418. that._options.visibilityChanged(that)
  79419. }
  79420. },
  79421. show: function() {
  79422. var that = this;
  79423. if (!that._visible) {
  79424. that._visible = true;
  79425. that._options.visibilityChanged(that)
  79426. }
  79427. },
  79428. setInvisibility: function() {
  79429. this._label.hide()
  79430. },
  79431. isVisible: function() {
  79432. return this._visible
  79433. },
  79434. _getFormatObject: function(tooltip) {
  79435. var formatObject = points.symbolPoint._getFormatObject.call(this, tooltip),
  79436. percent = this.percent;
  79437. formatObject.percent = percent;
  79438. formatObject.percentText = tooltip.formatValue(percent, "percent");
  79439. return formatObject
  79440. },
  79441. getColor: function() {
  79442. return this._styles.normal.fill
  79443. },
  79444. coordsIn: function(x, y) {
  79445. var that = this,
  79446. lx = x - that.centerX,
  79447. ly = y - that.centerY,
  79448. r = _sqrt(lx * lx + ly * ly),
  79449. fromAngle = that.fromAngle % 360,
  79450. toAngle = that.toAngle % 360,
  79451. angle;
  79452. if (r < that.radiusInner || r > that.radiusOuter || r === 0)
  79453. return false;
  79454. angle = _acos(lx / r) * DEG * (ly > 0 ? -1 : 1);
  79455. if (angle < 0)
  79456. angle += 360;
  79457. if (fromAngle === toAngle && _abs(that.toAngle - that.fromAngle) > 1E-4)
  79458. return true;
  79459. else
  79460. return fromAngle >= toAngle ? angle <= fromAngle && angle >= toAngle : !(angle >= fromAngle && angle <= toAngle)
  79461. }
  79462. })
  79463. })(jQuery, DevExpress);
  79464. /*! Module viz-core, file rangeSymbolPoint.js */
  79465. (function($, DX) {
  79466. var core = DX.viz.core,
  79467. points = core.series.points.mixins,
  79468. _extend = $.extend,
  79469. _isDefined = DX.utils.isDefined,
  79470. _math = Math,
  79471. _abs = _math.abs,
  79472. _min = _math.min,
  79473. _max = _math.max,
  79474. _round = _math.round,
  79475. DEFAULT_IMAGE_WIDTH = 20,
  79476. DEFAULT_IMAGE_HEIGHT = 20;
  79477. points.rangeSymbolPoint = _extend({}, points.symbolPoint, {
  79478. deleteLabel: function() {
  79479. var that = this;
  79480. that._topLabel.dispose();
  79481. that._topLabel = null;
  79482. that._bottomLabel.dispose();
  79483. that._bottomLabel = null
  79484. },
  79485. hideMarker: function(type) {
  79486. var graphic = this.graphic,
  79487. marker = graphic && graphic[type + "Marker"],
  79488. label = this["_" + type + "Label"];
  79489. if (marker && marker.attr("visibility") !== "hidden")
  79490. marker.attr({visibility: "hidden"});
  79491. label.hide()
  79492. },
  79493. setInvisibility: function() {
  79494. this.hideMarker("top");
  79495. this.hideMarker("bottom")
  79496. },
  79497. clearVisibility: function() {
  79498. var that = this,
  79499. graphic = that.graphic,
  79500. topMarker = graphic && graphic.topMarker,
  79501. bottomMarker = graphic && graphic.bottomMarker;
  79502. if (topMarker && topMarker.attr("visibility"))
  79503. topMarker.attr({visibility: null});
  79504. if (bottomMarker && bottomMarker.attr("visibility"))
  79505. bottomMarker.attr({visibility: null});
  79506. that._topLabel.clearVisibility();
  79507. that._bottomLabel.clearVisibility()
  79508. },
  79509. clearMarker: function() {
  79510. var that = this,
  79511. graphic = that.graphic,
  79512. topMarker = graphic && graphic.topMarker,
  79513. bottomMarker = graphic && graphic.bottomMarker,
  79514. emptySettings = that._emptySettings;
  79515. topMarker && topMarker.attr(emptySettings);
  79516. bottomMarker && bottomMarker.attr(emptySettings)
  79517. },
  79518. _getLabelPosition: function(markerType) {
  79519. var position,
  79520. labelsInside = this._options.label.position === "inside";
  79521. if (!this._options.rotated)
  79522. position = markerType === "top" ^ labelsInside ? "top" : "bottom";
  79523. else
  79524. position = markerType === "top" ^ labelsInside ? "right" : "left";
  79525. return position
  79526. },
  79527. _getLabelMinFormatObject: function() {
  79528. var that = this;
  79529. return {
  79530. index: 0,
  79531. argument: that.initialArgument,
  79532. value: that.initialMinValue,
  79533. seriesName: that.series.name,
  79534. originalValue: that.originalMinValue,
  79535. originalArgument: that.originalArgument,
  79536. point: that
  79537. }
  79538. },
  79539. _updateLabelData: function() {
  79540. var maxFormatObject = this._getLabelFormatObject();
  79541. maxFormatObject.index = 1;
  79542. this._topLabel.setData(maxFormatObject);
  79543. this._bottomLabel.setData(this._getLabelMinFormatObject())
  79544. },
  79545. _updateLabelOptions: function() {
  79546. var that = this,
  79547. options = this._options.label;
  79548. (!that._topLabel || !that._bottomLabel) && that._createLabel();
  79549. that._topLabel.setOptions(options);
  79550. that._bottomLabel.setOptions(options)
  79551. },
  79552. _createLabel: function() {
  79553. this._topLabel = core.CoreFactory.createLabel();
  79554. this._bottomLabel = core.CoreFactory.createLabel()
  79555. },
  79556. _getGraphicBbox: function(location) {
  79557. location = location || this._labelLocation;
  79558. var options = this._options,
  79559. images = this._getImage(options.image),
  79560. image = location === "top" ? this._checkImage(images.top) : this._checkImage(images.bottom),
  79561. bbox,
  79562. coord = this._getPositionFromLocation(location);
  79563. if (options.visible)
  79564. bbox = image ? this._getImageBbox(coord.x, coord.y) : this._getSymbolBbox(coord.x, coord.y, options.styles.normal.r);
  79565. else
  79566. bbox = {
  79567. x: coord.x,
  79568. y: coord.y,
  79569. width: 0,
  79570. height: 0
  79571. };
  79572. return bbox
  79573. },
  79574. _getPositionFromLocation: function(location) {
  79575. var x,
  79576. y,
  79577. isTop = location === "top";
  79578. if (!this._options.rotated) {
  79579. x = this.x;
  79580. y = isTop ? _min(this.y, this.minY) : _max(this.y, this.minY)
  79581. }
  79582. else {
  79583. x = isTop ? _max(this.x, this.minX) : _min(this.x, this.minX);
  79584. y = this.y
  79585. }
  79586. return {
  79587. x: x,
  79588. y: y
  79589. }
  79590. },
  79591. _checkOverlay: function(bottomCoord, topCoord, topValue) {
  79592. return bottomCoord < topCoord + topValue
  79593. },
  79594. _getOverlayCorrections: function(type, topCoords, bottomCoords) {
  79595. var isVertical = type === "vertical",
  79596. coordSelector = isVertical ? "y" : "x",
  79597. valueSelector = isVertical ? "height" : "width",
  79598. visibleArea = this.translators[coordSelector].getCanvasVisibleArea(),
  79599. minBound = visibleArea.min,
  79600. maxBound = visibleArea.max,
  79601. delta = _round((topCoords[coordSelector] + topCoords[valueSelector] - bottomCoords[coordSelector]) / 2),
  79602. coord1 = topCoords[coordSelector] - delta,
  79603. coord2 = bottomCoords[coordSelector] + delta;
  79604. if (coord1 < minBound) {
  79605. delta = minBound - topCoords[coordSelector];
  79606. coord1 += delta;
  79607. coord2 += delta
  79608. }
  79609. else if (coord2 + bottomCoords[valueSelector] > maxBound) {
  79610. delta = -(bottomCoords[coordSelector] + bottomCoords[valueSelector] - maxBound);
  79611. coord1 += delta;
  79612. coord2 += delta
  79613. }
  79614. return {
  79615. coord1: coord1,
  79616. coord2: coord2
  79617. }
  79618. },
  79619. _checkLabelsOverlay: function(topLocation) {
  79620. var that = this,
  79621. topCoords = that._topLabel.getBoundingRect(),
  79622. bottomCoords = that._bottomLabel.getBoundingRect(),
  79623. corrections = {};
  79624. if (!that._options.rotated) {
  79625. if (topLocation === "top") {
  79626. if (this._checkOverlay(bottomCoords.y, topCoords.y, topCoords.height)) {
  79627. corrections = this._getOverlayCorrections("vertical", topCoords, bottomCoords);
  79628. that._topLabel.shift(topCoords.x, corrections.coord1);
  79629. that._bottomLabel.shift(bottomCoords.x, corrections.coord2)
  79630. }
  79631. }
  79632. else if (this._checkOverlay(topCoords.y, bottomCoords.y, bottomCoords.height)) {
  79633. corrections = this._getOverlayCorrections("vertical", bottomCoords, topCoords);
  79634. that._topLabel.shift(topCoords.x, corrections.coord2);
  79635. that._bottomLabel.shift(bottomCoords.x, corrections.coord1)
  79636. }
  79637. }
  79638. else if (topLocation === "top") {
  79639. if (this._checkOverlay(topCoords.x, bottomCoords.x, bottomCoords.width)) {
  79640. corrections = this._getOverlayCorrections("horizontal", bottomCoords, topCoords);
  79641. that._topLabel.shift(corrections.coord2, topCoords.y);
  79642. that._bottomLabel.shift(corrections.coord1, bottomCoords.y)
  79643. }
  79644. }
  79645. else if (this._checkOverlay(bottomCoords.x, topCoords.x, topCoords.width)) {
  79646. corrections = this._getOverlayCorrections("horizontal", topCoords, bottomCoords);
  79647. that._topLabel.shift(corrections.coord1, topCoords.y);
  79648. that._bottomLabel.shift(corrections.coord2, bottomCoords.y)
  79649. }
  79650. },
  79651. _drawLabel: function(renderer, group) {
  79652. var that = this,
  79653. coord,
  79654. labels = [],
  79655. notInverted = that._options.rotated ? that.x >= that.minX : that.y < that.minY,
  79656. customVisibility = that._getCustomLabelVisibility();
  79657. that._topLabel.pointPosition = notInverted ? "top" : "bottom";
  79658. that._bottomLabel.pointPosition = notInverted ? "bottom" : "top";
  79659. if ((that.series.getLabelVisibility() || customVisibility !== null) && that.hasValue()) {
  79660. that.visibleTopMarker !== false && labels.push(that._topLabel);
  79661. that.visibleBottomMarker !== false && labels.push(that._bottomLabel);
  79662. $.each(labels, function(_, label) {
  79663. var pointPosition = label.pointPosition;
  79664. label.draw(renderer, group, customVisibility);
  79665. coord = that._addLabelAlignmentAndOffset(label, that._getLabelCoords(label, pointPosition));
  79666. coord = that._checkLabelPosition(label, coord, pointPosition);
  79667. that._labelLocation = label.pointPosition;
  79668. label.setFigureToDrawConnector(that._getLabelConnector());
  79669. that._labelLocation = null;
  79670. label.shift(_round(coord.x), _round(coord.y))
  79671. });
  79672. that._checkLabelsOverlay(that._topLabel.pointPosition)
  79673. }
  79674. else {
  79675. that._topLabel.hide();
  79676. that._bottomLabel.hide()
  79677. }
  79678. },
  79679. _getImage: function(imageOption) {
  79680. var image = {};
  79681. if (_isDefined(imageOption))
  79682. if (typeof imageOption === "string")
  79683. image.top = image.bottom = imageOption;
  79684. else {
  79685. image.top = {
  79686. url: typeof imageOption.url === "string" ? imageOption.url : imageOption.url && imageOption.url.rangeMaxPoint,
  79687. width: typeof imageOption.width === "number" ? imageOption.width : imageOption.width && imageOption.width.rangeMaxPoint,
  79688. height: typeof imageOption.height === "number" ? imageOption.height : imageOption.height && imageOption.height.rangeMaxPoint
  79689. };
  79690. image.bottom = {
  79691. url: typeof imageOption.url === "string" ? imageOption.url : imageOption.url && imageOption.url.rangeMinPoint,
  79692. width: typeof imageOption.width === "number" ? imageOption.width : imageOption.width && imageOption.width.rangeMinPoint,
  79693. height: typeof imageOption.height === "number" ? imageOption.height : imageOption.height && imageOption.height.rangeMinPoint
  79694. }
  79695. }
  79696. return image
  79697. },
  79698. _checkSymbol: function(oldOptions, newOptions) {
  79699. var that = this,
  79700. oldSymbol = oldOptions.symbol,
  79701. newSymbol = newOptions.symbol,
  79702. symbolChanged = oldSymbol === "circle" && newSymbol !== "circle" || oldSymbol !== "circle" && newSymbol === "circle",
  79703. oldImages = that._getImage(oldOptions.image),
  79704. newImages = that._getImage(newOptions.image),
  79705. topImageChanged = that._checkImage(oldImages.top) !== that._checkImage(newImages.top),
  79706. bottomImageChanged = that._checkImage(oldImages.bottom) !== that._checkImage(newImages.bottom);
  79707. return symbolChanged || topImageChanged || bottomImageChanged
  79708. },
  79709. _getSettingsForTwoMarkers: function(style) {
  79710. var that = this,
  79711. options = that._options,
  79712. settings = {},
  79713. x = options.rotated ? _min(that.x, that.minX) : that.x,
  79714. y = options.rotated ? that.y : _min(that.y, that.minY),
  79715. radius = style.r,
  79716. points = that._populatePointShape(options.symbol, radius);
  79717. settings.top = _extend({
  79718. translateX: x + that.width,
  79719. translateY: y,
  79720. r: radius
  79721. }, style);
  79722. settings.bottom = _extend({
  79723. translateX: x,
  79724. translateY: y + that.height,
  79725. r: radius
  79726. }, style);
  79727. if (points)
  79728. settings.top.points = settings.bottom.points = points;
  79729. return settings
  79730. },
  79731. _hasGraphic: function() {
  79732. return this.graphic && this.graphic.topMarker && this.graphic.bottomMarker
  79733. },
  79734. _drawOneMarker: function(renderer, markerType, imageSettings, settings) {
  79735. var that = this,
  79736. graphic = that.graphic;
  79737. if (graphic[markerType])
  79738. that._updateOneMarker(markerType, settings);
  79739. else
  79740. graphic[markerType] = that._createMarker(renderer, graphic, imageSettings, settings)
  79741. },
  79742. _drawMarker: function(renderer, group, animationEnabled, firstDrawing, style) {
  79743. var that = this,
  79744. settings = that._getSettingsForTwoMarkers(style || that._getStyle()),
  79745. image = that._getImage(that._options.image);
  79746. if (that._checkImage(image.top))
  79747. settings.top = that._getImageSettings(settings.top, image.top);
  79748. if (that._checkImage(image.bottom))
  79749. settings.bottom = that._getImageSettings(settings.bottom, image.bottom);
  79750. that.graphic = that.graphic || renderer.g().append(group);
  79751. that.visibleTopMarker && that._drawOneMarker(renderer, 'topMarker', image.top, settings.top);
  79752. that.visibleBottomMarker && that._drawOneMarker(renderer, 'bottomMarker', image.bottom, settings.bottom)
  79753. },
  79754. _getSettingsForTracker: function(radius) {
  79755. var that = this,
  79756. rotated = that._options.rotated;
  79757. return {
  79758. translateX: rotated ? _min(that.x, that.minX) - radius : that.x - radius,
  79759. translateY: rotated ? that.y - radius : _min(that.y, that.minY) - radius,
  79760. width: that.width + 2 * radius,
  79761. height: that.height + 2 * radius
  79762. }
  79763. },
  79764. isInVisibleArea: function() {
  79765. var that = this,
  79766. rotated = that._options.rotated,
  79767. argument = !rotated ? that.x : that.y,
  79768. maxValue = !rotated ? _max(that.minY, that.y) : _max(that.minX, that.x),
  79769. minValue = !rotated ? _min(that.minY, that.y) : _min(that.minX, that.x),
  79770. translators = that.translators,
  79771. notVisibleByArg,
  79772. notVisibleByVal,
  79773. tmp,
  79774. visibleTopMarker = true,
  79775. visibleBottomMarker = true,
  79776. visibleRangeArea = true,
  79777. visibleArgArea,
  79778. visibleValArea;
  79779. if (translators) {
  79780. visibleArgArea = translators[!rotated ? "x" : "y"].getCanvasVisibleArea();
  79781. visibleValArea = translators[!rotated ? "y" : "x"].getCanvasVisibleArea();
  79782. notVisibleByArg = visibleArgArea.max < argument || visibleArgArea.min > argument;
  79783. notVisibleByVal = visibleValArea.min > minValue && visibleValArea.min > maxValue || visibleValArea.max < minValue && visibleValArea.max < maxValue;
  79784. if (notVisibleByArg || notVisibleByVal)
  79785. visibleTopMarker = visibleBottomMarker = visibleRangeArea = false;
  79786. else {
  79787. visibleTopMarker = visibleValArea.min <= minValue && visibleValArea.max > minValue;
  79788. visibleBottomMarker = visibleValArea.min < maxValue && visibleValArea.max >= maxValue;
  79789. if (rotated) {
  79790. tmp = visibleTopMarker;
  79791. visibleTopMarker = visibleBottomMarker;
  79792. visibleBottomMarker = tmp
  79793. }
  79794. }
  79795. }
  79796. that.visibleTopMarker = visibleTopMarker;
  79797. that.visibleBottomMarker = visibleBottomMarker;
  79798. return visibleRangeArea
  79799. },
  79800. getTooltipParams: function() {
  79801. var that = this,
  79802. x,
  79803. y,
  79804. min,
  79805. max,
  79806. minValue,
  79807. translators = that.translators,
  79808. visibleAreaX = translators.x.getCanvasVisibleArea(),
  79809. visibleAreaY = translators.y.getCanvasVisibleArea();
  79810. if (!that._options.rotated) {
  79811. minValue = _min(that.y, that.minY);
  79812. x = that.x;
  79813. min = visibleAreaY.min > minValue ? visibleAreaY.min : minValue;
  79814. max = visibleAreaY.max < minValue + that.height ? visibleAreaY.max : minValue + that.height;
  79815. y = min + (max - min) / 2
  79816. }
  79817. else {
  79818. minValue = _min(that.x, that.minX);
  79819. y = that.y;
  79820. min = visibleAreaX.min > minValue ? visibleAreaX.min : minValue;
  79821. max = visibleAreaX.max < minValue + that.width ? visibleAreaX.max : minValue + that.width;
  79822. x = min + (max - min) / 2
  79823. }
  79824. return {
  79825. x: x,
  79826. y: y,
  79827. offset: 0
  79828. }
  79829. },
  79830. _translate: function(translators) {
  79831. var that = this,
  79832. rotated = that._options.rotated;
  79833. that.minX = that.minY = translators.y.translate(that.minValue);
  79834. points.symbolPoint._translate.call(that, translators);
  79835. that.height = rotated ? 0 : _abs(that.minY - that.y);
  79836. that.width = rotated ? _abs(that.x - that.minX) : 0
  79837. },
  79838. _updateData: function(data) {
  79839. var that = this;
  79840. points.symbolPoint._updateData.call(that, data);
  79841. that.minValue = that.initialMinValue = that.originalMinValue = data.minValue
  79842. },
  79843. _getImageSettings: function(settings, image) {
  79844. return {
  79845. href: image.url || image.toString(),
  79846. width: image.width || DEFAULT_IMAGE_WIDTH,
  79847. height: image.height || DEFAULT_IMAGE_HEIGHT,
  79848. translateX: settings.translateX,
  79849. translateY: settings.translateY
  79850. }
  79851. },
  79852. getCrosshairCoords: function(x, y) {
  79853. var coords;
  79854. if (this._options.rotated)
  79855. coords = {
  79856. y: this.vy,
  79857. x: Math.abs(this.vx - x) < Math.abs(this.minX - x) ? this.vx : this.minX
  79858. };
  79859. else
  79860. coords = {
  79861. x: this.vx,
  79862. y: Math.abs(this.vy - y) < Math.abs(this.minY - y) ? this.vy : this.minY
  79863. };
  79864. return coords
  79865. },
  79866. _updateOneMarker: function(markerType, settings) {
  79867. this.graphic && this.graphic[markerType] && this.graphic[markerType].attr(settings)
  79868. },
  79869. _updateMarker: function(animationEnabled, style) {
  79870. this._drawMarker(undefined, undefined, false, false, style)
  79871. },
  79872. _getFormatObject: function(tooltip) {
  79873. var that = this,
  79874. initialMinValue = that.initialMinValue,
  79875. initialValue = that.initialValue,
  79876. initialArgument = that.initialArgument,
  79877. minValue = tooltip.formatValue(initialMinValue),
  79878. value = tooltip.formatValue(initialValue);
  79879. return {
  79880. argument: initialArgument,
  79881. argumentText: tooltip.formatValue(initialArgument, "argument"),
  79882. valueText: minValue + " - " + value,
  79883. rangeValue1Text: minValue,
  79884. rangeValue2Text: value,
  79885. rangeValue1: initialMinValue,
  79886. rangeValue2: initialValue,
  79887. seriesName: that.series.name,
  79888. point: that,
  79889. originalMinValue: that.originalMinValue,
  79890. originalValue: that.originalValue,
  79891. originalArgument: that.originalArgument
  79892. }
  79893. },
  79894. getLabel: function() {
  79895. return [this._topLabel, this._bottomLabel]
  79896. },
  79897. getBoundingRect: $.noop,
  79898. coordsIn: function(x, y) {
  79899. var trackerRadius = this._storeTrackerR(),
  79900. xCond = x >= this.x - trackerRadius && x <= this.x + trackerRadius,
  79901. yCond = y >= this.y - trackerRadius && y <= this.y + trackerRadius;
  79902. if (this._options.rotated)
  79903. return yCond && (xCond || x >= this.minX - trackerRadius && x <= this.minX + trackerRadius);
  79904. else
  79905. return xCond && (yCond || y >= this.minY - trackerRadius && y <= this.minY + trackerRadius)
  79906. }
  79907. })
  79908. })(jQuery, DevExpress);
  79909. /*! Module viz-core, file rangeBarPoint.js */
  79910. (function($, DX) {
  79911. var points = DX.viz.core.series.points.mixins,
  79912. rangeSymbolPointMethods = points.rangeSymbolPoint,
  79913. _extend = $.extend;
  79914. points.rangeBarPoint = _extend({}, points.barPoint, {
  79915. deleteLabel: rangeSymbolPointMethods.deleteLabel,
  79916. _getFormatObject: rangeSymbolPointMethods._getFormatObject,
  79917. clearVisibility: function() {
  79918. var graphic = this.graphic;
  79919. if (graphic && graphic.attr("visibility"))
  79920. graphic.attr({visibility: null});
  79921. this._topLabel.clearVisibility();
  79922. this._bottomLabel.clearVisibility()
  79923. },
  79924. setInvisibility: function() {
  79925. var graphic = this.graphic;
  79926. if (graphic && graphic.attr("visibility") !== "hidden")
  79927. graphic.attr({visibility: "hidden"});
  79928. this._topLabel.hide();
  79929. this._bottomLabel.hide()
  79930. },
  79931. getTooltipParams: function(location) {
  79932. var edgeLocation = location === 'edge',
  79933. x,
  79934. y;
  79935. if (this._options.rotated) {
  79936. x = edgeLocation ? this.x + this.width : this.x + this.width / 2;
  79937. y = this.y + this.height / 2
  79938. }
  79939. else {
  79940. x = this.x + this.width / 2;
  79941. y = edgeLocation ? this.y : this.y + this.height / 2
  79942. }
  79943. return {
  79944. x: x,
  79945. y: y,
  79946. offset: 0
  79947. }
  79948. },
  79949. _translate: function(translator) {
  79950. var that = this,
  79951. barMethods = points.barPoint;
  79952. barMethods._translate.call(that, translator);
  79953. if (that._options.rotated)
  79954. that.width = that.width || 1;
  79955. else
  79956. that.height = that.height || 1
  79957. },
  79958. _updateData: rangeSymbolPointMethods._updateData,
  79959. _getLabelPosition: rangeSymbolPointMethods._getLabelPosition,
  79960. _getLabelMinFormatObject: rangeSymbolPointMethods._getLabelMinFormatObject,
  79961. _updateLabelData: rangeSymbolPointMethods._updateLabelData,
  79962. _updateLabelOptions: rangeSymbolPointMethods._updateLabelOptions,
  79963. getCrosshairCoords: rangeSymbolPointMethods.getCrosshairCoords,
  79964. _createLabel: rangeSymbolPointMethods._createLabel,
  79965. _checkOverlay: rangeSymbolPointMethods._checkOverlay,
  79966. _checkLabelsOverlay: rangeSymbolPointMethods._checkLabelsOverlay,
  79967. _getOverlayCorrections: rangeSymbolPointMethods._getOverlayCorrections,
  79968. _drawLabel: rangeSymbolPointMethods._drawLabel,
  79969. _getLabelCoords: rangeSymbolPointMethods._getLabelCoords,
  79970. _getGraphicBbox: function(location) {
  79971. location = location || this._labelLocation;
  79972. var isTop = location === "top",
  79973. bbox = points.barPoint._getGraphicBbox.call(this);
  79974. if (!this._options.rotated) {
  79975. bbox.y = isTop ? bbox.y : bbox.y + bbox.height;
  79976. bbox.height = 0
  79977. }
  79978. else {
  79979. bbox.x = isTop ? bbox.x + bbox.width : bbox.x;
  79980. bbox.width = 0
  79981. }
  79982. return bbox
  79983. },
  79984. getLabel: rangeSymbolPointMethods.getLabel,
  79985. getBoundingRect: $.noop
  79986. })
  79987. })(jQuery, DevExpress);
  79988. /*! Module viz-core, file candlestickPoint.js */
  79989. (function($, DX) {
  79990. var viz = DX.viz,
  79991. points = viz.core.series.points.mixins,
  79992. _isNumeric = $.isNumeric,
  79993. _extend = $.extend,
  79994. _math = Math,
  79995. _abs = _math.abs,
  79996. _min = _math.min,
  79997. _max = _math.max,
  79998. _round = _math.round,
  79999. DEFAULT_FINANCIAL_TRACKER_MARGIN = 2;
  80000. points.candlestickPoint = _extend({}, points.barPoint, {
  80001. _getContinuousPoints: function(minValueName, maxValueName) {
  80002. var that = this,
  80003. x = that.x,
  80004. createPoint = that._options.rotated ? function(x, y) {
  80005. return [y, x]
  80006. } : function(x, y) {
  80007. return [x, y]
  80008. },
  80009. width = that.width,
  80010. min = that[minValueName],
  80011. max = that[maxValueName],
  80012. points;
  80013. if (min === max)
  80014. points = [].concat(createPoint(x, that.highY)).concat(createPoint(x, that.lowY)).concat(createPoint(x, that.closeY)).concat(createPoint(x - width / 2, that.closeY)).concat(createPoint(x + width / 2, that.closeY)).concat(createPoint(x, that.closeY));
  80015. else
  80016. points = [].concat(createPoint(x, that.highY)).concat(createPoint(x, max)).concat(createPoint(x + width / 2, max)).concat(createPoint(x + width / 2, min)).concat(createPoint(x, min)).concat(createPoint(x, that.lowY)).concat(createPoint(x, min)).concat(createPoint(x - width / 2, min)).concat(createPoint(x - width / 2, max)).concat(createPoint(x, max));
  80017. return points
  80018. },
  80019. _getCategoryPoints: function(y) {
  80020. var that = this,
  80021. x = that.x,
  80022. createPoint = that._options.rotated ? function(x, y) {
  80023. return [y, x]
  80024. } : function(x, y) {
  80025. return [x, y]
  80026. };
  80027. return [].concat(createPoint(x, that.highY)).concat(createPoint(x, that.lowY)).concat(createPoint(x, y)).concat(createPoint(x - that.width / 2, y)).concat(createPoint(x + that.width / 2, y)).concat(createPoint(x, y))
  80028. },
  80029. _getPoints: function() {
  80030. var that = this,
  80031. points,
  80032. minValueName,
  80033. maxValueName,
  80034. openValue = that.openValue,
  80035. closeValue = that.closeValue;
  80036. if (_isNumeric(openValue) && _isNumeric(closeValue)) {
  80037. minValueName = openValue > closeValue ? "closeY" : "openY";
  80038. maxValueName = openValue > closeValue ? "openY" : "closeY";
  80039. points = that._getContinuousPoints(minValueName, maxValueName)
  80040. }
  80041. else if (openValue === closeValue)
  80042. points = [that.x, that.highY, that.x, that.lowY];
  80043. else
  80044. points = that._getCategoryPoints(_isNumeric(openValue) ? that.openY : that.closeY);
  80045. return points
  80046. },
  80047. getColor: function() {
  80048. var that = this;
  80049. return that._isReduction ? that._options.reduction.color : that._styles.normal.stroke || that.series.getColor()
  80050. },
  80051. _drawMarkerInGroup: function(group, attributes, renderer) {
  80052. var that = this;
  80053. that.graphic = renderer.path(that._getPoints(), "area").attr({"stroke-linecap": "square"}).attr(attributes).data({point: that}).sharp().append(group)
  80054. },
  80055. _fillStyle: function() {
  80056. var that = this,
  80057. styles = that._options.styles;
  80058. if (that._isReduction && that._isPositive)
  80059. that._styles = styles.reductionPositive;
  80060. else if (that._isReduction)
  80061. that._styles = styles.reduction;
  80062. else if (that._isPositive)
  80063. that._styles = styles.positive;
  80064. else
  80065. that._styles = styles
  80066. },
  80067. _getMinTrackerWidth: function() {
  80068. return 2 + 2 * this._styles.normal['stroke-width']
  80069. },
  80070. correctCoordinates: function(correctOptions) {
  80071. var minWidth = this._getMinTrackerWidth(),
  80072. maxWidth = 10,
  80073. width = correctOptions.width;
  80074. width = width < minWidth ? minWidth : width > maxWidth ? maxWidth : width;
  80075. this.width = width + width % 2;
  80076. this.xCorrection = correctOptions.offset
  80077. },
  80078. _getMarkerGroup: function(group) {
  80079. var that = this,
  80080. markerGroup;
  80081. if (that._isReduction && that._isPositive)
  80082. markerGroup = group.reductionPositiveMarkersGroup;
  80083. else if (that._isReduction)
  80084. markerGroup = group.reductionMarkersGroup;
  80085. else if (that._isPositive)
  80086. markerGroup = group.defaultPositiveMarkersGroup;
  80087. else
  80088. markerGroup = group.defaultMarkersGroup;
  80089. return markerGroup
  80090. },
  80091. _drawMarker: function(renderer, group) {
  80092. this._drawMarkerInGroup(this._getMarkerGroup(group), this._getStyle(), renderer)
  80093. },
  80094. _getSettingsForTracker: function() {
  80095. var that = this,
  80096. highY = that.highY,
  80097. lowY = that.lowY,
  80098. rotated = that._options.rotated,
  80099. x,
  80100. y,
  80101. width,
  80102. height;
  80103. if (highY === lowY) {
  80104. highY = rotated ? highY + DEFAULT_FINANCIAL_TRACKER_MARGIN : highY - DEFAULT_FINANCIAL_TRACKER_MARGIN;
  80105. lowY = rotated ? lowY - DEFAULT_FINANCIAL_TRACKER_MARGIN : lowY + DEFAULT_FINANCIAL_TRACKER_MARGIN
  80106. }
  80107. if (rotated) {
  80108. x = _min(lowY, highY);
  80109. y = that.x - that.width / 2;
  80110. width = _abs(lowY - highY);
  80111. height = that.width
  80112. }
  80113. else {
  80114. x = that.x - that.width / 2;
  80115. y = _min(lowY, highY);
  80116. width = that.width;
  80117. height = _abs(lowY - highY)
  80118. }
  80119. return {
  80120. x: x,
  80121. y: y,
  80122. width: width,
  80123. height: height
  80124. }
  80125. },
  80126. _getGraphicBbox: function() {
  80127. var that = this,
  80128. rotated = that._options.rotated,
  80129. x = that.x,
  80130. width = that.width,
  80131. lowY = that.lowY,
  80132. highY = that.highY;
  80133. return {
  80134. x: !rotated ? x - _round(width / 2) : lowY,
  80135. y: !rotated ? highY : x - _round(width / 2),
  80136. width: !rotated ? width : highY - lowY,
  80137. height: !rotated ? lowY - highY : width
  80138. }
  80139. },
  80140. getTooltipParams: function(location) {
  80141. var that = this;
  80142. if (that.graphic) {
  80143. var x,
  80144. y,
  80145. min,
  80146. max,
  80147. minValue = _min(that.lowY, that.highY),
  80148. maxValue = _max(that.lowY, that.highY),
  80149. visibleAreaX = that.translators.x.getCanvasVisibleArea(),
  80150. visibleAreaY = that.translators.y.getCanvasVisibleArea(),
  80151. edgeLocation = location === 'edge';
  80152. if (!that._options.rotated) {
  80153. min = _max(visibleAreaY.min, minValue);
  80154. max = _min(visibleAreaY.max, maxValue);
  80155. x = that.x;
  80156. y = edgeLocation ? min : min + (max - min) / 2
  80157. }
  80158. else {
  80159. min = _max(visibleAreaX.min, minValue);
  80160. max = _min(visibleAreaX.max, maxValue);
  80161. y = that.x;
  80162. x = edgeLocation ? max : min + (max - min) / 2
  80163. }
  80164. return {
  80165. x: x,
  80166. y: y,
  80167. offset: 0
  80168. }
  80169. }
  80170. },
  80171. hasValue: function() {
  80172. return this.highValue !== null && this.lowValue !== null
  80173. },
  80174. _translate: function() {
  80175. var that = this,
  80176. rotated = that._options.rotated,
  80177. translators = that.translators,
  80178. argTranslator = rotated ? translators.y : translators.x,
  80179. valTranslator = rotated ? translators.x : translators.y,
  80180. centerValue,
  80181. height;
  80182. that.vx = that.vy = that.x = argTranslator.translate(that.argument) + (that.xCorrection || 0);
  80183. that.openY = that.openValue !== null ? valTranslator.translate(that.openValue) : null;
  80184. that.highY = valTranslator.translate(that.highValue);
  80185. that.lowY = valTranslator.translate(that.lowValue);
  80186. that.closeY = that.closeValue !== null ? valTranslator.translate(that.closeValue) : null;
  80187. height = _abs(that.lowY - that.highY);
  80188. centerValue = _min(that.lowY, that.highY) + _abs(that.lowY - that.highY) / 2;
  80189. that._calculateVisibility(!rotated ? that.x : centerValue, !rotated ? centerValue : that.x)
  80190. },
  80191. getCrosshairCoords: function(x, y) {
  80192. var coords,
  80193. valueCoord = this._options.rotated ? x : y,
  80194. value = Math.abs(this.lowY - valueCoord) < Math.abs(this.closeY - valueCoord) ? this.lowY : this.closeY;
  80195. value = Math.abs(value - valueCoord) < Math.abs(this.openY - valueCoord) ? value : this.openY;
  80196. value = Math.abs(value - valueCoord) < Math.abs(this.highY - valueCoord) ? value : this.highY;
  80197. if (this._options.rotated)
  80198. coords = {
  80199. y: this.vy,
  80200. x: value
  80201. };
  80202. else
  80203. coords = {
  80204. x: this.vx,
  80205. y: value
  80206. };
  80207. return coords
  80208. },
  80209. _updateData: function(data) {
  80210. var that = this,
  80211. label = that._label,
  80212. reductionColor = this._options.reduction.color;
  80213. that.value = that.initialValue = data.reductionValue;
  80214. that.originalValue = data.value;
  80215. that.lowValue = that.originalLowValue = data.lowValue;
  80216. that.highValue = that.originalHighValue = data.highValue;
  80217. that.openValue = that.originalOpenValue = data.openValue;
  80218. that.closeValue = that.originalCloseValue = data.closeValue;
  80219. that._isPositive = data.openValue < data.closeValue;
  80220. that._isReduction = data.isReduction;
  80221. if (that._isReduction)
  80222. label.setColor(reductionColor)
  80223. },
  80224. _updateMarker: function(animationEnabled, style, group) {
  80225. var that = this,
  80226. graphic = that.graphic;
  80227. graphic.attr({points: that._getPoints()}).attr(style || that._getStyle()).sharp();
  80228. group && graphic.append(that._getMarkerGroup(group))
  80229. },
  80230. _getLabelFormatObject: function() {
  80231. var that = this;
  80232. return {
  80233. openValue: that.openValue,
  80234. highValue: that.highValue,
  80235. lowValue: that.lowValue,
  80236. closeValue: that.closeValue,
  80237. reductionValue: that.initialValue,
  80238. argument: that.initialArgument,
  80239. value: that.initialValue,
  80240. seriesName: that.series.name,
  80241. originalOpenValue: that.originalOpenValue,
  80242. originalCloseValue: that.originalCloseValue,
  80243. originalLowValue: that.originalLowValue,
  80244. originalHighValue: that.originalHighValue,
  80245. originalArgument: that.originalArgument,
  80246. point: that
  80247. }
  80248. },
  80249. _getFormatObject: function(tooltip) {
  80250. var that = this,
  80251. highValue = tooltip.formatValue(that.highValue),
  80252. openValue = tooltip.formatValue(that.openValue),
  80253. closeValue = tooltip.formatValue(that.closeValue),
  80254. lowValue = tooltip.formatValue(that.lowValue),
  80255. symbolMethods = points.symbolPoint,
  80256. formatObject = symbolMethods._getFormatObject.call(that, tooltip);
  80257. return _extend({}, formatObject, {
  80258. valueText: "h: " + highValue + (openValue !== "" ? " o: " + openValue : "") + (closeValue !== "" ? " c: " + closeValue : "") + " l: " + lowValue,
  80259. highValueText: highValue,
  80260. openValueText: openValue,
  80261. closeValueText: closeValue,
  80262. lowValueText: lowValue
  80263. })
  80264. }
  80265. })
  80266. })(jQuery, DevExpress);
  80267. /*! Module viz-core, file stockPoint.js */
  80268. (function($, DX) {
  80269. var points = DX.viz.core.series.points.mixins,
  80270. _extend = $.extend,
  80271. _isNumeric = $.isNumeric;
  80272. points.stockPoint = _extend({}, points.candlestickPoint, {
  80273. _getPoints: function() {
  80274. var that = this,
  80275. createPoint = that._options.rotated ? function(x, y) {
  80276. return [y, x]
  80277. } : function(x, y) {
  80278. return [x, y]
  80279. },
  80280. openYExist = _isNumeric(that.openY),
  80281. closeYExist = _isNumeric(that.closeY),
  80282. x = that.x,
  80283. width = that.width,
  80284. points;
  80285. points = [].concat(createPoint(x, that.highY));
  80286. openYExist && (points = points.concat(createPoint(x, that.openY)));
  80287. openYExist && (points = points.concat(createPoint(x - width / 2, that.openY)));
  80288. openYExist && (points = points.concat(createPoint(x, that.openY)));
  80289. closeYExist && (points = points.concat(createPoint(x, that.closeY)));
  80290. closeYExist && (points = points.concat(createPoint(x + width / 2, that.closeY)));
  80291. closeYExist && (points = points.concat(createPoint(x, that.closeY)));
  80292. points = points.concat(createPoint(x, that.lowY));
  80293. return points
  80294. },
  80295. _drawMarkerInGroup: function(group, attributes, renderer) {
  80296. this.graphic = renderer.path(this._getPoints(), "line").attr({"stroke-linecap": "square"}).attr(attributes).data({point: this}).sharp().append(group)
  80297. },
  80298. _getMinTrackerWidth: function() {
  80299. var width = 2 + this._styles.normal['stroke-width'];
  80300. return width + width % 2
  80301. }
  80302. })
  80303. })(jQuery, DevExpress);
  80304. /*! Module viz-core, file polarPoint.js */
  80305. (function($, DX, undefined) {
  80306. var _extend = $.extend,
  80307. viz = DX.viz,
  80308. points = viz.core.series.points.mixins,
  80309. utils = DX.utils,
  80310. isDefined = utils.isDefined,
  80311. normalizeAngle = utils.normalizeAngle,
  80312. _math = Math,
  80313. _max = _math.max,
  80314. ERROR_BARS_ANGLE_OFFSET = 90,
  80315. CANVAS_POSITION_START = "canvas_position_start",
  80316. CANVAS_POSITION_TOP = "canvas_position_top",
  80317. CANVAS_POSITION_END = "canvas_position_end",
  80318. CANVAS_POSITION_DEFAULT = "canvas_position_default";
  80319. points.polarSymbolPoint = _extend({}, points.symbolPoint, {
  80320. _getLabelCoords: points.piePoint._getLabelCoords,
  80321. _moveLabelOnCanvas: points.barPoint._moveLabelOnCanvas,
  80322. _getLabelPosition: function() {
  80323. return "outside"
  80324. },
  80325. _translate: function(translator) {
  80326. var that = this,
  80327. coord = translator.translate(that.argument, that.value),
  80328. center = translator.translate(CANVAS_POSITION_START, CANVAS_POSITION_TOP);
  80329. that.vx = normalizeAngle(coord.angle);
  80330. that.vy = that.radiusOuter = coord.radius;
  80331. that.radius = coord.radius;
  80332. that.middleAngle = -coord.angle;
  80333. that.angle = -coord.angle;
  80334. that.x = coord.x;
  80335. that.y = coord.y;
  80336. that.defaultX = that.centerX = center.x;
  80337. that.defaultY = that.centerY = center.y;
  80338. that._translateErrorBars(translator);
  80339. that.inVisibleArea = true
  80340. },
  80341. _translateErrorBars: function(translator) {
  80342. var that = this;
  80343. isDefined(that.lowError) && (that._lowErrorCoord = that.centerY - translator.translate(that.argument, that.lowError).radius);
  80344. isDefined(that.highError) && (that._highErrorCoord = that.centerY - translator.translate(that.argument, that.highError).radius);
  80345. that._errorBarPos = that.centerX;
  80346. that._baseErrorBarPos = (that._options.errorBars || {}).type === "stdDeviation" ? that._lowErrorCoord + (that._highErrorCoord - that._lowErrorCoord) / 2 : that.centerY - that.radius
  80347. },
  80348. _getTranslates: function(animationEnabled) {
  80349. return animationEnabled ? this.getDefaultCoords() : {
  80350. x: this.x,
  80351. y: this.y
  80352. }
  80353. },
  80354. getDefaultCoords: function() {
  80355. var cossin = utils.getCosAndSin(-this.angle),
  80356. radius = this.translators.translate(CANVAS_POSITION_START, CANVAS_POSITION_DEFAULT).radius,
  80357. x = this.defaultX + radius * cossin.cos,
  80358. y = this.defaultY + radius * cossin.sin;
  80359. return {
  80360. x: x,
  80361. y: y
  80362. }
  80363. },
  80364. _addLabelAlignmentAndOffset: function(label, coord) {
  80365. return coord
  80366. },
  80367. _getVisibleArea: function() {
  80368. var canvas = this.translators.canvas;
  80369. return {
  80370. minX: canvas.left,
  80371. maxX: canvas.width - canvas.right,
  80372. minY: canvas.top,
  80373. maxY: canvas.height - canvas.bottom
  80374. }
  80375. },
  80376. _checkLabelPosition: function(label, coord) {
  80377. var that = this,
  80378. visibleArea = that._getVisibleArea(),
  80379. graphicBbox = that._getGraphicBbox();
  80380. if (that._isPointInVisibleArea(visibleArea, graphicBbox))
  80381. coord = that._moveLabelOnCanvas(coord, visibleArea, label.getBoundingRect(), true, true);
  80382. return coord
  80383. },
  80384. _getErrorBarSettings: function(errorBarOptions, animationEnabled) {
  80385. var settings = points.symbolPoint._getErrorBarSettings.call(this, errorBarOptions, animationEnabled);
  80386. settings.rotate = ERROR_BARS_ANGLE_OFFSET - this.angle;
  80387. settings.rotateX = this.centerX;
  80388. settings.rotateY = this.centerY;
  80389. return settings
  80390. },
  80391. getCoords: function(min) {
  80392. return min ? this.getDefaultCoords() : {
  80393. x: this.x,
  80394. y: this.y
  80395. }
  80396. }
  80397. });
  80398. points.polarBarPoint = _extend({}, points.barPoint, {
  80399. _translateErrorBars: points.polarSymbolPoint._translateErrorBars,
  80400. _getErrorBarSettings: points.polarSymbolPoint._getErrorBarSettings,
  80401. _getVisibleArea: points.polarSymbolPoint._getVisibleArea,
  80402. _moveLabelOnCanvas: points.barPoint._moveLabelOnCanvas,
  80403. _getLabelCoords: points.piePoint._getLabelCoords,
  80404. _getLabelConnector: points.piePoint._getLabelConnector,
  80405. getBoundaryCoords: points.piePoint.getBoundaryCoords,
  80406. getTooltipParams: points.piePoint.getTooltipParams,
  80407. _getLabelPosition: points.piePoint._getLabelPosition,
  80408. _translate: function(translator) {
  80409. var that = this,
  80410. maxRadius = translator.translate(CANVAS_POSITION_TOP, CANVAS_POSITION_END).radius;
  80411. that.radiusInner = translator.translate(that.argument, that.minValue).radius;
  80412. points.polarSymbolPoint._translate.call(that, translator);
  80413. if (that.radiusInner === null)
  80414. that.radiusInner = that.radius = maxRadius;
  80415. else if (that.radius === null)
  80416. this.radius = this.value >= 0 ? maxRadius : 0;
  80417. that.radiusOuter = _max(that.radiusInner, that.radius);
  80418. that.radiusInner = that.defaultRadius = _math.min(that.radiusInner, that.radius);
  80419. that.middleAngle = that.angle = -utils.normalizeAngle(that.middleAngleCorrection - that.angle)
  80420. },
  80421. _checkVisibility: function(translator) {
  80422. return translator.checkVisibility(this.radius, this.radiusInner)
  80423. },
  80424. getMarkerCoords: function() {
  80425. return {
  80426. x: this.centerX,
  80427. y: this.centerY,
  80428. outerRadius: this.radiusOuter,
  80429. innerRadius: this.defaultRadius,
  80430. startAngle: this.middleAngle - this.interval / 2,
  80431. endAngle: this.middleAngle + this.interval / 2
  80432. }
  80433. },
  80434. _drawMarker: function(renderer, group, animationEnabled) {
  80435. var that = this,
  80436. styles = that._getStyle(),
  80437. coords = that.getMarkerCoords(),
  80438. innerRadius = coords.innerRadius,
  80439. outerRadius = coords.outerRadius,
  80440. start = that.translators.translate(that.argument, CANVAS_POSITION_DEFAULT),
  80441. x = coords.x,
  80442. y = coords.y;
  80443. if (animationEnabled) {
  80444. innerRadius = 0;
  80445. outerRadius = 0;
  80446. x = start.x;
  80447. y = start.y
  80448. }
  80449. that.graphic = renderer.arc(x, y, innerRadius, outerRadius, coords.startAngle, coords.endAngle).attr(styles).data({point: that}).append(group)
  80450. },
  80451. _checkLabelPosition: function(label, coord) {
  80452. var that = this,
  80453. visibleArea = that._getVisibleArea(),
  80454. angleFunctions = utils.getCosAndSin(that.middleAngle),
  80455. x = that.centerX + that.defaultRadius * angleFunctions.cos,
  80456. y = that.centerY - that.defaultRadius * angleFunctions.sin;
  80457. if (x > visibleArea.minX && x < visibleArea.maxX && y > visibleArea.minY && y < visibleArea.maxY)
  80458. coord = that._moveLabelOnCanvas(coord, visibleArea, label.getBoundingRect(), true, true);
  80459. return coord
  80460. },
  80461. _addLabelAlignmentAndOffset: function(label, coord) {
  80462. return coord
  80463. },
  80464. correctCoordinates: function(correctOptions) {
  80465. this.middleAngleCorrection = correctOptions.offset;
  80466. this.interval = correctOptions.width
  80467. },
  80468. coordsIn: function(x, y) {
  80469. var val = this.translators.untranslate(x, y),
  80470. coords = this.getMarkerCoords(),
  80471. isBetweenAngles = coords.startAngle < coords.endAngle ? -val.phi >= coords.startAngle && -val.phi <= coords.endAngle : -val.phi <= coords.startAngle && -val.phi >= coords.endAngle;
  80472. return val.r >= coords.innerRadius && val.r <= coords.outerRadius && isBetweenAngles
  80473. }
  80474. })
  80475. })(jQuery, DevExpress);
  80476. /*! Module viz-core, file dataValidator.js */
  80477. (function($, DX, undefined) {
  80478. var viz = DX.viz,
  80479. parseUtils = new viz.core.ParseUtils,
  80480. STRING = "string",
  80481. NUMERIC = "numeric",
  80482. DATETIME = "datetime",
  80483. DISCRETE = "discrete",
  80484. CONTINUOUS = "continuous",
  80485. LOGARITHMIC = "logarithmic",
  80486. VALUE_TYPE = "valueType",
  80487. ARGUMENT_TYPE = "argumentType",
  80488. axisTypeParser = viz.core.utils.enumParser([STRING, NUMERIC, DATETIME]),
  80489. utils = DX.utils,
  80490. _each = $.each,
  80491. _isDefined = utils.isDefined;
  80492. function groupingValues(data, others, valueField, index) {
  80493. if (!_isDefined(index) || index < 0)
  80494. return;
  80495. _each(data.slice(index), function(_, cell) {
  80496. if (!_isDefined(cell[valueField]))
  80497. return;
  80498. others[valueField] += cell[valueField];
  80499. cell[valueField] = undefined;
  80500. cell["original" + valueField] = undefined
  80501. })
  80502. }
  80503. function mergeSort(data, field) {
  80504. function merge_sort(array, low, high, field) {
  80505. if (low < high) {
  80506. var mid = Math.floor((low + high) / 2);
  80507. merge_sort(array, low, mid, field);
  80508. merge_sort(array, mid + 1, high, field);
  80509. merge(array, low, mid, high, field)
  80510. }
  80511. }
  80512. var n = data.length;
  80513. merge_sort(data, 0, n - 1, field);
  80514. return data
  80515. }
  80516. function merge(array, low, mid, high, field) {
  80517. var newArray = new Array(high - low + 1),
  80518. countL = low,
  80519. countR = mid + 1,
  80520. k,
  80521. i = 0;
  80522. while (countL <= mid && countR <= high) {
  80523. if (array[countL][field] <= array[countR][field] || !_isDefined(array[countR][field])) {
  80524. newArray[i] = array[countL];
  80525. countL++
  80526. }
  80527. else {
  80528. newArray[i] = array[countR];
  80529. countR++
  80530. }
  80531. i++
  80532. }
  80533. if (countL > mid)
  80534. for (k = countR; k <= high; k++, i++)
  80535. newArray[i] = array[k];
  80536. else
  80537. for (k = countL; k <= mid; k++, i++)
  80538. newArray[i] = array[k];
  80539. for (k = 0; k <= high - low; k++)
  80540. array[k + low] = newArray[k];
  80541. return array
  80542. }
  80543. function DataValidator(data, groups, incidentOccured, dataPrepareOptions) {
  80544. var that = this;
  80545. groups = groups || [[]];
  80546. that._nullData = !data;
  80547. that.groups = groups;
  80548. that.data = data || [];
  80549. that._parsers = {};
  80550. that._errorShowList = {};
  80551. that._skipFields = {};
  80552. that.options = dataPrepareOptions || {};
  80553. that.incidentOccured = incidentOccured;
  80554. that.userArgumentCategories = that.groups.argumentOptions && that.groups.argumentOptions.categories || [];
  80555. if (!incidentOccured)
  80556. that.incidentOccured = $.noop
  80557. }
  80558. viz.core.DataValidator = DataValidator;
  80559. DataValidator.prototype = {
  80560. ctor: DataValidator,
  80561. validate: function validate() {
  80562. var that = this,
  80563. dataLength;
  80564. that._data = that.data;
  80565. that.groups.argumentType = null;
  80566. that.groups.argumentAxisType = null;
  80567. _each(that.groups, function(_, group) {
  80568. group.valueType = null;
  80569. group.valueAxisType = null;
  80570. _each(group, function(_, series) {
  80571. series.updateDataType({})
  80572. });
  80573. group.valueAxis && group.valueAxis.resetTypes(VALUE_TYPE)
  80574. });
  80575. if (that.groups.argumentAxes)
  80576. _each(that.groups.argumentAxes, function(_, axis) {
  80577. axis.resetTypes(ARGUMENT_TYPE)
  80578. });
  80579. that._checkType();
  80580. that._checkAxisType();
  80581. if (!utils.isArray(that.data) || that._nullData)
  80582. that._incorrectDataMessage();
  80583. if (that.options.convertToAxisDataType) {
  80584. that._createParser();
  80585. that._parse()
  80586. }
  80587. that._groupData();
  80588. that._sort();
  80589. dataLength = that._data.length;
  80590. _each(that._skipFields, function(field, fieldValue) {
  80591. if (fieldValue === dataLength)
  80592. that.incidentOccured("W2002", [field])
  80593. });
  80594. return that._data
  80595. },
  80596. _checkValueTypeOfGroup: function(group, cell) {
  80597. var that = this;
  80598. _each(group, function(_, series) {
  80599. _each(series.getValueFields(), function(_, field) {
  80600. group.valueType = that._getType(cell[field], group.valueType)
  80601. })
  80602. });
  80603. return group.valueType
  80604. },
  80605. _checkArgumentTypeOfGroup: function(group, cell) {
  80606. var that = this;
  80607. _each(group, function(_, series) {
  80608. that.groups.argumentType = that._getType(cell[series.getArgumentField()], that.groups.argumentType)
  80609. });
  80610. return that.groups.argumentType
  80611. },
  80612. _checkType: function _checkType() {
  80613. var that = this,
  80614. groupsWithUndefinedValueType = [],
  80615. groupsWithUndefinedArgumentType = [],
  80616. groups = that.groups,
  80617. argumentTypeGroup = groups.argumentOptions && axisTypeParser(groups.argumentOptions.argumentType);
  80618. _each(groups, function(_, group) {
  80619. if (!group.length)
  80620. return null;
  80621. var valueTypeGroup = group.valueOptions && axisTypeParser(group.valueOptions.valueType);
  80622. group.valueType = valueTypeGroup;
  80623. groups.argumentType = argumentTypeGroup;
  80624. !valueTypeGroup && groupsWithUndefinedValueType.push(group);
  80625. !argumentTypeGroup && groupsWithUndefinedArgumentType.push(group)
  80626. });
  80627. if (groupsWithUndefinedValueType.length || groupsWithUndefinedArgumentType.length)
  80628. _each(that.data, function(_, cell) {
  80629. var defineVal,
  80630. defineArg;
  80631. if (!utils.isObject(cell))
  80632. return;
  80633. _each(groupsWithUndefinedValueType, function(_, group) {
  80634. defineVal = that._checkValueTypeOfGroup(group, cell)
  80635. });
  80636. _each(groupsWithUndefinedArgumentType, function(_, group) {
  80637. defineArg = that._checkArgumentTypeOfGroup(group, cell)
  80638. });
  80639. if (!that.options.checkTypeForAllData && defineVal && defineArg)
  80640. return false
  80641. })
  80642. },
  80643. _checkAxisType: function _checkAxisType() {
  80644. var that = this,
  80645. groups = that.groups,
  80646. argumentOptions = groups.argumentOptions || {};
  80647. _each(groups, function(_, group) {
  80648. _each(group, function(_, series) {
  80649. var optionsSeries = {},
  80650. valueOptions = group.valueOptions || {},
  80651. valueCategories = valueOptions.categories || [];
  80652. optionsSeries.argumentAxisType = that._correctAxisType(groups.argumentType, argumentOptions.type, !!that.userArgumentCategories.length);
  80653. optionsSeries.valueAxisType = that._correctAxisType(group.valueType, valueOptions.type, !!valueCategories.length);
  80654. groups.argumentAxisType = groups.argumentAxisType || optionsSeries.argumentAxisType;
  80655. group.valueAxisType = group.valueAxisType || optionsSeries.valueAxisType;
  80656. optionsSeries.argumentType = groups.argumentType;
  80657. optionsSeries.valueType = group.valueType;
  80658. optionsSeries.showZero = valueOptions.showZero;
  80659. series.updateDataType(optionsSeries)
  80660. });
  80661. if (group.valueAxis) {
  80662. group.valueAxis.setTypes(group.valueAxisType, group.valueType, VALUE_TYPE);
  80663. group.valueAxis.validate(false)
  80664. }
  80665. });
  80666. if (that.groups.argumentAxes)
  80667. _each(that.groups.argumentAxes, function(_, axis) {
  80668. axis.setTypes(that.groups.argumentAxisType, that.groups.argumentType, ARGUMENT_TYPE);
  80669. axis.validate(true)
  80670. })
  80671. },
  80672. _createParser: function _createParser() {
  80673. var that = this,
  80674. groups = that.groups;
  80675. _each(groups, function(_, group) {
  80676. _each(group, function(_, series) {
  80677. that._parsers[series.getArgumentField()] = that._createParserUnit(groups.argumentType, groups.argumentAxisType === LOGARITHMIC ? that._filterForLogAxis : null);
  80678. _each(series.getValueFields(), function(_, field) {
  80679. that._parsers[field] = that._createParserUnit(group.valueType, group.valueAxisType === LOGARITHMIC ? that._filterForLogAxis : null, series.getOptions().ignoreEmptyPoints)
  80680. });
  80681. if (series.getTagField())
  80682. that._parsers[series.getTagField()] = null
  80683. })
  80684. })
  80685. },
  80686. _parse: function _parse() {
  80687. var that = this,
  80688. parsedData = [];
  80689. _each(that.data, function(_, cell) {
  80690. var parserObject = {};
  80691. if (!utils.isObject(cell)) {
  80692. cell && that._incorrectDataMessage();
  80693. return
  80694. }
  80695. _each(that._parsers, function(field, parser) {
  80696. parserObject[field] = parser ? parser(cell[field], field) : cell[field];
  80697. parserObject["original" + field] = cell[field]
  80698. });
  80699. parsedData.push(parserObject)
  80700. });
  80701. this._data = parsedData
  80702. },
  80703. _groupMinSlices: function(argumentField, valueField, smallValuesGrouping) {
  80704. smallValuesGrouping = smallValuesGrouping || {};
  80705. var that = this,
  80706. mode = smallValuesGrouping.mode,
  80707. count = smallValuesGrouping.topCount,
  80708. threshold = smallValuesGrouping.threshold,
  80709. name = smallValuesGrouping.groupName || "others",
  80710. others = {},
  80711. data = that._data.slice(),
  80712. index;
  80713. if (!mode || mode === "none")
  80714. return;
  80715. others[argumentField] = name + "";
  80716. others[valueField] = 0;
  80717. data.sort(function(a, b) {
  80718. if (_isDefined(b[valueField]) && _isDefined(a[valueField]))
  80719. return b[valueField] - a[valueField];
  80720. else if (!_isDefined(b[valueField]) && a[valueField])
  80721. return -1;
  80722. else if (!_isDefined(a[valueField]) && b[valueField])
  80723. return 1
  80724. });
  80725. if (mode === "smallValueThreshold") {
  80726. _each(data, function(i, cell) {
  80727. if (_isDefined(index) || !_isDefined(cell[valueField]))
  80728. return;
  80729. if (threshold > cell[valueField])
  80730. index = i
  80731. });
  80732. groupingValues(data, others, valueField, index)
  80733. }
  80734. else if (mode === "topN")
  80735. groupingValues(data, others, valueField, count);
  80736. others[valueField] && that._data.push(others)
  80737. },
  80738. _groupData: function() {
  80739. var that = this,
  80740. groups = that.groups,
  80741. isPie = groups.length && groups[0].length && (groups[0][0].type === "pie" || groups[0][0].type === "doughnut" || groups[0][0].type === "donut"),
  80742. argumentField,
  80743. valueFields;
  80744. if (!isPie)
  80745. return;
  80746. _each(groups, function(_, group) {
  80747. _each(group, function(_, series) {
  80748. argumentField = series.getArgumentField();
  80749. valueFields = series.getValueFields();
  80750. if (groups.argumentAxisType === DISCRETE)
  80751. that._groupSameArguments(argumentField, valueFields);
  80752. that._groupMinSlices(argumentField, valueFields[0], series.getOptions().smallValuesGrouping)
  80753. })
  80754. })
  80755. },
  80756. _groupSameArguments: function(argumentField, valueFields) {
  80757. var that = this,
  80758. argument,
  80759. dataOfArguments = {},
  80760. parsedData = that._data;
  80761. _each(parsedData, function(i, cell) {
  80762. if (!_isDefined(cell[argumentField]) || !_isDefined(cell[valueFields[0]]))
  80763. return;
  80764. argument = cell[argumentField];
  80765. if (_isDefined(dataOfArguments[argument])) {
  80766. var data = parsedData[dataOfArguments[argument]];
  80767. _each(valueFields, function(_, field) {
  80768. data[field] += cell[field];
  80769. cell[field] = undefined;
  80770. cell["original" + field] = undefined
  80771. })
  80772. }
  80773. else
  80774. dataOfArguments[argument] = i
  80775. })
  80776. },
  80777. _getType: function _getType(unit, type) {
  80778. if (type === STRING || utils.isString(unit))
  80779. return STRING;
  80780. if (type === DATETIME || utils.isDate(unit))
  80781. return DATETIME;
  80782. if (utils.isNumber(unit))
  80783. return NUMERIC;
  80784. return type
  80785. },
  80786. _correctAxisType: function _correctAxisType(type, axisType, hasCategories) {
  80787. if (type === STRING && (axisType === CONTINUOUS || axisType === LOGARITHMIC))
  80788. this.incidentOccured("E2002");
  80789. if (axisType === LOGARITHMIC)
  80790. return LOGARITHMIC;
  80791. axisType = (hasCategories || axisType === DISCRETE || type === STRING) && DISCRETE;
  80792. return axisType || CONTINUOUS
  80793. },
  80794. _filterForLogAxis: function(val, field) {
  80795. if (val <= 0) {
  80796. this.incidentOccured("E2004", [field]);
  80797. return null
  80798. }
  80799. return val
  80800. },
  80801. _createParserUnit: function _createParserUnit(type, filter, ignoreEmptyPoints) {
  80802. var that = this,
  80803. parser = type ? parseUtils.getParser(type, undefined, true) : function(unit) {
  80804. return unit
  80805. };
  80806. return function(unit, field) {
  80807. var parseUnit = parser(unit);
  80808. if (filter)
  80809. parseUnit = filter.call(that, parseUnit, field);
  80810. parseUnit === null && ignoreEmptyPoints && (parseUnit = undefined);
  80811. if (parseUnit === undefined) {
  80812. that._addSkipFields(field);
  80813. that._validUnit(unit, field, type)
  80814. }
  80815. return parseUnit
  80816. }
  80817. },
  80818. _validUnit: function _validUnit(unit, field) {
  80819. if (!unit)
  80820. return;
  80821. if (!utils.isNumber(unit) && !utils.isDate(unit) && !utils.isString(unit)) {
  80822. this.incidentOccured("E2003", [field]);
  80823. return
  80824. }
  80825. this.incidentOccured("E2004", [field])
  80826. },
  80827. _sort: function _sort() {
  80828. var that = this,
  80829. sortingMethod = that.options.sortingMethod,
  80830. data = that._data,
  80831. groups = that.groups,
  80832. hash = {},
  80833. argumentField = groups.length && groups[0].length && groups[0][0].getArgumentField();
  80834. if (utils.isFunction(sortingMethod))
  80835. data.sort(sortingMethod);
  80836. else if (that.userArgumentCategories.length) {
  80837. _each(that.userArgumentCategories, function(index, value) {
  80838. hash[value] = index
  80839. });
  80840. data.sort(function sortCat(a, b) {
  80841. a = a[argumentField];
  80842. b = b[argumentField];
  80843. return hash[a] - hash[b]
  80844. })
  80845. }
  80846. else if (sortingMethod === true && groups.argumentType !== STRING)
  80847. mergeSort(data, argumentField)
  80848. },
  80849. _addSkipFields: function _addSkipFields(field) {
  80850. this._skipFields[field] = (this._skipFields[field] || 0) + 1
  80851. },
  80852. _incorrectDataMessage: function() {
  80853. if (this._erorrDataSource !== true) {
  80854. this._erorrDataSource = true;
  80855. this.incidentOccured("E2001")
  80856. }
  80857. }
  80858. }
  80859. })(jQuery, DevExpress);
  80860. /*! Module viz-core, file default.js */
  80861. (function(DX, undefined) {
  80862. var WHITE = "#ffffff",
  80863. BLACK = "#000000",
  80864. LIGHT_GREY = "#d3d3d3",
  80865. GREY_GREEN = "#303030",
  80866. RED = "#ff0000";
  80867. DX.viz.core.registerTheme({
  80868. name: "generic.light",
  80869. font: {
  80870. color: '#767676',
  80871. family: "'Segoe UI', 'Helvetica Neue', 'Trebuchet MS', Verdana",
  80872. weight: 400,
  80873. size: 12,
  80874. cursor: 'default'
  80875. },
  80876. redrawOnResize: true,
  80877. backgroundColor: WHITE,
  80878. primaryTitleColor: "#232323",
  80879. secondaryTitleColor: "#767676",
  80880. axisColor: LIGHT_GREY,
  80881. axisLabelColor: "#a8a8a8",
  80882. title: {font: {
  80883. family: "'Segoe UI Light', 'Helvetica Neue Light', 'Segoe UI', 'Helvetica Neue', 'Trebuchet MS', Verdana",
  80884. weight: 200
  80885. }},
  80886. loadingIndicator: {text: "Loading..."},
  80887. tooltip: {
  80888. enabled: false,
  80889. border: {
  80890. width: 1,
  80891. color: LIGHT_GREY,
  80892. dashStyle: 'solid',
  80893. visible: true
  80894. },
  80895. font: {color: '#232323'},
  80896. color: WHITE,
  80897. arrowLength: 10,
  80898. paddingLeftRight: 18,
  80899. paddingTopBottom: 15,
  80900. shared: false,
  80901. location: 'center',
  80902. format: '',
  80903. argumentFormat: '',
  80904. precision: 0,
  80905. argumentPrecision: 0,
  80906. percentPrecision: 0,
  80907. shadow: {
  80908. opacity: 0.4,
  80909. offsetX: 0,
  80910. offsetY: 4,
  80911. blur: 2,
  80912. color: BLACK
  80913. }
  80914. },
  80915. legend: {
  80916. hoverMode: 'includePoints',
  80917. verticalAlignment: 'top',
  80918. horizontalAlignment: 'right',
  80919. position: 'outside',
  80920. visible: true,
  80921. margin: 10,
  80922. markerSize: 12,
  80923. border: {
  80924. visible: false,
  80925. width: 1,
  80926. cornerRadius: 0,
  80927. dashStyle: 'solid'
  80928. },
  80929. paddingLeftRight: 20,
  80930. paddingTopBottom: 15,
  80931. columnCount: 0,
  80932. rowCount: 0,
  80933. columnItemSpacing: 20,
  80934. rowItemSpacing: 8
  80935. },
  80936. "chart:common": {
  80937. animation: {
  80938. enabled: true,
  80939. duration: 1000,
  80940. easing: 'easeOutCubic',
  80941. maxPointCountSupported: 300
  80942. },
  80943. commonSeriesSettings: {
  80944. border: {
  80945. visible: false,
  80946. width: 2
  80947. },
  80948. showInLegend: true,
  80949. visible: true,
  80950. hoverMode: 'nearestPoint',
  80951. selectionMode: 'includePoints',
  80952. hoverStyle: {
  80953. hatching: {
  80954. direction: 'right',
  80955. width: 2,
  80956. step: 6,
  80957. opacity: 0.75
  80958. },
  80959. border: {
  80960. visible: false,
  80961. width: 3
  80962. }
  80963. },
  80964. selectionStyle: {
  80965. hatching: {
  80966. direction: 'right',
  80967. width: 2,
  80968. step: 6,
  80969. opacity: 0.5
  80970. },
  80971. border: {
  80972. visible: false,
  80973. width: 3
  80974. }
  80975. },
  80976. valueErrorBar: {
  80977. displayMode: "auto",
  80978. value: 1,
  80979. color: BLACK,
  80980. lineWidth: 2,
  80981. edgeLength: 8
  80982. },
  80983. label: {
  80984. visible: false,
  80985. alignment: 'center',
  80986. rotationAngle: 0,
  80987. horizontalOffset: 0,
  80988. verticalOffset: 0,
  80989. radialOffset: 0,
  80990. format: '',
  80991. argumentFormat: '',
  80992. precision: 0,
  80993. argumentPrecision: 0,
  80994. percentPrecision: 0,
  80995. showForZeroValues: true,
  80996. customizeText: undefined,
  80997. maxLabelCount: undefined,
  80998. position: 'outside',
  80999. font: {color: WHITE},
  81000. border: {
  81001. visible: false,
  81002. width: 1,
  81003. color: LIGHT_GREY,
  81004. dashStyle: 'solid'
  81005. },
  81006. connector: {
  81007. visible: false,
  81008. width: 1
  81009. }
  81010. }
  81011. },
  81012. seriesSelectionMode: 'single',
  81013. pointSelectionMode: 'single',
  81014. equalRowHeight: true,
  81015. dataPrepareSettings: {
  81016. checkTypeForAllData: false,
  81017. convertToAxisDataType: true,
  81018. sortingMethod: true
  81019. },
  81020. title: {
  81021. font: {size: 28},
  81022. margin: 10
  81023. },
  81024. adaptiveLayout: {
  81025. width: 80,
  81026. height: 80,
  81027. keepLabels: true
  81028. },
  81029. _rtl: {legend: {itemTextPosition: 'left'}},
  81030. resolveLabelOverlapping: "none"
  81031. },
  81032. "chart:common:axis": {
  81033. visible: false,
  81034. setTicksAtUnitBeginning: true,
  81035. valueMarginsEnabled: true,
  81036. placeholderSize: null,
  81037. logarithmBase: 10,
  81038. discreteAxisDivisionMode: 'betweenLabels',
  81039. width: 1,
  81040. label: {
  81041. visible: true,
  81042. precision: 0,
  81043. format: ""
  81044. },
  81045. grid: {
  81046. visible: false,
  81047. width: 1
  81048. },
  81049. minorGrid: {
  81050. visible: false,
  81051. width: 1,
  81052. opacity: 0.3
  81053. },
  81054. tick: {visible: false},
  81055. minorTick: {
  81056. visible: false,
  81057. opacity: 0.3
  81058. },
  81059. stripStyle: {
  81060. paddingLeftRight: 10,
  81061. paddingTopBottom: 5
  81062. },
  81063. constantLineStyle: {
  81064. width: 1,
  81065. color: BLACK,
  81066. dashStyle: "solid",
  81067. label: {
  81068. visible: true,
  81069. position: "inside"
  81070. }
  81071. }
  81072. },
  81073. chart: {
  81074. commonSeriesSettings: {
  81075. type: 'line',
  81076. stack: 'default',
  81077. point: {
  81078. visible: true,
  81079. symbol: 'circle',
  81080. size: 12,
  81081. border: {
  81082. visible: false,
  81083. width: 1
  81084. },
  81085. hoverMode: 'onlyPoint',
  81086. selectionMode: 'onlyPoint',
  81087. hoverStyle: {
  81088. border: {
  81089. visible: true,
  81090. width: 4
  81091. },
  81092. size: 12
  81093. },
  81094. selectionStyle: {
  81095. border: {
  81096. visible: true,
  81097. width: 4
  81098. },
  81099. size: 12
  81100. }
  81101. },
  81102. scatter: {},
  81103. line: {
  81104. width: 2,
  81105. dashStyle: 'solid',
  81106. hoverStyle: {
  81107. width: 3,
  81108. hatching: {direction: 'none'}
  81109. },
  81110. selectionStyle: {width: 3}
  81111. },
  81112. stackedline: {
  81113. width: 2,
  81114. dashStyle: 'solid',
  81115. hoverStyle: {
  81116. width: 3,
  81117. hatching: {direction: 'none'}
  81118. },
  81119. selectionStyle: {width: 3}
  81120. },
  81121. stackedspline: {
  81122. width: 2,
  81123. dashStyle: 'solid',
  81124. hoverStyle: {
  81125. width: 3,
  81126. hatching: {direction: 'none'}
  81127. },
  81128. selectionStyle: {width: 3}
  81129. },
  81130. fullstackedline: {
  81131. width: 2,
  81132. dashStyle: 'solid',
  81133. hoverStyle: {
  81134. width: 3,
  81135. hatching: {direction: 'none'}
  81136. },
  81137. selectionStyle: {width: 3}
  81138. },
  81139. fullstackedspline: {
  81140. width: 2,
  81141. dashStyle: 'solid',
  81142. hoverStyle: {
  81143. width: 3,
  81144. hatching: {direction: 'none'}
  81145. },
  81146. selectionStyle: {width: 3}
  81147. },
  81148. stepline: {
  81149. width: 2,
  81150. dashStyle: 'solid',
  81151. hoverStyle: {
  81152. width: 3,
  81153. hatching: {direction: 'none'}
  81154. },
  81155. selectionStyle: {width: 3}
  81156. },
  81157. area: {
  81158. point: {visible: false},
  81159. opacity: 0.5
  81160. },
  81161. stackedarea: {
  81162. point: {visible: false},
  81163. opacity: 0.5
  81164. },
  81165. fullstackedarea: {
  81166. point: {visible: false},
  81167. opacity: 0.5
  81168. },
  81169. fullstackedsplinearea: {
  81170. point: {visible: false},
  81171. opacity: 0.5
  81172. },
  81173. steparea: {
  81174. border: {
  81175. visible: true,
  81176. width: 2
  81177. },
  81178. point: {visible: false},
  81179. hoverStyle: {border: {
  81180. visible: true,
  81181. width: 3
  81182. }},
  81183. selectionStyle: {border: {
  81184. visible: true,
  81185. width: 3
  81186. }},
  81187. opacity: 0.5
  81188. },
  81189. spline: {
  81190. width: 2,
  81191. hoverStyle: {
  81192. width: 3,
  81193. hatching: {direction: 'none'}
  81194. },
  81195. selectionStyle: {width: 3}
  81196. },
  81197. splinearea: {
  81198. point: {visible: false},
  81199. opacity: 0.5
  81200. },
  81201. stackedsplinearea: {
  81202. point: {visible: false},
  81203. opacity: 0.5
  81204. },
  81205. bar: {
  81206. cornerRadius: 0,
  81207. point: {
  81208. hoverStyle: {border: {visible: false}},
  81209. selectionStyle: {border: {visible: false}}
  81210. }
  81211. },
  81212. stackedbar: {
  81213. cornerRadius: 0,
  81214. point: {
  81215. hoverStyle: {border: {visible: false}},
  81216. selectionStyle: {border: {visible: false}}
  81217. },
  81218. label: {position: "inside"}
  81219. },
  81220. fullstackedbar: {
  81221. cornerRadius: 0,
  81222. point: {
  81223. hoverStyle: {border: {visible: false}},
  81224. selectionStyle: {border: {visible: false}}
  81225. },
  81226. label: {position: "inside"}
  81227. },
  81228. rangebar: {
  81229. cornerRadius: 0,
  81230. point: {
  81231. hoverStyle: {border: {visible: false}},
  81232. selectionStyle: {border: {visible: false}}
  81233. }
  81234. },
  81235. rangearea: {
  81236. point: {visible: false},
  81237. opacity: 0.5
  81238. },
  81239. rangesplinearea: {
  81240. point: {visible: false},
  81241. opacity: 0.5
  81242. },
  81243. bubble: {
  81244. opacity: 0.5,
  81245. point: {
  81246. hoverStyle: {border: {visible: false}},
  81247. selectionStyle: {border: {visible: false}}
  81248. }
  81249. },
  81250. candlestick: {
  81251. width: 1,
  81252. reduction: {color: RED},
  81253. hoverStyle: {
  81254. width: 3,
  81255. hatching: {direction: 'none'}
  81256. },
  81257. selectionStyle: {width: 3},
  81258. point: {border: {visible: true}}
  81259. },
  81260. stock: {
  81261. width: 1,
  81262. reduction: {color: RED},
  81263. hoverStyle: {
  81264. width: 3,
  81265. hatching: {direction: 'none'}
  81266. },
  81267. selectionStyle: {width: 3},
  81268. point: {border: {visible: true}}
  81269. }
  81270. },
  81271. crosshair: {
  81272. enabled: false,
  81273. color: '#f78119',
  81274. width: 1,
  81275. dashStyle: 'solid',
  81276. label: {
  81277. visible: false,
  81278. font: {
  81279. color: WHITE,
  81280. size: 12
  81281. }
  81282. },
  81283. verticalLine: {visible: true},
  81284. horizontalLine: {visible: true}
  81285. },
  81286. commonAxisSettings: {
  81287. multipleAxesSpacing: 5,
  81288. label: {
  81289. overlappingBehavior: {
  81290. mode: 'auto',
  81291. rotationAngle: 90,
  81292. staggeringSpacing: 5
  81293. },
  81294. indentFromAxis: 10
  81295. },
  81296. title: {
  81297. font: {size: 16},
  81298. margin: 6
  81299. },
  81300. constantLineStyle: {
  81301. paddingLeftRight: 10,
  81302. paddingTopBottom: 10
  81303. }
  81304. },
  81305. horizontalAxis: {
  81306. position: 'bottom',
  81307. axisDivisionFactor: 50,
  81308. label: {alignment: "center"},
  81309. stripStyle: {label: {
  81310. horizontalAlignment: 'center',
  81311. verticalAlignment: 'top'
  81312. }},
  81313. constantLineStyle: {label: {
  81314. horizontalAlignment: 'right',
  81315. verticalAlignment: 'top'
  81316. }},
  81317. constantLines: {}
  81318. },
  81319. verticalAxis: {
  81320. position: 'left',
  81321. axisDivisionFactor: 30,
  81322. label: {
  81323. alignment: 'right',
  81324. overlappingBehavior: {mode: 'enlargeTickInterval'}
  81325. },
  81326. stripStyle: {label: {
  81327. horizontalAlignment: 'left',
  81328. verticalAlignment: 'center'
  81329. }},
  81330. constantLineStyle: {label: {
  81331. horizontalAlignment: 'left',
  81332. verticalAlignment: 'top'
  81333. }},
  81334. constantLines: {}
  81335. },
  81336. argumentAxis: {},
  81337. valueAxis: {grid: {visible: true}},
  81338. commonPaneSettings: {
  81339. backgroundColor: 'none',
  81340. border: {
  81341. color: LIGHT_GREY,
  81342. width: 1,
  81343. visible: false,
  81344. top: true,
  81345. bottom: true,
  81346. left: true,
  81347. right: true,
  81348. dashStyle: 'solid'
  81349. }
  81350. },
  81351. scrollBar: {
  81352. visible: false,
  81353. offset: 5,
  81354. color: "gray",
  81355. width: 10
  81356. },
  81357. useAggregation: false,
  81358. adjustOnZoom: true,
  81359. rotated: false,
  81360. zoomingMode: 'none',
  81361. scrollingMode: 'none',
  81362. synchronizeMultiAxes: true,
  81363. equalBarWidth: true,
  81364. minBubbleSize: 12,
  81365. maxBubbleSize: 0.2
  81366. },
  81367. pie: {
  81368. commonSeriesSettings: {
  81369. type: 'pie',
  81370. pie: {
  81371. border: {
  81372. visible: false,
  81373. width: 2,
  81374. color: WHITE
  81375. },
  81376. hoverStyle: {
  81377. hatching: {
  81378. direction: 'right',
  81379. width: 4,
  81380. step: 10,
  81381. opacity: 0.75
  81382. },
  81383. border: {
  81384. visible: false,
  81385. width: 2
  81386. }
  81387. },
  81388. selectionStyle: {
  81389. hatching: {
  81390. direction: 'right',
  81391. width: 4,
  81392. step: 10,
  81393. opacity: 0.5
  81394. },
  81395. border: {
  81396. visible: false,
  81397. width: 2
  81398. }
  81399. }
  81400. },
  81401. doughnut: {
  81402. innerRadius: 0.5,
  81403. border: {
  81404. visible: false,
  81405. width: 2,
  81406. color: WHITE
  81407. },
  81408. hoverStyle: {
  81409. hatching: {
  81410. direction: 'right',
  81411. width: 4,
  81412. step: 10,
  81413. opacity: 0.75
  81414. },
  81415. border: {
  81416. visible: false,
  81417. width: 2
  81418. }
  81419. },
  81420. selectionStyle: {
  81421. hatching: {
  81422. direction: 'right',
  81423. width: 4,
  81424. step: 10,
  81425. opacity: 0.5
  81426. },
  81427. border: {
  81428. visible: false,
  81429. width: 2
  81430. }
  81431. }
  81432. },
  81433. donut: {
  81434. innerRadius: 0.5,
  81435. border: {
  81436. visible: false,
  81437. width: 2,
  81438. color: WHITE
  81439. },
  81440. hoverStyle: {
  81441. hatching: {
  81442. direction: 'right',
  81443. width: 4,
  81444. step: 10,
  81445. opacity: 0.75
  81446. },
  81447. border: {
  81448. visible: false,
  81449. width: 2
  81450. }
  81451. },
  81452. selectionStyle: {
  81453. hatching: {
  81454. direction: 'right',
  81455. width: 4,
  81456. step: 10,
  81457. opacity: 0.5
  81458. },
  81459. border: {
  81460. visible: false,
  81461. width: 2
  81462. }
  81463. }
  81464. }
  81465. },
  81466. legend: {
  81467. hoverMode: 'markPoint',
  81468. backgroundColor: "none"
  81469. },
  81470. adaptiveLayout: {keepLabels: false}
  81471. },
  81472. pieIE8: {commonSeriesSettings: {
  81473. pie: {
  81474. hoverStyle: {border: {
  81475. visible: true,
  81476. color: WHITE
  81477. }},
  81478. selectionStyle: {border: {
  81479. visible: true,
  81480. color: WHITE
  81481. }}
  81482. },
  81483. donut: {
  81484. hoverStyle: {border: {
  81485. visible: true,
  81486. color: WHITE
  81487. }},
  81488. selectionStyle: {border: {
  81489. visible: true,
  81490. color: WHITE
  81491. }}
  81492. },
  81493. doughnut: {
  81494. hoverStyle: {border: {
  81495. visible: true,
  81496. color: WHITE
  81497. }},
  81498. selectionStyle: {border: {
  81499. visible: true,
  81500. color: WHITE
  81501. }}
  81502. }
  81503. }},
  81504. gauge: {
  81505. scale: {
  81506. majorTick: {
  81507. visible: true,
  81508. length: 5,
  81509. width: 2,
  81510. showCalculatedTicks: true,
  81511. useTicksAutoArrangement: true
  81512. },
  81513. minorTick: {
  81514. visible: false,
  81515. length: 3,
  81516. width: 1,
  81517. showCalculatedTicks: true
  81518. },
  81519. label: {visible: true}
  81520. },
  81521. rangeContainer: {
  81522. offset: 0,
  81523. width: 5,
  81524. backgroundColor: '#808080'
  81525. },
  81526. valueIndicators: {
  81527. _default: {color: '#c2c2c2'},
  81528. rangebar: {
  81529. space: 2,
  81530. size: 10,
  81531. color: '#cbc5cf',
  81532. backgroundColor: 'none',
  81533. text: {
  81534. indent: 0,
  81535. font: {
  81536. size: 14,
  81537. color: null
  81538. }
  81539. }
  81540. },
  81541. twocolorneedle: {secondColor: '#e18e92'},
  81542. trianglemarker: {
  81543. space: 2,
  81544. length: 14,
  81545. width: 13,
  81546. color: '#8798a5'
  81547. },
  81548. textcloud: {
  81549. arrowLength: 5,
  81550. horizontalOffset: 6,
  81551. verticalOffset: 3,
  81552. color: '#679ec5',
  81553. text: {font: {
  81554. color: WHITE,
  81555. size: 18
  81556. }}
  81557. }
  81558. },
  81559. title: {
  81560. layout: {
  81561. horizontalAlignment: 'center',
  81562. verticalAlignment: 'top',
  81563. overlay: 0
  81564. },
  81565. font: {size: 16}
  81566. },
  81567. subtitle: {font: {size: 14}},
  81568. indicator: {
  81569. hasPositiveMeaning: true,
  81570. layout: {
  81571. horizontalAlignment: 'center',
  81572. verticalAlignment: 'bottom',
  81573. overlay: 0
  81574. },
  81575. text: {font: {size: 18}}
  81576. },
  81577. _circular: {
  81578. scale: {
  81579. orientation: 'outside',
  81580. label: {indentFromTick: 10}
  81581. },
  81582. rangeContainer: {orientation: 'outside'},
  81583. valueIndicatorType: 'rectangleneedle',
  81584. subvalueIndicatorType: 'trianglemarker',
  81585. valueIndicators: {
  81586. _type: 'rectangleneedle',
  81587. _default: {
  81588. offset: 20,
  81589. indentFromCenter: 0,
  81590. width: 2,
  81591. spindleSize: 14,
  81592. spindleGapSize: 10
  81593. },
  81594. triangleneedle: {width: 4},
  81595. twocolorneedle: {
  81596. space: 2,
  81597. secondFraction: 0.4
  81598. },
  81599. rangebar: {offset: 30},
  81600. trianglemarker: {offset: 6},
  81601. textcloud: {offset: -6}
  81602. }
  81603. },
  81604. _linear: {
  81605. scale: {
  81606. horizontalOrientation: 'right',
  81607. verticalOrientation: 'bottom',
  81608. label: {indentFromTick: -10}
  81609. },
  81610. rangeContainer: {
  81611. horizontalOrientation: 'right',
  81612. verticalOrientation: 'bottom'
  81613. },
  81614. valueIndicatorType: 'rangebar',
  81615. subvalueIndicatorType: 'trianglemarker',
  81616. valueIndicators: {
  81617. _type: 'rectangle',
  81618. _default: {
  81619. offset: 2.5,
  81620. length: 15,
  81621. width: 15
  81622. },
  81623. rectangle: {width: 10},
  81624. rangebar: {
  81625. offset: 10,
  81626. horizontalOrientation: 'right',
  81627. verticalOrientation: 'bottom'
  81628. },
  81629. trianglemarker: {
  81630. offset: -1,
  81631. horizontalOrientation: 'left',
  81632. verticalOrientation: 'top'
  81633. },
  81634. textcloud: {
  81635. offset: -1,
  81636. horizontalOrientation: 'left',
  81637. verticalOrientation: 'top'
  81638. }
  81639. }
  81640. }
  81641. },
  81642. barGauge: {
  81643. backgroundColor: '#e0e0e0',
  81644. relativeInnerRadius: 0.3,
  81645. barSpacing: 4,
  81646. label: {
  81647. indent: 20,
  81648. connectorWidth: 2,
  81649. font: {size: 16}
  81650. },
  81651. title: {
  81652. layout: {
  81653. horizontalAlignment: 'center',
  81654. verticalAlignment: 'top',
  81655. overlay: 0
  81656. },
  81657. font: {size: 16}
  81658. },
  81659. subtitle: {font: {size: 14}},
  81660. indicator: {
  81661. hasPositiveMeaning: true,
  81662. layout: {
  81663. horizontalAlignment: 'center',
  81664. verticalAlignment: 'bottom',
  81665. overlay: 0
  81666. },
  81667. text: {font: {size: 18}}
  81668. }
  81669. },
  81670. rangeSelector: {
  81671. scale: {
  81672. showCustomBoundaryTicks: true,
  81673. showMinorTicks: true,
  81674. useTicksAutoArrangement: true,
  81675. setTicksAtUnitBeginning: true,
  81676. label: {
  81677. visible: true,
  81678. topIndent: 7,
  81679. font: {size: 11}
  81680. },
  81681. tick: {
  81682. width: 1,
  81683. color: BLACK,
  81684. opacity: 0.1
  81685. },
  81686. marker: {
  81687. visible: true,
  81688. separatorHeight: 33,
  81689. topIndent: 10,
  81690. textLeftIndent: 7,
  81691. textTopIndent: 11,
  81692. label: {}
  81693. },
  81694. logarithmBase: 10
  81695. },
  81696. selectedRangeColor: "#606060",
  81697. sliderMarker: {
  81698. visible: true,
  81699. paddingTopBottom: 2,
  81700. paddingLeftRight: 4,
  81701. color: '#606060',
  81702. invalidRangeColor: RED,
  81703. font: {
  81704. color: WHITE,
  81705. size: 11
  81706. }
  81707. },
  81708. sliderHandle: {
  81709. width: 1,
  81710. color: BLACK,
  81711. opacity: 0.2
  81712. },
  81713. shutter: {opacity: 0.75},
  81714. background: {
  81715. color: "#c0bae1",
  81716. visible: true,
  81717. image: {location: 'full'}
  81718. },
  81719. behavior: {
  81720. snapToTicks: true,
  81721. animationEnabled: true,
  81722. moveSelectedRangeByClick: true,
  81723. manualRangeSelectionEnabled: true,
  81724. allowSlidersSwap: true,
  81725. callSelectedRangeChanged: "onMovingComplete"
  81726. },
  81727. redrawOnResize: true,
  81728. chart: {
  81729. useAggregation: false,
  81730. equalBarWidth: true,
  81731. minBubbleSize: 12,
  81732. maxBubbleSize: 0.2,
  81733. topIndent: 0.1,
  81734. bottomIndent: 0,
  81735. valueAxis: {
  81736. inverted: false,
  81737. logarithmBase: 10
  81738. },
  81739. commonSeriesSettings: {
  81740. type: "area",
  81741. point: {visible: false}
  81742. }
  81743. }
  81744. },
  81745. map: {
  81746. background: {
  81747. borderWidth: 1,
  81748. borderColor: '#cacaca'
  81749. },
  81750. areaSettings: {
  81751. borderWidth: 1,
  81752. borderColor: WHITE,
  81753. color: '#d2d2d2',
  81754. hoveredBorderColor: GREY_GREEN,
  81755. selectedBorderWidth: 2,
  81756. selectedBorderColor: GREY_GREEN,
  81757. label: {
  81758. enabled: false,
  81759. stroke: WHITE,
  81760. 'stroke-width': 2,
  81761. 'stroke-opacity': 0.5,
  81762. font: {
  81763. color: '#2b2b2b',
  81764. size: 16,
  81765. opacity: 0.5
  81766. }
  81767. }
  81768. },
  81769. markerSettings: {
  81770. label: {
  81771. enabled: true,
  81772. stroke: WHITE,
  81773. 'stroke-width': 1,
  81774. 'stroke-opacity': 0.5,
  81775. font: {
  81776. color: '#2b2b2b',
  81777. size: 12
  81778. }
  81779. },
  81780. _dot: {
  81781. borderWidth: 2,
  81782. borderColor: WHITE,
  81783. color: '#ba4d51',
  81784. size: 8,
  81785. selectedStep: 2,
  81786. backStep: 18,
  81787. backColor: WHITE,
  81788. backOpacity: 0.32,
  81789. shadow: true
  81790. },
  81791. _bubble: {
  81792. minSize: 20,
  81793. maxSize: 50,
  81794. color: '#ba4d51',
  81795. hoveredBorderWidth: 1,
  81796. hoveredBorderColor: GREY_GREEN,
  81797. selectedBorderWidth: 2,
  81798. selectedBorderColor: GREY_GREEN
  81799. },
  81800. _pie: {
  81801. size: 50,
  81802. hoveredBorderWidth: 1,
  81803. hoveredBorderColor: GREY_GREEN,
  81804. selectedBorderWidth: 2,
  81805. selectedBorderColor: GREY_GREEN
  81806. },
  81807. _image: {size: 20}
  81808. },
  81809. legend: {
  81810. verticalAlignment: 'bottom',
  81811. horizontalAlignment: 'right',
  81812. position: 'inside',
  81813. backgroundOpacity: 0.65,
  81814. border: {
  81815. visible: true,
  81816. color: '#cacaca'
  81817. },
  81818. paddingLeftRight: 16,
  81819. paddingTopBottom: 12,
  81820. markerColor: '#ba4d51'
  81821. },
  81822. controlBar: {
  81823. borderColor: '#5d5d5d',
  81824. borderWidth: 3,
  81825. color: WHITE,
  81826. margin: 20,
  81827. opacity: 0.3
  81828. },
  81829. _rtl: {legend: {itemTextPosition: 'left'}}
  81830. },
  81831. sparkline: {
  81832. lineColor: '#666666',
  81833. lineWidth: 2,
  81834. areaOpacity: 0.2,
  81835. minColor: '#e8c267',
  81836. maxColor: '#e55253',
  81837. barPositiveColor: '#a9a9a9',
  81838. barNegativeColor: '#d7d7d7',
  81839. winColor: '#a9a9a9',
  81840. lossColor: '#d7d7d7',
  81841. firstLastColor: '#666666',
  81842. pointSymbol: 'circle',
  81843. pointColor: WHITE,
  81844. pointSize: 4,
  81845. type: "line",
  81846. argumentField: "arg",
  81847. valueField: "val",
  81848. winlossThreshold: 0,
  81849. showFirstLast: true,
  81850. showMinMax: false,
  81851. tooltip: {enabled: true}
  81852. },
  81853. bullet: {
  81854. color: '#e8c267',
  81855. targetColor: '#666666',
  81856. targetWidth: 4,
  81857. showTarget: true,
  81858. showZeroLevel: true,
  81859. tooltip: {enabled: true}
  81860. },
  81861. polar: {
  81862. commonSeriesSettings: {
  81863. type: 'scatter',
  81864. closed: true,
  81865. point: {
  81866. visible: true,
  81867. symbol: 'circle',
  81868. size: 12,
  81869. border: {
  81870. visible: false,
  81871. width: 1
  81872. },
  81873. hoverMode: 'onlyPoint',
  81874. selectionMode: 'onlyPoint',
  81875. hoverStyle: {
  81876. border: {
  81877. visible: true,
  81878. width: 4
  81879. },
  81880. size: 12
  81881. },
  81882. selectionStyle: {
  81883. border: {
  81884. visible: true,
  81885. width: 4
  81886. },
  81887. size: 12
  81888. }
  81889. },
  81890. scatter: {},
  81891. line: {
  81892. width: 2,
  81893. dashStyle: 'solid',
  81894. hoverStyle: {
  81895. width: 3,
  81896. hatching: {direction: 'none'}
  81897. },
  81898. selectionStyle: {width: 3}
  81899. },
  81900. area: {
  81901. point: {visible: false},
  81902. opacity: 0.5
  81903. },
  81904. stackedline: {width: 2},
  81905. bar: {opacity: 0.8},
  81906. stackedbar: {opacity: 0.8}
  81907. },
  81908. adaptiveLayout: {
  81909. width: 170,
  81910. height: 170,
  81911. keepLabels: true
  81912. },
  81913. equalBarWidth: true,
  81914. commonAxisSettings: {
  81915. visible: true,
  81916. label: {
  81917. overlappingBehavior: {mode: 'enlargeTickInterval'},
  81918. indentFromAxis: 5
  81919. },
  81920. grid: {visible: true},
  81921. minorGrid: {visible: true},
  81922. tick: {visible: true},
  81923. title: {
  81924. font: {size: 16},
  81925. margin: 10
  81926. }
  81927. },
  81928. argumentAxis: {
  81929. startAngle: 0,
  81930. firstPointOnStartAngle: false,
  81931. period: undefined
  81932. },
  81933. valueAxis: {tick: {visible: false}},
  81934. horizontalAxis: {
  81935. position: 'top',
  81936. axisDivisionFactor: 50,
  81937. label: {alignment: "center"}
  81938. },
  81939. verticalAxis: {
  81940. position: 'top',
  81941. axisDivisionFactor: 30,
  81942. label: {alignment: "right"}
  81943. }
  81944. }
  81945. });
  81946. DX.viz.core.registerTheme({
  81947. name: "generic.dark",
  81948. font: {color: '#808080'},
  81949. backgroundColor: GREY_GREEN,
  81950. primaryTitleColor: "#dbdbdb",
  81951. secondaryTitleColor: "#a3a3a3",
  81952. axisColor: "#555555",
  81953. axisLabelColor: "#707070",
  81954. tooltip: {
  81955. color: '#2b2b2b',
  81956. border: {color: '#494949'},
  81957. font: {color: '#929292'}
  81958. },
  81959. "chart:common": {commonSeriesSettings: {
  81960. label: {border: {color: '#494949'}},
  81961. valueErrorBar: {color: WHITE}
  81962. }},
  81963. "chart:common:axis": {constantLineStyle: {color: WHITE}},
  81964. chart: {
  81965. crosshair: {color: '#515151'},
  81966. commonPaneSettings: {border: {color: '#494949'}}
  81967. },
  81968. pieIE8: {commonSeriesSettings: {
  81969. pie: {
  81970. hoverStyle: {border: {color: '#2b2b2b'}},
  81971. selectionStyle: {border: {color: '#2b2b2b'}}
  81972. },
  81973. donut: {
  81974. hoverStyle: {border: {color: '#2b2b2b'}},
  81975. selectionStyle: {border: {color: '#2b2b2b'}}
  81976. },
  81977. doughnut: {
  81978. hoverStyle: {border: {color: '#2b2b2b'}},
  81979. selectionStyle: {border: {color: '#2b2b2b'}}
  81980. }
  81981. }},
  81982. gauge: {
  81983. rangeContainer: {backgroundColor: '#b5b5b5'},
  81984. valueIndicators: {
  81985. _default: {color: '#b5b5b5'},
  81986. rangebar: {color: '#84788b'},
  81987. twocolorneedle: {secondColor: '#ba544d'},
  81988. trianglemarker: {color: '#b7918f'},
  81989. textcloud: {color: '#ba544d'}
  81990. }
  81991. },
  81992. barGauge: {backgroundColor: "#3c3c3c"},
  81993. rangeSelector: {
  81994. selectedRangeColor: '#b5b5b5',
  81995. scale: {tick: {
  81996. color: WHITE,
  81997. opacity: 0.05
  81998. }},
  81999. sliderMarker: {
  82000. color: '#b5b5b5',
  82001. font: {color: GREY_GREEN}
  82002. },
  82003. sliderHandle: {
  82004. color: WHITE,
  82005. opacity: 0.2
  82006. },
  82007. shutter: {
  82008. color: '#2b2b2b',
  82009. opacity: 0.9
  82010. }
  82011. },
  82012. map: {
  82013. background: {borderColor: '#3f3f3f'},
  82014. areaSettings: {
  82015. borderColor: GREY_GREEN,
  82016. color: '#686868',
  82017. hoveredBorderColor: WHITE,
  82018. selectedBorderColor: WHITE,
  82019. label: {
  82020. stroke: BLACK,
  82021. font: {color: WHITE}
  82022. }
  82023. },
  82024. markerSettings: {
  82025. label: {
  82026. stroke: BLACK,
  82027. font: {color: WHITE}
  82028. },
  82029. _bubble: {
  82030. hoveredBorderColor: WHITE,
  82031. selectedBorderColor: WHITE
  82032. },
  82033. _pie: {
  82034. hoveredBorderColor: WHITE,
  82035. selectedBorderColor: WHITE
  82036. }
  82037. },
  82038. legend: {
  82039. border: {color: '#3f3f3f'},
  82040. font: {color: WHITE}
  82041. },
  82042. controlBar: {
  82043. borderColor: '#c7c7c7',
  82044. color: GREY_GREEN
  82045. }
  82046. },
  82047. sparkline: {
  82048. lineColor: '#c7c7c7',
  82049. firstLastColor: '#c7c7c7',
  82050. barPositiveColor: '#b8b8b8',
  82051. barNegativeColor: '#8e8e8e',
  82052. winColor: '#b8b8b8',
  82053. lossColor: '#8e8e8e',
  82054. pointColor: GREY_GREEN
  82055. },
  82056. bullet: {targetColor: '#8e8e8e'}
  82057. }, "generic.light");
  82058. DX.viz.core.currentTheme("generic.light");
  82059. DX.viz.core.registerThemeAlias("desktop.light", "generic.light");
  82060. DX.viz.core.registerThemeAlias("desktop.dark", "generic.dark")
  82061. })(DevExpress);
  82062. /*! Module viz-core, file android.js */
  82063. (function(DX) {
  82064. var ANDROID5_LIGHT = "android5.light",
  82065. registerThemeAlias = DX.viz.core.registerThemeAlias;
  82066. DX.viz.core.registerTheme({
  82067. name: ANDROID5_LIGHT,
  82068. backgroundColor: "#ffffff",
  82069. primaryTitleColor: "#232323",
  82070. secondaryTitleColor: "#767676",
  82071. axisColor: "#d3d3d3",
  82072. axisLabelColor: "#a8a8a8",
  82073. tooltip: {
  82074. color: "#e8e8e8",
  82075. font: {color: "#808080"}
  82076. },
  82077. legend: {font: {color: "#000000"}},
  82078. pieIE8: {commonSeriesSettings: {
  82079. pie: {
  82080. hoverStyle: {border: {color: '#e8e8e8'}},
  82081. selectionStyle: {border: {color: '#e8e8e8'}}
  82082. },
  82083. donut: {
  82084. hoverStyle: {border: {color: '#e8e8e8'}},
  82085. selectionStyle: {border: {color: '#e8e8e8'}}
  82086. },
  82087. doughnut: {
  82088. hoverStyle: {border: {color: '#e8e8e8'}},
  82089. selectionStyle: {border: {color: '#e8e8e8'}}
  82090. }
  82091. }}
  82092. }, "generic.light");
  82093. registerThemeAlias("android", ANDROID5_LIGHT);
  82094. registerThemeAlias("android.holo-dark", ANDROID5_LIGHT);
  82095. registerThemeAlias("android.holo-light", ANDROID5_LIGHT);
  82096. registerThemeAlias("android.dark", ANDROID5_LIGHT);
  82097. registerThemeAlias("android.light", ANDROID5_LIGHT)
  82098. })(DevExpress);
  82099. /*! Module viz-core, file ios.js */
  82100. (function(DX) {
  82101. var IOS7_DEFAULT = "ios7.default",
  82102. core = DX.viz.core;
  82103. core.registerTheme({
  82104. name: IOS7_DEFAULT,
  82105. backgroundColor: "#ffffff",
  82106. primaryTitleColor: "#000000",
  82107. secondaryTitleColor: "#767676",
  82108. axisColor: "#ececec",
  82109. axisLabelColor: "#b8b8b8",
  82110. legend: {font: {color: '#000000'}},
  82111. tooltip: {font: {color: '#808080'}},
  82112. "chart:common": {commonSeriesSettings: {label: {border: {color: '#d3d3d3'}}}},
  82113. chart: {commonPaneSettings: {border: {color: '#d3d3d3'}}}
  82114. }, "generic.light");
  82115. core.registerThemeAlias("ios", IOS7_DEFAULT)
  82116. })(DevExpress);
  82117. /*! Module viz-core, file win8.js */
  82118. (function(DX) {
  82119. var core = DX.viz.core,
  82120. registerTheme = core.registerTheme,
  82121. registerThemeSchemeAlias = core.registerThemeSchemeAlias,
  82122. BLACK = "#000000",
  82123. WHITE = "#ffffff";
  82124. registerTheme({
  82125. name: "win8.black",
  82126. backgroundColor: BLACK,
  82127. primaryTitleColor: WHITE,
  82128. secondaryTitleColor: "#d8d8d8",
  82129. axisColor: "#4c4c4c",
  82130. axisLabelColor: "#a0a0a0",
  82131. title: {font: {color: WHITE}},
  82132. legend: {font: {color: WHITE}},
  82133. tooltip: {
  82134. color: BLACK,
  82135. font: {color: WHITE}
  82136. },
  82137. "chart:common": {commonSeriesSettings: {label: {border: {color: '#454545'}}}},
  82138. chart: {commonPaneSettings: {border: {color: '#454545'}}},
  82139. pieIE8: {commonSeriesSettings: {
  82140. pie: {
  82141. hoverStyle: {border: {color: BLACK}},
  82142. selectionStyle: {border: {color: BLACK}}
  82143. },
  82144. donut: {
  82145. hoverStyle: {border: {color: BLACK}},
  82146. selectionStyle: {border: {color: BLACK}}
  82147. },
  82148. doughnut: {
  82149. hoverStyle: {border: {color: BLACK}},
  82150. selectionStyle: {border: {color: BLACK}}
  82151. }
  82152. }},
  82153. barGauge: {backgroundColor: "#2b3036"},
  82154. rangeSelector: {scale: {tick: {opacity: 0.15}}}
  82155. }, "generic.dark");
  82156. registerTheme({
  82157. name: "win8.white",
  82158. backgroundColor: WHITE,
  82159. primaryTitleColor: BLACK,
  82160. secondaryTitleColor: "#767676",
  82161. axisColor: "#ececec",
  82162. axisLabelColor: "#b8b8b8",
  82163. title: {font: {color: '#808080'}},
  82164. legend: {font: {color: BLACK}},
  82165. tooltip: {font: {color: '#808080'}}
  82166. }, "generic.light");
  82167. registerThemeSchemeAlias("win8.dark", "win8.black");
  82168. registerThemeSchemeAlias("win8.light", "win8.white")
  82169. })(DevExpress);
  82170. /*! Module viz-core, file themeManager.js */
  82171. (function($, DX, undefined) {
  82172. var viz = DX.viz,
  82173. Palette = viz.core.Palette,
  82174. utils = DX.utils,
  82175. _findTheme = DX.viz.core.findTheme,
  82176. _isString = utils.isString,
  82177. _isDefined = utils.isDefined,
  82178. HOVER_COLOR_HIGHLIGHTING = 20,
  82179. HIGHLIGHTING_STEP = 50,
  82180. FONT = "font",
  82181. COMMON_AXIS_SETTINGS = "commonAxisSettings",
  82182. PIE_FONT_FIELDS = ["legend." + FONT, "title." + FONT, "tooltip." + FONT, "loadingIndicator." + FONT, "commonSeriesSettings.label." + FONT],
  82183. POLAR_FONT_FIELDS = PIE_FONT_FIELDS.concat([COMMON_AXIS_SETTINGS + ".label." + FONT, COMMON_AXIS_SETTINGS + ".title." + FONT]),
  82184. CHART_FONT_FIELDS = POLAR_FONT_FIELDS.concat(["crosshair.label." + FONT]),
  82185. chartToFontFieldsMap = {
  82186. pie: PIE_FONT_FIELDS,
  82187. chart: CHART_FONT_FIELDS,
  82188. polar: POLAR_FONT_FIELDS
  82189. };
  82190. viz.charts = viz.charts || {};
  82191. viz.charts.ThemeManager = viz.core.BaseThemeManager.inherit(function() {
  82192. var ctor = function(options, themeGroupName) {
  82193. var that = this,
  82194. themeObj;
  82195. that.callBase.apply(that, arguments);
  82196. options = options || {};
  82197. that._userOptions = options;
  82198. that._mergeAxisTitleOptions = [];
  82199. that._themeSection = themeGroupName;
  82200. that._fontFields = chartToFontFieldsMap[themeGroupName];
  82201. that._IE8 = DX.browser.msie && DX.browser.version < 9;
  82202. themeObj = options.theme && _findTheme(_isString(options.theme) ? options.theme : options.theme.name) || {};
  82203. that.palette = new Palette(options.palette, {
  82204. stepHighlight: HIGHLIGHTING_STEP,
  82205. theme: themeObj.name
  82206. });
  82207. that._callback = $.noop
  82208. };
  82209. var dispose = function() {
  82210. var that = this;
  82211. that.palette.dispose();
  82212. that.palette = that._userOptions = that._mergedSettings = null;
  82213. return that.callBase.apply(that, arguments)
  82214. };
  82215. var resetPalette = function() {
  82216. this.palette.reset()
  82217. };
  82218. var updatePalette = function(palette) {
  82219. this.palette = new Palette(palette || this._theme.defaultPalette, {
  82220. stepHighlight: HIGHLIGHTING_STEP,
  82221. theme: this.themeName
  82222. })
  82223. };
  82224. var processTitleOptions = function(options) {
  82225. return _isString(options) ? {text: options} : options
  82226. };
  82227. var processAxisOptions = function(axisOptions) {
  82228. if (!axisOptions)
  82229. return;
  82230. axisOptions = $.extend(true, {}, axisOptions);
  82231. axisOptions.title = processTitleOptions(axisOptions.title);
  82232. if (axisOptions.type === "logarithmic" && axisOptions.logarithmBase <= 0 || axisOptions.logarithmBase && !$.isNumeric(axisOptions.logarithmBase)) {
  82233. axisOptions.logarithmBase = undefined;
  82234. axisOptions.logarithmBaseError = true
  82235. }
  82236. if (axisOptions.label) {
  82237. if (axisOptions.label.alignment)
  82238. axisOptions.label["userAlignment"] = true;
  82239. if (_isString(axisOptions.label.overlappingBehavior))
  82240. axisOptions.label.overlappingBehavior = {mode: axisOptions.label.overlappingBehavior};
  82241. if (!axisOptions.label.overlappingBehavior || !axisOptions.label.overlappingBehavior.mode)
  82242. axisOptions.label.overlappingBehavior = axisOptions.label.overlappingBehavior || {}
  82243. }
  82244. return axisOptions
  82245. };
  82246. var applyParticularAxisOptions = function(name, userOptions, rotated) {
  82247. var theme = this._theme,
  82248. position = !(rotated ^ name === "valueAxis") ? "horizontalAxis" : "verticalAxis",
  82249. commonAxisSettings = processAxisOptions(this._userOptions["commonAxisSettings"], name);
  82250. return $.extend(true, {}, theme.commonAxisSettings, theme[position], theme[name], commonAxisSettings, processAxisOptions(userOptions, name))
  82251. };
  82252. var mergeOptions = function(name, userOptions) {
  82253. userOptions = userOptions || this._userOptions[name];
  82254. var theme = this._theme[name],
  82255. result = this._mergedSettings[name];
  82256. if (result)
  82257. return result;
  82258. if ($.isPlainObject(theme) && $.isPlainObject(userOptions))
  82259. result = $.extend(true, {}, theme, userOptions);
  82260. else
  82261. result = _isDefined(userOptions) ? userOptions : theme;
  82262. this._mergedSettings[name] = result;
  82263. return result
  82264. };
  82265. var applyParticularTheme = {
  82266. base: mergeOptions,
  82267. argumentAxis: applyParticularAxisOptions,
  82268. valueAxisRangeSelector: function() {
  82269. return mergeOptions.call(this, "valueAxis")
  82270. },
  82271. valueAxis: applyParticularAxisOptions,
  82272. title: function(name) {
  82273. var userOptions = processTitleOptions(this._userOptions[name]);
  82274. return mergeOptions.call(this, name, userOptions)
  82275. },
  82276. series: function(name, userOptions) {
  82277. var theme = this._theme,
  82278. userCommonSettings = this._userOptions.commonSeriesSettings || {},
  82279. themeCommonSettings = theme.commonSeriesSettings,
  82280. type = ((userOptions.type || userCommonSettings.type || themeCommonSettings.type) + "").toLowerCase(),
  82281. settings,
  82282. palette = this.palette,
  82283. isBar = ~type.indexOf("bar"),
  82284. isLine = ~type.indexOf("line"),
  82285. isArea = ~type.indexOf("area"),
  82286. isBubble = type === "bubble",
  82287. mainSeriesColor,
  82288. resolveLabelsOverlapping = this.getOptions("resolveLabelsOverlapping"),
  82289. resolveLabelOverlapping = this.getOptions("resolveLabelOverlapping"),
  82290. containerBackgroundColor = this.getOptions("containerBackgroundColor"),
  82291. seriesVisibility;
  82292. if (isBar || isBubble) {
  82293. userOptions = $.extend(true, {}, userCommonSettings, userCommonSettings[type], userOptions);
  82294. seriesVisibility = userOptions.visible;
  82295. userCommonSettings = {type: {}};
  82296. $.extend(true, userOptions, userOptions.point);
  82297. userOptions.visible = seriesVisibility
  82298. }
  82299. settings = $.extend(true, {}, themeCommonSettings, themeCommonSettings[type], userCommonSettings, userCommonSettings[type], userOptions);
  82300. settings.type = type;
  82301. settings.widgetType = this._themeSection.split(".").slice(-1)[0];
  82302. settings.containerBackgroundColor = containerBackgroundColor;
  82303. if (settings.widgetType !== "pie")
  82304. mainSeriesColor = settings.color || palette.getNextColor();
  82305. else
  82306. mainSeriesColor = function() {
  82307. return palette.getNextColor()
  82308. };
  82309. settings.mainSeriesColor = mainSeriesColor;
  82310. settings._IE8 = this._IE8;
  82311. settings.resolveLabelOverlapping = resolveLabelOverlapping;
  82312. settings.resolveLabelsOverlapping = resolveLabelsOverlapping;
  82313. if (settings.label && (isLine || isArea && type !== "rangearea" || type === "scatter"))
  82314. settings.label.position = "outside";
  82315. return settings
  82316. },
  82317. pieSegment: function(name, seriesSettings, segmentSettings) {
  82318. var settings = $.extend(true, {}, seriesSettings, segmentSettings),
  82319. mainColor = new DX.Color(settings.color || this.palette.getNextColor());
  82320. settings.color = mainColor.toHex();
  82321. settings.border.color = settings.border.color || mainColor.toHex();
  82322. settings.hoverStyle.color = settings.hoverStyle.color || this._IE8 && mainColor.highlight(HOVER_COLOR_HIGHLIGHTING) || mainColor.toHex();
  82323. settings.hoverStyle.border.color = settings.hoverStyle.border.color || mainColor.toHex();
  82324. settings.selectionStyle.color = settings.selectionStyle.color || this._IE8 && mainColor.highlight(HOVER_COLOR_HIGHLIGHTING) || mainColor.toHex();
  82325. settings.selectionStyle.border.color = settings.selectionStyle.border.color || mainColor.toHex();
  82326. return settings
  82327. },
  82328. animation: function(name) {
  82329. var userOptions = this._userOptions[name];
  82330. userOptions = $.isPlainObject(userOptions) ? userOptions : _isDefined(userOptions) ? {enabled: !!userOptions} : {};
  82331. return mergeOptions.call(this, name, userOptions)
  82332. }
  82333. };
  82334. return {
  82335. _themeSection: "chart",
  82336. ctor: ctor,
  82337. dispose: dispose,
  82338. resetPalette: resetPalette,
  82339. getOptions: function(name) {
  82340. return (applyParticularTheme[name] || applyParticularTheme.base).apply(this, arguments)
  82341. },
  82342. refresh: function() {
  82343. this._mergedSettings = {};
  82344. return this.callBase.apply(this, arguments)
  82345. },
  82346. resetOptions: function(name) {
  82347. this._mergedSettings[name] = null
  82348. },
  82349. update: function(options) {
  82350. this._userOptions = options
  82351. },
  82352. updatePalette: updatePalette
  82353. }
  82354. }())
  82355. })(jQuery, DevExpress);
  82356. /*! Module viz-core, file factory.js */
  82357. (function($, DX) {
  82358. var viz = DX.viz,
  82359. charts = viz.charts,
  82360. series = charts.series;
  82361. charts.factory = function() {
  82362. var createSeriesFamily = function(options) {
  82363. return new series.SeriesFamily(options)
  82364. };
  82365. var createThemeManager = function(options, groupName) {
  82366. return new charts.ThemeManager(options, groupName)
  82367. };
  82368. var createTracker = function(options, name) {
  82369. return name === "dxPieChart" ? new charts.PieTracker(options) : new charts.ChartTracker(options)
  82370. };
  82371. var createTitle = function(renderer, options, group) {
  82372. return new charts.ChartTitle(renderer, options, group)
  82373. };
  82374. var createChartLayoutManager = function(options) {
  82375. return new charts.LayoutManager(options)
  82376. };
  82377. var createCrosshair = function(renderer, options, params, group) {
  82378. return new charts.Crosshair(renderer, options, params, group)
  82379. };
  82380. return {
  82381. createSeriesFamily: createSeriesFamily,
  82382. createThemeManager: createThemeManager,
  82383. createTracker: createTracker,
  82384. createChartLayoutManager: createChartLayoutManager,
  82385. createTitle: createTitle,
  82386. createCrosshair: createCrosshair,
  82387. createScrollBar: function(renderer, group) {
  82388. return new DevExpress.viz.charts.ScrollBar(renderer, group)
  82389. }
  82390. }
  82391. }()
  82392. })(jQuery, DevExpress);
  82393. /*! Module viz-core, file baseWidget.js */
  82394. (function(DX, $, undefined) {
  82395. var core = DX.viz.core,
  82396. _windowResizeCallbacks = DX.utils.windowResizeCallbacks,
  82397. _Number = Number,
  82398. _stringFormat = DX.utils.stringFormat,
  82399. _isFunction = DX.utils.isFunction,
  82400. _parseScalar = core.utils.parseScalar,
  82401. OPTION_RTL_ENABLED = "rtlEnabled",
  82402. OPTION_LOADING_INDICATOR = "loadingIndicator";
  82403. function defaultIncidentOccured(options) {
  82404. var args = [options.id];
  82405. args.push.apply(args, options.args || []);
  82406. DX.log.apply(null, args)
  82407. }
  82408. function getTrue() {
  82409. return true
  82410. }
  82411. function getFalse() {
  82412. return false
  82413. }
  82414. function areCanvasesDifferent(canvas1, canvas2) {
  82415. return !(canvas1.width === canvas2.width && canvas1.height === canvas2.height && canvas1.left === canvas2.left && canvas1.top === canvas2.top && canvas1.right === canvas2.right && canvas1.bottom === canvas2.bottom)
  82416. }
  82417. function createResizeHandler(callback) {
  82418. var $window = $(window),
  82419. width,
  82420. height,
  82421. timeout;
  82422. handler.dispose = function() {
  82423. clearTimeout(timeout);
  82424. return this
  82425. };
  82426. return handler;
  82427. function handler() {
  82428. width = $window.width();
  82429. height = $window.height();
  82430. clearTimeout(timeout);
  82431. timeout = setTimeout(trigger, 100)
  82432. }
  82433. function trigger() {
  82434. $window.width() === width && $window.height() === height && callback()
  82435. }
  82436. }
  82437. core.DEBUG_createResizeHandler = createResizeHandler;
  82438. core.BaseWidget = DX.DOMComponent.inherit({
  82439. _eventsMap: {
  82440. onIncidentOccurred: {
  82441. name: 'incidentOccured',
  82442. deprecated: 'incidentOccured',
  82443. deprecatedContext: $.noop,
  82444. deprecatedArgs: function(arg) {
  82445. return [arg.target]
  82446. }
  82447. },
  82448. onDrawn: {
  82449. name: 'drawn',
  82450. deprecated: 'drawn',
  82451. deprecatedContext: $.noop,
  82452. deprecatedArgs: function(arg) {
  82453. return [arg.component]
  82454. }
  82455. },
  82456. incidentOccured: {newName: 'onIncidentOccurred'},
  82457. drawn: {newName: 'onDrawn'},
  82458. onTooltipShown: {name: 'tooltipShown'},
  82459. onTooltipHidden: {name: 'tooltipHidden'},
  82460. onLoadingIndicatorReady: {name: "loadingIndicatorReady"}
  82461. },
  82462. _setDeprecatedOptions: function() {
  82463. this.callBase.apply(this, arguments);
  82464. $.extend(this._deprecatedOptions, {
  82465. incidentOccured: {
  82466. since: '14.2',
  82467. message: "Use the 'onIncidentOccurred' option instead"
  82468. },
  82469. drawn: {
  82470. since: '14.2',
  82471. message: "Use the 'onDrawn' option instead"
  82472. }
  82473. })
  82474. },
  82475. _setDefaultOptions: function() {
  82476. this.callBase.apply(this, arguments);
  82477. this.option({incidentOccured: defaultIncidentOccured})
  82478. },
  82479. _init: function() {
  82480. var that = this;
  82481. that.callBase.apply(that, arguments);
  82482. that._themeManager = that._createThemeManager();
  82483. that._themeManager.setCallback(function() {
  82484. that._handleThemeOptions()
  82485. });
  82486. that._renderer = new DX.viz.renderers.Renderer({cssClass: that._rootClassPrefix + " " + that._rootClass});
  82487. that._initIncidentOccured();
  82488. that._renderVisibilityChange();
  82489. that._initEventTrigger();
  82490. that._initTooltip();
  82491. that._initCore();
  82492. that._setThemeAndRtl();
  82493. that._initSize();
  82494. that._setupResizeHandler();
  82495. that._initLoadingIndicator()
  82496. },
  82497. _initTooltip: function() {
  82498. this._tooltip = new core.Tooltip({
  82499. cssClass: this._rootClassPrefix + "-tooltip",
  82500. eventTrigger: this._eventTrigger
  82501. })
  82502. },
  82503. _getAnimationOptions: $.noop,
  82504. _initSize: function() {
  82505. var canvas = null;
  82506. if (this._isContainerVisible()) {
  82507. canvas = this._calculateCanvas();
  82508. if (canvas)
  82509. this._updateSize(canvas, true)
  82510. }
  82511. if (!canvas)
  82512. this._setHiddenState()
  82513. },
  82514. _setHiddenState: function() {
  82515. var that = this;
  82516. that._clean = that._render = $.noop;
  82517. that._canvas = null;
  82518. that._incidentOccured('W2001', [that.NAME])
  82519. },
  82520. _setVisibleState: function() {
  82521. delete this._clean;
  82522. delete this._render
  82523. },
  82524. _updateSize: function(canvas, isDrawRequired) {
  82525. var that = this;
  82526. that._renderer.resize(canvas.width, canvas.height);
  82527. isDrawRequired && that._renderer.draw(that._$element[0]);
  82528. that._canvas = canvas;
  82529. that._applySize();
  82530. that._updateLoadingIndicatorCanvas()
  82531. },
  82532. _updateCanvasAndResize: function() {
  82533. var that = this,
  82534. canvas = that._calculateCanvas();
  82535. if (canvas)
  82536. if (areCanvasesDifferent(canvas, that._canvas) || that.__forceRender) {
  82537. that._updateSize(canvas);
  82538. that._resize()
  82539. }
  82540. return canvas
  82541. },
  82542. render: function() {
  82543. var that = this,
  82544. canvas,
  82545. visible = that._isContainerVisible();
  82546. if (that._canvas) {
  82547. if (visible)
  82548. canvas = that._updateCanvasAndResize();
  82549. if (!canvas) {
  82550. that._clean();
  82551. that._renderer.clear();
  82552. that._setHiddenState()
  82553. }
  82554. }
  82555. else {
  82556. if (visible) {
  82557. canvas = that._calculateCanvas();
  82558. if (canvas) {
  82559. that._setVisibleState();
  82560. that._updateSize(canvas, true);
  82561. that._render()
  82562. }
  82563. }
  82564. if (!canvas)
  82565. that._setHiddenState()
  82566. }
  82567. },
  82568. _handleResize: function() {
  82569. if (this._canvas)
  82570. this._updateCanvasAndResize()
  82571. },
  82572. _dispose: function() {
  82573. var that = this;
  82574. that.callBase.apply(that, arguments);
  82575. that._removeResizeHandler();
  82576. that._eventTrigger.dispose();
  82577. that._disposeCore();
  82578. that._disposeLoadingIndicator();
  82579. that._renderer.dispose();
  82580. that._tooltip && that._tooltip.dispose();
  82581. that._themeManager.dispose();
  82582. that._themeManager = that._renderer = that._eventTrigger = that._tooltip = null
  82583. },
  82584. _initEventTrigger: function() {
  82585. var that = this;
  82586. that._eventTrigger = createEventTrigger(that._eventsMap, function(name, deprecatedName) {
  82587. var data = {callback: that._createActionByOption(name)};
  82588. that._suppressDeprecatedWarnings();
  82589. if (that.option(name) === undefined)
  82590. data.deprecatedCallback = that.option(deprecatedName);
  82591. that._resumeDeprecatedWarnings();
  82592. return data
  82593. })
  82594. },
  82595. _isContainerVisible: function() {
  82596. return this._$element.is(':visible')
  82597. },
  82598. _calculateCanvas: function() {
  82599. var that = this,
  82600. size = that.option('size') || {},
  82601. margin = that.option('margin') || {},
  82602. defaultCanvas = that._getDefaultSize() || {},
  82603. canvas = {};
  82604. if (size.width <= 0 || size.height <= 0)
  82605. canvas = null;
  82606. else {
  82607. canvas.width = size.width > 0 ? _Number(size.width) : that._$element.width() || defaultCanvas.width;
  82608. canvas.height = size.height > 0 ? _Number(size.height) : that._$element.height() || defaultCanvas.height;
  82609. canvas.left = margin.left > 0 ? _Number(margin.left) : defaultCanvas.left || 0;
  82610. canvas.top = margin.top > 0 ? _Number(margin.top) : defaultCanvas.top || 0;
  82611. canvas.right = margin.right > 0 ? _Number(margin.right) : defaultCanvas.right || 0;
  82612. canvas.bottom = margin.bottom > 0 ? _Number(margin.bottom) : defaultCanvas.bottom || 0;
  82613. canvas = canvas.width - canvas.left - canvas.right > 0 && canvas.height - canvas.top - canvas.bottom > 0 ? canvas : null
  82614. }
  82615. return canvas
  82616. },
  82617. DEBUG_getCanvas: function() {
  82618. return this._canvas
  82619. },
  82620. DEBUG_getEventTrigger: function() {
  82621. return this._eventTrigger
  82622. },
  82623. _getOption: function(name, isScalar) {
  82624. var theme = this._themeManager.theme(name),
  82625. option = this.option(name);
  82626. return isScalar ? option !== undefined ? option : theme : $.extend(true, {}, theme, option)
  82627. },
  82628. _setupResizeHandler: function() {
  82629. if (_parseScalar(this._getOption('redrawOnResize', true), true))
  82630. this._addResizeHandler();
  82631. else
  82632. this._removeResizeHandler()
  82633. },
  82634. _addResizeHandler: function() {
  82635. var that = this;
  82636. if (!that._resizeHandler) {
  82637. that._resizeHandler = createResizeHandler(function() {
  82638. that._handleResize()
  82639. });
  82640. _windowResizeCallbacks.add(that._resizeHandler)
  82641. }
  82642. },
  82643. _removeResizeHandler: function() {
  82644. if (this._resizeHandler) {
  82645. _windowResizeCallbacks.remove(this._resizeHandler);
  82646. this._resizeHandler.dispose();
  82647. this._resizeHandler = null
  82648. }
  82649. },
  82650. _optionChanged: function(args) {
  82651. var that = this;
  82652. if (!that._eventTrigger.update(args.name))
  82653. switch (args.name) {
  82654. case'size':
  82655. case'margin':
  82656. that.render();
  82657. break;
  82658. case'redrawOnResize':
  82659. that._setupResizeHandler();
  82660. break;
  82661. case OPTION_LOADING_INDICATOR:
  82662. that._handleLoadingIndicatorOptionChanged();
  82663. break;
  82664. case"theme":
  82665. case OPTION_RTL_ENABLED:
  82666. that._setThemeAndRtl();
  82667. break;
  82668. case"encodeHtml":
  82669. case"pathModified":
  82670. that._handleThemeOptions();
  82671. break;
  82672. case"tooltip":
  82673. that._setTooltipOptions();
  82674. break;
  82675. default:
  82676. that._invalidate();
  82677. that.callBase.apply(that, arguments)
  82678. }
  82679. },
  82680. _handleThemeOptions: function() {
  82681. var that = this,
  82682. options = {
  82683. rtl: that.option(OPTION_RTL_ENABLED),
  82684. encodeHtml: that.option("encodeHtml"),
  82685. pathModified: that.option("pathModified"),
  82686. animation: that._getAnimationOptions()
  82687. };
  82688. that._renderer.setOptions(options);
  82689. that._setTooltipRendererOptions(options);
  82690. that._setTooltipOptions();
  82691. that._updateLoadingIndicatorOptions();
  82692. that._handleThemeOptionsCore()
  82693. },
  82694. _handleThemeOptionsCore: function() {
  82695. this._initialized && this._refresh()
  82696. },
  82697. _visibilityChanged: function() {
  82698. this.render()
  82699. },
  82700. _initIncidentOccured: function() {
  82701. var that = this;
  82702. that._incidentOccured = function(errorOrWarningId, options) {
  82703. that._eventTrigger('incidentOccured', {target: {
  82704. id: errorOrWarningId,
  82705. type: errorOrWarningId[0] === 'E' ? 'error' : 'warning',
  82706. args: options,
  82707. text: _stringFormat.apply(null, [DX.ERROR_MESSAGES[errorOrWarningId]].concat(options ? options.slice(0) : [])),
  82708. widget: that.NAME,
  82709. version: DX.VERSION
  82710. }})
  82711. }
  82712. },
  82713. _setThemeAndRtl: function() {
  82714. this._themeManager.setTheme(this.option("theme"), this.option(OPTION_RTL_ENABLED))
  82715. },
  82716. _setTooltipRendererOptions: function(options) {
  82717. this._tooltip.setRendererOptions(options)
  82718. },
  82719. _setTooltipOptions: function() {
  82720. this._tooltip.update(this._getOption("tooltip"))
  82721. },
  82722. _initLoadingIndicator: function() {
  82723. if (this._getOption(OPTION_LOADING_INDICATOR).show) {
  82724. this.showLoadingIndicator();
  82725. this._loadIndicator.forceShow()
  82726. }
  82727. },
  82728. _handleLoadingIndicatorOptionChanged: function() {
  82729. var that = this;
  82730. if (!that._skipOptionChanged) {
  82731. that._updateLoadingIndicatorOptions();
  82732. if (that._getOption(OPTION_LOADING_INDICATOR).show)
  82733. that.showLoadingIndicator();
  82734. else
  82735. that.hideLoadingIndicator()
  82736. }
  82737. },
  82738. _updateLoadingIndicatorCanvas: function() {
  82739. this._loadIndicator && this._canvas && this._loadIndicator.applyCanvas(this._canvas)
  82740. },
  82741. _updateLoadingIndicatorOptions: function() {
  82742. this._loadIndicator && this._loadIndicator.applyOptions(this._getOption(OPTION_LOADING_INDICATOR))
  82743. },
  82744. _endLoading: function(complete) {
  82745. if (this._loadIndicator) {
  82746. this._resetIsReady();
  82747. this._loadIndicator.endLoading(complete)
  82748. }
  82749. else
  82750. complete && complete()
  82751. },
  82752. _reappendLoadingIndicator: function() {
  82753. this._loadIndicator && this._loadIndicator.toForeground()
  82754. },
  82755. _disposeLoadingIndicator: function() {
  82756. if (this._loadIndicator) {
  82757. this._loadIndicator.dispose();
  82758. this._loadIndicator = null
  82759. }
  82760. },
  82761. _scheduleLoadingIndicatorHiding: function() {
  82762. this._loadIndicator && this._loadIndicator.scheduleHiding()
  82763. },
  82764. _fulfillLoadingIndicatorHiding: function() {
  82765. this._loadIndicator && this._loadIndicator.fulfillHiding() && this._toggleLoadingIndicatorState(false)
  82766. },
  82767. _normalizeHtml: function(html) {
  82768. var re = /xmlns="[\s\S]*?"/gi,
  82769. first = true;
  82770. html = html.replace(re, function(match) {
  82771. if (!first)
  82772. return "";
  82773. first = false;
  82774. return match
  82775. });
  82776. return html.replace(/xmlns:NS1="[\s\S]*?"/gi, "").replace(/NS1:xmlns:xlink="([\s\S]*?)"/gi, 'xmlns:xlink="$1"')
  82777. },
  82778. _dataIsReady: getTrue,
  82779. _resetIsReady: function() {
  82780. this.isReady = getFalse
  82781. },
  82782. _drawn: function() {
  82783. var that = this;
  82784. that.isReady = getFalse;
  82785. that._dataIsReady() && that._renderer.onEndAnimation(function() {
  82786. that.isReady = getTrue
  82787. });
  82788. that._eventTrigger('drawn', {})
  82789. },
  82790. _toggleLoadingIndicatorState: function(state) {
  82791. if (Boolean(this._getOption(OPTION_LOADING_INDICATOR).show) !== state) {
  82792. this._skipOptionChanged = true;
  82793. this.option(OPTION_LOADING_INDICATOR, {show: state});
  82794. this._skipOptionChanged = false
  82795. }
  82796. },
  82797. _handleLoadingIndicatorShown: function() {
  82798. this._tooltip.hide()
  82799. },
  82800. showLoadingIndicator: function() {
  82801. var that = this;
  82802. if (!that._loadIndicator) {
  82803. that._loadIndicator = new core.LoadIndicator({
  82804. container: that._$element,
  82805. eventTrigger: that._eventTrigger
  82806. });
  82807. that._updateLoadingIndicatorCanvas();
  82808. that._updateLoadingIndicatorOptions()
  82809. }
  82810. that._toggleLoadingIndicatorState(true);
  82811. that._loadIndicator.show();
  82812. that._handleLoadingIndicatorShown()
  82813. },
  82814. hideLoadingIndicator: function() {
  82815. var that = this;
  82816. if (that._loadIndicator) {
  82817. that._toggleLoadingIndicatorState(false);
  82818. that._loadIndicator.hide()
  82819. }
  82820. },
  82821. svg: function() {
  82822. return this._normalizeHtml(this._renderer.svg())
  82823. },
  82824. isReady: getFalse
  82825. });
  82826. function createEventTrigger(eventsMap, callbackGetter) {
  82827. var triggers = {},
  82828. timers = {};
  82829. $.each(eventsMap, function(name, info) {
  82830. if (info.name)
  82831. createItem(name)
  82832. });
  82833. trigger.update = function(name) {
  82834. var eventInfo = eventsMap[name];
  82835. if (eventInfo)
  82836. createItem(eventInfo.newName || name);
  82837. return !!eventInfo
  82838. };
  82839. trigger.dispose = function() {
  82840. $.each(timers, function(timer) {
  82841. clearTimeout(timer)
  82842. });
  82843. eventsMap = callbackGetter = triggers = timers = null
  82844. };
  82845. return trigger;
  82846. function trigger(eventName, arg, complete) {
  82847. triggers[eventName](arg, complete)
  82848. }
  82849. function createItem(name) {
  82850. var eventInfo = eventsMap[name],
  82851. data = callbackGetter(name, eventInfo.deprecated);
  82852. triggers[eventInfo.name] = createCallback(data.callback, _isFunction(data.deprecatedCallback) && data.deprecatedCallback, eventInfo.deprecatedContext, eventInfo.deprecatedArgs)
  82853. }
  82854. function createCallback(callback, deprectatedCallback, deprecatedContext, deprecatedArgs) {
  82855. return function(arg, complete) {
  82856. var timer = setTimeout(function() {
  82857. callback(arg);
  82858. deprectatedCallback && deprectatedCallback.apply(deprecatedContext(arg), deprecatedArgs(arg));
  82859. complete && complete();
  82860. delete timers[timer]
  82861. });
  82862. timers[timer] = 1
  82863. }
  82864. }
  82865. }
  82866. core.DEBUG_createEventTrigger = createEventTrigger
  82867. })(DevExpress, jQuery);
  82868. /*! Module viz-core, file CoreFactory.js */
  82869. (function(DX, undefined) {
  82870. var viz = DX.viz,
  82871. core = viz.core,
  82872. seriesNS = core.series;
  82873. core.CoreFactory = {
  82874. createSeries: function(renderSettings, options) {
  82875. return new seriesNS.Series(renderSettings, options)
  82876. },
  82877. createPoint: function(series, data, options) {
  82878. return new seriesNS.points.Point(series, data, options)
  82879. },
  82880. createLabel: function() {
  82881. return new core.series.points.Label
  82882. },
  82883. createTranslator1D: function(fromValue, toValue, fromAngle, toAngle) {
  82884. return (new core.Translator1D).setDomain(fromValue, toValue).setCodomain(fromAngle, toAngle)
  82885. },
  82886. createTranslator2D: function(range, canvas, options) {
  82887. return new core.Translator2D(range, canvas, options)
  82888. },
  82889. createTickManager: function(types, data, options) {
  82890. return new core.tickManager.TickManager(types, data, options)
  82891. },
  82892. createLegend: function(settings) {
  82893. return new core.Legend(settings)
  82894. },
  82895. createSeriesFamily: function(options) {
  82896. return new seriesNS.helpers.SeriesFamily(options)
  82897. },
  82898. createDataValidator: function(data, groups, incidentOccured, dataPrepareOptions) {
  82899. return new core.DataValidator(data, groups, incidentOccured, dataPrepareOptions)
  82900. }
  82901. }
  82902. })(DevExpress);
  82903. DevExpress.MOD_VIZ_CORE = true
  82904. }
  82905. if (!DevExpress.MOD_VIZ_CHARTS) {
  82906. if (!DevExpress.MOD_VIZ_CORE)
  82907. throw Error('Required module is not referenced: viz-core');
  82908. /*! Module viz-charts, file chartTitle.js */
  82909. (function($, DX, undefined) {
  82910. var viz = DX.viz,
  82911. vizUtils = viz.core.utils,
  82912. isDefined = DX.utils.isDefined,
  82913. DEFAULT_MARGIN = 10;
  82914. function parseMargins(options) {
  82915. options.margin = isDefined(options.margin) ? options.margin : {};
  82916. if (typeof options.margin === 'number') {
  82917. options.margin = options.margin >= 0 ? options.margin : DEFAULT_MARGIN;
  82918. options.margin = {
  82919. top: options.margin,
  82920. bottom: options.margin,
  82921. left: options.margin,
  82922. right: options.margin
  82923. }
  82924. }
  82925. else {
  82926. options.margin.top = options.margin.top >= 0 ? options.margin.top : DEFAULT_MARGIN;
  82927. options.margin.bottom = options.margin.bottom >= 0 ? options.margin.bottom : DEFAULT_MARGIN;
  82928. options.margin.left = options.margin.left >= 0 ? options.margin.left : DEFAULT_MARGIN;
  82929. options.margin.right = options.margin.right >= 0 ? options.margin.right : DEFAULT_MARGIN
  82930. }
  82931. }
  82932. function parseAlignments(options) {
  82933. options.verticalAlignment = (options.verticalAlignment || '').toLowerCase();
  82934. options.horizontalAlignment = (options.horizontalAlignment || '').toLowerCase();
  82935. if (options.verticalAlignment !== 'top' && options.verticalAlignment !== 'bottom')
  82936. options.verticalAlignment = 'top';
  82937. if (options.horizontalAlignment !== 'left' && options.horizontalAlignment !== 'center' && options.horizontalAlignment !== 'right')
  82938. options.horizontalAlignment = 'center'
  82939. }
  82940. function ChartTitle(renderer, options, group) {
  82941. var that = this;
  82942. that.update(options);
  82943. that.renderer = renderer;
  82944. that.titleGroup = group
  82945. }
  82946. viz.charts.ChartTitle = ChartTitle;
  82947. ChartTitle.prototype = {
  82948. dispose: function() {
  82949. var that = this;
  82950. that.renderer = null;
  82951. that.clipRect = null;
  82952. that.title = null;
  82953. that.innerTitleGroup = null;
  82954. that.titleGroup = null;
  82955. that.options = null
  82956. },
  82957. update: function(options) {
  82958. var that = this;
  82959. if (options) {
  82960. parseAlignments(options);
  82961. that.horizontalAlignment = options.horizontalAlignment;
  82962. that.verticalAlignment = options.verticalAlignment;
  82963. parseMargins(options);
  82964. that.margin = options.margin;
  82965. that.options = options
  82966. }
  82967. },
  82968. _setBoundingRect: function() {
  82969. var that = this,
  82970. options = that.options,
  82971. margin = that.changedMargin || that.margin,
  82972. box;
  82973. if (!that.innerTitleGroup)
  82974. return;
  82975. box = that.innerTitleGroup.getBBox();
  82976. box.height += margin.top + margin.bottom;
  82977. box.width += margin.left + margin.right;
  82978. box.x -= margin.left;
  82979. box.y -= margin.top;
  82980. if (isDefined(options.placeholderSize))
  82981. box.height = options.placeholderSize;
  82982. that.boundingRect = box
  82983. },
  82984. draw: function(size) {
  82985. var that = this,
  82986. titleOptions = that.options,
  82987. renderer = that.renderer;
  82988. if (!titleOptions.text)
  82989. return that;
  82990. size && that.setSize(size);
  82991. that.changedMargin = null;
  82992. if (!that.innerTitleGroup) {
  82993. that.innerTitleGroup = renderer.g();
  82994. that.clipRect = that.createClipRect();
  82995. that.titleGroup && that.clipRect && that.titleGroup.attr({clipId: that.clipRect.id})
  82996. }
  82997. else
  82998. that.innerTitleGroup.clear();
  82999. that.innerTitleGroup.append(that.titleGroup);
  83000. that.title = renderer.text(titleOptions.text, 0, 0).css(vizUtils.patchFontOptions(titleOptions.font)).attr({align: that.horizontalAlignment}).append(that.innerTitleGroup);
  83001. that.title.text = titleOptions.text;
  83002. that._correctTitleLength();
  83003. that._setClipRectSettings();
  83004. return that
  83005. },
  83006. _correctTitleLength: function() {
  83007. var that = this,
  83008. text = that.title.text,
  83009. lineLength,
  83010. box;
  83011. that.title.attr({text: text});
  83012. that._setBoundingRect();
  83013. box = that.getLayoutOptions();
  83014. if (that._width > box.width || text.indexOf("<br/>") !== -1)
  83015. return;
  83016. lineLength = text.length * that._width / box.width;
  83017. that.title.attr({text: text.substr(0, ~~lineLength - 1 - 3) + "..."});
  83018. that.title.setTitle(text);
  83019. that._setBoundingRect()
  83020. },
  83021. changeSize: function(size) {
  83022. var that = this,
  83023. margin = $.extend(true, {}, that.margin);
  83024. if (margin.top + margin.bottom < size.height) {
  83025. if (that.innerTitleGroup) {
  83026. that.options._incidentOccured("W2103");
  83027. that.innerTitleGroup.dispose();
  83028. that.innerTitleGroup = null
  83029. }
  83030. if (that.clipRect) {
  83031. that.clipRect.dispose();
  83032. that.clipRect = null
  83033. }
  83034. }
  83035. else if (size.height > 0) {
  83036. vizUtils.decreaseGaps(margin, ["top", "bottom"], size.height);
  83037. size.height && (that.changedMargin = margin)
  83038. }
  83039. that._correctTitleLength();
  83040. that._setBoundingRect();
  83041. that._setClipRectSettings();
  83042. return that
  83043. },
  83044. getLayoutOptions: function() {
  83045. var options = this.options,
  83046. boundingRect = this.innerTitleGroup ? this.boundingRect : {
  83047. width: 0,
  83048. height: 0,
  83049. x: 0,
  83050. y: 0
  83051. };
  83052. boundingRect.verticalAlignment = options.verticalAlignment;
  83053. boundingRect.horizontalAlignment = options.horizontalAlignment;
  83054. boundingRect.cutLayoutSide = options.verticalAlignment;
  83055. return boundingRect
  83056. },
  83057. getBBox: function() {
  83058. var bbox = $.extend({}, this.getLayoutOptions());
  83059. bbox.x = this._x;
  83060. bbox.y = this._y;
  83061. return bbox
  83062. },
  83063. setSize: function(size) {
  83064. this._width = size.width || this._width;
  83065. return this
  83066. },
  83067. shift: function(x, y) {
  83068. var that = this,
  83069. box = that.getLayoutOptions();
  83070. that._x = x;
  83071. that._y = y;
  83072. x -= box.x;
  83073. y -= box.y;
  83074. that.innerTitleGroup && that.innerTitleGroup.move(x, y);
  83075. that.clipRect && that.clipRect.attr({
  83076. translateX: x,
  83077. translateY: y
  83078. });
  83079. return that
  83080. },
  83081. createClipRect: function() {
  83082. if (isDefined(this.options.placeholderSize))
  83083. return this.renderer.clipRect(0, 0, 0, 0)
  83084. },
  83085. _setClipRectSettings: function() {
  83086. var bbox = this.getLayoutOptions(),
  83087. clipRect = this.clipRect;
  83088. if (clipRect)
  83089. clipRect.attr({
  83090. x: bbox.x,
  83091. y: bbox.y,
  83092. width: bbox.width,
  83093. height: bbox.height
  83094. })
  83095. }
  83096. };
  83097. DX.viz.charts.ChartTitle.__DEFAULT_MARGIN = DEFAULT_MARGIN
  83098. })(jQuery, DevExpress);
  83099. /*! Module viz-charts, file axesConstants.js */
  83100. (function($, DX, undefined) {
  83101. var _map = $.map;
  83102. function getFormatObject(value, options, axisMinMax) {
  83103. var formatObject = {
  83104. value: value,
  83105. valueText: DX.formatHelper.format(value, options.format, options.precision) || ""
  83106. };
  83107. if (axisMinMax) {
  83108. formatObject.min = axisMinMax.min;
  83109. formatObject.max = axisMinMax.max
  83110. }
  83111. return formatObject
  83112. }
  83113. DX.viz.charts.axes = {};
  83114. DX.viz.charts.axes.constants = {
  83115. logarithmic: "logarithmic",
  83116. discrete: "discrete",
  83117. numeric: "numeric",
  83118. left: "left",
  83119. right: "right",
  83120. top: "top",
  83121. bottom: "bottom",
  83122. center: "center",
  83123. canvasPositionPrefix: "canvas_position_",
  83124. canvasPositionTop: "canvas_position_top",
  83125. canvasPositionBottom: "canvas_position_bottom",
  83126. canvasPositionLeft: "canvas_position_left",
  83127. canvasPositionRight: "canvas_position_right",
  83128. canvasPositionStart: "canvas_position_start",
  83129. canvasPositionEnd: "canvas_position_end",
  83130. horizontal: "horizontal",
  83131. vertical: "vertical",
  83132. halfTickLength: 4,
  83133. convertTicksToValues: function(ticks) {
  83134. return _map(ticks || [], function(item) {
  83135. return item.value
  83136. })
  83137. },
  83138. convertValuesToTicks: function(values) {
  83139. return _map(values || [], function(item) {
  83140. return {value: item}
  83141. })
  83142. },
  83143. validateOverlappingMode: function(mode) {
  83144. return mode !== "ignore" ? "enlargeTickInterval" : "ignore"
  83145. },
  83146. formatLabel: function(value, options, axisMinMax) {
  83147. var formatObject = getFormatObject(value, options, axisMinMax);
  83148. return $.isFunction(options.customizeText) ? options.customizeText.call(formatObject, formatObject) : formatObject.valueText
  83149. },
  83150. formatHint: function(value, options, axisMinMax) {
  83151. var formatObject = getFormatObject(value, options, axisMinMax);
  83152. return $.isFunction(options.customizeHint) ? options.customizeHint.call(formatObject, formatObject) : undefined
  83153. }
  83154. }
  83155. })(jQuery, DevExpress);
  83156. /*! Module viz-charts, file xyAxes.js */
  83157. (function($, DX, undefined) {
  83158. var viz = DX.viz,
  83159. core = viz.core,
  83160. axes = viz.charts.axes,
  83161. constants = axes.constants,
  83162. _abs = Math.abs,
  83163. _extend = $.extend,
  83164. CANVAS_POSITION_PREFIX = constants.canvasPositionPrefix,
  83165. TOP = constants.top,
  83166. BOTTOM = constants.bottom,
  83167. LEFT = constants.left,
  83168. RIGHT = constants.right,
  83169. CENTER = constants.center;
  83170. axes.xyAxes = {};
  83171. axes.xyAxes.linear = {
  83172. _getSharpParam: function(oposite) {
  83173. return this._isHorizontal ^ oposite ? "h" : "v"
  83174. },
  83175. _createAxisElement: function() {
  83176. var axisCoord = this._axisPosition,
  83177. canvas = this._getCanvasStartEnd(),
  83178. points = this._isHorizontal ? [canvas.start, axisCoord, canvas.end, axisCoord] : [axisCoord, canvas.start, axisCoord, canvas.end];
  83179. return this._renderer.path(points, "line")
  83180. },
  83181. _getTranslatedCoord: function(value, offset) {
  83182. return this._translator.translate(value, offset)
  83183. },
  83184. _getCanvasStartEnd: function() {
  83185. return {
  83186. start: this._translator.translateSpecialCase(constants.canvasPositionStart),
  83187. end: this._translator.translateSpecialCase(constants.canvasPositionEnd)
  83188. }
  83189. },
  83190. _getScreenDelta: function() {
  83191. return _abs(this._translator.translateSpecialCase(constants.canvasPositionStart) - this._translator.translateSpecialCase(constants.canvasPositionEnd))
  83192. },
  83193. _initAxisPositions: function() {
  83194. var that = this,
  83195. position = that._options.position,
  83196. delta = 0;
  83197. if (that.delta)
  83198. delta = that.delta[position] || 0;
  83199. that._axisPosition = that._additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + position) + delta
  83200. },
  83201. _drawTitle: function() {
  83202. var that = this,
  83203. options = that._options,
  83204. titleOptions = options.title,
  83205. attr = {
  83206. opacity: titleOptions.opacity,
  83207. align: CENTER
  83208. };
  83209. if (!titleOptions.text || !that._axisTitleGroup)
  83210. return;
  83211. that._title = that._renderer.text(titleOptions.text, 0, 0).css(core.utils.patchFontOptions(titleOptions.font)).attr(attr).append(that._axisTitleGroup)
  83212. },
  83213. _adjustConstantLineLabels: function() {
  83214. var that = this,
  83215. options = that._options,
  83216. isHorizontal = that._isHorizontal,
  83217. lines = that._constantLines,
  83218. labels = that._constantLineLabels,
  83219. label,
  83220. line,
  83221. lineBox,
  83222. linesOptions,
  83223. labelOptions,
  83224. box,
  83225. x,
  83226. y,
  83227. i,
  83228. padding = isHorizontal ? {
  83229. top: 0,
  83230. bottom: 0
  83231. } : {
  83232. left: 0,
  83233. right: 0
  83234. },
  83235. paddingTopBottom,
  83236. paddingLeftRight,
  83237. labelVerticalAlignment,
  83238. labelHorizontalAlignment,
  83239. labelIsInside,
  83240. labelHeight,
  83241. labelWidth,
  83242. delta = 0;
  83243. if (labels === undefined && lines === undefined)
  83244. return;
  83245. for (i = 0; i < labels.length; i++) {
  83246. x = y = 0;
  83247. linesOptions = options.constantLines[i];
  83248. paddingTopBottom = linesOptions.paddingTopBottom;
  83249. paddingLeftRight = linesOptions.paddingLeftRight;
  83250. labelOptions = linesOptions.label;
  83251. labelVerticalAlignment = labelOptions.verticalAlignment;
  83252. labelHorizontalAlignment = labelOptions.horizontalAlignment;
  83253. labelIsInside = labelOptions.position === "inside";
  83254. label = labels[i];
  83255. if (label !== null) {
  83256. line = lines[i];
  83257. box = label.getBBox();
  83258. lineBox = line.getBBox();
  83259. labelHeight = box.height;
  83260. labelWidth = box.width;
  83261. if (isHorizontal)
  83262. if (labelIsInside) {
  83263. if (labelHorizontalAlignment === LEFT)
  83264. x -= paddingLeftRight;
  83265. else
  83266. x += paddingLeftRight;
  83267. switch (labelVerticalAlignment) {
  83268. case CENTER:
  83269. y += lineBox.y + lineBox.height / 2 - box.y - labelHeight / 2;
  83270. break;
  83271. case BOTTOM:
  83272. y += lineBox.y + lineBox.height - box.y - labelHeight - paddingTopBottom;
  83273. break;
  83274. default:
  83275. y += lineBox.y - box.y + paddingTopBottom;
  83276. break
  83277. }
  83278. }
  83279. else if (labelVerticalAlignment === BOTTOM) {
  83280. delta = that.delta && that.delta[BOTTOM] || 0;
  83281. y += paddingTopBottom - box.y + that._additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + BOTTOM) + delta;
  83282. if (padding[BOTTOM] < labelHeight + paddingTopBottom)
  83283. padding[BOTTOM] = labelHeight + paddingTopBottom
  83284. }
  83285. else {
  83286. delta = that.delta && that.delta[TOP] || 0;
  83287. y -= paddingTopBottom + box.y + labelHeight - that._additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + TOP) - delta;
  83288. if (padding[TOP] < paddingTopBottom + labelHeight)
  83289. padding[TOP] = paddingTopBottom + labelHeight
  83290. }
  83291. else if (labelIsInside) {
  83292. switch (labelHorizontalAlignment) {
  83293. case CENTER:
  83294. x += lineBox.x + labelWidth / 2 - box.x - labelWidth / 2;
  83295. break;
  83296. case RIGHT:
  83297. x -= paddingLeftRight;
  83298. break;
  83299. default:
  83300. x += paddingLeftRight;
  83301. break
  83302. }
  83303. if (labelVerticalAlignment === BOTTOM)
  83304. y += lineBox.y - box.y + paddingTopBottom;
  83305. else
  83306. y += lineBox.y - box.y - labelHeight - paddingTopBottom
  83307. }
  83308. else {
  83309. y += lineBox.y + lineBox.height / 2 - box.y - labelHeight / 2;
  83310. if (labelHorizontalAlignment === RIGHT) {
  83311. x += paddingLeftRight;
  83312. if (padding[RIGHT] < paddingLeftRight + labelWidth)
  83313. padding[RIGHT] = paddingLeftRight + labelWidth
  83314. }
  83315. else {
  83316. x -= paddingLeftRight;
  83317. if (padding[LEFT] < paddingLeftRight + labelWidth)
  83318. padding[LEFT] = paddingLeftRight + labelWidth
  83319. }
  83320. }
  83321. label.move(x, y)
  83322. }
  83323. }
  83324. that.padding = padding
  83325. },
  83326. _checkAlignmentConstantLineLabels: function(labelOptions) {
  83327. var position = labelOptions.position,
  83328. verticalAlignment = (labelOptions.verticalAlignment || "").toLowerCase(),
  83329. horizontalAlignment = (labelOptions.horizontalAlignment || "").toLowerCase();
  83330. if (this._isHorizontal)
  83331. if (position === "outside") {
  83332. verticalAlignment = verticalAlignment === BOTTOM ? BOTTOM : TOP;
  83333. horizontalAlignment = CENTER
  83334. }
  83335. else {
  83336. verticalAlignment = verticalAlignment === CENTER ? CENTER : verticalAlignment === BOTTOM ? BOTTOM : TOP;
  83337. horizontalAlignment = horizontalAlignment === LEFT ? LEFT : RIGHT
  83338. }
  83339. else if (position === "outside") {
  83340. verticalAlignment = CENTER;
  83341. horizontalAlignment = horizontalAlignment === LEFT ? LEFT : RIGHT
  83342. }
  83343. else {
  83344. verticalAlignment = verticalAlignment === BOTTOM ? BOTTOM : TOP;
  83345. horizontalAlignment = horizontalAlignment === RIGHT ? RIGHT : horizontalAlignment === CENTER ? CENTER : LEFT
  83346. }
  83347. labelOptions.verticalAlignment = verticalAlignment;
  83348. labelOptions.horizontalAlignment = horizontalAlignment
  83349. },
  83350. _getConstantLineLabelsCoords: function(value, lineLabelOptions) {
  83351. var that = this,
  83352. additionalTranslator = that._additionalTranslator,
  83353. align = CENTER,
  83354. x = value,
  83355. y = value;
  83356. if (that._isHorizontal)
  83357. y = additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + lineLabelOptions.verticalAlignment);
  83358. else
  83359. x = additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + lineLabelOptions.horizontalAlignment);
  83360. switch (lineLabelOptions.horizontalAlignment) {
  83361. case LEFT:
  83362. align = !that._isHorizontal && lineLabelOptions.position === "inside" ? LEFT : RIGHT;
  83363. break;
  83364. case CENTER:
  83365. align = CENTER;
  83366. break;
  83367. case RIGHT:
  83368. align = !that._isHorizontal && lineLabelOptions.position === "inside" ? RIGHT : LEFT;
  83369. break
  83370. }
  83371. return {
  83372. x: x,
  83373. y: y,
  83374. align: align
  83375. }
  83376. },
  83377. _getAdjustedStripLabelCoords: function(stripOptions, label, rect) {
  83378. var x = 0,
  83379. y = 0,
  83380. horizontalAlignment = stripOptions.label.horizontalAlignment,
  83381. verticalAlignment = stripOptions.label.verticalAlignment,
  83382. box = label.getBBox(),
  83383. rectBox = rect.getBBox();
  83384. if (horizontalAlignment === LEFT)
  83385. x += stripOptions.paddingLeftRight;
  83386. else if (horizontalAlignment === RIGHT)
  83387. x -= stripOptions.paddingLeftRight;
  83388. if (verticalAlignment === TOP)
  83389. y += rectBox.y - box.y + stripOptions.paddingTopBottom;
  83390. else if (verticalAlignment === CENTER)
  83391. y += rectBox.y + rectBox.height / 2 - box.y - box.height / 2;
  83392. else if (verticalAlignment === BOTTOM)
  83393. y -= stripOptions.paddingTopBottom;
  83394. return {
  83395. x: x,
  83396. y: y
  83397. }
  83398. },
  83399. _adjustTitle: function() {
  83400. var that = this,
  83401. options = that._options,
  83402. position = options.position,
  83403. title = that._title,
  83404. margin = options.title.margin,
  83405. boxGroup,
  83406. boxTitle,
  83407. params,
  83408. centerPosition = that._translator.translateSpecialCase(CANVAS_POSITION_PREFIX + CENTER),
  83409. axisElementsGroup = that._axisElementsGroup,
  83410. heightTitle,
  83411. axisPosition = that._axisPosition,
  83412. noLabels;
  83413. if (!title || !axisElementsGroup)
  83414. return;
  83415. boxTitle = title.getBBox();
  83416. boxGroup = axisElementsGroup.getBBox();
  83417. noLabels = boxGroup.isEmpty;
  83418. heightTitle = boxTitle.height;
  83419. if (that._isHorizontal)
  83420. if (position === BOTTOM)
  83421. params = {
  83422. y: (noLabels ? axisPosition : boxGroup.y + boxGroup.height) - boxTitle.y + margin,
  83423. x: centerPosition
  83424. };
  83425. else
  83426. params = {
  83427. y: (noLabels ? axisPosition : boxGroup.y) - heightTitle - boxTitle.y - margin,
  83428. x: centerPosition
  83429. };
  83430. else {
  83431. if (position === LEFT)
  83432. params = {
  83433. x: (noLabels ? axisPosition : boxGroup.x) - heightTitle - boxTitle.y - margin,
  83434. y: centerPosition
  83435. };
  83436. else
  83437. params = {
  83438. x: (noLabels ? axisPosition : boxGroup.x + boxGroup.width) + heightTitle + boxTitle.y + margin,
  83439. y: centerPosition
  83440. };
  83441. params.rotate = options.position === LEFT ? 270 : 90
  83442. }
  83443. title.attr(params)
  83444. },
  83445. coordsIn: function(x, y) {
  83446. var rect = this.getBoundingRect();
  83447. return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height
  83448. },
  83449. _getTicksOptions: function() {
  83450. var options = this._options;
  83451. return {
  83452. base: options.type === constants.logarithmic ? options.logarithmBase : undefined,
  83453. tickInterval: this._translator.getBusinessRange().stubData ? null : options.tickInterval,
  83454. gridSpacingFactor: options.axisDivisionFactor,
  83455. incidentOccured: options.incidentOccured,
  83456. setTicksAtUnitBeginning: options.setTicksAtUnitBeginning,
  83457. showMinorTicks: options.minorTick.visible || options.minorGrid.visible,
  83458. minorTickInterval: options.minorTickInterval,
  83459. minorTickCount: options.minorTickCount
  83460. }
  83461. },
  83462. _getOverlappingBehaviorOptions: function() {
  83463. var that = this,
  83464. options = that._options,
  83465. getText = function() {
  83466. return ""
  83467. },
  83468. overlappingBehavior = options.label.overlappingBehavior ? _extend({}, options.label.overlappingBehavior) : null;
  83469. if (overlappingBehavior) {
  83470. if (!that._isHorizontal)
  83471. overlappingBehavior.mode = constants.validateOverlappingMode(overlappingBehavior.mode);
  83472. if (overlappingBehavior.mode !== "rotate")
  83473. overlappingBehavior.rotationAngle = 0
  83474. }
  83475. if (!that._translator.getBusinessRange().stubData)
  83476. getText = function(value, labelOptions) {
  83477. return constants.formatLabel(value, labelOptions, {
  83478. min: options.min,
  83479. max: options.max
  83480. })
  83481. };
  83482. return {
  83483. hasLabelFormat: that._hasLabelFormat,
  83484. labelOptions: options.label,
  83485. overlappingBehavior: overlappingBehavior,
  83486. isHorizontal: that._isHorizontal,
  83487. textOptions: that._textOptions,
  83488. textFontStyles: that._textFontStyles,
  83489. textSpacing: options.label.minSpacing,
  83490. getText: getText,
  83491. renderText: function(text, x, y, options) {
  83492. return that._renderer.text(text, x, y, options).append(that._renderer.root)
  83493. },
  83494. translate: function(value, useAdditionalTranslator) {
  83495. return useAdditionalTranslator ? that._additionalTranslator.translate(value) : that._translator.translate(value)
  83496. },
  83497. isInverted: that._translator.getBusinessRange().invert
  83498. }
  83499. },
  83500. _getSpiderCategoryOption: $.noop,
  83501. _getMinMax: function() {
  83502. return {
  83503. min: this._options.min,
  83504. max: this._options.max
  83505. }
  83506. },
  83507. _getStick: function() {
  83508. return !this._options.valueMarginsEnabled
  83509. },
  83510. _getStripLabelCoords: function(stripLabelOptions, stripFrom, stripTo) {
  83511. var that = this,
  83512. additionalTranslator = that._additionalTranslator,
  83513. isHorizontal = that._isHorizontal,
  83514. align = isHorizontal ? CENTER : LEFT,
  83515. x,
  83516. y;
  83517. if (isHorizontal) {
  83518. if (stripLabelOptions.horizontalAlignment === CENTER) {
  83519. x = stripFrom + (stripTo - stripFrom) / 2;
  83520. align = CENTER
  83521. }
  83522. else if (stripLabelOptions.horizontalAlignment === LEFT) {
  83523. x = stripFrom;
  83524. align = LEFT
  83525. }
  83526. else if (stripLabelOptions.horizontalAlignment === RIGHT) {
  83527. x = stripTo;
  83528. align = RIGHT
  83529. }
  83530. y = additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + stripLabelOptions.verticalAlignment)
  83531. }
  83532. else {
  83533. x = additionalTranslator.translateSpecialCase(CANVAS_POSITION_PREFIX + stripLabelOptions.horizontalAlignment);
  83534. align = stripLabelOptions.horizontalAlignment;
  83535. if (stripLabelOptions.verticalAlignment === TOP)
  83536. y = stripFrom;
  83537. else if (stripLabelOptions.verticalAlignment === CENTER)
  83538. y = stripTo + (stripFrom - stripTo) / 2;
  83539. else if (stripLabelOptions.verticalAlignment === BOTTOM)
  83540. y = stripTo
  83541. }
  83542. return {
  83543. x: x,
  83544. y: y,
  83545. align: align
  83546. }
  83547. },
  83548. _getTranslatedValue: function(value, y, offset) {
  83549. return {
  83550. x: this._translator.translate(value, offset),
  83551. y: y
  83552. }
  83553. },
  83554. _getSkippedCategory: function() {
  83555. var that = this,
  83556. options = that._options,
  83557. categories = that._translator.getVisibleCategories() || that._translator.getBusinessRange().categories,
  83558. categoryToSkip;
  83559. if (categories && !!that._tickOffset && !options.valueMarginsEnabled)
  83560. categoryToSkip = options.inverted ? categories[0] : categories[categories.length - 1];
  83561. return categoryToSkip
  83562. }
  83563. }
  83564. })(jQuery, DevExpress);
  83565. /*! Module viz-charts, file polarAxes.js */
  83566. (function($, DX, undefined) {
  83567. var viz = DX.viz,
  83568. core = viz.core,
  83569. utils = DX.utils,
  83570. constants = viz.charts.axes.constants,
  83571. _math = Math,
  83572. _abs = _math.abs,
  83573. _round = _math.round,
  83574. _extend = $.extend,
  83575. _noop = $.noop,
  83576. _map = $.map,
  83577. HALF_PI_ANGLE = 90;
  83578. viz.charts.axes.polarAxes = {};
  83579. function getPolarQuarter(angle) {
  83580. var quarter;
  83581. angle = utils.normalizeAngle(angle);
  83582. if (angle >= 315 && angle <= 360 || angle < 45 && angle >= 0)
  83583. quarter = 1;
  83584. else if (angle >= 45 && angle < 135)
  83585. quarter = 2;
  83586. else if (angle >= 135 && angle < 225)
  83587. quarter = 3;
  83588. else if (angle >= 225 && angle < 315)
  83589. quarter = 4;
  83590. return quarter
  83591. }
  83592. viz.charts.axes.polarAxes.circular = {
  83593. _overlappingBehaviorType: "circular",
  83594. _createAxisElement: function() {
  83595. var additionalTranslator = this._additionalTranslator;
  83596. return this._renderer.circle(additionalTranslator.getCenter().x, additionalTranslator.getCenter().y, additionalTranslator.getRadius())
  83597. },
  83598. _setBoundingRect: function() {
  83599. this.boundingRect = {
  83600. width: 0,
  83601. height: 0
  83602. }
  83603. },
  83604. _getTicksOptions: viz.charts.axes.xyAxes.linear._getTicksOptions,
  83605. _getOverlappingBehaviorOptions: function() {
  83606. var that = this,
  83607. additionalTranslator = that._additionalTranslator,
  83608. startAngle = additionalTranslator.getStartAngle(),
  83609. options = viz.charts.axes.xyAxes.linear._getOverlappingBehaviorOptions.call(that),
  83610. translator = that._translator,
  83611. indentFromAxis = that._options.label.indentFromAxis || 0;
  83612. if (options.overlappingBehavior)
  83613. options.overlappingBehavior = {mode: constants.validateOverlappingMode(options.overlappingBehavior.mode)};
  83614. options.translate = function(value) {
  83615. return core.utils.convertPolarToXY(additionalTranslator.getCenter(), startAngle, translator.translate(value), additionalTranslator.translate(constants.canvasPositionBottom))
  83616. };
  83617. options.addMinMax = {min: true};
  83618. options.isInverted = translator.getBusinessRange().invert;
  83619. options.circularRadius = additionalTranslator.getRadius() + indentFromAxis;
  83620. options.circularStartAngle = options.circularEndAngle = startAngle;
  83621. options.isHorizontal = false;
  83622. return options
  83623. },
  83624. _getSpiderCategoryOption: function() {
  83625. return this._options.firstPointOnStartAngle
  83626. },
  83627. _getMinMax: function() {
  83628. var options = this._options;
  83629. return {
  83630. min: undefined,
  83631. max: utils.isNumber(options.period) && options.argumentType === constants.numeric ? options.period : undefined
  83632. }
  83633. },
  83634. _getStick: function() {
  83635. return this._options.firstPointOnStartAngle || this._options.type !== constants.discrete
  83636. },
  83637. measureLabels: function() {
  83638. var that = this,
  83639. options = that._options,
  83640. indentFromAxis = options.label.indentFromAxis || 0,
  83641. widthAxis = options.visible ? options.width : 0,
  83642. maxLabelParams;
  83643. if (!that._axisElementsGroup || !that._options.label.visible)
  83644. return {
  83645. height: widthAxis,
  83646. width: widthAxis
  83647. };
  83648. that._updateTickManager();
  83649. maxLabelParams = that._tickManager.getMaxLabelParams();
  83650. return {
  83651. height: maxLabelParams.height + indentFromAxis + constants.halfTickLength,
  83652. width: maxLabelParams.width + indentFromAxis + constants.halfTickLength
  83653. }
  83654. },
  83655. _getTranslatedCoord: function(value, offset) {
  83656. return this._translator.translate(value, offset) - HALF_PI_ANGLE
  83657. },
  83658. _getCanvasStartEnd: function() {
  83659. return {
  83660. start: 0 - HALF_PI_ANGLE,
  83661. end: 360 - HALF_PI_ANGLE
  83662. }
  83663. },
  83664. _createStrip: function(fromAngle, toAngle, attr) {
  83665. var center = this._additionalTranslator.getCenter(),
  83666. r = this._additionalTranslator.getRadius();
  83667. return this._renderer.arc(center.x, center.y, 0, r, -toAngle, -fromAngle).attr(attr)
  83668. },
  83669. _getStripLabelCoords: function(_, stripFrom, stripTo) {
  83670. var that = this,
  83671. angle = stripFrom + (stripTo - stripFrom) / 2,
  83672. cossin = utils.getCosAndSin(-angle),
  83673. halfRad = that._additionalTranslator.getRadius() / 2,
  83674. center = that._additionalTranslator.getCenter(),
  83675. x = _round(center.x + halfRad * cossin.cos),
  83676. y = _round(center.y - halfRad * cossin.sin);
  83677. return {
  83678. x: x,
  83679. y: y,
  83680. align: constants.center
  83681. }
  83682. },
  83683. _createConstantLine: function(value, attr) {
  83684. var center = this._additionalTranslator.getCenter(),
  83685. r = this._additionalTranslator.getRadius();
  83686. return this._createPathElement([center.x, center.y, center.x + r, center.y], attr).rotate(value, center.x, center.y)
  83687. },
  83688. _getConstantLineLabelsCoords: function(value) {
  83689. var that = this,
  83690. cossin = utils.getCosAndSin(-value),
  83691. halfRad = that._additionalTranslator.getRadius() / 2,
  83692. center = that._additionalTranslator.getCenter(),
  83693. x = _round(center.x + halfRad * cossin.cos),
  83694. y = _round(center.y - halfRad * cossin.sin);
  83695. return {
  83696. x: x,
  83697. y: y,
  83698. align: constants.center
  83699. }
  83700. },
  83701. _checkAlignmentConstantLineLabels: _noop,
  83702. _getScreenDelta: function() {
  83703. return 2 * Math.PI * this._additionalTranslator.getRadius()
  83704. },
  83705. _getTickCoord: function(tick) {
  83706. var center = this._additionalTranslator.getCenter(),
  83707. r = this._additionalTranslator.getRadius();
  83708. return {
  83709. x1: center.x + r - constants.halfTickLength,
  83710. y1: center.y,
  83711. x2: center.x + r + constants.halfTickLength,
  83712. y2: center.y,
  83713. angle: tick.angle
  83714. }
  83715. },
  83716. _getLabelAdjustedCoord: function(tick) {
  83717. var that = this,
  83718. pos = tick.labelPos,
  83719. cossin = utils.getCosAndSin(pos.angle),
  83720. cos = cossin.cos,
  83721. sin = cossin.sin,
  83722. box = tick.label.getBBox(),
  83723. halfWidth = box.width / 2,
  83724. halfHeight = box.height / 2,
  83725. indentFromAxis = that._options.label.indentFromAxis || 0,
  83726. x = pos.x + indentFromAxis * cos,
  83727. y = pos.y + (pos.y - box.y - halfHeight) + indentFromAxis * sin;
  83728. switch (getPolarQuarter(pos.angle)) {
  83729. case 1:
  83730. x += halfWidth;
  83731. y += halfHeight * sin;
  83732. break;
  83733. case 2:
  83734. x += halfWidth * cos;
  83735. y += halfHeight;
  83736. break;
  83737. case 3:
  83738. x += -halfWidth;
  83739. y += halfHeight * sin;
  83740. break;
  83741. case 4:
  83742. x += halfWidth * cos;
  83743. y += -halfHeight;
  83744. break
  83745. }
  83746. return {
  83747. x: x,
  83748. y: y
  83749. }
  83750. },
  83751. _getGridLineDrawer: function() {
  83752. var that = this,
  83753. r = that._additionalTranslator.getRadius(),
  83754. center = that._additionalTranslator.getCenter();
  83755. return function(tick) {
  83756. return that._createPathElement([center.x, center.y, center.x + r, center.y], tick.gridStyle).rotate(tick.angle, center.x, center.y)
  83757. }
  83758. },
  83759. _getTranslatedValue: function(value, _, offset) {
  83760. var additionalTranslator = this._additionalTranslator,
  83761. startAngle = additionalTranslator.getStartAngle(),
  83762. angle = this._translator.translate(value, -offset),
  83763. coords = core.utils.convertPolarToXY(additionalTranslator.getCenter(), startAngle, angle, additionalTranslator.translate(constants.canvasPositionBottom));
  83764. return {
  83765. x: coords.x,
  83766. y: coords.y,
  83767. angle: angle + startAngle - HALF_PI_ANGLE
  83768. }
  83769. },
  83770. _getAdjustedStripLabelCoords: function(_, label) {
  83771. var y,
  83772. box = label.getBBox();
  83773. y = label.attr("y") - box.y - box.height / 2;
  83774. return {
  83775. x: 0,
  83776. y: y
  83777. }
  83778. },
  83779. coordsIn: function(x, y) {
  83780. return core.utils.convertXYToPolar(this._additionalTranslator.getCenter(), x, y).r > this._additionalTranslator.getRadius()
  83781. },
  83782. _rotateTick: function(tick, angle) {
  83783. var center = this._additionalTranslator.getCenter();
  83784. tick.graphic.rotate(angle, center.x, center.y)
  83785. }
  83786. };
  83787. viz.charts.axes.polarAxes.circularSpider = _extend({}, viz.charts.axes.polarAxes.circular, {
  83788. _createAxisElement: function() {
  83789. var points = _map(this.getSpiderTicks(), function(tick) {
  83790. return {
  83791. x: tick.posX,
  83792. y: tick.posY
  83793. }
  83794. });
  83795. return this._renderer.path(points, "area")
  83796. },
  83797. _getStick: function() {
  83798. return true
  83799. },
  83800. _getSpiderCategoryOption: function() {
  83801. return true
  83802. },
  83803. getSpiderTicks: function() {
  83804. var that = this;
  83805. that._spiderTicks = constants.convertValuesToTicks(that._tickManager.getFullTicks());
  83806. that._initTicks(that._spiderTicks, {}, {});
  83807. return that._spiderTicks
  83808. },
  83809. _createStrip: function(fromAngle, toAngle, attr) {
  83810. var center = this._additionalTranslator.getCenter(),
  83811. spiderTicks = this.getSpiderTicks(),
  83812. firstTick,
  83813. lastTick,
  83814. points = _map(spiderTicks, function(tick, i) {
  83815. var result = [],
  83816. nextTick;
  83817. if (tick.angle >= fromAngle && tick.angle <= toAngle) {
  83818. if (!firstTick) {
  83819. firstTick = spiderTicks[i - 1] || spiderTicks[spiderTicks.length - 1];
  83820. result.push((tick.posX + firstTick.posX) / 2, (tick.posY + firstTick.posY) / 2)
  83821. }
  83822. result.push(tick.posX, tick.posY);
  83823. nextTick = spiderTicks[i + 1] || spiderTicks[0];
  83824. lastTick = {
  83825. x: (tick.posX + nextTick.posX) / 2,
  83826. y: (tick.posY + nextTick.posY) / 2
  83827. }
  83828. }
  83829. else
  83830. result = null;
  83831. return result
  83832. });
  83833. points.push(lastTick.x, lastTick.y);
  83834. points.push(center.x, center.y);
  83835. return this._renderer.path(points, "area").attr(attr)
  83836. },
  83837. _getTranslatedCoord: function(value, offset) {
  83838. return this._translator.translate(value, offset) - HALF_PI_ANGLE
  83839. },
  83840. _setTickOffset: function() {
  83841. this._tickOffset = false
  83842. }
  83843. });
  83844. viz.charts.axes.polarAxes.linear = {
  83845. _overlappingBehaviorType: "linear",
  83846. _getMinMax: viz.charts.axes.polarAxes.circular._getMinMax,
  83847. _getStick: viz.charts.axes.xyAxes.linear._getStick,
  83848. _getTicksOptions: viz.charts.axes.xyAxes.linear._getTicksOptions,
  83849. _getSpiderCategoryOption: $.noop,
  83850. _createAxisElement: function() {
  83851. var additionalTranslator = this._additionalTranslator,
  83852. centerCoord = additionalTranslator.getCenter(),
  83853. points = [centerCoord.x, centerCoord.y, centerCoord.x + additionalTranslator.getRadius(), centerCoord.y];
  83854. return this._renderer.path(points, "line").rotate(additionalTranslator.getStartAngle() - HALF_PI_ANGLE, centerCoord.x, centerCoord.y)
  83855. },
  83856. _setBoundingRect: viz.charts.axes.polarAxes.circular._setBoundingRect,
  83857. _getScreenDelta: function() {
  83858. return this._additionalTranslator.getRadius()
  83859. },
  83860. _getTickCoord: function(tick) {
  83861. return {
  83862. x1: tick.posX - constants.halfTickLength,
  83863. y1: tick.posY,
  83864. x2: tick.posX + constants.halfTickLength,
  83865. y2: tick.posY,
  83866. angle: tick.angle + HALF_PI_ANGLE
  83867. }
  83868. },
  83869. _getOverlappingBehaviorOptions: function() {
  83870. var that = this,
  83871. translator = that._translator,
  83872. orthTranslator = that._additionalTranslator,
  83873. options = viz.charts.axes.xyAxes.linear._getOverlappingBehaviorOptions.call(this),
  83874. startAngle = utils.normalizeAngle(that._additionalTranslator.getStartAngle());
  83875. if (options.overlappingBehavior)
  83876. options.overlappingBehavior = {mode: constants.validateOverlappingMode(options.overlappingBehavior.mode)};
  83877. options.isHorizontal = startAngle > 45 && startAngle < 135 || startAngle > 225 && startAngle < 315 ? true : false;
  83878. options.isInverted = translator.getBusinessRange().invert;
  83879. options.translate = function(value) {
  83880. return core.utils.convertPolarToXY(orthTranslator.getCenter(), that._options.startAngle, orthTranslator.translate(constants.canvasPositionTop), translator.translate(value)).x
  83881. };
  83882. return options
  83883. },
  83884. _getLabelAdjustedCoord: function(tick) {
  83885. var that = this,
  83886. pos = tick.labelPos,
  83887. cossin = utils.getCosAndSin(pos.angle),
  83888. indentFromAxis = that._options.label.indentFromAxis || 0,
  83889. box = tick.label.getBBox(),
  83890. x,
  83891. y;
  83892. x = pos.x - _abs(indentFromAxis * cossin.sin) + _abs(box.width / 2 * cossin.cos);
  83893. y = pos.y + (pos.y - box.y) - _abs(box.height / 2 * cossin.sin) + _abs(indentFromAxis * cossin.cos);
  83894. return {
  83895. x: x,
  83896. y: y
  83897. }
  83898. },
  83899. _getGridLineDrawer: function() {
  83900. var that = this,
  83901. pos = that._additionalTranslator.getCenter();
  83902. return function(tick) {
  83903. return that._renderer.circle(pos.x, pos.y, utils.getDistance(pos.x, pos.y, tick.posX, tick.posY)).attr(tick.gridStyle).sharp()
  83904. }
  83905. },
  83906. _getTranslatedValue: function(value, _, offset) {
  83907. var additionalTranslator = this._additionalTranslator,
  83908. startAngle = additionalTranslator.getStartAngle(),
  83909. angle = additionalTranslator.translate(constants.canvasPositionStart),
  83910. xy = core.utils.convertPolarToXY(additionalTranslator.getCenter(), startAngle, angle, this._translator.translate(value, offset));
  83911. return {
  83912. x: xy.x,
  83913. y: xy.y,
  83914. angle: angle + startAngle - HALF_PI_ANGLE
  83915. }
  83916. },
  83917. _getTranslatedCoord: function(value, offset) {
  83918. return this._translator.translate(value, offset)
  83919. },
  83920. _getCanvasStartEnd: function() {
  83921. return {
  83922. start: 0,
  83923. end: this._additionalTranslator.getRadius()
  83924. }
  83925. },
  83926. _createStrip: function(fromPoint, toPoint, attr) {
  83927. var center = this._additionalTranslator.getCenter();
  83928. return this._renderer.arc(center.x, center.y, fromPoint, toPoint, 0, 360).attr(attr)
  83929. },
  83930. _getAdjustedStripLabelCoords: viz.charts.axes.polarAxes.circular._getAdjustedStripLabelCoords,
  83931. _getStripLabelCoords: function(_, stripFrom, stripTo) {
  83932. var that = this,
  83933. labelPos = stripFrom + (stripTo - stripFrom) / 2,
  83934. center = that._additionalTranslator.getCenter(),
  83935. y = _round(center.y - labelPos);
  83936. return {
  83937. x: center.x,
  83938. y: y,
  83939. align: constants.center
  83940. }
  83941. },
  83942. _createConstantLine: function(value, attr) {
  83943. var center = this._additionalTranslator.getCenter();
  83944. return this._renderer.circle(center.x, center.y, value).attr(attr).sharp()
  83945. },
  83946. _getConstantLineLabelsCoords: function(value) {
  83947. var that = this,
  83948. center = that._additionalTranslator.getCenter(),
  83949. y = _round(center.y - value);
  83950. return {
  83951. x: center.x,
  83952. y: y,
  83953. align: constants.center
  83954. }
  83955. },
  83956. _checkAlignmentConstantLineLabels: _noop,
  83957. _rotateTick: function(tick, angle) {
  83958. tick.graphic.rotate(angle, tick.posX, tick.posY)
  83959. }
  83960. };
  83961. viz.charts.axes.polarAxes.linearSpider = _extend({}, viz.charts.axes.polarAxes.linear, {
  83962. _createPathElement: function(points, attr) {
  83963. return this._renderer.path(points, "area").attr(attr).sharp()
  83964. },
  83965. setSpiderTicks: function(ticks) {
  83966. this._spiderTicks = ticks
  83967. },
  83968. _getGridLineDrawer: function() {
  83969. var that = this,
  83970. pos = that._additionalTranslator.getCenter();
  83971. return function(tick) {
  83972. var radius = utils.getDistance(pos.x, pos.y, tick.posX, tick.posY);
  83973. return that._createPathElement(that._getGridPoints(pos, radius), tick.gridStyle)
  83974. }
  83975. },
  83976. _getGridPoints: function(pos, radius) {
  83977. return _map(this._spiderTicks, function(tick) {
  83978. var cossin = utils.getCosAndSin(tick.angle);
  83979. return {
  83980. x: _round(pos.x + radius * cossin.cos),
  83981. y: _round(pos.y + radius * cossin.sin)
  83982. }
  83983. })
  83984. },
  83985. _createStrip: function(fromPoint, toPoint, attr) {
  83986. var center = this._additionalTranslator.getCenter(),
  83987. innerPoints = this._getGridPoints(center, toPoint),
  83988. outerPoints = this._getGridPoints(center, fromPoint);
  83989. return this._renderer.path([outerPoints, innerPoints.reverse()], "area").attr(attr)
  83990. },
  83991. _createConstantLine: function(value, attr) {
  83992. var center = this._additionalTranslator.getCenter(),
  83993. points = this._getGridPoints(center, value);
  83994. return this._createPathElement(points, attr)
  83995. }
  83996. })
  83997. })(jQuery, DevExpress);
  83998. /*! Module viz-charts, file baseAxis.js */
  83999. (function($, DX, undefined) {
  84000. var viz = DX.viz,
  84001. core = viz.core,
  84002. utils = DX.utils,
  84003. constants = viz.charts.axes.constants,
  84004. _isDefined = utils.isDefined,
  84005. _isNumber = utils.isNumber,
  84006. _getSignificantDigitPosition = utils.getSignificantDigitPosition,
  84007. _roundValue = utils.roundValue,
  84008. _math = Math,
  84009. _abs = _math.abs,
  84010. _round = _math.round,
  84011. _extend = $.extend,
  84012. _each = $.each,
  84013. _noop = $.noop,
  84014. WIDGET_CLASS = "dxc",
  84015. DEFAULT_AXIS_LABEL_SPACING = 5,
  84016. MAX_GRID_BORDER_ADHENSION = 4,
  84017. LABEL_BACKGROUND_PADDING_X = 8,
  84018. LABEL_BACKGROUND_PADDING_Y = 4,
  84019. Axis;
  84020. function validateAxisOptions(options, isHorizontal) {
  84021. var labelOptions = options.label,
  84022. position = options.position,
  84023. defaultPosition = isHorizontal ? constants.bottom : constants.left,
  84024. secondaryPosition = isHorizontal ? constants.top : constants.right;
  84025. if (position !== defaultPosition && position !== secondaryPosition)
  84026. position = defaultPosition;
  84027. if (position === constants.right && !labelOptions.userAlignment)
  84028. labelOptions.alignment = constants.left;
  84029. options.position = position;
  84030. options.hoverMode = options.hoverMode ? options.hoverMode.toLowerCase() : "none";
  84031. labelOptions.minSpacing = _isDefined(labelOptions.minSpacing) ? labelOptions.minSpacing : DEFAULT_AXIS_LABEL_SPACING
  84032. }
  84033. Axis = DX.viz.charts.axes.Axis = function(renderSettings) {
  84034. var that = this;
  84035. that._renderer = renderSettings.renderer;
  84036. that._isHorizontal = renderSettings.isHorizontal;
  84037. that._incidentOccured = renderSettings.incidentOccured;
  84038. that._stripsGroup = renderSettings.stripsGroup;
  84039. that._labelAxesGroup = renderSettings.labelAxesGroup;
  84040. that._constantLinesGroup = renderSettings.constantLinesGroup;
  84041. that._axesContainerGroup = renderSettings.axesContainerGroup;
  84042. that._gridContainerGroup = renderSettings.gridGroup;
  84043. that._axisClass = renderSettings.axisClass;
  84044. that._setType(renderSettings.axesType, renderSettings.drawingType);
  84045. that._createAxisGroups();
  84046. that._tickManager = that._createTickManager()
  84047. };
  84048. Axis.prototype = {
  84049. constructor: Axis,
  84050. dispose: function() {
  84051. var that = this;
  84052. that._axisElementsGroup && that._axisElementsGroup.dispose();
  84053. that._stripLabels = that._strips = null;
  84054. that._title = null;
  84055. that._axisStripGroup = that._axisConstantLineGroup = that._axisLabelGroup = null;
  84056. that._axisLineGroup = that._axisElementsGroup = that._axisGridGroup = null;
  84057. that._axisGroup = that._axisTitleGroup = null;
  84058. that._axesContainerGroup = that._stripsGroup = that._constantLinesGroup = null;
  84059. that._renderer = that._options = that._textOptions = that._textFontStyles = null;
  84060. that._translator = that._additionalTranslator = null;
  84061. that._majorTicks = that._minorTicks = null;
  84062. that._tickManager = null
  84063. },
  84064. getOptions: function() {
  84065. return this._options
  84066. },
  84067. setPane: function(pane) {
  84068. this.pane = pane;
  84069. this._options.pane = pane
  84070. },
  84071. setTypes: function(type, axisType, typeSelector) {
  84072. this._options.type = type || this._options.type;
  84073. this._options[typeSelector] = axisType || this._options[typeSelector]
  84074. },
  84075. resetTypes: function(typeSelector) {
  84076. this._options.type = this._initTypes.type;
  84077. this._options[typeSelector] = this._initTypes[typeSelector]
  84078. },
  84079. getTranslator: function() {
  84080. return this._translator
  84081. },
  84082. updateOptions: function(options) {
  84083. var that = this,
  84084. labelOpt = options.label;
  84085. that._options = options;
  84086. that._initTypes = {
  84087. type: options.type,
  84088. argumentType: options.argumentType,
  84089. valueType: options.valueType
  84090. };
  84091. validateAxisOptions(options, that._isHorizontal);
  84092. that._setTickOffset();
  84093. that.pane = options.pane;
  84094. that.name = options.name;
  84095. that.priority = options.priority;
  84096. that._virtual = options.virtual;
  84097. that._hasLabelFormat = labelOpt.format !== "" && _isDefined(labelOpt.format);
  84098. that._textOptions = {
  84099. align: labelOpt.alignment,
  84100. opacity: labelOpt.opacity
  84101. };
  84102. that._textFontStyles = core.utils.patchFontOptions(labelOpt.font);
  84103. if (options.type === constants.logarithmic) {
  84104. if (options.logarithmBaseError) {
  84105. that._incidentOccured("E2104");
  84106. delete options.logarithmBaseError
  84107. }
  84108. that.calcInterval = function(value, prevValue) {
  84109. return utils.getLog(value / prevValue, options.logarithmBase)
  84110. }
  84111. }
  84112. },
  84113. updateSize: function(clearAxis) {
  84114. var that = this,
  84115. options = that._options,
  84116. direction = that._isHorizontal ? "horizontal" : "vertical";
  84117. if (options.title.text && that._axisTitleGroup) {
  84118. that._incidentOccured("W2105", [direction]);
  84119. that._axisTitleGroup.dispose();
  84120. that._axisTitleGroup = null
  84121. }
  84122. if (clearAxis && that._axisElementsGroup && options.label.visible && !that._translator.getBusinessRange().stubData) {
  84123. that._incidentOccured("W2106", [direction]);
  84124. that._axisElementsGroup.dispose();
  84125. that._axisElementsGroup = null
  84126. }
  84127. that._setBoundingRect()
  84128. },
  84129. _updateTranslatorInterval: function() {
  84130. var that = this,
  84131. i,
  84132. majorTicks,
  84133. majorTicksLength,
  84134. translator = that._translator,
  84135. businessRange = translator.getBusinessRange();
  84136. if (!businessRange.categories && !businessRange.isSynchronized) {
  84137. that.getMajorTicks(true);
  84138. businessRange.addRange(that._tickManager.getTickBounds());
  84139. translator.reinit()
  84140. }
  84141. that._majorTicks = majorTicks = that.getMajorTicks();
  84142. if (!businessRange.categories) {
  84143. majorTicksLength = majorTicks.length;
  84144. for (i = 0; i < majorTicksLength - 1; i++)
  84145. businessRange.addRange({interval: _abs(majorTicks[i].value - majorTicks[i + 1].value)})
  84146. }
  84147. that._decimatedTicks = businessRange.categories ? that.getDecimatedTicks() : [];
  84148. that._minorTicks = that.getMinorTicks()
  84149. },
  84150. setTranslator: function(translator, additionalTranslator) {
  84151. var that = this,
  84152. range = translator.getBusinessRange();
  84153. this._minBound = range.minVisible;
  84154. this._maxBound = range.maxVisible;
  84155. that._translator = translator;
  84156. that._additionalTranslator = additionalTranslator;
  84157. that.resetTicks();
  84158. that._updateTranslatorInterval()
  84159. },
  84160. resetTicks: function() {
  84161. this._deleteLabels();
  84162. this._majorTicks = this._minorTicks = null
  84163. },
  84164. getCurrentLabelPos: function() {
  84165. var that = this,
  84166. options = that._options,
  84167. position = options.position,
  84168. labelOffset = options.label.indentFromAxis,
  84169. axisPosition = that._axisPosition;
  84170. return position === constants.top || position === constants.left ? axisPosition - labelOffset : axisPosition + labelOffset
  84171. },
  84172. getUntranslatedValue: function(pos) {
  84173. var that = this,
  84174. translator = that._translator,
  84175. value = translator.untranslate(pos);
  84176. if (_isDefined(value))
  84177. return constants.formatLabel(_isNumber(value) ? _roundValue(value, _getSignificantDigitPosition(translator.getBusinessRange().interval)) : value, that._options.label);
  84178. return null
  84179. },
  84180. _drawAxis: function() {
  84181. var that = this,
  84182. options = that._options,
  84183. axis = that._createAxis({
  84184. "stroke-width": options.width,
  84185. stroke: options.color,
  84186. "stroke-opacity": options.opacity
  84187. });
  84188. axis.append(that._axisLineGroup)
  84189. },
  84190. _correctMinForTicks: function(min, max, screenDelta) {
  84191. var digitPosition = _getSignificantDigitPosition(_abs(max - min) / screenDelta),
  84192. newMin = _roundValue(Number(min), digitPosition),
  84193. correctingValue;
  84194. if (newMin < min) {
  84195. correctingValue = _math.pow(10, -digitPosition);
  84196. newMin = utils.applyPrecisionByMinDelta(newMin, correctingValue, newMin + correctingValue)
  84197. }
  84198. if (newMin > max)
  84199. newMin = min;
  84200. return newMin
  84201. },
  84202. _getTickManagerData: function() {
  84203. var that = this,
  84204. options = that._options,
  84205. screenDelta = that._getScreenDelta(),
  84206. min = that._minBound,
  84207. max = that._maxBound,
  84208. categories = that._translator.getVisibleCategories() || that._translator.getBusinessRange().categories,
  84209. customTicks = $.isArray(categories) ? categories : that._majorTicks && constants.convertTicksToValues(that._majorTicks),
  84210. customMinorTicks = that._minorTicks && constants.convertTicksToValues(that._minorTicks);
  84211. if (_isNumber(min) && options.type !== constants.logarithmic)
  84212. min = that._correctMinForTicks(min, max, screenDelta);
  84213. return {
  84214. min: min,
  84215. max: max,
  84216. customTicks: customTicks,
  84217. customMinorTicks: customMinorTicks,
  84218. screenDelta: screenDelta
  84219. }
  84220. },
  84221. _getTickManagerTypes: function() {
  84222. return {
  84223. axisType: this._options.type,
  84224. dataType: this._options.dataType
  84225. }
  84226. },
  84227. _createTickManager: function() {
  84228. return DX.viz.core.CoreFactory.createTickManager({}, {}, {overlappingBehaviorType: this._overlappingBehaviorType})
  84229. },
  84230. _getMarginsOptions: function() {
  84231. var range = this._translator.getBusinessRange();
  84232. return {
  84233. stick: range.stick,
  84234. minStickValue: range.minStickValue,
  84235. maxStickValue: range.maxStickValue,
  84236. percentStick: range.percentStick,
  84237. minValueMargin: this._options.minValueMargin,
  84238. maxValueMargin: this._options.maxValueMargin,
  84239. minSpaceCorrection: range.minSpaceCorrection,
  84240. maxSpaceCorrection: range.maxSpaceCorrection
  84241. }
  84242. },
  84243. _updateTickManager: function() {
  84244. var overlappingOptions = this._getOverlappingBehaviorOptions(),
  84245. options;
  84246. options = _extend(true, {}, this._getMarginsOptions(), overlappingOptions, this._getTicksOptions());
  84247. this._tickManager.update(this._getTickManagerTypes(), this._getTickManagerData(), options)
  84248. },
  84249. _correctLabelAlignment: function() {
  84250. var that = this,
  84251. labelOptions = that._options.label,
  84252. overlappingBehavior = that._tickManager.getOverlappingBehavior();
  84253. if (overlappingBehavior && overlappingBehavior.mode === "rotate") {
  84254. that._textOptions.rotate = overlappingBehavior.rotationAngle;
  84255. if (!labelOptions.userAlignment)
  84256. that._textOptions.align = constants.left
  84257. }
  84258. else if (!labelOptions.userAlignment)
  84259. that._textOptions.align = labelOptions.alignment
  84260. },
  84261. _correctLabelFormat: function() {
  84262. this._options.label = this._tickManager.getOptions().labelOptions
  84263. },
  84264. getTicksValues: function() {
  84265. return {
  84266. majorTicksValues: constants.convertTicksToValues(this._majorTicks || this.getMajorTicks()),
  84267. minorTicksValues: constants.convertTicksToValues(this._minorTicks || this.getMinorTicks())
  84268. }
  84269. },
  84270. getMajorTicks: function(withoutOverlappingBehavior) {
  84271. var that = this,
  84272. majorTicks;
  84273. that._updateTickManager();
  84274. that._textOptions.rotate = 0;
  84275. majorTicks = constants.convertValuesToTicks(that._tickManager.getTicks(withoutOverlappingBehavior));
  84276. that._correctLabelAlignment();
  84277. that._correctLabelFormat();
  84278. return majorTicks
  84279. },
  84280. getMinorTicks: function() {
  84281. return constants.convertValuesToTicks(this._tickManager.getMinorTicks())
  84282. },
  84283. getDecimatedTicks: function() {
  84284. return constants.convertValuesToTicks(this._tickManager.getDecimatedTicks())
  84285. },
  84286. setTicks: function(ticks) {
  84287. this.resetTicks();
  84288. this._majorTicks = constants.convertValuesToTicks(ticks.majorTicks);
  84289. this._minorTicks = constants.convertValuesToTicks(ticks.minorTicks)
  84290. },
  84291. _deleteLabels: function() {
  84292. this._axisElementsGroup && this._axisElementsGroup.clear()
  84293. },
  84294. _drawTicks: function(ticks) {
  84295. var that = this,
  84296. group = that._axisLineGroup;
  84297. _each(ticks || [], function(_, tick) {
  84298. var coord = that._getTickCoord(tick),
  84299. points;
  84300. if (coord) {
  84301. points = that._isHorizontal ? [coord.x1, coord.y1, coord.x2, coord.y2] : [coord.y1, coord.x1, coord.y2, coord.x2];
  84302. tick.graphic = that._createPathElement(points, tick.tickStyle).append(group);
  84303. coord.angle && that._rotateTick(tick, coord.angle)
  84304. }
  84305. })
  84306. },
  84307. _createPathElement: function(points, attr, oposite) {
  84308. return this._renderer.path(points, "line").attr(attr).sharp(this._getSharpParam(oposite))
  84309. },
  84310. _createAxis: function(options) {
  84311. return this._createAxisElement().attr(options).sharp(this._getSharpParam(true))
  84312. },
  84313. _getTickCoord: function(tick) {
  84314. var coords;
  84315. if (_isDefined(tick.posX) && _isDefined(tick.posY))
  84316. coords = {
  84317. x1: tick.posX,
  84318. y1: tick.posY - constants.halfTickLength,
  84319. x2: tick.posX,
  84320. y2: tick.posY + constants.halfTickLength
  84321. };
  84322. else
  84323. coords = null;
  84324. return coords
  84325. },
  84326. setPercentLabelFormat: function() {
  84327. if (!this._hasLabelFormat)
  84328. this._options.label.format = "percent"
  84329. },
  84330. resetAutoLabelFormat: function() {
  84331. if (!this._hasLabelFormat)
  84332. delete this._options.label.format
  84333. },
  84334. _drawLabels: function() {
  84335. var that = this,
  84336. renderer = that._renderer,
  84337. group = that._axisElementsGroup,
  84338. emptyStrRegExp = /^\s+$/;
  84339. _each(that._majorTicks, function(_, tick) {
  84340. var text = tick.labelText,
  84341. xCoord,
  84342. yCoord;
  84343. if (_isDefined(text) && text !== "" && !emptyStrRegExp.test(text)) {
  84344. xCoord = that._isHorizontal ? tick.labelPos.x : tick.labelPos.y;
  84345. yCoord = that._isHorizontal ? tick.labelPos.y : tick.labelPos.x;
  84346. if (!tick.label)
  84347. tick.label = renderer.text(text, xCoord, yCoord).css(tick.labelFontStyle).attr(tick.labelStyle).append(group);
  84348. else
  84349. tick.label.css(tick.labelFontStyle).attr(tick.labelStyle).attr({
  84350. text: text,
  84351. x: xCoord,
  84352. y: yCoord
  84353. });
  84354. tick.label.data({argument: tick.value})
  84355. }
  84356. })
  84357. },
  84358. getMultipleAxesSpacing: function() {
  84359. return this._options.multipleAxesSpacing || 0
  84360. },
  84361. _drawTitle: _noop,
  84362. _getGridLineDrawer: function(borderOptions) {
  84363. var that = this,
  84364. translator = that._translator,
  84365. additionalTranslator = that._additionalTranslator,
  84366. isHorizontal = that._isHorizontal,
  84367. canvasStart = isHorizontal ? constants.left : constants.top,
  84368. canvasEnd = isHorizontal ? constants.right : constants.bottom,
  84369. positionFrom = additionalTranslator.translateSpecialCase(constants.canvasPositionStart),
  84370. positionTo = additionalTranslator.translateSpecialCase(constants.canvasPositionEnd),
  84371. firstBorderLinePosition = borderOptions.visible && borderOptions[canvasStart] ? translator.translateSpecialCase(constants.canvasPositionPrefix + canvasStart) : undefined,
  84372. lastBorderLinePosition = borderOptions.visible && borderOptions[canvasEnd] ? translator.translateSpecialCase(constants.canvasPositionPrefix + canvasEnd) : undefined,
  84373. getPoints = isHorizontal ? function(tick) {
  84374. return tick.posX !== null ? [tick.posX, positionFrom, tick.posX, positionTo] : null
  84375. } : function(tick) {
  84376. return tick.posX !== null ? [positionFrom, tick.posX, positionTo, tick.posX] : null
  84377. };
  84378. return function(tick) {
  84379. var points;
  84380. if (_abs(tick.posX - firstBorderLinePosition) < MAX_GRID_BORDER_ADHENSION || _abs(tick.posX - lastBorderLinePosition) < MAX_GRID_BORDER_ADHENSION)
  84381. return;
  84382. points = getPoints(tick);
  84383. return points && that._createPathElement(points, tick.gridStyle)
  84384. }
  84385. },
  84386. _drawGrids: function(ticks, borderOptions) {
  84387. var that = this,
  84388. group = that._axisGridGroup,
  84389. drawLine = that._getGridLineDrawer(borderOptions || {visible: false});
  84390. _each(ticks || [], function(_, tick) {
  84391. tick.grid = drawLine(tick);
  84392. tick.grid && tick.grid.append(group)
  84393. })
  84394. },
  84395. _getConstantLinePos: function(lineValue, canvasStart, canvasEnd) {
  84396. var parsedValue = this._validateUnit(lineValue, "E2105", "constantLine"),
  84397. value = this._getTranslatedCoord(parsedValue);
  84398. if (!_isDefined(value) || value < _math.min(canvasStart, canvasEnd) || value > _math.max(canvasStart, canvasEnd))
  84399. return {};
  84400. return {
  84401. value: value,
  84402. parsedValue: parsedValue
  84403. }
  84404. },
  84405. _createConstantLine: function(value, attr) {
  84406. var that = this,
  84407. additionalTranslator = this._additionalTranslator,
  84408. positionFrom = additionalTranslator.translateSpecialCase(constants.canvasPositionStart),
  84409. positionTo = additionalTranslator.translateSpecialCase(constants.canvasPositionEnd),
  84410. points = this._isHorizontal ? [value, positionTo, value, positionFrom] : [positionFrom, value, positionTo, value];
  84411. return that._createPathElement(points, attr)
  84412. },
  84413. _drawConstantLinesAndLabels: function(lineOptions, canvasStart, canvasEnd) {
  84414. if (!_isDefined(lineOptions.value))
  84415. return;
  84416. var that = this,
  84417. pos = that._getConstantLinePos(lineOptions.value, canvasStart, canvasEnd),
  84418. labelOptions = lineOptions.label || {},
  84419. value = pos.value,
  84420. attr = {
  84421. stroke: lineOptions.color,
  84422. "stroke-width": lineOptions.width,
  84423. dashStyle: lineOptions.dashStyle
  84424. };
  84425. if (!_isDefined(value)) {
  84426. that._constantLines.push(null);
  84427. if (labelOptions.visible)
  84428. that._constantLineLabels.push(null);
  84429. return
  84430. }
  84431. that._constantLines.push(that._createConstantLine(value, attr).append(that._axisConstantLineGroup));
  84432. that._constantLineLabels.push(labelOptions.visible ? that._drawConstantLineLabels(pos.parsedValue, labelOptions, value) : null)
  84433. },
  84434. _drawConstantLine: function() {
  84435. var that = this,
  84436. options = that._options,
  84437. data = options.constantLines,
  84438. canvas = that._getCanvasStartEnd();
  84439. if (that._translator.getBusinessRange().stubData)
  84440. return;
  84441. that._constantLines = [];
  84442. that._constantLineLabels = [];
  84443. _each(data, function(_, dataItem) {
  84444. that._drawConstantLinesAndLabels(dataItem, canvas.start, canvas.end)
  84445. })
  84446. },
  84447. _drawConstantLineLabels: function(parsedValue, lineLabelOptions, value) {
  84448. var that = this,
  84449. text = lineLabelOptions.text,
  84450. options = that._options,
  84451. labelOptions = options.label,
  84452. coords;
  84453. that._checkAlignmentConstantLineLabels(lineLabelOptions);
  84454. text = _isDefined(text) ? text : constants.formatLabel(parsedValue, labelOptions);
  84455. coords = that._getConstantLineLabelsCoords(value, lineLabelOptions);
  84456. return that._renderer.text(text, coords.x, coords.y).css(core.utils.patchFontOptions(_extend({}, labelOptions.font, lineLabelOptions.font))).attr({align: coords.align}).append(that._axisConstantLineGroup)
  84457. },
  84458. _adjustConstantLineLabels: _noop,
  84459. _getStripPos: function(startValue, endValue, canvasStart, canvasEnd, range) {
  84460. var isContinous = !!(range.minVisible || range.maxVisible),
  84461. categories = range.categories || [],
  84462. start,
  84463. end,
  84464. firstValue = startValue,
  84465. lastValue = endValue,
  84466. startCategoryIndex,
  84467. endCategoryIndex,
  84468. min = range.minVisible;
  84469. if (!isContinous) {
  84470. startCategoryIndex = $.inArray(startValue, categories);
  84471. endCategoryIndex = $.inArray(endValue, categories);
  84472. if (startCategoryIndex === -1 || endCategoryIndex === -1)
  84473. return {
  84474. stripFrom: 0,
  84475. stripTo: 0
  84476. };
  84477. if (startCategoryIndex > endCategoryIndex) {
  84478. firstValue = endValue;
  84479. lastValue = startValue
  84480. }
  84481. }
  84482. start = this._getTranslatedCoord(this._validateUnit(firstValue, "E2105", "strip"), -1);
  84483. end = this._getTranslatedCoord(this._validateUnit(lastValue, "E2105", "strip"), 1);
  84484. if (!_isDefined(start) && isContinous)
  84485. start = startValue < min ? canvasStart : canvasEnd;
  84486. if (!_isDefined(end) && isContinous)
  84487. end = endValue < min ? canvasStart : canvasEnd;
  84488. return start < end ? {
  84489. stripFrom: start,
  84490. stripTo: end
  84491. } : {
  84492. stripFrom: end,
  84493. stripTo: start
  84494. }
  84495. },
  84496. _createStrip: function(fromPoint, toPoint, attr) {
  84497. var x,
  84498. y,
  84499. width,
  84500. height,
  84501. additionalTranslator = this._additionalTranslator,
  84502. positionFrom = additionalTranslator.translateSpecialCase(constants.canvasPositionStart),
  84503. positionTo = additionalTranslator.translateSpecialCase(constants.canvasPositionEnd);
  84504. if (this._isHorizontal) {
  84505. x = fromPoint;
  84506. y = _math.min(positionFrom, positionTo);
  84507. width = toPoint - fromPoint;
  84508. height = _abs(positionFrom - positionTo)
  84509. }
  84510. else {
  84511. x = _math.min(positionFrom, positionTo);
  84512. y = fromPoint;
  84513. width = _abs(positionFrom - positionTo);
  84514. height = _abs(fromPoint - toPoint)
  84515. }
  84516. return this._renderer.rect(x, y, width, height).attr(attr)
  84517. },
  84518. _drawStrip: function() {
  84519. var that = this,
  84520. options = that._options,
  84521. stripData = options.strips,
  84522. canvas = this._getCanvasStartEnd(),
  84523. i,
  84524. stripOptions,
  84525. stripPos,
  84526. stripLabelOptions,
  84527. attr,
  84528. range = that._translator.getBusinessRange();
  84529. if (range.stubData)
  84530. return;
  84531. that._strips = [];
  84532. that._stripLabels = [];
  84533. for (i = 0; i < stripData.length; i++) {
  84534. stripOptions = stripData[i];
  84535. stripLabelOptions = stripOptions.label || {};
  84536. attr = {fill: stripOptions.color};
  84537. if (_isDefined(stripOptions.startValue) && _isDefined(stripOptions.endValue) && _isDefined(stripOptions.color)) {
  84538. stripPos = that._getStripPos(stripOptions.startValue, stripOptions.endValue, canvas.start, canvas.end, range);
  84539. if (stripPos.stripTo - stripPos.stripFrom === 0 || !_isDefined(stripPos.stripTo) || !_isDefined(stripPos.stripFrom)) {
  84540. that._strips.push(null);
  84541. if (stripLabelOptions.text)
  84542. that._stripLabels.push(null);
  84543. continue
  84544. }
  84545. that._strips.push(that._createStrip(stripPos.stripFrom, stripPos.stripTo, attr).append(that._axisStripGroup));
  84546. that._stripLabels.push(stripLabelOptions.text ? that._drawStripLabel(stripLabelOptions, stripPos.stripFrom, stripPos.stripTo) : null)
  84547. }
  84548. }
  84549. },
  84550. _drawStripLabel: function(stripLabelOptions, stripFrom, stripTo) {
  84551. var that = this,
  84552. options = that._options,
  84553. coords = that._getStripLabelCoords(stripLabelOptions, stripFrom, stripTo);
  84554. return that._renderer.text(stripLabelOptions.text, coords.x, coords.y).css(core.utils.patchFontOptions(_extend({}, options.label.font, stripLabelOptions.font))).attr({align: coords.align}).append(that._axisLabelGroup)
  84555. },
  84556. _adjustStripLabels: function() {
  84557. var that = this,
  84558. labels = that._stripLabels,
  84559. rects = that._strips,
  84560. i,
  84561. coords;
  84562. if (labels === undefined && rects === undefined)
  84563. return;
  84564. for (i = 0; i < labels.length; i++)
  84565. if (labels[i] !== null) {
  84566. coords = that._getAdjustedStripLabelCoords(that._options.strips[i], labels[i], rects[i]);
  84567. labels[i].move(coords.x, coords.y)
  84568. }
  84569. },
  84570. _initAxisPositions: _noop,
  84571. _adjustLabels: function() {
  84572. var that = this,
  84573. options = that._options,
  84574. majorTicks = that._majorTicks,
  84575. majorTicksLength = majorTicks.length,
  84576. isHorizontal = that._isHorizontal,
  84577. overlappingBehavior = that._tickManager ? that._tickManager.getOverlappingBehavior() : options.label.overlappingBehavior,
  84578. position = options.position,
  84579. label,
  84580. labelHeight,
  84581. isNeedLabelAdjustment,
  84582. staggeringSpacing,
  84583. i,
  84584. box,
  84585. hasLabels = false,
  84586. boxAxis = that._axisElementsGroup && that._axisElementsGroup.getBBox() || {};
  84587. _each(majorTicks, function(_, tick) {
  84588. if (tick.label) {
  84589. tick.label.attr(that._getLabelAdjustedCoord(tick, boxAxis));
  84590. hasLabels = true
  84591. }
  84592. });
  84593. isNeedLabelAdjustment = hasLabels && isHorizontal && overlappingBehavior && overlappingBehavior.mode === "stagger";
  84594. if (isNeedLabelAdjustment) {
  84595. labelHeight = 0;
  84596. for (i = 0; i < majorTicksLength; i = i + 2) {
  84597. label = majorTicks[i].label;
  84598. box = label && label.getBBox() || {};
  84599. if (box.height > labelHeight)
  84600. labelHeight = box.height
  84601. }
  84602. staggeringSpacing = overlappingBehavior.staggeringSpacing;
  84603. labelHeight = _round(labelHeight) + staggeringSpacing;
  84604. for (i = 1; i < majorTicksLength; i = i + 2) {
  84605. label = majorTicks[i].label;
  84606. if (label)
  84607. if (position === constants.bottom)
  84608. label.move(0, labelHeight);
  84609. else if (position === constants.top)
  84610. label.move(0, -labelHeight)
  84611. }
  84612. for (i = 0; i < majorTicksLength; i++)
  84613. majorTicks[i].label && majorTicks[i].label.rotate(0)
  84614. }
  84615. },
  84616. _getLabelAdjustedCoord: function(tick, boxAxis) {
  84617. var that = this,
  84618. options = that._options,
  84619. box = tick.label.getBBox(),
  84620. x,
  84621. y,
  84622. isHorizontal = that._isHorizontal,
  84623. position = options.position,
  84624. shift = that.padding && that.padding[position] || 0,
  84625. textOptions = that._textOptions,
  84626. labelSettingsY = tick.label.attr("y");
  84627. if (isHorizontal && position === constants.bottom)
  84628. y = 2 * labelSettingsY - box.y + shift;
  84629. else if (!isHorizontal) {
  84630. if (position === constants.left)
  84631. if (textOptions.align === constants.right)
  84632. x = box.x + box.width - shift;
  84633. else if (textOptions.align === constants.center)
  84634. x = box.x + box.width / 2 - shift - (boxAxis.width / 2 || 0);
  84635. else
  84636. x = box.x - shift - (boxAxis.width || 0);
  84637. else if (textOptions.align === constants.center)
  84638. x = box.x + box.width / 2 + (boxAxis.width / 2 || 0) + shift;
  84639. else if (textOptions.align === constants.right)
  84640. x = box.x + box.width + (boxAxis.width || 0) + shift;
  84641. else
  84642. x = box.x + shift;
  84643. y = labelSettingsY + ~~(labelSettingsY - box.y - box.height / 2)
  84644. }
  84645. else if (isHorizontal && position === constants.top)
  84646. y = 2 * labelSettingsY - box.y - box.height - shift;
  84647. return {
  84648. x: x,
  84649. y: y
  84650. }
  84651. },
  84652. _adjustTitle: _noop,
  84653. _createAxisGroups: function() {
  84654. var that = this,
  84655. renderer = that._renderer,
  84656. classSelector = WIDGET_CLASS + "-" + that._axisClass + "-";
  84657. that._axisGroup = renderer.g().attr({"class": classSelector + "axis"});
  84658. that._axisStripGroup = renderer.g().attr({"class": classSelector + "strips"});
  84659. that._axisGridGroup = renderer.g().attr({"class": classSelector + "grid"});
  84660. that._axisElementsGroup = renderer.g().attr({"class": classSelector + "elements"}).append(that._axisGroup);
  84661. that._axisLineGroup = renderer.g().attr({"class": classSelector + "line"}).append(that._axisGroup);
  84662. that._axisTitleGroup = renderer.g().attr({"class": classSelector + "title"}).append(that._axisGroup);
  84663. that._axisConstantLineGroup = renderer.g().attr({"class": classSelector + "constant-lines"});
  84664. that._axisLabelGroup = renderer.g().attr({"class": classSelector + "axis-labels"})
  84665. },
  84666. _clearAxisGroups: function(adjustAxis) {
  84667. var that = this,
  84668. classSelector = WIDGET_CLASS + "-" + that._axisClass + "-";
  84669. that._axisGroup.remove();
  84670. that._axisStripGroup.remove();
  84671. that._axisLabelGroup.remove();
  84672. that._axisConstantLineGroup.remove();
  84673. that._axisGridGroup.remove();
  84674. if (that._axisTitleGroup)
  84675. that._axisTitleGroup.clear();
  84676. else if (!adjustAxis)
  84677. that._axisTitleGroup = that._renderer.g().attr({"class": classSelector + "title"}).append(that._axisGroup);
  84678. if (that._axisElementsGroup)
  84679. that._axisElementsGroup.clear();
  84680. else if (!adjustAxis)
  84681. that._axisElementsGroup = that._renderer.g().attr({"class": classSelector + "elements"}).append(that._axisGroup);
  84682. that._axisLineGroup.clear();
  84683. that._axisStripGroup.clear();
  84684. that._axisGridGroup.clear();
  84685. that._axisConstantLineGroup.clear();
  84686. that._axisLabelGroup.clear()
  84687. },
  84688. _initTicks: function(ticks, tickOptions, gridOptions, withLabels) {
  84689. var that = this,
  84690. options = that._options,
  84691. tickStyle = {
  84692. stroke: tickOptions.color,
  84693. "stroke-width": 1,
  84694. "stroke-opacity": tickOptions.opacity
  84695. },
  84696. gridStyle = {
  84697. stroke: gridOptions.color,
  84698. "stroke-width": gridOptions.width,
  84699. "stroke-opacity": gridOptions.opacity
  84700. },
  84701. currentLabelConst = that.getCurrentLabelPos(),
  84702. categoryToSkip = that._getSkippedCategory();
  84703. _each(ticks || [], function(_, tick) {
  84704. var coord;
  84705. if (!(categoryToSkip && categoryToSkip === tick.value)) {
  84706. coord = that._getTranslatedValue(tick.value, that._axisPosition, that._tickOffset);
  84707. tick.posX = coord.x;
  84708. tick.posY = coord.y;
  84709. tick.angle = coord.angle
  84710. }
  84711. tick.tickStyle = tickStyle;
  84712. tick.gridStyle = gridStyle;
  84713. if (withLabels) {
  84714. tick.labelText = constants.formatLabel(tick.value, options.label, {
  84715. min: that._minBound,
  84716. max: that._maxBound
  84717. });
  84718. tick.labelPos = that._getTranslatedValue(tick.value, currentLabelConst);
  84719. tick.labelStyle = that._textOptions;
  84720. tick.labelFontStyle = that._textFontStyles;
  84721. tick.labelHint = constants.formatHint(tick.value, options.label, {
  84722. min: that._minBound,
  84723. max: that._maxBound
  84724. })
  84725. }
  84726. })
  84727. },
  84728. _setTickOffset: function() {
  84729. var options = this._options,
  84730. discreteAxisDivisionMode = options.discreteAxisDivisionMode;
  84731. this._tickOffset = +(discreteAxisDivisionMode !== "crossLabels" || !discreteAxisDivisionMode)
  84732. },
  84733. drawGrids: function(borderOptions) {
  84734. var that = this,
  84735. options = that._options;
  84736. borderOptions = borderOptions || {};
  84737. that._axisGridGroup.append(that._gridContainerGroup);
  84738. if (options.grid.visible)
  84739. that._drawGrids(that._majorTicks.concat(that._decimatedTicks), borderOptions);
  84740. options.minorGrid.visible && that._drawGrids(that._minorTicks, borderOptions)
  84741. },
  84742. draw: function(adjustAxis) {
  84743. var that = this,
  84744. options = that._options,
  84745. areLabelsVisible;
  84746. if (that._axisGroup)
  84747. that._clearAxisGroups(adjustAxis);
  84748. areLabelsVisible = options.label.visible && that._axisElementsGroup && !that._translator.getBusinessRange().stubData;
  84749. that._updateTranslatorInterval();
  84750. that._initAxisPositions();
  84751. that._initTicks(that._majorTicks, options.tick, options.grid, areLabelsVisible);
  84752. that._initTicks(that._decimatedTicks, options.tick, options.grid, false);
  84753. that._initTicks(that._minorTicks, options.minorTick, options.minorGrid);
  84754. if (!that._virtual) {
  84755. options.visible && that._drawAxis();
  84756. if (options.tick.visible) {
  84757. that._drawTicks(that._majorTicks);
  84758. that._drawTicks(that._decimatedTicks)
  84759. }
  84760. options.minorTick.visible && that._drawTicks(that._minorTicks);
  84761. areLabelsVisible && that._drawLabels();
  84762. that._drawTitle()
  84763. }
  84764. options.strips && that._drawStrip();
  84765. options.constantLines && that._drawConstantLine();
  84766. that._axisStripGroup.append(that._stripsGroup);
  84767. that._axisConstantLineGroup.append(that._constantLinesGroup);
  84768. that._axisGroup.append(that._axesContainerGroup);
  84769. that._axisLabelGroup.append(that._labelAxesGroup);
  84770. that._adjustConstantLineLabels();
  84771. areLabelsVisible && that._adjustLabels();
  84772. that._createHints();
  84773. that._adjustStripLabels();
  84774. that._adjustTitle();
  84775. that._setBoundingRect()
  84776. },
  84777. _createHints: function() {
  84778. var that = this;
  84779. _each(that._majorTicks || [], function(_, tick) {
  84780. var labelHint = tick.labelHint;
  84781. if (_isDefined(labelHint) && labelHint !== "")
  84782. tick.label.setTitle(labelHint)
  84783. })
  84784. },
  84785. _setBoundingRect: function() {
  84786. var that = this,
  84787. options = that._options,
  84788. axisBox = that._axisElementsGroup ? that._axisElementsGroup.getBBox() : {
  84789. x: 0,
  84790. y: 0,
  84791. width: 0,
  84792. height: 0,
  84793. isEmpty: true
  84794. },
  84795. lineBox = that._axisLineGroup.getBBox(),
  84796. placeholderSize = options.placeholderSize,
  84797. start,
  84798. isHorizontal = that._isHorizontal,
  84799. coord = isHorizontal ? "y" : "x",
  84800. side = isHorizontal ? "height" : "width",
  84801. shiftCoords = options.crosshairEnabled ? isHorizontal ? LABEL_BACKGROUND_PADDING_Y : LABEL_BACKGROUND_PADDING_X : 0,
  84802. axisTitleBox = that._title && that._axisTitleGroup ? that._axisTitleGroup.getBBox() : axisBox;
  84803. if (axisBox.isEmpty && axisTitleBox.isEmpty && !placeholderSize) {
  84804. that.boundingRect = axisBox;
  84805. return
  84806. }
  84807. start = lineBox[coord] || that._axisPosition;
  84808. if (options.position === (isHorizontal && constants.bottom || constants.right)) {
  84809. axisBox[side] = placeholderSize || axisTitleBox[coord] + axisTitleBox[side] - start + shiftCoords;
  84810. axisBox[coord] = start
  84811. }
  84812. else {
  84813. axisBox[side] = placeholderSize || lineBox[side] + start - axisTitleBox[coord] + shiftCoords;
  84814. axisBox[coord] = axisTitleBox.isEmpty ? start : axisTitleBox[coord] - shiftCoords
  84815. }
  84816. that.boundingRect = axisBox
  84817. },
  84818. getBoundingRect: function() {
  84819. return this._axisElementsGroup ? this.boundingRect : {
  84820. x: 0,
  84821. y: 0,
  84822. width: 0,
  84823. height: 0
  84824. }
  84825. },
  84826. shift: function(x, y) {
  84827. var settings = {};
  84828. if (x)
  84829. settings.translateX = x;
  84830. if (y)
  84831. settings.translateY = y;
  84832. this._axisGroup.attr(settings)
  84833. },
  84834. applyClipRects: function(elementsClipID, canvasClipID) {
  84835. this._axisGroup.attr({clipId: canvasClipID});
  84836. this._axisStripGroup.attr({clipId: elementsClipID})
  84837. },
  84838. validate: function(isArgumentAxis) {
  84839. var that = this,
  84840. options = that._options,
  84841. parseUtils = new core.ParseUtils,
  84842. dataType = isArgumentAxis ? options.argumentType : options.valueType,
  84843. parser = dataType ? parseUtils.getParser(dataType, "axis") : function(unit) {
  84844. return unit
  84845. };
  84846. that.parser = parser;
  84847. options.dataType = dataType;
  84848. if (options.min !== undefined)
  84849. options.min = that._validateUnit(options.min, "E2106");
  84850. if (options.max !== undefined)
  84851. options.max = that._validateUnit(options.max, "E2106");
  84852. if (that._minBound !== undefined)
  84853. that._minBound = that._validateUnit(that._minBound);
  84854. if (that._maxBound !== undefined)
  84855. that._maxBound = that._validateUnit(that._maxBound)
  84856. },
  84857. _validateUnit: function(unit, idError, parameters) {
  84858. var that = this;
  84859. unit = that.parser(unit);
  84860. if (unit === undefined && idError)
  84861. that._incidentOccured(idError, [parameters]);
  84862. return unit
  84863. },
  84864. zoom: function(min, max, skipAdjusting) {
  84865. var that = this,
  84866. minOpt = that._options.min,
  84867. maxOpt = that._options.max;
  84868. skipAdjusting = skipAdjusting || that._options.type === constants.discrete;
  84869. min = that._validateUnit(min);
  84870. max = that._validateUnit(max);
  84871. if (!skipAdjusting) {
  84872. if (minOpt !== undefined) {
  84873. min = minOpt > min ? minOpt : min;
  84874. max = minOpt > max ? minOpt : max
  84875. }
  84876. if (maxOpt !== undefined) {
  84877. max = maxOpt < max ? maxOpt : max;
  84878. min = maxOpt < min ? maxOpt : min
  84879. }
  84880. }
  84881. that._zoomArgs = {
  84882. min: min,
  84883. max: max
  84884. };
  84885. return that._zoomArgs
  84886. },
  84887. resetZoom: function() {
  84888. this._zoomArgs = null
  84889. },
  84890. getRangeData: function() {
  84891. var that = this,
  84892. options = that._options,
  84893. minMax = that._getMinMax(),
  84894. min = minMax.min,
  84895. max = minMax.max,
  84896. zoomArgs = that._zoomArgs || {},
  84897. type = options.type,
  84898. rangeMin,
  84899. rangeMax,
  84900. rangeMinVisible,
  84901. rangeMaxVisible;
  84902. if (type === constants.logarithmic) {
  84903. min = min <= 0 ? undefined : min;
  84904. max = max <= 0 ? undefined : max
  84905. }
  84906. if (type !== constants.discrete) {
  84907. rangeMin = min;
  84908. rangeMax = max;
  84909. if (_isDefined(min) && _isDefined(max)) {
  84910. rangeMin = min < max ? min : max;
  84911. rangeMax = max > min ? max : min
  84912. }
  84913. rangeMinVisible = _isDefined(zoomArgs.min) ? zoomArgs.min : rangeMin;
  84914. rangeMaxVisible = _isDefined(zoomArgs.max) ? zoomArgs.max : rangeMax
  84915. }
  84916. else {
  84917. rangeMinVisible = _isDefined(zoomArgs.min) ? zoomArgs.min : min;
  84918. rangeMaxVisible = _isDefined(zoomArgs.max) ? zoomArgs.max : max
  84919. }
  84920. return {
  84921. min: rangeMin,
  84922. max: rangeMax,
  84923. stick: that._getStick(),
  84924. categories: options.categories,
  84925. dataType: options.dataType,
  84926. axisType: type,
  84927. base: options.logarithmBase,
  84928. invert: options.inverted,
  84929. addSpiderCategory: that._getSpiderCategoryOption(),
  84930. minVisible: rangeMinVisible,
  84931. maxVisible: rangeMaxVisible
  84932. }
  84933. },
  84934. _setType: function(axesType, drawingType) {
  84935. var that = this;
  84936. _each(DX.viz.charts.axes[axesType][drawingType], function(methodName, method) {
  84937. that[methodName] = method
  84938. })
  84939. },
  84940. _getSharpParam: function() {
  84941. return true
  84942. },
  84943. getSpiderTicks: _noop,
  84944. setSpiderTicks: _noop,
  84945. measureLabels: _noop,
  84946. coordsIn: _noop,
  84947. _getSkippedCategory: _noop
  84948. }
  84949. })(jQuery, DevExpress);
  84950. /*! Module viz-charts, file scrollBar.js */
  84951. (function($, DX, math) {
  84952. var MIN_SCROLL_BAR_SIZE = 2,
  84953. isDefined = DX.utils.isDefined,
  84954. _min = math.min,
  84955. _max = math.max;
  84956. DX.viz.charts.ScrollBar = function(renderer, group) {
  84957. this._translator = DX.viz.core.CoreFactory.createTranslator2D({}, {}, {});
  84958. this._scroll = renderer.rect().append(group);
  84959. this._addEvents()
  84960. };
  84961. function _getXCoord(canvas, pos, offset, width) {
  84962. var x = 0;
  84963. if (pos === "right")
  84964. x = canvas.width - canvas.right + offset;
  84965. else if (pos === "left")
  84966. x = canvas.left - offset - width;
  84967. return x
  84968. }
  84969. function _getYCoord(canvas, pos, offset, width) {
  84970. var y = 0;
  84971. if (pos === "top")
  84972. y = canvas.top - offset;
  84973. else if (pos === "bottom")
  84974. y = canvas.height - canvas.bottom + width + offset;
  84975. return y
  84976. }
  84977. DX.viz.charts.ScrollBar.prototype = {
  84978. _addEvents: function() {
  84979. var that = this,
  84980. $scroll = $(that._scroll.element),
  84981. startPosX = 0,
  84982. startPosY = 0,
  84983. scrollChangeHandler = function(e) {
  84984. var dX = (startPosX - e.pageX) * that._scale,
  84985. dY = (startPosY - e.pageY) * that._scale;
  84986. $scroll.trigger(new $.Event("dxc-scroll-move", $.extend(e, {
  84987. type: "dxc-scroll-move",
  84988. pointers: [{
  84989. pageX: startPosX + dX,
  84990. pageY: startPosY + dY
  84991. }]
  84992. })))
  84993. };
  84994. $scroll.on("dxpointerdown", function(e) {
  84995. startPosX = e.pageX;
  84996. startPosY = e.pageY;
  84997. $scroll.trigger(new $.Event("dxc-scroll-start", {pointers: [{
  84998. pageX: startPosX,
  84999. pageY: startPosY
  85000. }]}));
  85001. $(document).on("dxpointermove", scrollChangeHandler)
  85002. });
  85003. $(document).on("dxpointerup", function() {
  85004. $(document).off("dxpointermove", scrollChangeHandler)
  85005. })
  85006. },
  85007. update: function(options) {
  85008. var that = this,
  85009. position = options.position,
  85010. isVertical = options.rotated,
  85011. defaultPosition = isVertical ? "right" : "top",
  85012. secondaryPosition = isVertical ? "left" : "bottom";
  85013. if (position !== defaultPosition && position !== secondaryPosition)
  85014. position = defaultPosition;
  85015. that._scroll.attr({
  85016. rotate: !options.rotated ? -90 : 0,
  85017. rotateX: 0,
  85018. rotateY: 0,
  85019. fill: options.color,
  85020. width: options.width,
  85021. opacity: options.opacity
  85022. });
  85023. that._layoutOptions = {
  85024. width: options.width,
  85025. offset: options.offset,
  85026. vertical: isVertical,
  85027. position: position
  85028. };
  85029. return that
  85030. },
  85031. init: function(range, canvas) {
  85032. var that = this;
  85033. that._translateWithOffset = range.axisType === "discrete" && !range.stick && 1 || 0;
  85034. that._translator.update($.extend({}, range, {
  85035. minVisible: null,
  85036. maxVisible: null,
  85037. visibleCategories: null
  85038. }), $.extend({}, canvas), {direction: that._layoutOptions.vertical ? "vertical" : "horizontal"});
  85039. return that
  85040. },
  85041. getOptions: function() {
  85042. return this._layoutOptions
  85043. },
  85044. shift: function(x, y) {
  85045. this._scroll.attr({
  85046. translateX: x,
  85047. translateY: y
  85048. })
  85049. },
  85050. setPane: function(panes) {
  85051. var position = this._layoutOptions.position,
  85052. pane;
  85053. if (position === "left" || position === "top")
  85054. pane = panes[0];
  85055. else
  85056. pane = panes[panes.length - 1];
  85057. this.pane = pane.name;
  85058. this._canvas = pane.canvas;
  85059. return this
  85060. },
  85061. getMultipleAxesSpacing: function() {
  85062. return 0
  85063. },
  85064. getBoundingRect: function() {
  85065. var options = this._layoutOptions,
  85066. isVertical = options.vertical,
  85067. offset = options.offset,
  85068. width = options.width,
  85069. pos = options.position,
  85070. size = width + offset,
  85071. canvas = this._canvas;
  85072. return isVertical ? {
  85073. x: _getXCoord(canvas, pos, offset, width),
  85074. y: canvas.top,
  85075. width: size,
  85076. height: canvas.height - canvas.top - canvas.bottom
  85077. } : {
  85078. x: canvas.left,
  85079. y: _getYCoord(canvas, pos, offset, width),
  85080. width: canvas.width - canvas.left - canvas.right,
  85081. height: size
  85082. }
  85083. },
  85084. applyLayout: function() {
  85085. var canvas = this._canvas,
  85086. options = this._layoutOptions,
  85087. pos = options.position,
  85088. offset = options.offset,
  85089. width = options.width;
  85090. this.shift(_getXCoord(canvas, pos, offset, width), _getYCoord(canvas, pos, offset, width))
  85091. },
  85092. setPosition: function(min, max) {
  85093. var that = this,
  85094. translator = that._translator,
  85095. minPoint = isDefined(min) ? translator.translate(min, -that._translateWithOffset) : translator.translate("canvas_position_start"),
  85096. maxPoint = isDefined(max) ? translator.translate(max, that._translateWithOffset) : translator.translate("canvas_position_end");
  85097. that._offset = _min(minPoint, maxPoint);
  85098. that._scale = translator.getScale(min, max);
  85099. that._applyPosition(_min(minPoint, maxPoint), _max(minPoint, maxPoint))
  85100. },
  85101. transform: function(translate, scale) {
  85102. var x = this._translator.getCanvasVisibleArea().min,
  85103. dx = x - (x * scale - translate),
  85104. lx = this._offset + dx / (this._scale * scale);
  85105. this._applyPosition(lx, lx + this._translator.canvasLength / (this._scale * scale))
  85106. },
  85107. dispose: function() {
  85108. this._scroll.dispose();
  85109. this._scroll = this._translator = null
  85110. },
  85111. _applyPosition: function(x1, x2) {
  85112. var that = this,
  85113. visibleArea = that._translator.getCanvasVisibleArea(),
  85114. height;
  85115. x1 = _max(x1, visibleArea.min);
  85116. x1 = _min(x1, visibleArea.max);
  85117. x2 = _min(x2, visibleArea.max);
  85118. x2 = _max(x2, visibleArea.min);
  85119. height = math.abs(x2 - x1);
  85120. that._scroll.attr({
  85121. y: x1,
  85122. height: height < MIN_SCROLL_BAR_SIZE ? MIN_SCROLL_BAR_SIZE : height
  85123. })
  85124. }
  85125. }
  85126. })(jQuery, DevExpress, Math);
  85127. /*! Module viz-charts, file baseChart.js */
  85128. (function($, DX, undefined) {
  85129. var ui = DX.ui,
  85130. charts = DX.viz.charts,
  85131. utils = DX.utils,
  85132. ACTIONS_BY_PRIORITY = ['reinit', '_reinitDataSource', '_dataInit', 'force_render', "_resize"],
  85133. core = DX.viz.core,
  85134. _each = $.each,
  85135. _map = $.map,
  85136. _extend = $.extend,
  85137. DEFAULT_ANIMATION_OPTIONS = {asyncSeriesRendering: true},
  85138. _isDefined = utils.isDefined,
  85139. DEFAULT_OPACITY = 0.3;
  85140. function createEventMapObject(name, deprecatedArgs) {
  85141. return {
  85142. name: name,
  85143. deprecated: name,
  85144. deprecatedContext: function(arg) {
  85145. return arg.target
  85146. },
  85147. deprecatedArgs: deprecatedArgs || function(arg) {
  85148. return [arg.target, arg.jQueryEvent]
  85149. }
  85150. }
  85151. }
  85152. function checkHeightLabelsInCanvas(points, canvas, isRotated) {
  85153. var commonLabelSize = 0,
  85154. canvasSize = canvas.end - canvas.start,
  85155. label,
  85156. bbox;
  85157. for (var i = 0; i < points.length; i++) {
  85158. label = points[i].getLabel();
  85159. if (label.isVisible()) {
  85160. bbox = label.getBoundingRect();
  85161. commonLabelSize += isRotated ? bbox.width : bbox.height
  85162. }
  85163. else
  85164. points[i] = null
  85165. }
  85166. if (canvasSize > 0)
  85167. while (commonLabelSize > canvasSize)
  85168. commonLabelSize -= killSmallValues(points, isRotated)
  85169. }
  85170. function killSmallValues(points, isRotated) {
  85171. var smallestValuePoint = {originalValue: Infinity},
  85172. label,
  85173. bbox,
  85174. indexOfPoint;
  85175. _each(points, function(index, point) {
  85176. if (point && smallestValuePoint.originalValue >= point.originalValue) {
  85177. smallestValuePoint = point;
  85178. indexOfPoint = index
  85179. }
  85180. });
  85181. if (indexOfPoint !== null) {
  85182. label = points[indexOfPoint].getLabel();
  85183. bbox = label.getBoundingRect();
  85184. label.hide();
  85185. points[indexOfPoint] = null;
  85186. return isRotated ? bbox.width : bbox.height
  85187. }
  85188. return 0
  85189. }
  85190. function resolveLabelOverlappingInOneDirection(points, canvas, isRotated, shiftFunction) {
  85191. var stubCanvas = {
  85192. start: isRotated ? canvas.left : canvas.top,
  85193. end: isRotated ? canvas.width - canvas.right : canvas.height - canvas.bottom
  85194. };
  85195. checkHeightLabelsInCanvas(points, stubCanvas, isRotated);
  85196. var rollingStocks = $.map(points, function(point) {
  85197. return point && new RollingStock(point, isRotated, shiftFunction)
  85198. });
  85199. rollingStocks.sort(function(a, b) {
  85200. return a.getPointPosition() - b.getPointPosition()
  85201. });
  85202. if (!checkStackOverlap(rollingStocks))
  85203. return;
  85204. rollingStocks.reverse();
  85205. moveRollingStock(rollingStocks, stubCanvas)
  85206. }
  85207. function overlapRollingStock(firstRolling, secondRolling) {
  85208. if (!firstRolling || !secondRolling)
  85209. return;
  85210. return firstRolling.getBoundingRect().end > secondRolling.getBoundingRect().start
  85211. }
  85212. function checkStackOverlap(rollingStocks) {
  85213. var i,
  85214. j,
  85215. currentRollingStock,
  85216. nextRollingStock,
  85217. overlap;
  85218. for (i = 0; i < rollingStocks.length; i++) {
  85219. currentRollingStock = rollingStocks[i];
  85220. for (j = i + 1; j < rollingStocks.length; j++) {
  85221. nextRollingStock = rollingStocks[j];
  85222. if (overlapRollingStock(currentRollingStock, nextRollingStock)) {
  85223. currentRollingStock.toChain(nextRollingStock);
  85224. overlap = true;
  85225. rollingStocks[j] = null
  85226. }
  85227. }
  85228. }
  85229. return overlap
  85230. }
  85231. function moveRollingStock(rollingStocks, canvas) {
  85232. var i,
  85233. j,
  85234. currentRollingStock,
  85235. nextRollingStock,
  85236. currentBBox,
  85237. nextBBox;
  85238. for (i = 0; i < rollingStocks.length; i++) {
  85239. currentRollingStock = rollingStocks[i];
  85240. if (rollingStocksIsOut(currentRollingStock, canvas)) {
  85241. currentBBox = currentRollingStock.getBoundingRect();
  85242. for (j = i + 1; j < rollingStocks.length; j++) {
  85243. nextRollingStock = rollingStocks[j];
  85244. if (!nextRollingStock)
  85245. continue;
  85246. nextBBox = nextRollingStock.getBoundingRect();
  85247. if (nextBBox.end > currentBBox.start - (currentBBox.end - canvas.end)) {
  85248. nextRollingStock.toChain(currentRollingStock);
  85249. rollingStocks[i] = currentRollingStock = null;
  85250. break
  85251. }
  85252. }
  85253. }
  85254. currentRollingStock && currentRollingStock.setRollingStockInCanvas(canvas)
  85255. }
  85256. }
  85257. function rollingStocksIsOut(rollingStock, canvas) {
  85258. return rollingStock && rollingStock.getBoundingRect().end > canvas.end
  85259. }
  85260. function RollingStock(point, isRotated, shiftFunction) {
  85261. var label = point.getLabel(),
  85262. bbox = label.getBoundingRect();
  85263. this.labels = [label];
  85264. this.points = [point];
  85265. this.shiftFunction = shiftFunction;
  85266. this._bbox = {
  85267. start: isRotated ? bbox.x : bbox.y,
  85268. width: isRotated ? bbox.width : bbox.height,
  85269. end: isRotated ? bbox.x + bbox.width : bbox.y + bbox.height
  85270. };
  85271. this._pointPositionInitialize = isRotated ? point.getBoundaryCoords().x : point.getBoundaryCoords().y;
  85272. return this
  85273. }
  85274. RollingStock.prototype = {
  85275. toChain: function(nextRollingStock) {
  85276. var nextRollingStockBBox = nextRollingStock.getBoundingRect();
  85277. nextRollingStock.shift(nextRollingStockBBox.start - this._bbox.end);
  85278. this._changeBoxWidth(nextRollingStockBBox.width);
  85279. this.labels = this.labels.concat(nextRollingStock.labels);
  85280. this.points = this.points.concat(nextRollingStock.points)
  85281. },
  85282. getBoundingRect: function() {
  85283. return this._bbox
  85284. },
  85285. shift: function(shiftLength) {
  85286. var shiftFunction = this.shiftFunction;
  85287. _each(this.labels, function(index, label) {
  85288. var bbox = label.getBoundingRect(),
  85289. coords = shiftFunction(bbox, shiftLength, label);
  85290. label.shift(coords.x, coords.y)
  85291. });
  85292. this._bbox.end -= shiftLength;
  85293. this._bbox.start -= shiftLength
  85294. },
  85295. setRollingStockInCanvas: function(canvas) {
  85296. if (this._bbox.end > canvas.end)
  85297. this.shift(this._bbox.end - canvas.end)
  85298. },
  85299. getPointPosition: function() {
  85300. return this._pointPositionInitialize
  85301. },
  85302. _changeBoxWidth: function(width) {
  85303. this._bbox.end += width;
  85304. this._bbox.width += width
  85305. }
  85306. };
  85307. function getLegendFields(name) {
  85308. return {
  85309. nameField: name + 'Name',
  85310. colorField: name + 'Color',
  85311. indexField: name + 'Index'
  85312. }
  85313. }
  85314. function getLegendSettings(legendDataField) {
  85315. var formatObjectFields = getLegendFields(legendDataField);
  85316. return {
  85317. getFormatObject: function(data) {
  85318. var res = {};
  85319. res[formatObjectFields.indexField] = data.id;
  85320. res[formatObjectFields.colorField] = data.states.normal.fill;
  85321. res[formatObjectFields.nameField] = data.text;
  85322. return res
  85323. },
  85324. textField: formatObjectFields.nameField
  85325. }
  85326. }
  85327. function checkOverlapping(firstRect, secondRect) {
  85328. return (firstRect.x <= secondRect.x && secondRect.x <= firstRect.x + firstRect.width || firstRect.x >= secondRect.x && firstRect.x <= secondRect.x + secondRect.width) && (firstRect.y <= secondRect.y && secondRect.y <= firstRect.y + firstRect.height || firstRect.y >= secondRect.y && firstRect.y <= secondRect.y + secondRect.height)
  85329. }
  85330. charts.overlapping = {resolveLabelOverlappingInOneDirection: resolveLabelOverlappingInOneDirection};
  85331. charts.BaseChart = core.BaseWidget.inherit({
  85332. _eventsMap: $.extend({}, core.BaseWidget.prototype._eventsMap, {
  85333. onSeriesClick: createEventMapObject("seriesClick"),
  85334. onPointClick: createEventMapObject("pointClick"),
  85335. onArgumentAxisClick: createEventMapObject("argumentAxisClick", function(arg) {
  85336. return [arg.target, arg.argument, arg.jQueryEvent]
  85337. }),
  85338. onLegendClick: createEventMapObject("legendClick"),
  85339. onSeriesSelectionChanged: createEventMapObject('seriesSelectionChanged'),
  85340. onPointSelectionChanged: createEventMapObject('pointSelectionChanged'),
  85341. onSeriesHoverChanged: createEventMapObject('seriesHoverChanged'),
  85342. onPointHoverChanged: createEventMapObject('pointHoverChanged'),
  85343. onTooltipShown: createEventMapObject('tooltipShown'),
  85344. onTooltipHidden: createEventMapObject('tooltipHidden'),
  85345. onDone: createEventMapObject("done"),
  85346. seriesClick: {newName: 'onSeriesClick'},
  85347. pointClick: {newName: 'onPointClick'},
  85348. argumentAxisClick: {newName: 'onArgumentAxisClick'},
  85349. legendClick: {newName: 'onLegendClick'},
  85350. pointHoverChanged: {newName: 'onPointHoverChanged'},
  85351. seriesSelectionChanged: {newName: 'onSeriesSelectionChanged'},
  85352. pointSelectionChanged: {newName: 'onPointSelectionChanged'},
  85353. seriesHoverChanged: {newName: 'onSeriesHoverChanged'},
  85354. tooltipShown: {newName: 'onTooltipShown'},
  85355. tooltipHidden: {newName: 'onTooltipHidden'},
  85356. done: {newName: 'onDone'}
  85357. }),
  85358. _setDeprecatedOptions: function() {
  85359. this.callBase();
  85360. $.extend(this._deprecatedOptions, {
  85361. seriesClick: {
  85362. since: '14.2',
  85363. message: "Use the 'onSeriesClick' option instead"
  85364. },
  85365. pointClick: {
  85366. since: '14.2',
  85367. message: "Use the 'onPointClick' option instead"
  85368. },
  85369. argumentAxisClick: {
  85370. since: '14.2',
  85371. message: "Use the 'onArgumentAxisClick' option instead"
  85372. },
  85373. legendClick: {
  85374. since: '14.2',
  85375. message: "Use the 'onLegendClick' option instead"
  85376. },
  85377. seriesSelectionChanged: {
  85378. since: '14.2',
  85379. message: "Use the 'onSeriesSelectionChanged' option instead"
  85380. },
  85381. pointSelectionChanged: {
  85382. since: '14.2',
  85383. message: "Use the 'onPointSelectionChanged' option instead"
  85384. },
  85385. seriesHoverChanged: {
  85386. since: '14.2',
  85387. message: "Use the 'onSeriesHoverChanged' option instead"
  85388. },
  85389. pointHoverChanged: {
  85390. since: '14.2',
  85391. message: "Use the 'onPointHoverChanged' option instead"
  85392. },
  85393. tooltipShown: {
  85394. since: '14.2',
  85395. message: "Use the 'onTooltipShown' option instead"
  85396. },
  85397. tooltipHidden: {
  85398. since: '14.2',
  85399. message: "Use the 'onTooltipHidden' option instead"
  85400. },
  85401. done: {
  85402. since: '14.2',
  85403. message: "Use the 'onDone' option instead"
  85404. }
  85405. })
  85406. },
  85407. _rootClassPrefix: "dxc",
  85408. _rootClass: "dxc-chart",
  85409. _init: function() {
  85410. var that = this;
  85411. that.callBase.apply(that, arguments);
  85412. that._reinit()
  85413. },
  85414. _createThemeManager: function() {
  85415. var option = this.option(),
  85416. themeManager = charts.factory.createThemeManager(option, this._chartType);
  85417. themeManager.setTheme(option.theme, option.rtlEnabled);
  85418. return themeManager
  85419. },
  85420. _initCore: function() {
  85421. var that = this;
  85422. that._canvasClipRect = that._renderer.clipRect();
  85423. that._createHtmlStructure();
  85424. that._createLegend();
  85425. that._needHandleRenderComplete = true;
  85426. that.layoutManager = charts.factory.createChartLayoutManager(that._layoutManagerOptions());
  85427. that._createScrollBar();
  85428. that._$element.on('contextmenu', function(event) {
  85429. that.eventType = 'contextmenu';
  85430. if (ui.events.isTouchEvent(event) || ui.events.isPointerEvent(event))
  85431. event.preventDefault()
  85432. }).on('MSHoldVisual', function(event) {
  85433. that.eventType = 'MSHoldVisual';
  85434. event.preventDefault()
  85435. })
  85436. },
  85437. _layoutManagerOptions: function() {
  85438. return this._themeManager.getOptions("adaptiveLayout")
  85439. },
  85440. _reinit: function(needRedraw) {
  85441. var that = this;
  85442. charts._setCanvasValues(that._canvas);
  85443. that._createTracker();
  85444. that._reinitAxes();
  85445. that._reinitDataSource();
  85446. if (!that.series)
  85447. that._dataSpecificInit();
  85448. that._correctAxes();
  85449. needRedraw && that._endLoading(function() {
  85450. that._render({force: true})
  85451. })
  85452. },
  85453. _createHtmlStructure: function() {
  85454. var that = this,
  85455. renderer = that._renderer;
  85456. that._backgroundRect = renderer.rect(0, 0, 0, 0).attr({
  85457. fill: "gray",
  85458. opacity: 0.0001
  85459. });
  85460. that._panesBackgroundGroup = renderer.g().attr({'class': 'dxc-background'});
  85461. that._titleGroup = renderer.g().attr({'class': 'dxc-title'});
  85462. that._legendGroup = renderer.g().attr({
  85463. 'class': 'dxc-legend',
  85464. clipId: that._getCanvasClipRectID()
  85465. });
  85466. that._stripsGroup = renderer.g().attr({'class': 'dxc-strips-group'});
  85467. that._constantLinesGroup = renderer.g().attr({'class': 'dxc-constant-lines-group'});
  85468. that._axesGroup = renderer.g().attr({'class': 'dxc-axes-group'});
  85469. that._gridGroup = renderer.g().attr({'class': 'dxc-grids-group'});
  85470. that._panesBorderGroup = renderer.g().attr({'class': 'dxc-border'});
  85471. that._labelAxesGroup = renderer.g().attr({'class': 'dxc-strips-labels-group'});
  85472. that._scrollBarGroup = renderer.g().attr({'class': 'dxc-scroll-bar'});
  85473. that._seriesGroup = renderer.g().attr({'class': 'dxc-series-group'});
  85474. that._labelsGroup = renderer.g().attr({'class': 'dxc-labels-group'});
  85475. that._crosshairCursorGroup = renderer.g().attr({'class': 'dxc-crosshair-cursor'})
  85476. },
  85477. _disposeObjectsInArray: function(propName, fieldNames) {
  85478. $.each(this[propName] || [], function(_, item) {
  85479. if (fieldNames && item)
  85480. $.each(fieldNames, function(_, field) {
  85481. item[field] && item[field].dispose()
  85482. });
  85483. else
  85484. item && item.dispose()
  85485. });
  85486. this[propName] = null
  85487. },
  85488. _disposeCore: function() {
  85489. var that = this,
  85490. disposeObject = function(propName) {
  85491. if (that[propName]) {
  85492. that[propName].dispose();
  85493. that[propName] = null
  85494. }
  85495. },
  85496. disposeObjectsInArray = this._disposeObjectsInArray;
  85497. clearTimeout(that._delayedRedraw);
  85498. that._renderer.stopAllAnimations();
  85499. disposeObjectsInArray.call(that, "businessRanges", ["arg", "val"]);
  85500. that.translators = null;
  85501. disposeObjectsInArray.call(that, "series");
  85502. disposeObject("layoutManager");
  85503. disposeObject("tracker");
  85504. disposeObject("chartTitle");
  85505. disposeObject("_crosshair");
  85506. that.paneAxis = null;
  85507. that._userOptions = null;
  85508. that._canvas = null;
  85509. disposeObject("_canvasClipRect");
  85510. disposeObject("_panesBackgroundGroup");
  85511. disposeObject("_titleGroup");
  85512. disposeObject("_scrollBarGroup");
  85513. disposeObject("_legendGroup");
  85514. disposeObject("_stripsGroup");
  85515. disposeObject("_constantLinesGroup");
  85516. disposeObject("_axesGroup");
  85517. disposeObject("_gridGroup");
  85518. disposeObject("_labelAxesGroup");
  85519. disposeObject("_panesBorderGroup");
  85520. disposeObject("_seriesGroup");
  85521. disposeObject("_labelsGroup");
  85522. disposeObject("_crosshairCursorGroup")
  85523. },
  85524. _getAnimationOptions: function() {
  85525. return $.extend({}, DEFAULT_ANIMATION_OPTIONS, this._themeManager.getOptions("animation"))
  85526. },
  85527. _getDefaultSize: function() {
  85528. return {
  85529. width: 400,
  85530. height: 400
  85531. }
  85532. },
  85533. _getOption: function(name) {
  85534. return this._themeManager.getOptions(name)
  85535. },
  85536. _reinitDataSource: function() {
  85537. this._refreshDataSource()
  85538. },
  85539. _applySize: $.noop,
  85540. _resize: function() {
  85541. if (this._updateLockCount)
  85542. this._processRefreshData("_resize");
  85543. else
  85544. this._render(this.__renderOptions || {
  85545. animate: false,
  85546. isResize: true,
  85547. updateTracker: false
  85548. })
  85549. },
  85550. _createTracker: function() {
  85551. var that = this,
  85552. themeManager = that._themeManager;
  85553. if (that.tracker)
  85554. that.tracker.dispose();
  85555. that.tracker = charts.factory.createTracker({
  85556. seriesSelectionMode: themeManager.getOptions('seriesSelectionMode'),
  85557. pointSelectionMode: themeManager.getOptions('pointSelectionMode'),
  85558. seriesGroup: that._seriesGroup,
  85559. renderer: that._renderer,
  85560. tooltip: that._tooltip,
  85561. eventTrigger: that._eventTrigger
  85562. }, that.NAME)
  85563. },
  85564. _getTrackerSettings: function() {
  85565. var that = this;
  85566. return {
  85567. series: that.series,
  85568. legend: that.legend,
  85569. legendCallback: $.proxy(that.legend.getActionCallback, that.legend)
  85570. }
  85571. },
  85572. _updateTracker: function() {
  85573. this.tracker.update(this._getTrackerSettings())
  85574. },
  85575. _render: function(_options) {
  85576. var that = this,
  85577. drawOptions,
  85578. originalCanvas;
  85579. if (!that._initialized)
  85580. return;
  85581. if (!that._canvas)
  85582. return;
  85583. that._resetIsReady();
  85584. drawOptions = that._prepareDrawOptions(_options);
  85585. clearTimeout(that._delayedRedraw);
  85586. originalCanvas = that._canvas;
  85587. that._canvas = $.extend({}, that._canvas);
  85588. if (drawOptions.recreateCanvas)
  85589. that.__currentCanvas = that._canvas;
  85590. else
  85591. that._canvas = that.__currentCanvas;
  85592. that.DEBUG_canvas = that._canvas;
  85593. if (drawOptions.recreateCanvas) {
  85594. that._reappendLoadingIndicator();
  85595. that._updateCanvasClipRect()
  85596. }
  85597. that._renderer.stopAllAnimations(true);
  85598. charts._setCanvasValues(that._canvas);
  85599. that._cleanGroups(drawOptions);
  85600. that._renderElements(drawOptions);
  85601. that._canvas = originalCanvas
  85602. },
  85603. _renderElements: function(drawOptions) {
  85604. var that = this,
  85605. preparedOptions = that._prepareToRender(drawOptions),
  85606. isRotated = that._isRotated(),
  85607. isLegendInside = that._isLegendInside(),
  85608. trackerCanvases = [],
  85609. layoutTargets = that._getLayoutTargets(),
  85610. dirtyCanvas = $.extend({}, that._canvas),
  85611. argBusinessRange,
  85612. zoomMinArg,
  85613. zoomMaxArg;
  85614. !drawOptions.isResize && that._scheduleLoadingIndicatorHiding();
  85615. that.DEBUG_dirtyCanvas = dirtyCanvas;
  85616. that._renderTitleAndLegend(drawOptions, isLegendInside);
  85617. that._renderAxes(drawOptions, preparedOptions, isRotated);
  85618. if (drawOptions.drawTitle && drawOptions.drawLegend && drawOptions.adjustAxes && that.layoutManager.needMoreSpaceForPanesCanvas(that._getLayoutTargets(), isRotated)) {
  85619. that.layoutManager.updateDrawnElements(that._getAxesForTransform(isRotated), that._canvas, dirtyCanvas, that._getLayoutTargets(), isRotated);
  85620. if (that.chartTitle)
  85621. that.layoutManager.correctSizeElement(that.chartTitle, that._canvas);
  85622. that._updateCanvasClipRect(dirtyCanvas);
  85623. that._updateAxesLayout(drawOptions, preparedOptions, isRotated)
  85624. }
  85625. drawOptions.drawTitle && drawOptions.drawLegend && drawOptions.adjustAxes && that.layoutManager.placeDrawnElements(that._canvas);
  85626. that._applyClipRects(preparedOptions);
  85627. that._appendSeriesGroups();
  85628. that._createCrosshairCursor();
  85629. $.each(layoutTargets, function() {
  85630. var canvas = this.canvas;
  85631. trackerCanvases.push({
  85632. left: canvas.left,
  85633. right: canvas.width - canvas.right,
  85634. top: canvas.top,
  85635. bottom: canvas.height - canvas.bottom
  85636. })
  85637. });
  85638. if (that._scrollBar) {
  85639. argBusinessRange = that.businessRanges[0].arg;
  85640. if (argBusinessRange.categories && argBusinessRange.categories.length <= 1)
  85641. zoomMinArg = zoomMaxArg = undefined;
  85642. else {
  85643. zoomMinArg = argBusinessRange.minVisible;
  85644. zoomMaxArg = argBusinessRange.maxVisible
  85645. }
  85646. that._scrollBar.init(argBusinessRange, layoutTargets[0].canvas).setPosition(zoomMinArg, zoomMaxArg)
  85647. }
  85648. drawOptions.updateTracker && that._updateTracker();
  85649. that.tracker.setCanvases({
  85650. left: 0,
  85651. right: that._canvas.width,
  85652. top: 0,
  85653. bottom: that._canvas.height
  85654. }, trackerCanvases);
  85655. that._updateLegendPosition(drawOptions, isLegendInside);
  85656. var timeout = that._getSeriesRenderTimeout(drawOptions);
  85657. if (timeout >= 0)
  85658. that._delayedRedraw = setTimeout(renderSeries, timeout);
  85659. else
  85660. renderSeries();
  85661. function renderSeries() {
  85662. that._renderSeries(drawOptions, isRotated, isLegendInside)
  85663. }
  85664. },
  85665. _createCrosshairCursor: $.noop,
  85666. _appendSeriesGroups: function() {
  85667. var that = this,
  85668. root = that._renderer.root;
  85669. that._seriesGroup.append(root);
  85670. that._labelsGroup.append(root);
  85671. that._appendAdditionalSeriesGroups()
  85672. },
  85673. _renderSeries: function(drawOptions, isRotated, isLegendInside) {
  85674. var that = this,
  85675. themeManager = that._themeManager,
  85676. resolveLabelOverlapping = themeManager.getOptions("resolveLabelOverlapping");
  85677. drawOptions.hideLayoutLabels = that.layoutManager.needMoreSpaceForPanesCanvas(that._getLayoutTargets(), that._isRotated()) && !themeManager.getOptions("adaptiveLayout").keepLabels;
  85678. that._drawSeries(drawOptions, isRotated);
  85679. resolveLabelOverlapping !== "none" && that._resolveLabelOverlapping(resolveLabelOverlapping);
  85680. that._adjustSeries();
  85681. that._renderTrackers(isLegendInside);
  85682. if (that._dataSource && that._dataSource.isLoaded())
  85683. that._fulfillLoadingIndicatorHiding();
  85684. that.tracker.repairTooltip();
  85685. that._drawn();
  85686. that._renderCompleteHandler()
  85687. },
  85688. _getAnimateOption: function(series, drawOptions) {
  85689. return drawOptions.animate && series.getPoints().length <= drawOptions.animationPointsLimit && this._renderer.animationEnabled()
  85690. },
  85691. _resolveLabelOverlapping: function(resolveLabelOverlapping) {
  85692. var func;
  85693. switch (resolveLabelOverlapping) {
  85694. case"stack":
  85695. func = this._resolveLabelOverlappingStack;
  85696. break;
  85697. case"hide":
  85698. func = this._resolveLabelOverlappingHide;
  85699. break;
  85700. case"shift":
  85701. func = this._resolveLabelOverlappingShift;
  85702. break
  85703. }
  85704. $.isFunction(func) && func.call(this)
  85705. },
  85706. _getVisibleSeries: function() {
  85707. return $.grep(this.getAllSeries(), function(series) {
  85708. return series.isVisible()
  85709. })
  85710. },
  85711. _resolveLabelOverlappingHide: function() {
  85712. var labels = $.map(this._getVisibleSeries(), function(series) {
  85713. return $.map(series.getVisiblePoints(), function(point) {
  85714. return point.getLabel()
  85715. })
  85716. }),
  85717. currenctLabel,
  85718. nextLabel,
  85719. currenctLabelRect,
  85720. nextLabelRect,
  85721. i,
  85722. j;
  85723. for (i = 0; i < labels.length; i++) {
  85724. currenctLabel = labels[i];
  85725. currenctLabelRect = currenctLabel.getBoundingRect();
  85726. if (!currenctLabel.isVisible())
  85727. continue;
  85728. for (j = i + 1; j < labels.length; j++) {
  85729. nextLabel = labels[j];
  85730. nextLabelRect = nextLabel.getBoundingRect();
  85731. if (checkOverlapping(currenctLabelRect, nextLabelRect))
  85732. nextLabel.hide()
  85733. }
  85734. }
  85735. },
  85736. _cleanGroups: function(drawOptions) {
  85737. var that = this;
  85738. that._stripsGroup.remove();
  85739. that._constantLinesGroup.remove();
  85740. that._axesGroup.remove();
  85741. that._gridGroup.remove();
  85742. that._labelAxesGroup.remove();
  85743. that._labelsGroup.remove();
  85744. that._crosshairCursorGroup.remove();
  85745. if (!drawOptions || drawOptions.drawLegend)
  85746. that._legendGroup.remove().clear();
  85747. if (!drawOptions || drawOptions.drawTitle)
  85748. that._titleGroup.remove().clear();
  85749. that._stripsGroup.clear();
  85750. that._constantLinesGroup.clear();
  85751. that._axesGroup.clear();
  85752. that._gridGroup.clear();
  85753. that._labelAxesGroup.clear();
  85754. that._labelsGroup.clear();
  85755. that._crosshairCursorGroup.clear()
  85756. },
  85757. _drawTitle: function() {
  85758. var that = this,
  85759. options = that._themeManager.getOptions("title"),
  85760. width = that._canvas.width - that._canvas.left - that._canvas.right;
  85761. options._incidentOccured = that._incidentOccured;
  85762. if (that.chartTitle)
  85763. that.chartTitle.update(options, width);
  85764. else
  85765. that.chartTitle = charts.factory.createTitle(that._renderer, options, that._titleGroup)
  85766. },
  85767. _createLegend: function() {
  85768. var legendSettings = getLegendSettings(this._legendDataField);
  85769. this.legend = core.CoreFactory.createLegend({
  85770. renderer: this._renderer,
  85771. group: this._legendGroup,
  85772. backgroundClass: 'dxc-border',
  85773. itemGroupClass: 'dxc-item',
  85774. textField: legendSettings.textField,
  85775. getFormatObject: legendSettings.getFormatObject
  85776. })
  85777. },
  85778. _updateLegend: function() {
  85779. var that = this,
  85780. themeManager = that._themeManager,
  85781. legendOptions = themeManager.getOptions('legend'),
  85782. legendData = that._getLegendData();
  85783. legendOptions.containerBackgroundColor = themeManager.getOptions("containerBackgroundColor");
  85784. legendOptions._incidentOccured = that._incidentOccured;
  85785. that.legend.update(legendData, legendOptions)
  85786. },
  85787. _prepareDrawOptions: function(drawOptions) {
  85788. var animationOptions = this._getAnimationOptions(),
  85789. options;
  85790. options = $.extend({}, {
  85791. force: false,
  85792. adjustAxes: true,
  85793. drawLegend: true,
  85794. drawTitle: true,
  85795. adjustSeriesLabels: true,
  85796. animate: animationOptions.enabled,
  85797. animationPointsLimit: animationOptions.maxPointCountSupported,
  85798. asyncSeriesRendering: animationOptions.asyncSeriesRendering,
  85799. updateTracker: true
  85800. }, drawOptions, this.__renderOptions);
  85801. if (!_isDefined(options.recreateCanvas))
  85802. options.recreateCanvas = options.adjustAxes && options.drawLegend && options.drawTitle;
  85803. return options
  85804. },
  85805. _processRefreshData: function(newRefreshAction) {
  85806. var currentRefreshActionPosition = $.inArray(this._currentRefreshData, ACTIONS_BY_PRIORITY),
  85807. newRefreshActionPosition = $.inArray(newRefreshAction, ACTIONS_BY_PRIORITY);
  85808. if (!this._currentRefreshData || currentRefreshActionPosition >= 0 && newRefreshActionPosition < currentRefreshActionPosition)
  85809. this._currentRefreshData = newRefreshAction
  85810. },
  85811. _getLegendData: function() {
  85812. var that = this;
  85813. return _map(this._getLegendTargets(), function(item) {
  85814. var style = item.getLegendStyles(),
  85815. textOpacity,
  85816. opacity = style.normal.opacity;
  85817. if (!item.isVisible()) {
  85818. if (!_isDefined(opacity) || opacity > DEFAULT_OPACITY)
  85819. opacity = DEFAULT_OPACITY;
  85820. textOpacity = DEFAULT_OPACITY
  85821. }
  85822. return {
  85823. text: item[that._legendItemTextField],
  85824. id: item.index,
  85825. textOpacity: textOpacity,
  85826. states: {
  85827. hover: style.hover,
  85828. selection: style.selection,
  85829. normal: _extend({}, style.normal, {opacity: opacity})
  85830. }
  85831. }
  85832. })
  85833. },
  85834. _seriesVisibilityChanged: function() {
  85835. this._specialProcessSeries();
  85836. this._populateBusinessRange();
  85837. this._renderer.stopAllAnimations(true);
  85838. this._updateLegend();
  85839. this._render({
  85840. force: true,
  85841. asyncSeriesRendering: false,
  85842. updateTracker: false
  85843. })
  85844. },
  85845. _disposeSeries: function() {
  85846. var that = this;
  85847. $.each(that.series || [], function(_, series) {
  85848. series.dispose()
  85849. });
  85850. that.series = null;
  85851. $.each(that.seriesFamilies || [], function(_, family) {
  85852. family.dispose()
  85853. });
  85854. that.seriesFamilies = null;
  85855. that._needHandleRenderComplete = true
  85856. },
  85857. _optionChanged: function(args) {
  85858. var that = this,
  85859. themeManager = that._themeManager,
  85860. name = args.name;
  85861. themeManager.resetOptions(name);
  85862. themeManager.update(that._options);
  85863. that._scheduleLoadingIndicatorHiding();
  85864. if (name === 'animation') {
  85865. that._renderer.updateAnimationOptions(that._getAnimationOptions());
  85866. return
  85867. }
  85868. switch (name) {
  85869. case'size':
  85870. case'margin':
  85871. that._invalidate();
  85872. break;
  85873. case'dataSource':
  85874. that._needHandleRenderComplete = true;
  85875. that._processRefreshData('_reinitDataSource');
  85876. break;
  85877. case'palette':
  85878. themeManager.updatePalette(that.option(name));
  85879. that._refreshSeries('_dataInit');
  85880. break;
  85881. case'series':
  85882. case'commonSeriesSettings':
  85883. case'containerBackgroundColor':
  85884. case'dataPrepareSettings':
  85885. that._refreshSeries('_dataInit');
  85886. break;
  85887. case'legend':
  85888. case'seriesTemplate':
  85889. that._processRefreshData('_dataInit');
  85890. break;
  85891. case'title':
  85892. that._processRefreshData('force_render');
  85893. break;
  85894. case'valueAxis':
  85895. case'argumentAxis':
  85896. case'commonAxisSettings':
  85897. case'panes':
  85898. case'defaultPane':
  85899. that._refreshSeries('reinit');
  85900. that.paneAxis = {};
  85901. break;
  85902. case'rotated':
  85903. that._createScrollBar();
  85904. that._refreshSeries('reinit');
  85905. break;
  85906. case'customizePoint':
  85907. case'customizeLabel':
  85908. that._refreshSeries('reinit');
  85909. break;
  85910. case'scrollBar':
  85911. that._createScrollBar();
  85912. that._processRefreshData('force_render');
  85913. break;
  85914. case'tooltip':
  85915. that._organizeStackPoints();
  85916. break;
  85917. default:
  85918. that._processRefreshData('reinit')
  85919. }
  85920. that.callBase.apply(that, arguments)
  85921. },
  85922. _handleThemeOptionsCore: function() {
  85923. var that = this;
  85924. if (that._initialized) {
  85925. that._scheduleLoadingIndicatorHiding();
  85926. that._refreshSeries('reinit');
  85927. that.beginUpdate();
  85928. that._invalidate();
  85929. that.endUpdate()
  85930. }
  85931. },
  85932. _refreshSeries: function(actionName) {
  85933. this._disposeSeries();
  85934. this._processRefreshData(actionName)
  85935. },
  85936. _refresh: function() {
  85937. var that = this;
  85938. that._renderer.stopAllAnimations(true);
  85939. if (that._currentRefreshData) {
  85940. switch (that._currentRefreshData) {
  85941. case'force_render':
  85942. that._render({force: true});
  85943. break;
  85944. case'reinit':
  85945. that._reinit(true);
  85946. break;
  85947. default:
  85948. that[that._currentRefreshData] && that[that._currentRefreshData]()
  85949. }
  85950. delete that._currentRefreshData
  85951. }
  85952. else
  85953. that._render({force: true})
  85954. },
  85955. _dataSourceOptions: function() {
  85956. return {paginate: false}
  85957. },
  85958. _updateCanvasClipRect: function(canvas) {
  85959. var that = this,
  85960. width,
  85961. height;
  85962. canvas = canvas || that._canvas;
  85963. width = Math.max(canvas.width - canvas.left - canvas.right, 0);
  85964. height = Math.max(canvas.height - canvas.top - canvas.bottom, 0);
  85965. that._canvasClipRect.attr({
  85966. x: canvas.left,
  85967. y: canvas.top,
  85968. width: width,
  85969. height: height
  85970. });
  85971. that._backgroundRect.attr({
  85972. x: canvas.left,
  85973. y: canvas.top,
  85974. width: width,
  85975. height: height
  85976. }).append(that._renderer.root).toBackground()
  85977. },
  85978. _getCanvasClipRectID: function() {
  85979. return this._canvasClipRect.id
  85980. },
  85981. _dataSourceChangedHandler: function() {
  85982. this._resetZoom();
  85983. this._scheduleLoadingIndicatorHiding();
  85984. this._dataInit()
  85985. },
  85986. _dataInit: function() {
  85987. clearTimeout(this._delayedRedraw);
  85988. this._dataSpecificInit(true)
  85989. },
  85990. _dataSpecificInit: function(needRedraw) {
  85991. this.series = this.series || this._populateSeries();
  85992. this._repopulateSeries();
  85993. this._seriesPopulatedHandler(needRedraw)
  85994. },
  85995. _seriesPopulatedHandler: function(needRedraw) {
  85996. var that = this;
  85997. that._seriesPopulatedHandlerCore();
  85998. that._populateBusinessRange();
  85999. that._updateLegend();
  86000. needRedraw && that._endLoading(function() {
  86001. that._render({force: true})
  86002. })
  86003. },
  86004. _repopulateSeries: function() {
  86005. var that = this,
  86006. parsedData,
  86007. themeManager = that._themeManager,
  86008. data = that._dataSource && that._dataSource.items(),
  86009. dataValidatorOptions = themeManager.getOptions('dataPrepareSettings'),
  86010. seriesTemplate = themeManager.getOptions('seriesTemplate');
  86011. if (that._dataSource && seriesTemplate) {
  86012. that._templatedSeries = utils.processSeriesTemplate(seriesTemplate, that._dataSource.items());
  86013. that._populateSeries();
  86014. delete that._templatedSeries;
  86015. data = that.teamplateData || data
  86016. }
  86017. that._groupSeries();
  86018. that._dataValidator = DX.viz.core.CoreFactory.createDataValidator(data, that._groupedSeries, that._incidentOccured, dataValidatorOptions);
  86019. parsedData = that._dataValidator.validate();
  86020. themeManager.resetPalette();
  86021. $.each(that.series, function(_, singleSeries) {
  86022. singleSeries.updateData(parsedData);
  86023. that._processSingleSeries(singleSeries)
  86024. });
  86025. that._organizeStackPoints()
  86026. },
  86027. _organizeStackPoints: function() {
  86028. var that = this,
  86029. themeManager = that._themeManager,
  86030. sharedTooltip = themeManager.getOptions("tooltip").shared,
  86031. stackPoints = {};
  86032. $.each(that.series || [], function(_, singleSeries) {
  86033. that._resetStackPoints(singleSeries);
  86034. sharedTooltip && that._prepareStackPoints(singleSeries, stackPoints, true)
  86035. })
  86036. },
  86037. _renderCompleteHandler: function() {
  86038. var that = this,
  86039. allSeriesInited = true;
  86040. if (that._needHandleRenderComplete) {
  86041. $.each(that.series, function(_, s) {
  86042. allSeriesInited = allSeriesInited && s.canRenderCompleteHandle()
  86043. });
  86044. if (allSeriesInited) {
  86045. that._needHandleRenderComplete = false;
  86046. that._eventTrigger("done", {target: that})
  86047. }
  86048. }
  86049. },
  86050. _renderTitleAndLegend: function(drawOptions, legendHasInsidePosition) {
  86051. var that = this,
  86052. titleOptions = that._themeManager.getOptions("title"),
  86053. drawTitle = titleOptions.text && drawOptions.drawTitle,
  86054. drawLegend = drawOptions.drawLegend && that.legend && !legendHasInsidePosition,
  86055. drawElements = [];
  86056. if (drawTitle) {
  86057. that._titleGroup.append(that._renderer.root);
  86058. that._drawTitle();
  86059. drawElements.push(that.chartTitle)
  86060. }
  86061. if (drawLegend) {
  86062. that._legendGroup.append(that._renderer.root);
  86063. drawElements.push(that.legend)
  86064. }
  86065. drawElements.length && that.layoutManager.drawElements(drawElements, that._canvas);
  86066. if (drawTitle)
  86067. that.layoutManager.correctSizeElement(that.chartTitle, that._canvas)
  86068. },
  86069. _prepareStackPoints: $.noop,
  86070. _resetStackPoints: $.noop,
  86071. _resetZoom: $.noop,
  86072. _dataIsReady: function() {
  86073. return this._isDataSourceReady()
  86074. },
  86075. getAllSeries: function getAllSeries() {
  86076. return this.series.slice()
  86077. },
  86078. getSeriesByName: function getSeriesByName(name) {
  86079. var found = null;
  86080. $.each(this.series, function(i, singleSeries) {
  86081. if (singleSeries.name === name) {
  86082. found = singleSeries;
  86083. return false
  86084. }
  86085. });
  86086. return found
  86087. },
  86088. getSeriesByPos: function getSeriesByPos(pos) {
  86089. return this.series[pos]
  86090. },
  86091. clearSelection: function clearSelection() {
  86092. this.tracker.clearSelection()
  86093. },
  86094. hideTooltip: function() {
  86095. this.tracker._hideTooltip()
  86096. },
  86097. render: function(renderOptions) {
  86098. var that = this;
  86099. that.__renderOptions = renderOptions;
  86100. that.__forceRender = renderOptions && renderOptions.force;
  86101. that.callBase.apply(that, arguments);
  86102. that.__renderOptions = that.__forceRender = null;
  86103. return that
  86104. },
  86105. getSize: function() {
  86106. var canvas = this._canvas || {};
  86107. return {
  86108. width: canvas.width,
  86109. height: canvas.height
  86110. }
  86111. }
  86112. }).include(ui.DataHelperMixin)
  86113. })(jQuery, DevExpress);
  86114. /*! Module viz-charts, file advancedChart.js */
  86115. (function($, DX, undefined) {
  86116. var charts = DX.viz.charts,
  86117. utils = DX.utils,
  86118. core = DX.viz.core,
  86119. DEFAULT_AXIS_NAME = "defaultAxisName",
  86120. _isArray = utils.isArray,
  86121. _isDefined = utils.isDefined,
  86122. _each = $.each,
  86123. _extend = $.extend,
  86124. _map = $.map,
  86125. MIN = 'min',
  86126. MAX = 'max';
  86127. function prepareAxis(axisOptions) {
  86128. return _isArray(axisOptions) ? axisOptions.length === 0 ? [{}] : axisOptions : [axisOptions]
  86129. }
  86130. function unique(array) {
  86131. var values = {},
  86132. i,
  86133. len = array.length;
  86134. for (i = 0; i < len; i++)
  86135. values[array[i]] = true;
  86136. return _map(values, function(_, key) {
  86137. return key
  86138. })
  86139. }
  86140. function prepareVisibleArea(visibleArea, axisRange, useAggregation, aggregationRange) {
  86141. visibleArea.minVal = axisRange.min;
  86142. visibleArea.maxVal = axisRange.max;
  86143. if (useAggregation && !visibleArea.adjustOnZoom) {
  86144. visibleArea.minVal = _isDefined(visibleArea.minVal) ? visibleArea.minVal : aggregationRange.val.min;
  86145. visibleArea.maxVal = _isDefined(visibleArea.maxVal) ? visibleArea.maxVal : aggregationRange.val.max
  86146. }
  86147. }
  86148. function setTemplateFields(data, templateData, series) {
  86149. _each(data, function(_, data) {
  86150. _each(series.getTeamplatedFields(), function(_, field) {
  86151. data[field.teamplateField] = data[field.originalField]
  86152. });
  86153. templateData.push(data)
  86154. });
  86155. series.updateTeamplateFieldNames()
  86156. }
  86157. charts.AdvancedChart = charts.BaseChart.inherit({
  86158. _dispose: function() {
  86159. var that = this,
  86160. disposeObjectsInArray = this._disposeObjectsInArray;
  86161. that.callBase();
  86162. that.panes = null;
  86163. if (that.legend) {
  86164. that.legend.dispose();
  86165. that.legend = null
  86166. }
  86167. disposeObjectsInArray.call(that, "panesBackground");
  86168. disposeObjectsInArray.call(that, "seriesFamilies");
  86169. that._disposeAxes()
  86170. },
  86171. _reinitAxes: function() {
  86172. this.translators = {};
  86173. this.panes = this._createPanes();
  86174. this._populateAxes()
  86175. },
  86176. _populateSeries: function() {
  86177. var that = this,
  86178. themeManager = that._themeManager,
  86179. hasSeriesTemplate = !!themeManager.getOptions("seriesTemplate"),
  86180. series = hasSeriesTemplate ? that._templatedSeries : that.option("series"),
  86181. allSeriesOptions = _isArray(series) ? series : series ? [series] : [],
  86182. data,
  86183. extraOptions = that._getExtraOptions(),
  86184. particularSeriesOptions,
  86185. particularSeries,
  86186. rotated = that._isRotated(),
  86187. i;
  86188. that.teamplateData = [];
  86189. that._disposeSeries();
  86190. that.series = [];
  86191. themeManager.resetPalette();
  86192. for (i = 0; i < allSeriesOptions.length; i++) {
  86193. particularSeriesOptions = _extend(true, {}, allSeriesOptions[i], extraOptions);
  86194. data = particularSeriesOptions.data;
  86195. particularSeriesOptions.data = null;
  86196. particularSeriesOptions.rotated = rotated;
  86197. particularSeriesOptions.customizePoint = themeManager.getOptions("customizePoint");
  86198. particularSeriesOptions.customizeLabel = themeManager.getOptions("customizeLabel");
  86199. particularSeriesOptions.visibilityChanged = $.proxy(that._seriesVisibilityChanged, that);
  86200. particularSeriesOptions.resolveLabelsOverlapping = themeManager.getOptions("resolveLabelsOverlapping");
  86201. particularSeriesOptions.incidentOccured = that._incidentOccured;
  86202. if (!particularSeriesOptions.name)
  86203. particularSeriesOptions.name = "Series " + (i + 1).toString();
  86204. var seriesTheme = themeManager.getOptions("series", particularSeriesOptions);
  86205. if (!that._checkPaneName(seriesTheme))
  86206. continue;
  86207. particularSeries = core.CoreFactory.createSeries({
  86208. renderer: that._renderer,
  86209. seriesGroup: that._seriesGroup,
  86210. labelsGroup: that._labelsGroup
  86211. }, seriesTheme);
  86212. if (!particularSeries.isUpdated)
  86213. that._incidentOccured("E2101", [seriesTheme.type]);
  86214. else {
  86215. particularSeries.index = that.series.length;
  86216. that.series.push(particularSeries);
  86217. if (hasSeriesTemplate)
  86218. setTemplateFields(data, that.teamplateData, particularSeries)
  86219. }
  86220. }
  86221. return that.series
  86222. },
  86223. _populateAxes: function() {
  86224. var that = this,
  86225. valueAxes = [],
  86226. argumentAxes,
  86227. panes = that.panes,
  86228. rotated = that._isRotated(),
  86229. valueAxisOptions = that.option("valueAxis") || {},
  86230. argumentOption = that.option("argumentAxis") || {},
  86231. argumentAxesOptions = prepareAxis(argumentOption)[0],
  86232. valueAxesOptions = prepareAxis(valueAxisOptions),
  86233. axisNames = [],
  86234. valueAxesCounter = 0,
  86235. paneWithNonVirtualAxis,
  86236. crosshairOptions = that._getOption("crosshair") || {},
  86237. crosshairEnabled = crosshairOptions.enabled,
  86238. horCrosshairEnabled = crosshairEnabled && crosshairOptions.horizontalLine.visible,
  86239. verCrosshairEnabled = crosshairEnabled && crosshairOptions.verticalLine.visible;
  86240. function getNextAxisName() {
  86241. return DEFAULT_AXIS_NAME + valueAxesCounter++
  86242. }
  86243. that._disposeAxes();
  86244. if (rotated)
  86245. paneWithNonVirtualAxis = argumentAxesOptions.position === "right" ? panes[panes.length - 1].name : panes[0].name;
  86246. else
  86247. paneWithNonVirtualAxis = argumentAxesOptions.position === "top" ? panes[0].name : panes[panes.length - 1].name;
  86248. argumentAxes = _map(panes, function(pane) {
  86249. return that._createAxis("argumentAxis", argumentAxesOptions, {
  86250. virtual: pane.name !== paneWithNonVirtualAxis,
  86251. pane: pane.name,
  86252. crosshairEnabled: rotated ? horCrosshairEnabled : verCrosshairEnabled
  86253. }, rotated)
  86254. });
  86255. _each(valueAxesOptions, function(priority, axisOptions) {
  86256. var axisPanes = [],
  86257. name = axisOptions.name;
  86258. if (name && $.inArray(name, axisNames) !== -1) {
  86259. that._incidentOccured("E2102");
  86260. return
  86261. }
  86262. name && axisNames.push(name);
  86263. if (axisOptions.pane)
  86264. axisPanes.push(axisOptions.pane);
  86265. if (axisOptions.panes && axisOptions.panes.length)
  86266. axisPanes = axisPanes.concat(axisOptions.panes.slice(0));
  86267. axisPanes = unique(axisPanes);
  86268. if (!axisPanes.length)
  86269. axisPanes.push(undefined);
  86270. _each(axisPanes, function(_, pane) {
  86271. valueAxes.push(that._createAxis("valueAxis", axisOptions, {
  86272. name: name || getNextAxisName(),
  86273. pane: pane,
  86274. priority: priority,
  86275. crosshairEnabled: rotated ? verCrosshairEnabled : horCrosshairEnabled
  86276. }, rotated))
  86277. })
  86278. });
  86279. that._valueAxes = valueAxes;
  86280. that._argumentAxes = argumentAxes
  86281. },
  86282. _prepareStackPoints: function(singleSeries, stackPoints, isSharedTooltip) {
  86283. var points = singleSeries.getPoints(),
  86284. stackName = singleSeries.getStackName();
  86285. _each(points, function(_, point) {
  86286. var argument = point.argument;
  86287. if (!stackPoints[argument]) {
  86288. stackPoints[argument] = {};
  86289. stackPoints[argument][null] = []
  86290. }
  86291. if (stackName && !_isArray(stackPoints[argument][stackName])) {
  86292. stackPoints[argument][stackName] = [];
  86293. _each(stackPoints[argument][null], function(_, point) {
  86294. if (!point.stackName)
  86295. stackPoints[argument][stackName].push(point)
  86296. })
  86297. }
  86298. if (stackName) {
  86299. stackPoints[argument][stackName].push(point);
  86300. stackPoints[argument][null].push(point)
  86301. }
  86302. else
  86303. _each(stackPoints[argument], function(_, stack) {
  86304. stack.push(point)
  86305. });
  86306. if (isSharedTooltip) {
  86307. point.stackPoints = stackPoints[argument][stackName];
  86308. point.stackName = stackName
  86309. }
  86310. })
  86311. },
  86312. _resetStackPoints: function(singleSeries) {
  86313. _each(singleSeries.getPoints(), function(_, point) {
  86314. point.stackPoints = null;
  86315. point.stackName = null
  86316. })
  86317. },
  86318. _disposeAxes: function() {
  86319. var disposeObjectsInArray = this._disposeObjectsInArray;
  86320. disposeObjectsInArray.call(this, "_argumentAxes");
  86321. disposeObjectsInArray.call(this, "_valueAxes")
  86322. },
  86323. _drawAxes: function(panesBorderOptions, drawOptions, adjustUnits) {
  86324. var that = this,
  86325. drawAxes = function(axes) {
  86326. _each(axes, function(_, axis) {
  86327. axis.draw(adjustUnits)
  86328. })
  86329. },
  86330. drawStaticAxisElements = function(axes) {
  86331. _each(axes, function(_i, axis) {
  86332. axis.drawGrids(panesBorderOptions[axis.pane])
  86333. })
  86334. };
  86335. that._reinitTranslators();
  86336. that._prepareAxesAndDraw(drawAxes, drawStaticAxisElements, drawOptions)
  86337. },
  86338. _appendAdditionalSeriesGroups: function() {
  86339. var that = this,
  86340. root = that._renderer.root;
  86341. that._crosshairCursorGroup.append(root);
  86342. that._legendGroup.append(root);
  86343. that._scrollBar && that._scrollBarGroup.append(root)
  86344. },
  86345. _getLegendTargets: function() {
  86346. return _map(this.series, function(item) {
  86347. if (item.getOptions().showInLegend)
  86348. return item
  86349. })
  86350. },
  86351. _legendItemTextField: "name",
  86352. _seriesPopulatedHandlerCore: function() {
  86353. this._processSeriesFamilies();
  86354. this._processValueAxisFormat()
  86355. },
  86356. _renderTrackers: function() {
  86357. var that = this,
  86358. i;
  86359. for (i = 0; i < that.series.length; ++i)
  86360. that.series[i].drawTrackers()
  86361. },
  86362. _specialProcessSeries: function() {
  86363. this._processSeriesFamilies()
  86364. },
  86365. _processSeriesFamilies: function() {
  86366. var that = this,
  86367. types = [],
  86368. families = [],
  86369. paneSeries,
  86370. themeManager = that._themeManager,
  86371. familyOptions = {
  86372. equalBarWidth: that._getEqualBarWidth(),
  86373. minBubbleSize: themeManager.getOptions("minBubbleSize"),
  86374. maxBubbleSize: themeManager.getOptions("maxBubbleSize")
  86375. };
  86376. if (that.seriesFamilies && that.seriesFamilies.length) {
  86377. _each(that.seriesFamilies, function(_, family) {
  86378. family.updateOptions(familyOptions);
  86379. family.adjustSeriesValues()
  86380. });
  86381. return
  86382. }
  86383. _each(that.series, function(_, item) {
  86384. if ($.inArray(item.type, types) === -1)
  86385. types.push(item.type)
  86386. });
  86387. _each(that._getLayoutTargets(), function(_, pane) {
  86388. paneSeries = that._getSeriesForPane(pane.name);
  86389. _each(types, function(_, type) {
  86390. var family = core.CoreFactory.createSeriesFamily({
  86391. type: type,
  86392. pane: pane.name,
  86393. equalBarWidth: familyOptions.equalBarWidth,
  86394. minBubbleSize: familyOptions.minBubbleSize,
  86395. maxBubbleSize: familyOptions.maxBubbleSize
  86396. });
  86397. family.add(paneSeries);
  86398. family.adjustSeriesValues();
  86399. families.push(family)
  86400. })
  86401. });
  86402. that.seriesFamilies = families
  86403. },
  86404. _appendAxesGroups: function() {
  86405. var that = this,
  86406. root = that._renderer.root;
  86407. that._stripsGroup.append(root);
  86408. that._gridGroup.append(root);
  86409. that._axesGroup.append(root);
  86410. that._constantLinesGroup.append(root);
  86411. that._labelAxesGroup.append(root)
  86412. },
  86413. _updateAxesLayout: function(drawOptions, panesBorderOptions, rotated) {
  86414. this.layoutManager.updatePanesCanvases(this._getLayoutTargets(), this._canvas, rotated);
  86415. this._drawAxes(panesBorderOptions, drawOptions, true)
  86416. },
  86417. _populateBusinessRange: function(visibleArea) {
  86418. var that = this,
  86419. businessRanges = [],
  86420. themeManager = that._themeManager,
  86421. rotated = that._isRotated(),
  86422. useAggregation = themeManager.getOptions('useAggregation'),
  86423. argAxes = that._argumentAxes,
  86424. lastArgAxis = argAxes[argAxes.length - 1],
  86425. calcInterval = lastArgAxis.calcInterval,
  86426. argRange = new core.Range({rotated: !!rotated}),
  86427. argBusinessRange;
  86428. that._disposeObjectsInArray("businessRanges", ["arg", "val"]);
  86429. _each(argAxes, function(_, axis) {
  86430. argRange.addRange(axis.getRangeData())
  86431. });
  86432. _each(that._groupedSeries, function(_, group) {
  86433. var groupRange = new core.Range({
  86434. rotated: !!rotated,
  86435. isValueRange: true,
  86436. pane: group.valueAxis.pane,
  86437. axis: group.valueAxis.name
  86438. }),
  86439. groupAxisRange = group.valueAxis.getRangeData();
  86440. groupRange.addRange(groupAxisRange);
  86441. _each(group, function(_, series) {
  86442. visibleArea && prepareVisibleArea(visibleArea, groupAxisRange, useAggregation, series._originalBusinessRange);
  86443. var seriesRange = series.getRangeData(visibleArea, calcInterval);
  86444. groupRange.addRange(seriesRange.val);
  86445. argRange.addRange(seriesRange.arg)
  86446. });
  86447. if (!groupRange.isDefined())
  86448. groupRange.setStubData(group.valueAxis.getOptions().valueType === 'datetime' ? 'datetime' : undefined);
  86449. if (group.valueAxis.getOptions().showZero)
  86450. groupRange.correctValueZeroLevel();
  86451. groupRange.checkZeroStick();
  86452. businessRanges.push({
  86453. val: groupRange,
  86454. arg: argRange
  86455. })
  86456. });
  86457. if (!argRange.isDefined())
  86458. argRange.setStubData(argAxes[0].getOptions().argumentType);
  86459. if (visibleArea && visibleArea.notApplyMargins && argRange.axisType !== "discrete") {
  86460. argBusinessRange = argAxes[0].getTranslator().getBusinessRange();
  86461. argRange.addRange({
  86462. min: argBusinessRange.min,
  86463. max: argBusinessRange.max,
  86464. stick: true
  86465. })
  86466. }
  86467. that._correctBusinessRange(argRange, lastArgAxis);
  86468. that.businessRanges = businessRanges
  86469. },
  86470. _correctBusinessRange: function(range, lastArgAxis) {
  86471. var setTicksAtUnitBeginning = lastArgAxis.getOptions().setTicksAtUnitBeginning,
  86472. tickIntervalRange = {},
  86473. tickInterval = lastArgAxis.getOptions().tickInterval,
  86474. originInterval = tickInterval;
  86475. tickInterval = $.isNumeric(tickInterval) ? tickInterval : utils.dateToMilliseconds(tickInterval);
  86476. if (tickInterval && _isDefined(range[MIN]) && _isDefined(range[MAX]) && tickInterval >= Math.abs(range[MAX] - range[MIN])) {
  86477. if (utils.isDate(range[MIN])) {
  86478. if (!$.isNumeric(originInterval)) {
  86479. tickIntervalRange[MIN] = utils.addInterval(range[MIN], originInterval, true);
  86480. tickIntervalRange[MAX] = utils.addInterval(range[MAX], originInterval, false)
  86481. }
  86482. else {
  86483. tickIntervalRange[MIN] = new Date(range[MIN].valueOf() - tickInterval);
  86484. tickIntervalRange[MAX] = new Date(range[MAX].valueOf() + tickInterval)
  86485. }
  86486. if (setTicksAtUnitBeginning) {
  86487. utils.correctDateWithUnitBeginning(tickIntervalRange[MAX], originInterval);
  86488. utils.correctDateWithUnitBeginning(tickIntervalRange[MIN], originInterval)
  86489. }
  86490. }
  86491. else {
  86492. tickIntervalRange[MIN] = range[MIN] - tickInterval;
  86493. tickIntervalRange[MAX] = range[MAX] + tickInterval
  86494. }
  86495. range.addRange(tickIntervalRange)
  86496. }
  86497. },
  86498. _getArgumentAxes: function() {
  86499. return this._argumentAxes
  86500. },
  86501. _getValueAxes: function() {
  86502. return this._valueAxes
  86503. },
  86504. _processValueAxisFormat: function() {
  86505. var that = this,
  86506. valueAxes = that._valueAxes,
  86507. axesWithFullStackedFormat = [];
  86508. _each(that.series, function() {
  86509. if (this.isFullStackedSeries() && $.inArray(this.axis, axesWithFullStackedFormat) === -1)
  86510. axesWithFullStackedFormat.push(this.axis)
  86511. });
  86512. _each(valueAxes, function() {
  86513. if ($.inArray(this.name, axesWithFullStackedFormat) !== -1)
  86514. this.setPercentLabelFormat();
  86515. else
  86516. this.resetAutoLabelFormat()
  86517. })
  86518. },
  86519. _createAxis: function(typeSelector, userOptions, axisOptions, rotated) {
  86520. var that = this,
  86521. renderingSettings = _extend({
  86522. renderer: that._renderer,
  86523. incidentOccured: that._incidentOccured,
  86524. axisClass: typeSelector === "argumentAxis" ? "arg" : "val",
  86525. stripsGroup: that._stripsGroup,
  86526. labelAxesGroup: that._labelAxesGroup,
  86527. constantLinesGroup: that._constantLinesGroup,
  86528. axesContainerGroup: that._axesGroup,
  86529. gridGroup: that._gridGroup
  86530. }, that._getAxisRenderingOptions(typeSelector, userOptions, rotated)),
  86531. axis;
  86532. userOptions = that._prepareStripsAndConstantLines(typeSelector, userOptions, rotated);
  86533. axis = new charts.axes.Axis(renderingSettings);
  86534. axis.updateOptions(_extend(true, {}, userOptions, axisOptions, that._prepareAxisOptions(typeSelector, userOptions)));
  86535. return axis
  86536. },
  86537. _getTrackerSettings: function() {
  86538. return _extend(this.callBase(), {argumentAxis: this._argumentAxes})
  86539. },
  86540. _prepareStripsAndConstantLines: function(typeSelector, userOptions, rotated) {
  86541. userOptions = this._themeManager.getOptions(typeSelector, userOptions, rotated);
  86542. if (userOptions.strips)
  86543. _each(userOptions.strips, function(i) {
  86544. userOptions.strips[i] = _extend(true, {}, userOptions.stripStyle, userOptions.strips[i])
  86545. });
  86546. if (userOptions.constantLines)
  86547. _each(userOptions.constantLines, function(i, line) {
  86548. userOptions.constantLines[i] = _extend(true, {}, userOptions.constantLineStyle, line)
  86549. });
  86550. return userOptions
  86551. },
  86552. _legendDataField: 'series',
  86553. _adjustSeries: $.noop
  86554. })
  86555. })(jQuery, DevExpress);
  86556. /*! Module viz-charts, file chart.js */
  86557. (function($, DX, undefined) {
  86558. var viz = DX.viz,
  86559. core = viz.core,
  86560. charts = viz.charts,
  86561. utils = DX.utils,
  86562. MAX_ADJUSTMENT_ATTEMPTS = 5,
  86563. DEFAULT_PANE_NAME = "default",
  86564. ASYNC_SERIES_RENDERING_DELAY = 25,
  86565. DEFAULT_PANES = [{
  86566. name: DEFAULT_PANE_NAME,
  86567. border: {}
  86568. }],
  86569. _map = $.map,
  86570. _each = $.each,
  86571. _extend = $.extend,
  86572. _isArray = utils.isArray,
  86573. _isDefined = utils.isDefined;
  86574. function getFirstAxisNameForPane(axes, paneName) {
  86575. var result;
  86576. for (var i = 0; i < axes.length; i++)
  86577. if (axes[i].pane === paneName) {
  86578. result = axes[i].name;
  86579. break
  86580. }
  86581. if (!result)
  86582. result = axes[0].name;
  86583. return result
  86584. }
  86585. function hideGridsOnNonFirstValueAxisForPane(valAxes, paneName, synchronizeMultiAxes) {
  86586. var axesForPane = [],
  86587. firstShownAxis;
  86588. _each(valAxes, function(_, axis) {
  86589. if (axis.pane === paneName)
  86590. axesForPane.push(axis)
  86591. });
  86592. if (axesForPane.length > 1 && synchronizeMultiAxes)
  86593. _each(axesForPane, function(_, axis) {
  86594. var gridOpt = axis.getOptions().grid,
  86595. minorGridOpt = axis.getOptions().minorGrid;
  86596. if (firstShownAxis && gridOpt && gridOpt.visible) {
  86597. gridOpt.visible = false;
  86598. minorGridOpt && (minorGridOpt.visible = false)
  86599. }
  86600. else
  86601. firstShownAxis = firstShownAxis ? firstShownAxis : gridOpt && gridOpt.visible
  86602. })
  86603. }
  86604. function getPaneForAxis(paneAxis, axisNameWithoutPane) {
  86605. var result;
  86606. _each(paneAxis, function(paneName, pane) {
  86607. _each(pane, function(axisName) {
  86608. if (axisNameWithoutPane === axisName) {
  86609. result = paneName;
  86610. return false
  86611. }
  86612. })
  86613. });
  86614. return result
  86615. }
  86616. function findAxisOptions(valueAxes, valueAxesOptions, axisName) {
  86617. var result,
  86618. axInd;
  86619. for (axInd = 0; axInd < valueAxesOptions.length; axInd++)
  86620. if (valueAxesOptions[axInd].name === axisName) {
  86621. result = valueAxesOptions[axInd];
  86622. result.priority = axInd;
  86623. break
  86624. }
  86625. if (!result)
  86626. for (axInd = 0; axInd < valueAxes.length; axInd++)
  86627. if (valueAxes[axInd].name === axisName) {
  86628. result = valueAxes[axInd].getOptions();
  86629. result.priority = valueAxes[axInd].priority;
  86630. break
  86631. }
  86632. return result
  86633. }
  86634. function findAxis(paneName, axisName, axes) {
  86635. var axis,
  86636. i;
  86637. for (i = 0; i < axes.length; i++) {
  86638. axis = axes[i];
  86639. if (axis.name === axisName && axis.pane === paneName)
  86640. return axis
  86641. }
  86642. }
  86643. function prepareSegmentRectPoints(left, top, width, height, borderOptions) {
  86644. var maxSW = ~~((width < height ? width : height) / 2),
  86645. sw = borderOptions.width || 0,
  86646. newSW = sw < maxSW ? sw : maxSW;
  86647. left = left + newSW / 2;
  86648. top = top + newSW / 2;
  86649. width = width - newSW;
  86650. height = height - newSW;
  86651. var right = left + width,
  86652. bottom = top + height,
  86653. points = [],
  86654. segments = [],
  86655. segmentSequence,
  86656. visiblyOpt = 0,
  86657. prevSegmentVisibility = 0;
  86658. var allSegment = {
  86659. top: [[left, top], [right, top]],
  86660. right: [[right, top], [right, bottom]],
  86661. bottom: [[right, bottom], [left, bottom]],
  86662. left: [[left, bottom], [left, top]]
  86663. };
  86664. _each(allSegment, function(seg) {
  86665. var visibility = !!borderOptions[seg];
  86666. visiblyOpt = visiblyOpt * 2 + ~~visibility
  86667. });
  86668. switch (visiblyOpt) {
  86669. case 13:
  86670. case 9:
  86671. segmentSequence = ['left', 'top', 'right', 'bottom'];
  86672. break;
  86673. case 11:
  86674. segmentSequence = ['bottom', 'left', 'top', 'right'];
  86675. break;
  86676. default:
  86677. segmentSequence = ['top', 'right', 'bottom', 'left']
  86678. }
  86679. _each(segmentSequence, function(_, seg) {
  86680. var segmentVisibility = !!borderOptions[seg];
  86681. if (!prevSegmentVisibility && segments.length) {
  86682. points.push(segments);
  86683. segments = []
  86684. }
  86685. if (segmentVisibility)
  86686. _each(allSegment[seg].slice(prevSegmentVisibility), function(_, segment) {
  86687. segments = segments.concat(segment)
  86688. });
  86689. prevSegmentVisibility = ~~segmentVisibility
  86690. });
  86691. segments.length && points.push(segments);
  86692. points.length === 1 && (points = points[0]);
  86693. return {
  86694. points: points,
  86695. pathType: visiblyOpt === 15 ? "area" : "line"
  86696. }
  86697. }
  86698. function applyClipSettings(clipRects, settings) {
  86699. _each(clipRects || [], function(_, c) {
  86700. c && c.attr(settings)
  86701. })
  86702. }
  86703. function reinitTranslators(translators) {
  86704. _each(translators, function(_, axisTrans) {
  86705. _each(axisTrans, function(_, translator) {
  86706. translator.arg.reinit();
  86707. translator.val.reinit()
  86708. })
  86709. })
  86710. }
  86711. charts._test_prepareSegmentRectPoints = function() {
  86712. var original = prepareSegmentRectPoints.original || prepareSegmentRectPoints;
  86713. if (arguments[0])
  86714. prepareSegmentRectPoints = arguments[0];
  86715. prepareSegmentRectPoints.original = original;
  86716. prepareSegmentRectPoints.restore = function() {
  86717. prepareSegmentRectPoints = original
  86718. };
  86719. return prepareSegmentRectPoints
  86720. };
  86721. DX.registerComponent("dxChart", viz.charts, charts.AdvancedChart.inherit({
  86722. _chartType: "chart",
  86723. _setDefaultOptions: function() {
  86724. this.callBase();
  86725. this.option({defaultPane: DEFAULT_PANE_NAME})
  86726. },
  86727. _initCore: function() {
  86728. this.__ASYNC_SERIES_RENDERING_DELAY = ASYNC_SERIES_RENDERING_DELAY;
  86729. this.paneAxis = {};
  86730. this._panesClipRects = {};
  86731. this.callBase()
  86732. },
  86733. _disposeCore: function() {
  86734. var that = this,
  86735. disposeObjectsInArray = this._disposeObjectsInArray,
  86736. panesClipRects = that._panesClipRects;
  86737. that.callBase();
  86738. disposeObjectsInArray.call(panesClipRects, "fixed");
  86739. disposeObjectsInArray.call(panesClipRects, "base");
  86740. disposeObjectsInArray.call(panesClipRects, "wide");
  86741. that._panesClipRects = null
  86742. },
  86743. _correctAxes: function() {
  86744. this.series && this._correctValueAxes()
  86745. },
  86746. _getExtraOptions: $.noop,
  86747. _processSingleSeries: $.noop,
  86748. _groupSeries: function() {
  86749. var that = this,
  86750. panes = that.panes,
  86751. valAxes = that._valueAxes,
  86752. paneList = _map(panes, function(pane) {
  86753. return pane.name
  86754. }),
  86755. series = that.series,
  86756. paneAxis = that.paneAxis,
  86757. synchronizeMultiAxes = that._themeManager.getOptions("synchronizeMultiAxes"),
  86758. groupedSeries = that._groupedSeries = [];
  86759. _each(series, function(i, particularSeries) {
  86760. particularSeries.axis = particularSeries.axis || getFirstAxisNameForPane(valAxes, particularSeries.pane);
  86761. if (particularSeries.axis) {
  86762. paneAxis[particularSeries.pane] = paneAxis[particularSeries.pane] || {};
  86763. paneAxis[particularSeries.pane][particularSeries.axis] = true
  86764. }
  86765. });
  86766. _each(valAxes, function(_, axis) {
  86767. if (axis.name && axis.pane && $.inArray(axis.pane, paneList) !== -1) {
  86768. paneAxis[axis.pane] = paneAxis[axis.pane] || {};
  86769. paneAxis[axis.pane][axis.name] = true
  86770. }
  86771. });
  86772. that._correctValueAxes();
  86773. _each(paneAxis, function(paneName, pane) {
  86774. hideGridsOnNonFirstValueAxisForPane(valAxes, paneName, synchronizeMultiAxes);
  86775. _each(pane, function(axisName) {
  86776. var group = [];
  86777. _each(series, function(_, particularSeries) {
  86778. if (particularSeries.pane === paneName && particularSeries.axis === axisName)
  86779. group.push(particularSeries)
  86780. });
  86781. groupedSeries.push(group);
  86782. group.valueAxis = findAxis(paneName, axisName, valAxes);
  86783. group.valueOptions = group.valueAxis.getOptions()
  86784. })
  86785. });
  86786. groupedSeries.argumentAxes = that._argumentAxes;
  86787. groupedSeries.argumentOptions = groupedSeries.argumentAxes[0].getOptions()
  86788. },
  86789. _cleanPanesClipRects: function(clipArrayName) {
  86790. var that = this,
  86791. clipArray = that._panesClipRects[clipArrayName];
  86792. _each(clipArray || [], function(_, clipRect) {
  86793. clipRect && clipRect.dispose()
  86794. });
  86795. that._panesClipRects[clipArrayName] = []
  86796. },
  86797. _createPanes: function() {
  86798. var that = this,
  86799. panes = that.option("panes"),
  86800. panesNameCounter = 0,
  86801. bottomPaneName;
  86802. if (panes && _isArray(panes) && !panes.length || $.isEmptyObject(panes))
  86803. panes = DEFAULT_PANES;
  86804. that._cleanPanesClipRects("fixed");
  86805. that._cleanPanesClipRects("base");
  86806. that._cleanPanesClipRects("wide");
  86807. that.defaultPane = that.option("defaultPane");
  86808. panes = _extend(true, [], _isArray(panes) ? panes : panes ? [panes] : []);
  86809. _each(panes, function(_, pane) {
  86810. pane.name = !_isDefined(pane.name) ? DEFAULT_PANE_NAME + panesNameCounter++ : pane.name
  86811. });
  86812. if (!that._doesPaneExists(panes, that.defaultPane) && panes.length > 0) {
  86813. bottomPaneName = panes[panes.length - 1].name;
  86814. that._incidentOccured("W2101", [that.defaultPane, bottomPaneName]);
  86815. that.defaultPane = bottomPaneName
  86816. }
  86817. panes = that._isRotated() ? panes.reverse() : panes;
  86818. return panes
  86819. },
  86820. _doesPaneExists: function(panes, paneName) {
  86821. var found = false;
  86822. _each(panes, function(_, pane) {
  86823. if (pane.name === paneName) {
  86824. found = true;
  86825. return false
  86826. }
  86827. });
  86828. return found
  86829. },
  86830. _getAxisRenderingOptions: function(typeSelector, axisOptions, rotated) {
  86831. return {
  86832. axesType: "xyAxes",
  86833. drawingType: "linear",
  86834. isHorizontal: typeSelector === "argumentAxis" ? !rotated : rotated
  86835. }
  86836. },
  86837. _prepareAxisOptions: $.noop,
  86838. _checkPaneName: function(seriesTheme) {
  86839. var paneList = _map(this.panes, function(pane) {
  86840. return pane.name
  86841. });
  86842. seriesTheme.pane = seriesTheme.pane || this.defaultPane;
  86843. return $.inArray(seriesTheme.pane, paneList) !== -1
  86844. },
  86845. _correctValueAxes: function() {
  86846. var that = this,
  86847. rotated = that._isRotated(),
  86848. valueAxisOptions = that.option("valueAxis") || {},
  86849. valueAxesOptions = _isArray(valueAxisOptions) ? valueAxisOptions : [valueAxisOptions],
  86850. valueAxes = that._valueAxes || [],
  86851. defaultAxisName = valueAxes[0].name,
  86852. paneAxis = that.paneAxis || {},
  86853. panes = that.panes,
  86854. i,
  86855. neededAxis = {};
  86856. _each(valueAxes, function(_, axis) {
  86857. if (axis.pane)
  86858. return;
  86859. var pane = getPaneForAxis(that.paneAxis, axis.name);
  86860. if (!pane) {
  86861. pane = that.defaultPane;
  86862. paneAxis[pane] = paneAxis[pane] || {};
  86863. paneAxis[pane][axis.name] = true
  86864. }
  86865. axis.setPane(pane)
  86866. });
  86867. for (i = 0; i < panes.length; i++)
  86868. if (!paneAxis[panes[i].name]) {
  86869. paneAxis[panes[i].name] = {};
  86870. paneAxis[panes[i].name][defaultAxisName] = true
  86871. }
  86872. _each(that.paneAxis, function(paneName, axisNames) {
  86873. _each(axisNames, function(axisName) {
  86874. neededAxis[axisName + "-" + paneName] = true;
  86875. if (!findAxis(paneName, axisName, valueAxes)) {
  86876. var axisOptions = findAxisOptions(valueAxes, valueAxesOptions, axisName);
  86877. if (!axisOptions) {
  86878. that._incidentOccured("W2102", [axisName]);
  86879. axisOptions = {
  86880. name: axisName,
  86881. priority: valueAxes.length
  86882. }
  86883. }
  86884. valueAxes.push(that._createAxis("valueAxis", axisOptions, {
  86885. pane: paneName,
  86886. name: axisName
  86887. }, rotated))
  86888. }
  86889. })
  86890. });
  86891. valueAxes = $.grep(valueAxes, function(elem) {
  86892. return !!neededAxis[elem.name + "-" + elem.pane]
  86893. });
  86894. valueAxes.sort(function(a, b) {
  86895. return a.priority - b.priority
  86896. });
  86897. that._valueAxes = valueAxes
  86898. },
  86899. _getSeriesForPane: function(paneName) {
  86900. var paneSeries = [];
  86901. _each(this.series, function(_, oneSeries) {
  86902. if (oneSeries.pane === paneName)
  86903. paneSeries.push(oneSeries)
  86904. });
  86905. return paneSeries
  86906. },
  86907. _createTranslator: function(range, canvas, options) {
  86908. return core.CoreFactory.createTranslator2D(range, canvas, options)
  86909. },
  86910. _createPanesBorderOptions: function() {
  86911. var commonBorderOptions = this._themeManager.getOptions("commonPaneSettings").border,
  86912. panesBorderOptions = {};
  86913. _each(this.panes, function(_, pane) {
  86914. panesBorderOptions[pane.name] = _extend(true, {}, commonBorderOptions, pane.border)
  86915. });
  86916. return panesBorderOptions
  86917. },
  86918. _createScrollBar: function() {
  86919. var that = this,
  86920. scrollBarOptions = that._themeManager.getOptions("scrollBar") || {},
  86921. scrollBarGroup = that._scrollBarGroup;
  86922. if (scrollBarOptions.visible) {
  86923. scrollBarOptions.rotated = that._isRotated();
  86924. that._scrollBar = (that._scrollBar || charts.factory.createScrollBar(that._renderer, scrollBarGroup)).update(scrollBarOptions)
  86925. }
  86926. else {
  86927. scrollBarGroup.remove();
  86928. that._scrollBar && that._scrollBar.dispose();
  86929. that._scrollBar = null
  86930. }
  86931. },
  86932. _prepareToRender: function(drawOptions) {
  86933. var that = this,
  86934. panesBorderOptions = that._createPanesBorderOptions();
  86935. that._createPanesBackground();
  86936. that._appendAxesGroups();
  86937. that._transformed && that._resetTransform();
  86938. that._createTranslators(drawOptions);
  86939. that._options.useAggregation && _each(that.series, function(_, series) {
  86940. series._originalBusinessRange = series._originalBusinessRange || series.getRangeData();
  86941. series.resamplePoints(that._getTranslator(series.pane, series.axis).arg, that._zoomMinArg, that._zoomMaxArg)
  86942. });
  86943. if (_isDefined(that._zoomMinArg) || _isDefined(that._zoomMaxArg))
  86944. that._populateBusinessRange({
  86945. adjustOnZoom: that._themeManager.getOptions("adjustOnZoom"),
  86946. minArg: that._zoomMinArg,
  86947. maxArg: that._zoomMaxArg,
  86948. notApplyMargins: that._notApplyMargins
  86949. });
  86950. if (that._options.useAggregation || _isDefined(that._zoomMinArg) || _isDefined(that._zoomMaxArg))
  86951. that._updateTranslators();
  86952. return panesBorderOptions
  86953. },
  86954. _isLegendInside: function() {
  86955. return this.legend && this.legend.getPosition() === "inside"
  86956. },
  86957. _renderAxes: function(drawOptions, panesBorderOptions, rotated) {
  86958. if (drawOptions && drawOptions.recreateCanvas)
  86959. this.layoutManager.updatePanesCanvases(this.panes, this._canvas, rotated);
  86960. this._drawAxes(panesBorderOptions, drawOptions)
  86961. },
  86962. _isRotated: function() {
  86963. return this._themeManager.getOptions("rotated")
  86964. },
  86965. _getLayoutTargets: function() {
  86966. return this.panes
  86967. },
  86968. _applyClipRects: function(panesBorderOptions) {
  86969. var that = this,
  86970. canvasClipRectID = that._getCanvasClipRectID(),
  86971. i;
  86972. that._drawPanesBorders(panesBorderOptions);
  86973. that._createClipRectsForPanes();
  86974. for (i = 0; i < that._argumentAxes.length; i++)
  86975. that._argumentAxes[i].applyClipRects(that._getElementsClipRectID(that._argumentAxes[i].pane), canvasClipRectID);
  86976. for (i = 0; i < that._valueAxes.length; i++)
  86977. that._valueAxes[i].applyClipRects(that._getElementsClipRectID(that._valueAxes[i].pane), canvasClipRectID);
  86978. that._fillPanesBackground()
  86979. },
  86980. _getSeriesRenderTimeout: function(drawOptions) {
  86981. return drawOptions.asyncSeriesRendering ? ASYNC_SERIES_RENDERING_DELAY : undefined
  86982. },
  86983. _updateLegendPosition: function(drawOptions, legendHasInsidePosition) {
  86984. var that = this;
  86985. if (drawOptions.drawLegend && that.legend && legendHasInsidePosition) {
  86986. var panes = that.panes,
  86987. newCanvas = _extend({}, panes[0].canvas),
  86988. layoutManager = charts.factory.createChartLayoutManager();
  86989. newCanvas.right = panes[panes.length - 1].canvas.right;
  86990. newCanvas.bottom = panes[panes.length - 1].canvas.bottom;
  86991. that._legendGroup.append(that._renderer.root);
  86992. layoutManager.drawElements([that.legend], newCanvas);
  86993. layoutManager.placeDrawnElements(newCanvas)
  86994. }
  86995. },
  86996. _drawSeries: function(drawOptions, rotated) {
  86997. var that = this;
  86998. _each(that.seriesFamilies || [], function(_, seriesFamily) {
  86999. var translators = that._getTranslator(seriesFamily.pane) || {};
  87000. seriesFamily.updateSeriesValues(translators);
  87001. seriesFamily.adjustSeriesDimensions(translators)
  87002. });
  87003. _each(that.series, function(_, particularSeries) {
  87004. that._applyPaneClipRect(particularSeries);
  87005. particularSeries.setAdjustSeriesLabels(drawOptions.adjustSeriesLabels);
  87006. var tr = that._getTranslator(particularSeries.pane, particularSeries.axis),
  87007. translators = {};
  87008. translators[rotated ? "x" : "y"] = tr.val;
  87009. translators[rotated ? "y" : "x"] = tr.arg;
  87010. particularSeries.draw(translators, that._getAnimateOption(particularSeries, drawOptions), drawOptions.hideLayoutLabels, that.legend && that.legend.getActionCallback(particularSeries))
  87011. })
  87012. },
  87013. _applyPaneClipRect: function(seriesOptions) {
  87014. var that = this,
  87015. paneIndex = that._getPaneIndex(seriesOptions.pane),
  87016. panesClipRects = that._panesClipRects,
  87017. wideClipRect = panesClipRects.wide[paneIndex];
  87018. seriesOptions.setClippingParams(panesClipRects.base[paneIndex].id, wideClipRect && wideClipRect.id, that._getPaneBorderVisibility(paneIndex))
  87019. },
  87020. _createTranslators: function(drawOptions) {
  87021. var that = this,
  87022. rotated = that._isRotated(),
  87023. translators;
  87024. if (!drawOptions.recreateCanvas)
  87025. return;
  87026. that.translators = translators = {};
  87027. that.layoutManager.updatePanesCanvases(that.panes, that._canvas, rotated);
  87028. _each(that.paneAxis, function(paneName, pane) {
  87029. translators[paneName] = translators[paneName] || {};
  87030. _each(pane, function(axisName) {
  87031. var translator = that._createTranslator(new core.Range(that._getBusinessRange(paneName, axisName).val), that._getCanvasForPane(paneName), rotated ? {direction: "horizontal"} : {});
  87032. translator.pane = paneName;
  87033. translator.axis = axisName;
  87034. translators[paneName][axisName] = {val: translator}
  87035. })
  87036. });
  87037. _each(that._argumentAxes, function(_, axis) {
  87038. var translator = that._createTranslator(new core.Range(that._getBusinessRange(axis.pane).arg), that._getCanvasForPane(axis.pane), !rotated ? {direction: "horizontal"} : {});
  87039. _each(translators[axis.pane], function(valAxis, paneAxisTran) {
  87040. paneAxisTran.arg = translator
  87041. })
  87042. })
  87043. },
  87044. _updateTranslators: function() {
  87045. var that = this;
  87046. _each(that.translators, function(pane, axisTrans) {
  87047. _each(axisTrans, function(axis, translator) {
  87048. translator.arg.updateBusinessRange(new core.Range(that._getBusinessRange(pane).arg));
  87049. delete translator.arg._originalBusinessRange;
  87050. translator.val.updateBusinessRange(new core.Range(that._getBusinessRange(pane, axis).val));
  87051. delete translator.val._originalBusinessRange
  87052. })
  87053. })
  87054. },
  87055. _getAxesForTransform: function(rotated) {
  87056. return {
  87057. verticalAxes: !rotated ? this._getValueAxes() : this._getArgumentAxes(),
  87058. horizontalAxes: !rotated ? this._getArgumentAxes() : this._getValueAxes()
  87059. }
  87060. },
  87061. _reinitTranslators: function() {
  87062. var that = this;
  87063. _each(that._argumentAxes, function(_, axis) {
  87064. var translator = that._getTranslator(axis.pane);
  87065. if (translator) {
  87066. translator.arg.reinit();
  87067. axis.setTranslator(translator.arg, translator.val)
  87068. }
  87069. });
  87070. _each(that._valueAxes, function(_, axis) {
  87071. var translator = that._getTranslator(axis.pane, axis.name);
  87072. if (translator) {
  87073. translator.val.reinit();
  87074. axis.setTranslator(translator.val, translator.arg)
  87075. }
  87076. })
  87077. },
  87078. _prepareAxesAndDraw: function(drawAxes, drawStaticAxisElements, drawOptions) {
  87079. var that = this,
  87080. i = 0,
  87081. layoutManager = that.layoutManager,
  87082. rotated = that._isRotated(),
  87083. adjustmentCounter = 0,
  87084. synchronizeMultiAxes = that._themeManager.getOptions('synchronizeMultiAxes'),
  87085. layoutTargets = that._getLayoutTargets(),
  87086. verticalAxes = rotated ? that._argumentAxes : that._valueAxes,
  87087. horizontalAxes = rotated ? that._valueAxes : that._argumentAxes,
  87088. hElements = horizontalAxes,
  87089. vElements = verticalAxes;
  87090. if (that._scrollBar) {
  87091. that._scrollBar.setPane(layoutTargets);
  87092. if (rotated)
  87093. vElements = [that._scrollBar].concat(vElements);
  87094. else
  87095. hElements = hElements.concat([that._scrollBar])
  87096. }
  87097. do {
  87098. for (i = 0; i < that._argumentAxes.length; i++)
  87099. that._argumentAxes[i].resetTicks();
  87100. for (i = 0; i < that._valueAxes.length; i++)
  87101. that._valueAxes[i].resetTicks();
  87102. if (synchronizeMultiAxes)
  87103. charts.multiAxesSynchronizer.synchronize(that._valueAxes);
  87104. drawAxes(horizontalAxes);
  87105. layoutManager.requireAxesRedraw = false;
  87106. if (drawOptions.adjustAxes) {
  87107. layoutManager.applyHorizontalAxesLayout(hElements, layoutTargets, rotated);
  87108. !layoutManager.stopDrawAxes && reinitTranslators(that.translators)
  87109. }
  87110. drawAxes(verticalAxes);
  87111. if (drawOptions.adjustAxes && !layoutManager.stopDrawAxes) {
  87112. layoutManager.applyVerticalAxesLayout(vElements, layoutTargets, rotated);
  87113. !layoutManager.stopDrawAxes && reinitTranslators(that.translators)
  87114. }
  87115. adjustmentCounter = adjustmentCounter + 1
  87116. } while (!layoutManager.stopDrawAxes && layoutManager.requireAxesRedraw && adjustmentCounter < MAX_ADJUSTMENT_ATTEMPTS);
  87117. drawStaticAxisElements(verticalAxes);
  87118. drawStaticAxisElements(horizontalAxes);
  87119. that._scrollBar && that._scrollBar.applyLayout();
  87120. that.__axisAdjustmentsCount = adjustmentCounter
  87121. },
  87122. _getPanesParameters: function() {
  87123. var that = this,
  87124. panes = that.panes,
  87125. i,
  87126. params = [];
  87127. for (i = 0; i < panes.length; i++)
  87128. if (that._getPaneBorderVisibility(i))
  87129. params.push({
  87130. coords: panes[i].borderCoords,
  87131. clipRect: that._panesClipRects.fixed[i]
  87132. });
  87133. return params
  87134. },
  87135. _createCrosshairCursor: function() {
  87136. var that = this,
  87137. options = that._themeManager.getOptions("crosshair") || {},
  87138. axes = !that._isRotated() ? [that._argumentAxes, that._valueAxes] : [that._valueAxes, that._argumentAxes],
  87139. parameters = {
  87140. canvas: that._getCommonCanvas(),
  87141. panes: that._getPanesParameters(),
  87142. axes: axes
  87143. };
  87144. if (!options || !options.enabled)
  87145. return;
  87146. if (!that._crosshair)
  87147. that._crosshair = charts.factory.createCrosshair(that._renderer, options, parameters, that._crosshairCursorGroup);
  87148. else
  87149. that._crosshair.update(options, parameters);
  87150. that._crosshair.render()
  87151. },
  87152. _getCommonCanvas: function() {
  87153. var i,
  87154. canvas,
  87155. commonCanvas,
  87156. panes = this.panes;
  87157. for (i = 0; i < panes.length; i++) {
  87158. canvas = panes[i].canvas;
  87159. if (!commonCanvas)
  87160. commonCanvas = _extend({}, canvas);
  87161. else {
  87162. commonCanvas.right = canvas.right;
  87163. commonCanvas.bottom = canvas.bottom
  87164. }
  87165. }
  87166. return commonCanvas
  87167. },
  87168. _createPanesBackground: function() {
  87169. var that = this,
  87170. defaultBackgroundColor = that._themeManager.getOptions("commonPaneSettings").backgroundColor,
  87171. backgroundColor,
  87172. renderer = that._renderer,
  87173. rect,
  87174. i,
  87175. rects = [];
  87176. that._panesBackgroundGroup && that._panesBackgroundGroup.clear();
  87177. for (i = 0; i < that.panes.length; i++) {
  87178. backgroundColor = that.panes[i].backgroundColor || defaultBackgroundColor;
  87179. if (!backgroundColor || backgroundColor === "none") {
  87180. rects.push(null);
  87181. continue
  87182. }
  87183. rect = renderer.rect(0, 0, 0, 0).attr({
  87184. fill: backgroundColor,
  87185. "stroke-width": 0
  87186. }).append(that._panesBackgroundGroup);
  87187. rects.push(rect)
  87188. }
  87189. that.panesBackground = rects;
  87190. that._panesBackgroundGroup.append(renderer.root)
  87191. },
  87192. _fillPanesBackground: function() {
  87193. var that = this,
  87194. bc;
  87195. _each(that.panes, function(i, pane) {
  87196. bc = pane.borderCoords;
  87197. if (that.panesBackground[i] !== null)
  87198. that.panesBackground[i].attr({
  87199. x: bc.left,
  87200. y: bc.top,
  87201. width: bc.width,
  87202. height: bc.height
  87203. })
  87204. })
  87205. },
  87206. _calcPaneBorderCoords: function(pane) {
  87207. var canvas = pane.canvas,
  87208. bc = pane.borderCoords = pane.borderCoords || {};
  87209. bc.left = canvas.left;
  87210. bc.top = canvas.top;
  87211. bc.right = canvas.width - canvas.right;
  87212. bc.bottom = canvas.height - canvas.bottom;
  87213. bc.width = Math.max(bc.right - bc.left, 0);
  87214. bc.height = Math.max(bc.bottom - bc.top, 0)
  87215. },
  87216. _drawPanesBorders: function(panesBorderOptions) {
  87217. var that = this,
  87218. rotated = that._isRotated();
  87219. that._panesBorderGroup && that._panesBorderGroup.remove().clear();
  87220. _each(that.panes, function(i, pane) {
  87221. var bc,
  87222. borderOptions = panesBorderOptions[pane.name],
  87223. segmentRectParams,
  87224. attr = {
  87225. fill: "none",
  87226. stroke: borderOptions.color,
  87227. "stroke-opacity": borderOptions.opacity,
  87228. "stroke-width": borderOptions.width,
  87229. dashStyle: borderOptions.dashStyle,
  87230. "stroke-linecap": "square"
  87231. };
  87232. that._calcPaneBorderCoords(pane, rotated);
  87233. if (!borderOptions.visible)
  87234. return;
  87235. bc = pane.borderCoords;
  87236. segmentRectParams = prepareSegmentRectPoints(bc.left, bc.top, bc.width, bc.height, borderOptions);
  87237. that._renderer.path(segmentRectParams.points, segmentRectParams.pathType).attr(attr).append(that._panesBorderGroup)
  87238. });
  87239. that._panesBorderGroup.append(that._renderer.root)
  87240. },
  87241. _createClipRect: function(clipArray, index, left, top, width, height) {
  87242. var that = this,
  87243. clipRect = clipArray[index];
  87244. if (!clipRect) {
  87245. clipRect = that._renderer.clipRect(left, top, width, height);
  87246. clipArray[index] = clipRect
  87247. }
  87248. else
  87249. clipRect.attr({
  87250. x: left,
  87251. y: top,
  87252. width: width,
  87253. height: height
  87254. })
  87255. },
  87256. _createClipRectsForPanes: function() {
  87257. var that = this,
  87258. canvas = that._canvas;
  87259. _each(that.panes, function(i, pane) {
  87260. var needWideClipRect = false,
  87261. bc = pane.borderCoords,
  87262. left = bc.left,
  87263. top = bc.top,
  87264. width = bc.width,
  87265. height = bc.height,
  87266. panesClipRects = that._panesClipRects;
  87267. that._createClipRect(panesClipRects.fixed, i, left, top, width, height);
  87268. that._createClipRect(panesClipRects.base, i, left, top, width, height);
  87269. _each(that.series, function(_, series) {
  87270. if (series.pane === pane.name && (series.isFinancialSeries() || series.areErrorBarsVisible()))
  87271. needWideClipRect = true
  87272. });
  87273. if (needWideClipRect) {
  87274. if (that._isRotated()) {
  87275. top = 0;
  87276. height = canvas.height
  87277. }
  87278. else {
  87279. left = 0;
  87280. width = canvas.width
  87281. }
  87282. that._createClipRect(panesClipRects.wide, i, left, top, width, height)
  87283. }
  87284. else
  87285. panesClipRects.wide.push(null)
  87286. })
  87287. },
  87288. _getPaneIndex: function(paneName) {
  87289. var paneIndex;
  87290. _each(this.panes, function(index, pane) {
  87291. if (pane.name === paneName) {
  87292. paneIndex = index;
  87293. return false
  87294. }
  87295. });
  87296. return paneIndex
  87297. },
  87298. _getPaneBorderVisibility: function(paneIndex) {
  87299. var commonPaneBorderVisible = this._themeManager.getOptions("commonPaneSettings").border.visible,
  87300. pane = this.panes[paneIndex] || {},
  87301. paneBorder = pane.border || {};
  87302. return "visible" in paneBorder ? paneBorder.visible : commonPaneBorderVisible
  87303. },
  87304. _getElementsClipRectID: function(paneName) {
  87305. return this._panesClipRects.fixed[this._getPaneIndex(paneName)].id
  87306. },
  87307. _getTranslator: function(paneName, axisName) {
  87308. var paneTrans = this.translators[paneName],
  87309. foundTranslator = null;
  87310. if (!paneTrans)
  87311. return foundTranslator;
  87312. foundTranslator = paneTrans[axisName];
  87313. if (!foundTranslator)
  87314. _each(paneTrans, function(axis, trans) {
  87315. foundTranslator = trans;
  87316. return false
  87317. });
  87318. return foundTranslator
  87319. },
  87320. _getCanvasForPane: function(paneName) {
  87321. var panes = this.panes,
  87322. panesNumber = panes.length,
  87323. i;
  87324. for (i = 0; i < panesNumber; i++)
  87325. if (panes[i].name === paneName)
  87326. return panes[i].canvas
  87327. },
  87328. _getBusinessRange: function(paneName, axisName) {
  87329. var ranges = this.businessRanges || [],
  87330. rangesNumber = ranges.length,
  87331. foundRange,
  87332. i;
  87333. for (i = 0; i < rangesNumber; i++)
  87334. if (ranges[i].val.pane === paneName && ranges[i].val.axis === axisName) {
  87335. foundRange = ranges[i];
  87336. break
  87337. }
  87338. if (!foundRange)
  87339. for (i = 0; i < rangesNumber; i++)
  87340. if (ranges[i].val.pane === paneName) {
  87341. foundRange = ranges[i];
  87342. break
  87343. }
  87344. return foundRange
  87345. },
  87346. _transformArgument: function(translate, scale) {
  87347. var that = this,
  87348. rotated = that._isRotated(),
  87349. settings,
  87350. clipSettings,
  87351. panesClipRects = that._panesClipRects;
  87352. if (!that._transformed) {
  87353. that._transformed = true;
  87354. that._labelsGroup.remove();
  87355. that._resetIsReady();
  87356. _each(that.series || [], function(i, s) {
  87357. s.applyClip()
  87358. })
  87359. }
  87360. if (rotated) {
  87361. settings = {
  87362. translateY: translate,
  87363. scaleY: scale
  87364. };
  87365. clipSettings = {
  87366. translateY: -translate / scale,
  87367. scaleY: 1 / scale
  87368. }
  87369. }
  87370. else {
  87371. settings = {
  87372. translateX: translate,
  87373. scaleX: scale
  87374. };
  87375. clipSettings = {
  87376. translateX: -translate / scale,
  87377. scaleX: 1 / scale
  87378. }
  87379. }
  87380. applyClipSettings(panesClipRects.base, clipSettings);
  87381. applyClipSettings(panesClipRects.wide, clipSettings);
  87382. that._seriesGroup.attr(settings);
  87383. that._scrollBar && that._scrollBar.transform(-translate, scale)
  87384. },
  87385. _resetTransform: function() {
  87386. var that = this,
  87387. settings = {
  87388. translateX: 0,
  87389. translateY: 0,
  87390. scaleX: null,
  87391. scaleY: null
  87392. },
  87393. panesClipRects = that._panesClipRects;
  87394. applyClipSettings(panesClipRects.base, settings);
  87395. applyClipSettings(panesClipRects.wide, settings);
  87396. that._seriesGroup.attr(settings);
  87397. _each(that.series || [], function(i, s) {
  87398. s.resetClip()
  87399. });
  87400. that._transformed = false
  87401. },
  87402. _getTrackerSettings: function() {
  87403. var that = this,
  87404. themeManager = that._themeManager;
  87405. return _extend(this.callBase(), {
  87406. chart: that,
  87407. zoomingMode: themeManager.getOptions("zoomingMode"),
  87408. scrollingMode: themeManager.getOptions("scrollingMode"),
  87409. rotated: that._isRotated(),
  87410. crosshair: that._crosshair
  87411. })
  87412. },
  87413. _resolveLabelOverlappingStack: function() {
  87414. var that = this,
  87415. stackPoints = {},
  87416. isRotated = that._isRotated(),
  87417. shiftDirection = isRotated ? function(box, length) {
  87418. return {
  87419. x: box.x - length,
  87420. y: box.y
  87421. }
  87422. } : function(box, length) {
  87423. return {
  87424. x: box.x,
  87425. y: box.y - length
  87426. }
  87427. };
  87428. _each(this._getVisibleSeries(), function(_, particularSeries) {
  87429. that._prepareStackPoints(particularSeries, stackPoints)
  87430. });
  87431. _each(stackPoints, function(_, stacks) {
  87432. _each(stacks, function(_, points) {
  87433. charts.overlapping.resolveLabelOverlappingInOneDirection(points, that._getCommonCanvas(), isRotated, shiftDirection)
  87434. })
  87435. })
  87436. },
  87437. _getEqualBarWidth: function() {
  87438. return this._themeManager.getOptions("equalBarWidth")
  87439. },
  87440. zoomArgument: function(min, max, gesturesUsed) {
  87441. var that = this,
  87442. zoomArg;
  87443. if (!_isDefined(min) && !_isDefined(max))
  87444. return;
  87445. zoomArg = that._argumentAxes[0].zoom(min, max, gesturesUsed);
  87446. that._zoomMinArg = zoomArg.min;
  87447. that._zoomMaxArg = zoomArg.max;
  87448. that._notApplyMargins = gesturesUsed;
  87449. that._render({
  87450. force: true,
  87451. drawTitle: false,
  87452. drawLegend: false,
  87453. adjustAxes: false,
  87454. animate: false,
  87455. adjustSeriesLabels: false,
  87456. asyncSeriesRendering: false,
  87457. updateTracker: false
  87458. })
  87459. },
  87460. _resetZoom: function() {
  87461. var that = this;
  87462. that._zoomMinArg = that._zoomMaxArg = undefined;
  87463. that._argumentAxes[0] && that._argumentAxes[0].resetZoom()
  87464. },
  87465. getVisibleArgumentBounds: function() {
  87466. var range = this._argumentAxes[0].getTranslator().getBusinessRange(),
  87467. isDiscrete = range.axisType === "discrete",
  87468. categories = range.categories;
  87469. return {
  87470. minVisible: isDiscrete ? range.minVisible || categories[0] : range.minVisible,
  87471. maxVisible: isDiscrete ? range.maxVisible || categories[categories.length - 1] : range.maxVisible
  87472. }
  87473. }
  87474. }))
  87475. })(jQuery, DevExpress);
  87476. /*! Module viz-charts, file pieChart.js */
  87477. (function($, DX, undefined) {
  87478. var viz = DX.viz,
  87479. core = viz.core,
  87480. charts = viz.charts,
  87481. utils = DX.utils,
  87482. _extend = $.extend,
  87483. _noop = $.noop,
  87484. _getVerticallyShiftedAngularCoords = DX.viz.core.utils.getVerticallyShiftedAngularCoords;
  87485. DX.registerComponent("dxPieChart", viz.charts, charts.BaseChart.inherit({
  87486. _chartType: 'pie',
  87487. _reinitAxes: _noop,
  87488. _correctAxes: _noop,
  87489. _layoutManagerOptions: function() {
  87490. var diameter = this._themeManager.getOptions('diameter');
  87491. if (utils.isNumber(diameter)) {
  87492. if (diameter > 1)
  87493. diameter = 1;
  87494. else if (diameter < 0)
  87495. diameter = 0
  87496. }
  87497. else
  87498. diameter = undefined;
  87499. return _extend(true, {}, this.callBase(), {piePercentage: diameter})
  87500. },
  87501. _groupSeries: function() {
  87502. this.series.valueOptions = {valueType: "numeric"};
  87503. this._groupedSeries = [this.series];
  87504. this._groupedSeries.argumentOptions = this.series[0] && this.series[0].getOptions()
  87505. },
  87506. _populateBusinessRange: function() {
  87507. var businessRanges = [],
  87508. series = this.series,
  87509. singleSeries = series[0],
  87510. range = new core.Range,
  87511. singleSeriesRange;
  87512. this._disposeObjectsInArray("businessRanges");
  87513. if (singleSeries) {
  87514. singleSeriesRange = singleSeries.getRangeData();
  87515. range.addRange(singleSeriesRange.val);
  87516. if (!range.isDefined())
  87517. range.setStubData();
  87518. businessRanges.push(range)
  87519. }
  87520. this.businessRanges = businessRanges
  87521. },
  87522. _specialProcessSeries: function() {
  87523. this.series[0].arrangePoints()
  87524. },
  87525. _createTranslator: function(range) {
  87526. return core.CoreFactory.createTranslator1D(range.min, range.max, 360, 0)
  87527. },
  87528. _populateSeries: function() {
  87529. var that = this,
  87530. themeManager = that._themeManager,
  87531. hasSeriesTemplate = !!themeManager.getOptions("seriesTemplate"),
  87532. seriesOptions = hasSeriesTemplate ? that._templatedSeries : that.option("series"),
  87533. allSeriesOptions = $.isArray(seriesOptions) ? seriesOptions : seriesOptions ? [seriesOptions] : [],
  87534. data,
  87535. particularSeriesOptions,
  87536. particularSeries,
  87537. seriesTheme;
  87538. that._disposeSeries();
  87539. that.series = [];
  87540. themeManager.resetPalette();
  87541. if (allSeriesOptions.length) {
  87542. particularSeriesOptions = _extend(true, {}, allSeriesOptions[0]);
  87543. if (particularSeriesOptions.type && !utils.isString(particularSeriesOptions.type))
  87544. particularSeriesOptions.type = "";
  87545. data = particularSeriesOptions.data;
  87546. particularSeriesOptions.data = null;
  87547. particularSeriesOptions.incidentOccured = that._incidentOccured;
  87548. seriesTheme = themeManager.getOptions("series", particularSeriesOptions, true);
  87549. seriesTheme.visibilityChanged = $.proxy(that._seriesVisibilityChanged, that);
  87550. seriesTheme.customizePoint = themeManager.getOptions("customizePoint");
  87551. seriesTheme.customizeLabel = themeManager.getOptions("customizeLabel");
  87552. particularSeries = core.CoreFactory.createSeries({
  87553. renderer: that._renderer,
  87554. seriesGroup: that._seriesGroup,
  87555. labelsGroup: that._labelsGroup
  87556. }, seriesTheme);
  87557. if (!particularSeries.isUpdated)
  87558. that._incidentOccured("E2101", [seriesTheme.type]);
  87559. else {
  87560. that._processSingleSeries(particularSeries);
  87561. that.series.push(particularSeries)
  87562. }
  87563. particularSeriesOptions.data = data
  87564. }
  87565. return that.series
  87566. },
  87567. _processSingleSeries: function(singleSeries) {
  87568. singleSeries.arrangePoints()
  87569. },
  87570. _seriesPopulatedHandlerCore: _noop,
  87571. _getLegendTargets: function() {
  87572. return this.series[0] ? this.series[0].getPoints() : []
  87573. },
  87574. _legendItemTextField: "argument",
  87575. _prepareToRender: _noop,
  87576. _isLegendInside: _noop,
  87577. _renderAxes: _noop,
  87578. _isRotated: _noop,
  87579. _getLayoutTargets: function() {
  87580. return [{canvas: this._canvas}]
  87581. },
  87582. _getAxesForTransform: function() {
  87583. return {
  87584. verticalAxes: [],
  87585. horizontalAxes: []
  87586. }
  87587. },
  87588. _updateAxesLayout: _noop,
  87589. _applyClipRects: _noop,
  87590. _appendAdditionalSeriesGroups: _noop,
  87591. _getSeriesRenderTimeout: _noop,
  87592. _drawSeries: function(drawOptions) {
  87593. var that = this,
  87594. singleSeries = that.getSeries(),
  87595. legend = that.legend,
  87596. getActionCallbackProxy = $.proxy(legend.getActionCallback, legend);
  87597. if (singleSeries) {
  87598. that.layoutManager.applyPieChartSeriesLayout(that._canvas, singleSeries, true);
  87599. singleSeries.canvas = that._canvas;
  87600. singleSeries.resetLabelSetups();
  87601. if (singleSeries.drawLabelsWOPoints(that._createTranslator(that.businessRanges[0], that._canvas)))
  87602. that.layoutManager.applyPieChartSeriesLayout(that._canvas, singleSeries, drawOptions.hideLayoutLabels);
  87603. singleSeries.draw(that._createTranslator(that.businessRanges[0], that._canvas), that._getAnimateOption(singleSeries, drawOptions), drawOptions.hideLayoutLabels, getActionCallbackProxy)
  87604. }
  87605. },
  87606. _adjustSeries: function() {
  87607. var singleSeries = this.getSeries();
  87608. singleSeries && singleSeries.adjustLabels()
  87609. },
  87610. _updateLegendPosition: _noop,
  87611. _renderTrackers: _noop,
  87612. _createScrollBar: _noop,
  87613. _resolveLabelOverlappingShift: function() {
  87614. var series = this.series[0],
  87615. center = series.getCenter(),
  87616. lPoints = [],
  87617. rPoints = [];
  87618. $.each(series.getVisiblePoints(), function(_, point) {
  87619. var angle = utils.normalizeAngle(point.middleAngle);
  87620. (angle <= 90 || angle >= 270 ? rPoints : lPoints).push(point)
  87621. });
  87622. charts.overlapping.resolveLabelOverlappingInOneDirection(lPoints, this._canvas, false, shiftFunction);
  87623. charts.overlapping.resolveLabelOverlappingInOneDirection(rPoints, this._canvas, false, shiftFunction);
  87624. function shiftFunction(box, length) {
  87625. return _getVerticallyShiftedAngularCoords(box, -length, center)
  87626. }
  87627. },
  87628. getSeries: function getSeries() {
  87629. return this.series && this.series[0]
  87630. },
  87631. _legendDataField: 'point'
  87632. }))
  87633. })(jQuery, DevExpress);
  87634. /*! Module viz-charts, file polarChart.js */
  87635. (function($, DX, undefined) {
  87636. var charts = DX.viz.charts,
  87637. core = DX.viz.core,
  87638. DEFAULT_PANE_NAME = 'default';
  87639. var PolarChart = charts.AdvancedChart.inherit({
  87640. _chartType: 'polar',
  87641. _createPanes: function() {
  87642. return [{name: DEFAULT_PANE_NAME}]
  87643. },
  87644. _checkPaneName: function() {
  87645. return true
  87646. },
  87647. _getAxisRenderingOptions: function(typeSelector) {
  87648. var isArgumentAxis = typeSelector === "argumentAxis",
  87649. type = isArgumentAxis ? "circular" : "linear",
  87650. useSpiderWeb = this.option("useSpiderWeb");
  87651. if (useSpiderWeb)
  87652. type += "Spider";
  87653. return {
  87654. axesType: "polarAxes",
  87655. drawingType: type,
  87656. isHorizontal: true
  87657. }
  87658. },
  87659. _prepareAxisOptions: function(typeSelector, axisOptions) {
  87660. return {type: this.option("useSpiderWeb") && typeSelector === "argumentAxis" ? "discrete" : axisOptions.type}
  87661. },
  87662. _getExtraOptions: function() {
  87663. return {spiderWidget: this.option("useSpiderWeb")}
  87664. },
  87665. _correctAxes: $.noop,
  87666. _groupSeries: function() {
  87667. this._groupedSeries = [this.series];
  87668. this._groupedSeries[0].valueAxis = this._valueAxes[0];
  87669. this._groupedSeries[0].valueOptions = this._valueAxes[0].getOptions();
  87670. this._groupedSeries.argumentAxes = this._argumentAxes;
  87671. this._groupedSeries.argumentOptions = this._argumentAxes[0].getOptions()
  87672. },
  87673. _processSingleSeries: $.noop,
  87674. _prepareToRender: function() {
  87675. this._appendAxesGroups();
  87676. return {}
  87677. },
  87678. _isLegendInside: $.noop,
  87679. _renderAxes: function(drawOptions) {
  87680. this._drawAxes({}, drawOptions)
  87681. },
  87682. _reinitTranslators: function() {
  87683. var that = this,
  87684. valueAxes = that._valueAxes,
  87685. argumentAxes = that._argumentAxes,
  87686. translator = that._createTranslator({
  87687. arg: new core.Range(that.businessRanges[0].arg),
  87688. val: new core.Range(that.businessRanges[0].val)
  87689. }),
  87690. argTranslator = translator.getComponent("arg"),
  87691. valTranslator = translator.getComponent("val"),
  87692. i = 0;
  87693. that.translator = translator;
  87694. argumentAxes[0].setTranslator(argTranslator, valTranslator);
  87695. for (i; i < valueAxes.length; i++)
  87696. valueAxes[i].setTranslator(valTranslator, argTranslator)
  87697. },
  87698. _prepareAxesAndDraw: function(drawAxes, drawStaticAxisElements) {
  87699. var that = this,
  87700. valueAxes = that._valueAxes,
  87701. argAxes = that._argumentAxes,
  87702. argumentAxis = argAxes[0];
  87703. that._calcCanvas(argumentAxis.measureLabels());
  87704. that.translator.reinit();
  87705. drawAxes(argAxes);
  87706. $.each(valueAxes, function(_, valAxis) {
  87707. valAxis.setSpiderTicks(argumentAxis.getSpiderTicks())
  87708. });
  87709. drawAxes(valueAxes);
  87710. drawStaticAxisElements(argAxes);
  87711. drawStaticAxisElements(valueAxes)
  87712. },
  87713. _calcCanvas: function(measure) {
  87714. var canvas = this.translator.canvas;
  87715. canvas.left += measure.width;
  87716. canvas.right += measure.width;
  87717. canvas.top += measure.height;
  87718. canvas.bottom += measure.height
  87719. },
  87720. _isRotated: $.noop,
  87721. _getLayoutTargets: function() {
  87722. return [{canvas: this._canvas}]
  87723. },
  87724. _getAxesForTransform: function() {
  87725. var argAxes = this._getArgumentAxes();
  87726. return {
  87727. verticalAxes: argAxes,
  87728. horizontalAxes: argAxes
  87729. }
  87730. },
  87731. _applyClipRects: $.noop,
  87732. _getSeriesRenderTimeout: $.noop,
  87733. _drawSeries: function(drawOptions) {
  87734. var that = this,
  87735. i,
  87736. seriesFamilies = that.seriesFamilies || [],
  87737. series = that.series;
  87738. if (!series.length)
  87739. return;
  87740. for (i = 0; i < seriesFamilies.length; i++) {
  87741. var translators = {};
  87742. translators.val = that.translator;
  87743. translators.arg = that.translator;
  87744. seriesFamilies[i].updateSeriesValues(translators);
  87745. seriesFamilies[i].adjustSeriesDimensions(translators)
  87746. }
  87747. for (i = 0; i < series.length; i++)
  87748. series[i].draw(that.translator, that._getAnimateOption(series[i], drawOptions), drawOptions.hideLayoutLabels, that.legend && that.legend.getActionCallback(series[i]))
  87749. },
  87750. _updateLegendPosition: $.noop,
  87751. _createScrollBar: $.noop,
  87752. _createTranslator: function(br) {
  87753. var themeManager = this._themeManager,
  87754. axisUserOptions = this.option("argumentAxis"),
  87755. axisOptions = themeManager.getOptions("argumentAxis", axisUserOptions) || {};
  87756. return new core.PolarTranslator(br, $.extend(true, {}, this._canvas), {startAngle: axisOptions.startAngle})
  87757. },
  87758. _getSeriesForPane: function() {
  87759. return this.series
  87760. },
  87761. _getEqualBarWidth: function() {
  87762. return !!this._themeManager.getOptions("equalBarWidth")
  87763. }
  87764. });
  87765. DX.registerComponent('dxPolarChart', charts, PolarChart)
  87766. })(jQuery, DevExpress);
  87767. /*! Module viz-charts, file layoutManager.js */
  87768. (function($, DX, undefined) {
  87769. var _isNumber = DX.utils.isNumber,
  87770. _decreaseGaps = DX.viz.core.utils.decreaseGaps,
  87771. _round = Math.round,
  87772. _min = Math.min,
  87773. _max = Math.max,
  87774. _floor = Math.floor,
  87775. _sqrt = Math.sqrt,
  87776. _each = $.each,
  87777. _extend = $.extend;
  87778. function correctElementsPosition(elements, direction, canvas) {
  87779. _each(elements, function(_, element) {
  87780. var options = element.getLayoutOptions(),
  87781. side = options.cutLayoutSide;
  87782. canvas[side] -= options[direction]
  87783. })
  87784. }
  87785. function placeElementAndCutCanvas(elements, canvas) {
  87786. _each(elements, function(_, element) {
  87787. var shiftX,
  87788. shiftY,
  87789. options = element.getLayoutOptions(),
  87790. length = getLength(options.cutLayoutSide);
  87791. if (!options.width)
  87792. return;
  87793. switch (options.horizontalAlignment) {
  87794. case"left":
  87795. shiftX = canvas.left;
  87796. break;
  87797. case"center":
  87798. shiftX = (canvas.width - canvas.left - canvas.right - options.width) / 2 + canvas.left;
  87799. break;
  87800. case"right":
  87801. shiftX = canvas.width - canvas.right - options.width;
  87802. break
  87803. }
  87804. switch (options.verticalAlignment) {
  87805. case"top":
  87806. shiftY = canvas.top;
  87807. break;
  87808. case"bottom":
  87809. shiftY = canvas.height - canvas.bottom - options.height;
  87810. break
  87811. }
  87812. element.shift(_round(shiftX), _round(shiftY));
  87813. canvas[options.cutLayoutSide] += options[length];
  87814. setCanvasValues(canvas)
  87815. })
  87816. }
  87817. function getLength(side) {
  87818. return side === 'left' || side === 'right' ? 'width' : 'height'
  87819. }
  87820. function setCanvasValues(canvas) {
  87821. if (canvas) {
  87822. canvas.originalTop = canvas.top;
  87823. canvas.originalBottom = canvas.bottom;
  87824. canvas.originalLeft = canvas.left;
  87825. canvas.originalRight = canvas.right
  87826. }
  87827. }
  87828. function updateElements(elements, length, otherLength, dirtyCanvas, canvas, needRemoveSpace) {
  87829. _each(elements, function(_, element) {
  87830. var options = element.getLayoutOptions(),
  87831. side = options.cutLayoutSide,
  87832. freeSpaceWidth = dirtyCanvas.width - dirtyCanvas.left - dirtyCanvas.right,
  87833. freeSpaceHeight = dirtyCanvas.height - dirtyCanvas.top - dirtyCanvas.bottom,
  87834. updateObject = {};
  87835. element.setSize({
  87836. width: freeSpaceWidth,
  87837. height: freeSpaceHeight
  87838. });
  87839. updateObject[otherLength] = 0;
  87840. updateObject[length] = needRemoveSpace[length];
  87841. element.changeSize(updateObject);
  87842. canvas[side] -= options[length] - element.getLayoutOptions()[length];
  87843. needRemoveSpace[length] -= options[length] - element.getLayoutOptions()[length]
  87844. })
  87845. }
  87846. function updateAxis(axes, side, needRemoveSpace) {
  87847. if (axes && needRemoveSpace[side] > 0) {
  87848. _each(axes, function(i, axis) {
  87849. var bbox = axis.getBoundingRect();
  87850. axis.updateSize();
  87851. needRemoveSpace[side] -= bbox[side] - axis.getBoundingRect()[side]
  87852. });
  87853. if (needRemoveSpace[side] > 0)
  87854. _each(axes, function(_, axis) {
  87855. axis.updateSize(true)
  87856. })
  87857. }
  87858. }
  87859. function getNearestCoord(firstCoord, secondCoord, pointCenterCoord) {
  87860. var nearestCoord;
  87861. if (pointCenterCoord < firstCoord)
  87862. nearestCoord = firstCoord;
  87863. else if (secondCoord < pointCenterCoord)
  87864. nearestCoord = secondCoord;
  87865. else
  87866. nearestCoord = pointCenterCoord;
  87867. return nearestCoord
  87868. }
  87869. function getLengthFromCenter(x, y, paneCenterX, paneCenterY) {
  87870. return _sqrt((x - paneCenterX) * (x - paneCenterX) + (y - paneCenterY) * (y - paneCenterY))
  87871. }
  87872. function getInnerRadius(series) {
  87873. var innerRadius;
  87874. if (series.type === "pie")
  87875. innerRadius = 0;
  87876. else {
  87877. innerRadius = _isNumber(series.innerRadius) ? Number(series.innerRadius) : 0.5;
  87878. innerRadius = innerRadius < 0.2 ? 0.2 : innerRadius;
  87879. innerRadius = innerRadius > 0.8 ? 0.8 : innerRadius
  87880. }
  87881. return innerRadius
  87882. }
  87883. function isValidBox(box) {
  87884. return !!(box.x || box.y || box.width || box.height)
  87885. }
  87886. function correctDeltaMarginValue(panes, marginSides) {
  87887. var canvas,
  87888. deltaSide,
  87889. requireAxesRedraw = false;
  87890. _each(panes, function(_, pane) {
  87891. canvas = pane.canvas;
  87892. _each(marginSides, function(_, side) {
  87893. deltaSide = "delta" + side;
  87894. canvas[deltaSide] = _max(canvas[deltaSide] - (canvas[side.toLowerCase()] - canvas["original" + side]), 0);
  87895. if (canvas[deltaSide] > 0)
  87896. requireAxesRedraw = true
  87897. })
  87898. });
  87899. return requireAxesRedraw
  87900. }
  87901. function getPane(name, panes) {
  87902. var findPane = panes[0];
  87903. _each(panes, function(_, pane) {
  87904. if (name === pane.name)
  87905. findPane = pane
  87906. });
  87907. return findPane
  87908. }
  87909. function applyFoundExceedings(panes, rotated) {
  87910. var stopDrawAxes = false,
  87911. maxLeft = 0,
  87912. maxRight = 0,
  87913. maxTop = 0,
  87914. maxBottom = 0;
  87915. _each(panes, function(_, pane) {
  87916. maxLeft = _max(maxLeft, pane.canvas.deltaLeft);
  87917. maxRight = _max(maxRight, pane.canvas.deltaRight);
  87918. maxTop = _max(maxTop, pane.canvas.deltaTop);
  87919. maxBottom = _max(maxBottom, pane.canvas.deltaBottom)
  87920. });
  87921. if (rotated)
  87922. _each(panes, function(_, pane) {
  87923. pane.canvas.top += maxTop;
  87924. pane.canvas.bottom += maxBottom;
  87925. pane.canvas.right += pane.canvas.deltaRight;
  87926. pane.canvas.left += pane.canvas.deltaLeft
  87927. });
  87928. else
  87929. _each(panes, function(_, pane) {
  87930. pane.canvas.top += pane.canvas.deltaTop;
  87931. pane.canvas.bottom += pane.canvas.deltaBottom;
  87932. pane.canvas.right += maxRight;
  87933. pane.canvas.left += maxLeft
  87934. });
  87935. _each(panes, function(_, pane) {
  87936. if (pane.canvas.top + pane.canvas.bottom > pane.canvas.height)
  87937. stopDrawAxes = true;
  87938. if (pane.canvas.left + pane.canvas.right > pane.canvas.width)
  87939. stopDrawAxes = true
  87940. });
  87941. return stopDrawAxes
  87942. }
  87943. function LayoutManager(options) {
  87944. this._verticalElements = [];
  87945. this._horizontalElements = [];
  87946. this._options = options
  87947. }
  87948. LayoutManager.prototype = {
  87949. constructor: LayoutManager,
  87950. dispose: function() {
  87951. this._verticalElements = this._horizontalElements = this._options = null
  87952. },
  87953. drawElements: function(elements, canvas) {
  87954. var horizontalElements = [],
  87955. verticalElements = [];
  87956. _each(elements, function(_, element) {
  87957. var options,
  87958. length;
  87959. element.setSize({
  87960. width: canvas.width - canvas.left - canvas.right,
  87961. height: canvas.height - canvas.top - canvas.bottom
  87962. });
  87963. element.draw();
  87964. options = element.getLayoutOptions();
  87965. if (options) {
  87966. length = getLength(options.cutLayoutSide);
  87967. (length === 'width' ? horizontalElements : verticalElements).push(element);
  87968. canvas[options.cutLayoutSide] += options[length];
  87969. setCanvasValues(canvas)
  87970. }
  87971. });
  87972. this._horizontalElements = horizontalElements;
  87973. this._verticalElements = verticalElements;
  87974. return this
  87975. },
  87976. placeDrawnElements: function(canvas) {
  87977. correctElementsPosition(this._horizontalElements, 'width', canvas);
  87978. placeElementAndCutCanvas(this._horizontalElements, canvas);
  87979. correctElementsPosition(this._verticalElements, 'height', canvas);
  87980. placeElementAndCutCanvas(this._verticalElements, canvas);
  87981. return this
  87982. },
  87983. updatePanesCanvases: function(panes, canvas, rotated) {
  87984. var weightSum = 0;
  87985. _each(panes, function(_, pane) {
  87986. pane.weight = pane.weight || 1;
  87987. weightSum += pane.weight
  87988. });
  87989. var distributedSpace = 0,
  87990. padding = panes.padding || 10,
  87991. paneSpace = rotated ? canvas.width - canvas.left - canvas.right : canvas.height - canvas.top - canvas.bottom,
  87992. oneWeight = (paneSpace - padding * (panes.length - 1)) / weightSum,
  87993. startName = rotated ? "left" : "top",
  87994. endName = rotated ? "right" : "bottom";
  87995. _each(panes, function(_, pane) {
  87996. var calcLength = _round(pane.weight * oneWeight);
  87997. pane.canvas = pane.canvas || {};
  87998. _extend(pane.canvas, {
  87999. deltaLeft: 0,
  88000. deltaRight: 0,
  88001. deltaTop: 0,
  88002. deltaBottom: 0
  88003. }, canvas);
  88004. pane.canvas[startName] = canvas[startName] + distributedSpace;
  88005. pane.canvas[endName] = canvas[endName] + (paneSpace - calcLength - distributedSpace);
  88006. distributedSpace = distributedSpace + calcLength + padding;
  88007. setCanvasValues(pane.canvas)
  88008. })
  88009. },
  88010. applyVerticalAxesLayout: function(axes, panes, rotated) {
  88011. this._applyAxesLayout(axes, panes, rotated)
  88012. },
  88013. applyHorizontalAxesLayout: function(axes, panes, rotated) {
  88014. axes.reverse();
  88015. this._applyAxesLayout(axes, panes, rotated);
  88016. axes.reverse()
  88017. },
  88018. _applyAxesLayout: function(axes, panes, rotated) {
  88019. var that = this,
  88020. canvas,
  88021. axisPosition,
  88022. box,
  88023. delta,
  88024. axis,
  88025. axisLength,
  88026. direction,
  88027. directionMultiplier,
  88028. someDirection = [],
  88029. pane,
  88030. i;
  88031. _each(panes, function(_, pane) {
  88032. _extend(pane.canvas, {
  88033. deltaLeft: 0,
  88034. deltaRight: 0,
  88035. deltaTop: 0,
  88036. deltaBottom: 0
  88037. })
  88038. });
  88039. for (i = 0; i < axes.length; i++) {
  88040. axis = axes[i];
  88041. axisPosition = axis.getOptions().position || "left";
  88042. axis.delta = {};
  88043. box = axis.getBoundingRect();
  88044. pane = getPane(axis.pane, panes);
  88045. canvas = pane.canvas;
  88046. if (!isValidBox(box))
  88047. continue;
  88048. direction = "delta" + axisPosition.slice(0, 1).toUpperCase() + axisPosition.slice(1);
  88049. switch (axisPosition) {
  88050. case"right":
  88051. directionMultiplier = 1;
  88052. canvas.deltaLeft += axis.padding ? axis.padding.left : 0;
  88053. break;
  88054. case"left":
  88055. directionMultiplier = -1;
  88056. canvas.deltaRight += axis.padding ? axis.padding.right : 0;
  88057. break;
  88058. case"top":
  88059. directionMultiplier = -1;
  88060. canvas.deltaBottom += axis.padding ? axis.padding.bottom : 0;
  88061. break;
  88062. case"bottom":
  88063. directionMultiplier = 1;
  88064. canvas.deltaTop += axis.padding ? axis.padding.top : 0;
  88065. break
  88066. }
  88067. switch (axisPosition) {
  88068. case"right":
  88069. case"left":
  88070. if (!box.isEmpty) {
  88071. delta = box.y + box.height - (canvas.height - canvas.originalBottom);
  88072. if (delta > 0) {
  88073. that.requireAxesRedraw = true;
  88074. canvas.deltaBottom += delta
  88075. }
  88076. delta = canvas.originalTop - box.y;
  88077. if (delta > 0) {
  88078. that.requireAxesRedraw = true;
  88079. canvas.deltaTop += delta
  88080. }
  88081. }
  88082. axisLength = box.width;
  88083. someDirection = ["Left", "Right"];
  88084. break;
  88085. case"top":
  88086. case"bottom":
  88087. if (!box.isEmpty) {
  88088. delta = box.x + box.width - (canvas.width - canvas.originalRight);
  88089. if (delta > 0) {
  88090. that.requireAxesRedraw = true;
  88091. canvas.deltaRight += delta
  88092. }
  88093. delta = canvas.originalLeft - box.x;
  88094. if (delta > 0) {
  88095. that.requireAxesRedraw = true;
  88096. canvas.deltaLeft += delta
  88097. }
  88098. }
  88099. someDirection = ["Bottom", "Top"];
  88100. axisLength = box.height;
  88101. break
  88102. }
  88103. if (!axis.delta[axisPosition] && canvas[direction] > 0)
  88104. canvas[direction] += axis.getMultipleAxesSpacing();
  88105. axis.delta[axisPosition] = axis.delta[axisPosition] || 0;
  88106. axis.delta[axisPosition] += canvas[direction] * directionMultiplier;
  88107. canvas[direction] += axisLength
  88108. }
  88109. that.requireAxesRedraw = correctDeltaMarginValue(panes, someDirection) || that.requireAxesRedraw;
  88110. that.stopDrawAxes = applyFoundExceedings(panes, rotated)
  88111. },
  88112. applyPieChartSeriesLayout: function(canvas, singleSeries, hideLayoutLabels) {
  88113. var paneSpaceHeight = canvas.height - canvas.top - canvas.bottom,
  88114. paneSpaceWidth = canvas.width - canvas.left - canvas.right,
  88115. paneCenterX = paneSpaceWidth / 2 + canvas.left,
  88116. paneCenterY = paneSpaceHeight / 2 + canvas.top,
  88117. piePercentage = this._options.piePercentage,
  88118. accessibleRadius = _isNumber(piePercentage) ? piePercentage * _min(canvas.height, canvas.width) / 2 : _min(paneSpaceWidth, paneSpaceHeight) / 2,
  88119. minR = 0.7 * accessibleRadius,
  88120. innerRadius = getInnerRadius(singleSeries);
  88121. if (!hideLayoutLabels && !_isNumber(piePercentage))
  88122. _each(singleSeries.getPoints(), function(_, point) {
  88123. if (point._label.isVisible() && point.isVisible()) {
  88124. var labelBBox = point._label.getBoundingRect(),
  88125. nearestX = getNearestCoord(labelBBox.x, labelBBox.x + labelBBox.width, paneCenterX),
  88126. nearestY = getNearestCoord(labelBBox.y, labelBBox.y + labelBBox.height, paneCenterY),
  88127. minRadiusWithLabels = _max(getLengthFromCenter(nearestX, nearestY, paneCenterX, paneCenterY) - DX.viz.core.series.helpers.consts.pieLabelIndent, minR);
  88128. accessibleRadius = _min(accessibleRadius, minRadiusWithLabels)
  88129. }
  88130. });
  88131. singleSeries.correctPosition({
  88132. centerX: _floor(paneCenterX),
  88133. centerY: _floor(paneCenterY),
  88134. radiusInner: _floor(accessibleRadius * innerRadius),
  88135. radiusOuter: _floor(accessibleRadius)
  88136. })
  88137. },
  88138. updateDrawnElements: function(axes, canvas, dirtyCanvas, panes, rotated) {
  88139. var needRemoveSpace,
  88140. saveDirtyCanvas = _extend({}, dirtyCanvas);
  88141. needRemoveSpace = this.needMoreSpaceForPanesCanvas(panes, rotated);
  88142. if (!needRemoveSpace)
  88143. return;
  88144. needRemoveSpace.height = _decreaseGaps(dirtyCanvas, ["top", "bottom"], needRemoveSpace.height);
  88145. needRemoveSpace.width = _decreaseGaps(dirtyCanvas, ["left", "right"], needRemoveSpace.width);
  88146. canvas.top -= saveDirtyCanvas.top - dirtyCanvas.top;
  88147. canvas.bottom -= saveDirtyCanvas.bottom - dirtyCanvas.bottom;
  88148. canvas.left -= saveDirtyCanvas.left - dirtyCanvas.left;
  88149. canvas.right -= saveDirtyCanvas.right - dirtyCanvas.right;
  88150. updateElements(this._horizontalElements, "width", "height", dirtyCanvas, canvas, needRemoveSpace);
  88151. updateElements(this._verticalElements, "height", "width", dirtyCanvas, canvas, needRemoveSpace);
  88152. updateAxis(axes.verticalAxes, "width", needRemoveSpace);
  88153. updateAxis(axes.horizontalAxes, "height", needRemoveSpace)
  88154. },
  88155. needMoreSpaceForPanesCanvas: function(panes, rotated) {
  88156. var options = this._options,
  88157. width = options.width,
  88158. height = options.height,
  88159. piePercentage = options.piePercentage,
  88160. percentageIsValid = _isNumber(piePercentage),
  88161. needHorizontalSpace = 0,
  88162. needVerticalSpace = 0;
  88163. _each(panes, function(_, pane) {
  88164. var paneCanvas = pane.canvas,
  88165. minSize = percentageIsValid ? _min(paneCanvas.width, paneCanvas.height) * piePercentage : undefined,
  88166. needPaneHorizonralSpace = (percentageIsValid ? minSize : width) - (paneCanvas.width - paneCanvas.left - paneCanvas.right),
  88167. needPaneVerticalSpace = (percentageIsValid ? minSize : height) - (paneCanvas.height - paneCanvas.top - paneCanvas.bottom);
  88168. if (rotated) {
  88169. needHorizontalSpace += needPaneHorizonralSpace > 0 ? needPaneHorizonralSpace : 0;
  88170. needVerticalSpace = _max(needPaneVerticalSpace > 0 ? needPaneVerticalSpace : 0, needVerticalSpace)
  88171. }
  88172. else {
  88173. needHorizontalSpace = _max(needPaneHorizonralSpace > 0 ? needPaneHorizonralSpace : 0, needHorizontalSpace);
  88174. needVerticalSpace += needPaneVerticalSpace > 0 ? needPaneVerticalSpace : 0
  88175. }
  88176. });
  88177. return needHorizontalSpace > 0 || needVerticalSpace > 0 ? {
  88178. width: needHorizontalSpace,
  88179. height: needVerticalSpace
  88180. } : false
  88181. },
  88182. correctSizeElement: function(element, canvas) {
  88183. element.setSize({
  88184. width: canvas.width - canvas.right - canvas.left,
  88185. height: canvas.width - canvas.right - canvas.left
  88186. });
  88187. element.changeSize({
  88188. width: 0,
  88189. height: 0
  88190. })
  88191. }
  88192. };
  88193. DX.viz.charts._setCanvasValues = setCanvasValues;
  88194. DX.viz.charts.LayoutManager = LayoutManager
  88195. })(jQuery, DevExpress);
  88196. /*! Module viz-charts, file multiAxesSynchronizer.js */
  88197. (function($, DX, undefined) {
  88198. var Range = DX.viz.core.Range,
  88199. utils = DX.utils,
  88200. _adjustValue = utils.adjustValue,
  88201. _applyPrecisionByMinDelta = utils.applyPrecisionByMinDelta,
  88202. _isDefined = utils.isDefined,
  88203. _math = Math,
  88204. _floor = _math.floor,
  88205. _max = _math.max,
  88206. _each = $.each,
  88207. MIN_RANGE_FOR_ADJUST_BOUNDS = 0.1;
  88208. var getValueAxesPerPanes = function(valueAxes) {
  88209. var result = {};
  88210. _each(valueAxes, function(_, axis) {
  88211. var pane = axis.pane;
  88212. if (!result[pane])
  88213. result[pane] = [];
  88214. result[pane].push(axis)
  88215. });
  88216. return result
  88217. };
  88218. var restoreOriginalBusinessRange = function(axis) {
  88219. var businessRange,
  88220. translator = axis.getTranslator();
  88221. if (!translator._originalBusinessRange)
  88222. translator._originalBusinessRange = new Range(translator.getBusinessRange());
  88223. else {
  88224. businessRange = new Range(translator._originalBusinessRange);
  88225. translator.updateBusinessRange(businessRange)
  88226. }
  88227. };
  88228. var linearConvertor = {
  88229. transform: function(v, b) {
  88230. return utils.getLog(v, b)
  88231. },
  88232. addInterval: function(v, i) {
  88233. return v + i
  88234. },
  88235. getInterval: function(base, tickInterval) {
  88236. return tickInterval
  88237. },
  88238. adjustValue: _floor
  88239. };
  88240. var logConvertor = {
  88241. transform: function(v, b) {
  88242. return utils.raiseTo(v, b)
  88243. },
  88244. addInterval: function(v, i) {
  88245. return v * i
  88246. },
  88247. getInterval: function(base, tickInterval) {
  88248. return _math.pow(base, tickInterval)
  88249. },
  88250. adjustValue: _adjustValue
  88251. };
  88252. var convertAxisInfo = function(axisInfo, convertor) {
  88253. if (!axisInfo.isLogarithmic)
  88254. return;
  88255. var base = axisInfo.logarithmicBase,
  88256. tickValues = axisInfo.tickValues,
  88257. tick,
  88258. ticks = [],
  88259. interval,
  88260. i;
  88261. axisInfo.minValue = convertor.transform(axisInfo.minValue, base);
  88262. axisInfo.oldMinValue = convertor.transform(axisInfo.oldMinValue, base);
  88263. axisInfo.maxValue = convertor.transform(axisInfo.maxValue, base);
  88264. axisInfo.oldMaxValue = convertor.transform(axisInfo.oldMaxValue, base);
  88265. axisInfo.tickInterval = _math.round(axisInfo.tickInterval);
  88266. if (axisInfo.tickInterval < 1)
  88267. axisInfo.tickInterval = 1;
  88268. interval = convertor.getInterval(base, axisInfo.tickInterval);
  88269. tick = convertor.transform(tickValues[0], base);
  88270. for (i = 0; i < tickValues.length; i++) {
  88271. ticks.push(convertor.adjustValue(tick));
  88272. tick = convertor.addInterval(tick, interval)
  88273. }
  88274. ticks.tickInterval = axisInfo.tickInterval;
  88275. axisInfo.tickValues = ticks
  88276. };
  88277. var populateAxesInfo = function(axes) {
  88278. return $.map(axes, function(axis) {
  88279. restoreOriginalBusinessRange(axis);
  88280. var ticksValues = axis.getTicksValues(),
  88281. majorTicks = ticksValues.majorTicksValues,
  88282. options = axis.getOptions(),
  88283. minValue,
  88284. maxValue,
  88285. axisInfo = null,
  88286. businessRange,
  88287. tickInterval,
  88288. synchronizedValue;
  88289. if (majorTicks && majorTicks.length > 0 && utils.isNumber(majorTicks[0]) && options.type !== "discrete") {
  88290. businessRange = axis.getTranslator().getBusinessRange();
  88291. tickInterval = axis._tickManager.getTickInterval();
  88292. minValue = businessRange.minVisible;
  88293. maxValue = businessRange.maxVisible;
  88294. synchronizedValue = options.synchronizedValue;
  88295. if (minValue === maxValue && _isDefined(synchronizedValue)) {
  88296. minValue = majorTicks[0] - 1;
  88297. maxValue = majorTicks[0] + 1;
  88298. tickInterval = 1
  88299. }
  88300. axisInfo = {
  88301. axis: axis,
  88302. isLogarithmic: options.type === "logarithmic",
  88303. logarithmicBase: businessRange.base,
  88304. tickValues: majorTicks,
  88305. minorValues: ticksValues.minorTicksValues,
  88306. minValue: minValue,
  88307. oldMinValue: minValue,
  88308. maxValue: maxValue,
  88309. oldMaxValue: maxValue,
  88310. inverted: businessRange.invert,
  88311. tickInterval: tickInterval,
  88312. synchronizedValue: synchronizedValue
  88313. };
  88314. if (businessRange.stubData) {
  88315. axisInfo.stubData = true;
  88316. axisInfo.tickInterval = axisInfo.tickInterval || options.tickInterval;
  88317. axisInfo.isLogarithmic = false
  88318. }
  88319. convertAxisInfo(axisInfo, linearConvertor);
  88320. DX.utils.debug.assert(axisInfo.tickInterval !== undefined && axisInfo.tickInterval !== null, "tickInterval was not provided")
  88321. }
  88322. return axisInfo
  88323. })
  88324. };
  88325. var updateTickValues = function(axesInfo) {
  88326. var maxTicksCount = 0;
  88327. _each(axesInfo, function(_, axisInfo) {
  88328. maxTicksCount = _max(maxTicksCount, axisInfo.tickValues.length)
  88329. });
  88330. _each(axesInfo, function(_, axisInfo) {
  88331. var ticksMultiplier,
  88332. ticksCount,
  88333. additionalStartTicksCount = 0,
  88334. synchronizedValue = axisInfo.synchronizedValue,
  88335. tickValues = axisInfo.tickValues,
  88336. tickInterval = axisInfo.tickInterval;
  88337. if (_isDefined(synchronizedValue)) {
  88338. axisInfo.baseTickValue = axisInfo.invertedBaseTickValue = synchronizedValue;
  88339. axisInfo.tickValues = [axisInfo.baseTickValue]
  88340. }
  88341. else {
  88342. if (tickValues.length > 1 && tickInterval) {
  88343. ticksMultiplier = _floor((maxTicksCount + 1) / tickValues.length);
  88344. ticksCount = ticksMultiplier > 1 ? _floor((maxTicksCount + 1) / ticksMultiplier) : maxTicksCount;
  88345. additionalStartTicksCount = _floor((ticksCount - tickValues.length) / 2);
  88346. while (additionalStartTicksCount > 0 && tickValues[0] !== 0) {
  88347. tickValues.unshift(_applyPrecisionByMinDelta(tickValues[0], tickInterval, tickValues[0] - tickInterval));
  88348. additionalStartTicksCount--
  88349. }
  88350. while (tickValues.length < ticksCount)
  88351. tickValues.push(_applyPrecisionByMinDelta(tickValues[0], tickInterval, tickValues[tickValues.length - 1] + tickInterval));
  88352. axisInfo.tickInterval = tickInterval / ticksMultiplier
  88353. }
  88354. axisInfo.baseTickValue = tickValues[0];
  88355. axisInfo.invertedBaseTickValue = tickValues[tickValues.length - 1]
  88356. }
  88357. })
  88358. };
  88359. var getAxisRange = function(axisInfo) {
  88360. return axisInfo.maxValue - axisInfo.minValue || 1
  88361. };
  88362. var getMainAxisInfo = function(axesInfo) {
  88363. for (var i = 0; i < axesInfo.length; i++)
  88364. if (!axesInfo[i].stubData)
  88365. return axesInfo[i];
  88366. return null
  88367. };
  88368. var correctMinMaxValues = function(axesInfo) {
  88369. var mainAxisInfo = getMainAxisInfo(axesInfo),
  88370. mainAxisInfoTickInterval = mainAxisInfo.tickInterval;
  88371. _each(axesInfo, function(_, axisInfo) {
  88372. var scale,
  88373. move,
  88374. mainAxisBaseValueOffset,
  88375. valueFromAxisInfo;
  88376. if (axisInfo !== mainAxisInfo) {
  88377. if (mainAxisInfoTickInterval && axisInfo.tickInterval) {
  88378. if (axisInfo.stubData && _isDefined(axisInfo.synchronizedValue)) {
  88379. axisInfo.oldMinValue = axisInfo.minValue = axisInfo.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.minValue) / mainAxisInfoTickInterval * axisInfo.tickInterval;
  88380. axisInfo.oldMaxValue = axisInfo.maxValue = axisInfo.baseTickValue - (mainAxisInfo.baseTickValue - mainAxisInfo.maxValue) / mainAxisInfoTickInterval * axisInfo.tickInterval
  88381. }
  88382. scale = mainAxisInfoTickInterval / getAxisRange(mainAxisInfo) / axisInfo.tickInterval * getAxisRange(axisInfo);
  88383. axisInfo.maxValue = axisInfo.minValue + getAxisRange(axisInfo) / scale
  88384. }
  88385. if (mainAxisInfo.inverted && !axisInfo.inverted || !mainAxisInfo.inverted && axisInfo.inverted)
  88386. mainAxisBaseValueOffset = mainAxisInfo.maxValue - mainAxisInfo.invertedBaseTickValue;
  88387. else
  88388. mainAxisBaseValueOffset = mainAxisInfo.baseTickValue - mainAxisInfo.minValue;
  88389. valueFromAxisInfo = getAxisRange(axisInfo);
  88390. move = (mainAxisBaseValueOffset / getAxisRange(mainAxisInfo) - (axisInfo.baseTickValue - axisInfo.minValue) / valueFromAxisInfo) * valueFromAxisInfo;
  88391. axisInfo.minValue -= move;
  88392. axisInfo.maxValue -= move
  88393. }
  88394. })
  88395. };
  88396. var calculatePaddings = function(axesInfo) {
  88397. var minPadding,
  88398. maxPadding,
  88399. startPadding = 0,
  88400. endPadding = 0;
  88401. _each(axesInfo, function(_, axisInfo) {
  88402. var inverted = axisInfo.inverted;
  88403. minPadding = axisInfo.minValue > axisInfo.oldMinValue ? (axisInfo.minValue - axisInfo.oldMinValue) / getAxisRange(axisInfo) : 0;
  88404. maxPadding = axisInfo.maxValue < axisInfo.oldMaxValue ? (axisInfo.oldMaxValue - axisInfo.maxValue) / getAxisRange(axisInfo) : 0;
  88405. startPadding = _max(startPadding, inverted ? maxPadding : minPadding);
  88406. endPadding = _max(endPadding, inverted ? minPadding : maxPadding)
  88407. });
  88408. return {
  88409. start: startPadding,
  88410. end: endPadding
  88411. }
  88412. };
  88413. var correctMinMaxValuesByPaddings = function(axesInfo, paddings) {
  88414. _each(axesInfo, function(_, info) {
  88415. var range = getAxisRange(info),
  88416. inverted = info.inverted;
  88417. info.minValue -= paddings[inverted ? "end" : "start"] * range;
  88418. info.maxValue += paddings[inverted ? "start" : "end"] * range;
  88419. if (range > MIN_RANGE_FOR_ADJUST_BOUNDS) {
  88420. info.minValue = _math.min(info.minValue, _adjustValue(info.minValue));
  88421. info.maxValue = _max(info.maxValue, _adjustValue(info.maxValue))
  88422. }
  88423. })
  88424. };
  88425. var updateTickValuesIfSyncronizedValueUsed = function(axesInfo) {
  88426. var hasSyncronizedValue = false;
  88427. _each(axesInfo, function(_, info) {
  88428. hasSyncronizedValue = hasSyncronizedValue || _isDefined(info.synchronizedValue)
  88429. });
  88430. _each(axesInfo, function(_, info) {
  88431. var lastTickValue,
  88432. tickInterval = info.tickInterval,
  88433. tickValues = info.tickValues,
  88434. maxValue = info.maxValue,
  88435. minValue = info.minValue;
  88436. if (hasSyncronizedValue && tickInterval) {
  88437. while (tickValues[0] - tickInterval >= minValue)
  88438. tickValues.unshift(_adjustValue(tickValues[0] - tickInterval));
  88439. lastTickValue = tickValues[tickValues.length - 1];
  88440. while ((lastTickValue = lastTickValue + tickInterval) <= maxValue)
  88441. tickValues.push(utils.isExponential(lastTickValue) ? _adjustValue(lastTickValue) : _applyPrecisionByMinDelta(minValue, tickInterval, lastTickValue))
  88442. }
  88443. while (tickValues[0] < minValue)
  88444. tickValues.shift();
  88445. while (tickValues[tickValues.length - 1] > maxValue)
  88446. tickValues.pop()
  88447. })
  88448. };
  88449. var applyMinMaxValues = function(axesInfo) {
  88450. _each(axesInfo, function(_, info) {
  88451. var axis = info.axis,
  88452. range = axis.getTranslator().getBusinessRange();
  88453. if (range.min === range.minVisible)
  88454. range.min = info.minValue;
  88455. if (range.max === range.maxVisible)
  88456. range.max = info.maxValue;
  88457. range.minVisible = info.minValue;
  88458. range.maxVisible = info.maxValue;
  88459. if (_isDefined(info.stubData))
  88460. range.stubData = info.stubData;
  88461. if (range.min > range.minVisible)
  88462. range.min = range.minVisible;
  88463. if (range.max < range.maxVisible)
  88464. range.max = range.maxVisible;
  88465. range.isSynchronized = true;
  88466. axis.getTranslator().updateBusinessRange(range);
  88467. axis.setTicks({
  88468. majorTicks: info.tickValues,
  88469. minorTicks: info.minorValues
  88470. })
  88471. })
  88472. };
  88473. var correctAfterSynchronize = function(axesInfo) {
  88474. var invalidAxisInfo = [],
  88475. correctValue,
  88476. validAxisInfo;
  88477. _each(axesInfo, function(i, info) {
  88478. if (info.oldMaxValue - info.oldMinValue === 0)
  88479. invalidAxisInfo.push(info);
  88480. else if (!_isDefined(correctValue) && !_isDefined(info.synchronizedValue)) {
  88481. correctValue = _math.abs((info.maxValue - info.minValue) / (info.tickValues[_floor(info.tickValues.length / 2)] || info.maxValue));
  88482. validAxisInfo = info
  88483. }
  88484. });
  88485. if (!_isDefined(correctValue))
  88486. return;
  88487. _each(invalidAxisInfo, function(i, info) {
  88488. var firstTick = info.tickValues[0],
  88489. correctedTick = firstTick * correctValue,
  88490. tickValues = validAxisInfo.tickValues,
  88491. centralTick = tickValues[_floor(tickValues.length / 2)];
  88492. if (firstTick > 0) {
  88493. info.maxValue = correctedTick;
  88494. info.minValue = 0
  88495. }
  88496. else if (firstTick < 0) {
  88497. info.minValue = correctedTick;
  88498. info.maxValue = 0
  88499. }
  88500. else if (firstTick === 0) {
  88501. info.maxValue = validAxisInfo.maxValue - centralTick;
  88502. info.minValue = validAxisInfo.minValue - centralTick
  88503. }
  88504. })
  88505. };
  88506. DX.viz.charts.multiAxesSynchronizer = {synchronize: function(valueAxes) {
  88507. _each(getValueAxesPerPanes(valueAxes), function(_, axes) {
  88508. var axesInfo,
  88509. paddings;
  88510. if (axes.length > 1) {
  88511. axesInfo = populateAxesInfo(axes);
  88512. if (axesInfo.length === 0 || !getMainAxisInfo(axesInfo))
  88513. return;
  88514. updateTickValues(axesInfo);
  88515. correctMinMaxValues(axesInfo);
  88516. paddings = calculatePaddings(axesInfo);
  88517. correctMinMaxValuesByPaddings(axesInfo, paddings);
  88518. correctAfterSynchronize(axesInfo);
  88519. updateTickValuesIfSyncronizedValueUsed(axesInfo);
  88520. _each(axesInfo, function() {
  88521. convertAxisInfo(this, logConvertor)
  88522. });
  88523. applyMinMaxValues(axesInfo)
  88524. }
  88525. })
  88526. }}
  88527. })(jQuery, DevExpress);
  88528. /*! Module viz-charts, file tracker.js */
  88529. (function($, DX, math) {
  88530. var charts = DX.viz.charts,
  88531. eventsConsts = DX.viz.core.series.helpers.consts.events,
  88532. utils = DX.utils,
  88533. isDefined = utils.isDefined,
  88534. _floor = math.floor,
  88535. _each = $.each,
  88536. MULTIPLE_MODE = 'multiple',
  88537. ALL_ARGUMENTS_POINTS_MODE = 'allargumentpoints',
  88538. ALL_SERIES_POINTS_MODE = 'allseriespoints',
  88539. NONE_MODE = 'none',
  88540. POINTER_ACTION = "dxpointerdown dxpointermove",
  88541. POINT_SELECTION_CHANGED = "pointSelectionChanged",
  88542. LEGEND_CLICK = "legendClick",
  88543. SERIES_CLICK = "seriesClick",
  88544. POINT_CLICK = "pointClick",
  88545. RELEASE_POINT_SELECTED_STATE = "releasePointSelectedState",
  88546. SET_POINT_SELECTED_STATE = "setPointSelectedState",
  88547. DELAY = 100;
  88548. function processMode(mode) {
  88549. return (mode + "").toLowerCase()
  88550. }
  88551. function getNonVirtualAxis(axisArray) {
  88552. var axis;
  88553. _each(axisArray, function(_, a) {
  88554. if (!a._virtual) {
  88555. axis = a;
  88556. return false
  88557. }
  88558. });
  88559. return axis
  88560. }
  88561. function eventCanceled(event, target) {
  88562. return event.cancel || !target.getOptions()
  88563. }
  88564. var baseTrackerPrototype = {
  88565. ctor: function(options) {
  88566. var that = this,
  88567. data = {tracker: that};
  88568. if (processMode(options.pointSelectionMode) === MULTIPLE_MODE) {
  88569. that._setSelectedPoint = that._selectPointMultipleMode;
  88570. that._releaseSelectedPoint = that._releaseSelectedPointMultipleMode
  88571. }
  88572. else {
  88573. that._setSelectedPoint = that._selectPointSingleMode;
  88574. that._releaseSelectedPoint = that._releaseSelectedPointSingleMode
  88575. }
  88576. if (processMode(options.seriesSelectionMode) === MULTIPLE_MODE) {
  88577. that._releaseSelectedSeries = that._releaseSelectedSeriesMultipleMode;
  88578. that._setSelectedSeries = that._setSelectedSeriesMultipleMode
  88579. }
  88580. else {
  88581. that._releaseSelectedSeries = that._releaseSelectedSeriesSingleMode;
  88582. that._setSelectedSeries = that._setSelectedSeriesSingleMode
  88583. }
  88584. that._renderer = options.renderer;
  88585. that._tooltip = options.tooltip;
  88586. that._eventTrigger = options.eventTrigger;
  88587. options.seriesGroup.off().on(eventsConsts.selectSeries, data, that._selectSeries).on(eventsConsts.deselectSeries, data, that._deselectSeries).on(eventsConsts.selectPoint, data, that._selectPoint).on(eventsConsts.deselectPoint, data, that._deselectPoint).on(eventsConsts.showPointTooltip, data, that._showPointTooltip).on(eventsConsts.hidePointTooltip, data, that._hidePointTooltip);
  88588. that._renderer.root.off(POINTER_ACTION).off("dxclick dxhold").on(POINTER_ACTION, data, that._pointerHandler).on("dxclick", data, that._clickHandler).on("dxhold", {timeout: 300}, $.noop)
  88589. },
  88590. update: function(options) {
  88591. var that = this;
  88592. if (that._storedSeries !== options.series) {
  88593. that._storedSeries = options.series || [];
  88594. that._clean()
  88595. }
  88596. else {
  88597. that._hideTooltip(that.pointAtShownTooltip);
  88598. that._clearHover();
  88599. that.clearSelection()
  88600. }
  88601. that._legend = options.legend;
  88602. that.legendCallback = options.legendCallback;
  88603. that._prepare(that._renderer.root)
  88604. },
  88605. setCanvases: function(mainCanvas, paneCanvases) {
  88606. this._mainCanvas = mainCanvas;
  88607. this._canvases = paneCanvases
  88608. },
  88609. repairTooltip: function() {
  88610. var point = this.pointAtShownTooltip;
  88611. if (point && !point.isVisible())
  88612. this._hideTooltip(point, true);
  88613. else
  88614. this._showTooltip(point)
  88615. },
  88616. _prepare: function(root) {
  88617. root.off("dxmousewheel").on("dxmousewheel", {tracker: this}, function(e) {
  88618. e.data.tracker._pointerOut()
  88619. })
  88620. },
  88621. _selectPointMultipleMode: function(point) {
  88622. var that = this;
  88623. that._selectedPoint = that._selectedPoint || [];
  88624. if ($.inArray(point, that._selectedPoint) < 0) {
  88625. that._selectedPoint.push(point);
  88626. that._setPointState(point, SET_POINT_SELECTED_STATE, processMode(point.getOptions().selectionMode), POINT_SELECTION_CHANGED, that.legendCallback(point))
  88627. }
  88628. },
  88629. _releaseSelectedPointMultipleMode: function(point) {
  88630. var that = this,
  88631. points = that._selectedPoint || [],
  88632. pointIndex = $.inArray(point, points);
  88633. if (pointIndex >= 0) {
  88634. that._setPointState(point, RELEASE_POINT_SELECTED_STATE, processMode(point.getOptions().selectionMode), POINT_SELECTION_CHANGED, that.legendCallback(point));
  88635. points.splice(pointIndex, 1)
  88636. }
  88637. else if (!point)
  88638. _each(points, function(_, point) {
  88639. that._releaseSelectedPoint(point)
  88640. })
  88641. },
  88642. _selectPointSingleMode: function(point) {
  88643. var that = this;
  88644. if (that._selectedPoint !== point) {
  88645. that._releaseSelectedPoint();
  88646. that._selectedPoint = point;
  88647. that._setPointState(point, SET_POINT_SELECTED_STATE, processMode(point.getOptions().selectionMode), POINT_SELECTION_CHANGED, that.legendCallback(point))
  88648. }
  88649. },
  88650. _releaseSelectedPointSingleMode: function() {
  88651. var that = this,
  88652. point = that._selectedPoint;
  88653. if (point) {
  88654. that._setPointState(point, RELEASE_POINT_SELECTED_STATE, processMode(point.getOptions().selectionMode), POINT_SELECTION_CHANGED, that.legendCallback(point));
  88655. that._selectedPoint = null
  88656. }
  88657. },
  88658. _setPointState: function(point, action, mode, eventName, legendCallback) {
  88659. var that = this;
  88660. switch (mode) {
  88661. case ALL_ARGUMENTS_POINTS_MODE:
  88662. that._toAllArgumentPoints(point.argument, action, eventName);
  88663. break;
  88664. case ALL_SERIES_POINTS_MODE:
  88665. _each(point.series.getPoints(), function(_, point) {
  88666. point.series[action](point);
  88667. that._eventTrigger(eventName, {target: point})
  88668. });
  88669. break;
  88670. case NONE_MODE:
  88671. break;
  88672. default:
  88673. point.series[action](point, legendCallback);
  88674. that._eventTrigger(eventName, {target: point})
  88675. }
  88676. },
  88677. _toAllArgumentPoints: function(argument, func, eventName) {
  88678. var that = this;
  88679. _each(that._storedSeries, function(_, series) {
  88680. var neighborPoints = series.getPointsByArg(argument);
  88681. _each(neighborPoints || [], function(_, point) {
  88682. series[func](point);
  88683. eventName && that._eventTrigger(eventName, {target: point})
  88684. })
  88685. })
  88686. },
  88687. _setHoveredPoint: function(point, mode) {
  88688. var that = this;
  88689. var debug = DX.utils.debug;
  88690. debug.assert(point.series, 'series was not assigned to point or empty');
  88691. if (that.hoveredPoint === point || !point.series)
  88692. return;
  88693. that._releaseHoveredPoint();
  88694. if (point && point.getOptions() && mode !== NONE_MODE) {
  88695. that.hoveredPoint = point;
  88696. that._setPointState(point, 'setPointHoverState', mode || processMode(point.getOptions().hoverMode), "pointHoverChanged", that.legendCallback(point))
  88697. }
  88698. },
  88699. _releaseHoveredPoint: function() {
  88700. var that = this,
  88701. point = that.hoveredPoint,
  88702. mode;
  88703. if (!point || !point.getOptions())
  88704. return;
  88705. mode = processMode(point.getOptions().hoverMode);
  88706. if (mode === ALL_SERIES_POINTS_MODE)
  88707. _each(point.series.getPoints(), function(_, point) {
  88708. point.series.releasePointHoverState(point);
  88709. that._eventTrigger("pointHoverChanged", {target: point})
  88710. });
  88711. else if (mode === ALL_ARGUMENTS_POINTS_MODE)
  88712. that._toAllArgumentPoints(point.argument, 'releasePointHoverState', "pointHoverChanged");
  88713. else {
  88714. point.releaseHoverState(that.legendCallback(point));
  88715. that._eventTrigger("pointHoverChanged", {target: point})
  88716. }
  88717. if (that._tooltip.isEnabled())
  88718. that._hideTooltip(point);
  88719. that.hoveredPoint = null
  88720. },
  88721. _setSelectedSeriesMultipleMode: function(series, mode) {
  88722. var that = this;
  88723. that._selectedSeries = that._selectedSeries || [];
  88724. if ($.inArray(series, that._selectedSeries) < 0) {
  88725. that._selectedSeries.push(series);
  88726. series.setSelectedState(true, mode, that.legendCallback(series));
  88727. that._eventTrigger("seriesSelectionChanged", {target: series})
  88728. }
  88729. },
  88730. _setSelectedSeriesSingleMode: function(series, mode) {
  88731. var that = this;
  88732. if (series !== that._selectedSeries || series.lastSelectionMode !== mode) {
  88733. this._releaseSelectedSeries();
  88734. that._selectedSeries = series;
  88735. series.setSelectedState(true, mode, that.legendCallback(series));
  88736. that._eventTrigger("seriesSelectionChanged", {target: series})
  88737. }
  88738. },
  88739. _releaseSelectedSeriesMultipleMode: function(series) {
  88740. var that = this,
  88741. selectedSeries = that._selectedSeries || [],
  88742. seriesIndex = $.inArray(series, selectedSeries);
  88743. if (seriesIndex >= 0) {
  88744. series.setSelectedState(false, undefined, that.legendCallback(series));
  88745. that._eventTrigger("seriesSelectionChanged", {target: series});
  88746. selectedSeries.splice(seriesIndex, 1)
  88747. }
  88748. else if (!series)
  88749. _each(selectedSeries, function(_, series) {
  88750. that._releaseSelectedSeries(series)
  88751. })
  88752. },
  88753. _releaseSelectedSeriesSingleMode: function() {
  88754. var that = this,
  88755. series = that._selectedSeries;
  88756. if (series) {
  88757. series.setSelectedState(false, undefined, that.legendCallback(series));
  88758. that._eventTrigger("seriesSelectionChanged", {target: series});
  88759. that._selectedSeries = null
  88760. }
  88761. },
  88762. _setHoveredSeries: function(series, mode) {
  88763. var that = this;
  88764. if (mode !== NONE_MODE && that.hoveredSeries !== series || series.lastHoverMode !== mode) {
  88765. that._clearHover();
  88766. series.setHoverState(true, mode, that.legendCallback(series));
  88767. that._eventTrigger("seriesHoverChanged", {target: series})
  88768. }
  88769. that.hoveredSeries = series;
  88770. if (mode === NONE_MODE)
  88771. $(series).trigger('NoneMode')
  88772. },
  88773. _releaseHoveredSeries: function() {
  88774. var that = this;
  88775. if (that.hoveredSeries) {
  88776. that.hoveredSeries.setHoverState(false, undefined, that.legendCallback(that.hoveredSeries));
  88777. that._eventTrigger("seriesHoverChanged", {target: that.hoveredSeries});
  88778. that.hoveredSeries = null
  88779. }
  88780. },
  88781. _selectSeries: function(event, mode) {
  88782. event.data.tracker._setSelectedSeries(event.target, mode)
  88783. },
  88784. _deselectSeries: function(event, mode) {
  88785. event.data.tracker._releaseSelectedSeries(event.target, mode)
  88786. },
  88787. _selectPoint: function(event, point) {
  88788. event.data.tracker._setSelectedPoint(point)
  88789. },
  88790. _deselectPoint: function(event, point) {
  88791. event.data.tracker._releaseSelectedPoint(point)
  88792. },
  88793. clearSelection: function() {
  88794. this._releaseSelectedPoint();
  88795. this._releaseSelectedSeries()
  88796. },
  88797. _clean: function() {
  88798. var that = this;
  88799. that._selectedPoint = that._selectedSeries = that.hoveredPoint = that.hoveredSeries = null;
  88800. that._hideTooltip(that.pointAtShownTooltip)
  88801. },
  88802. _clearHover: function() {
  88803. this._releaseHoveredSeries();
  88804. this._releaseHoveredPoint()
  88805. },
  88806. _hideTooltip: function(point, silent) {
  88807. var that = this;
  88808. if (!that._tooltip || point && that.pointAtShownTooltip !== point)
  88809. return;
  88810. if (!silent && that.pointAtShownTooltip)
  88811. that.pointAtShownTooltip = null;
  88812. that._tooltip.hide()
  88813. },
  88814. _showTooltip: function(point) {
  88815. var that = this,
  88816. tooltipFormatObject,
  88817. eventData;
  88818. if (point && point.getOptions()) {
  88819. tooltipFormatObject = point.getTooltipFormatObject(that._tooltip);
  88820. if (!isDefined(tooltipFormatObject.valueText) && !tooltipFormatObject.points || !point.isVisible())
  88821. return;
  88822. if (!that.pointAtShownTooltip || that.pointAtShownTooltip !== point)
  88823. eventData = {target: point};
  88824. var coords = point.getTooltipParams(that._tooltip.getLocation()),
  88825. rootOffset = that._renderer.getRootOffset();
  88826. coords.x += rootOffset.left;
  88827. coords.y += rootOffset.top;
  88828. if (!that._tooltip.show(tooltipFormatObject, coords, eventData))
  88829. return;
  88830. that.pointAtShownTooltip = point
  88831. }
  88832. },
  88833. _showPointTooltip: function(event, point) {
  88834. var that = event.data.tracker,
  88835. pointWithTooltip = that.pointAtShownTooltip;
  88836. if (pointWithTooltip && pointWithTooltip !== point)
  88837. that._hideTooltip(pointWithTooltip);
  88838. that._showTooltip(point)
  88839. },
  88840. _hidePointTooltip: function(event, point) {
  88841. event.data.tracker._hideTooltip(point)
  88842. },
  88843. _enableOutHandler: function() {
  88844. if (this._outHandler)
  88845. return;
  88846. var that = this,
  88847. handler = function(e) {
  88848. var rootOffset = that._renderer.getRootOffset(),
  88849. x = _floor(e.pageX - rootOffset.left),
  88850. y = _floor(e.pageY - rootOffset.top);
  88851. if (!that._inCanvas(that._mainCanvas, x, y)) {
  88852. that._pointerOut();
  88853. that._disableOutHandler()
  88854. }
  88855. };
  88856. $(document).on(POINTER_ACTION, handler);
  88857. this._outHandler = handler
  88858. },
  88859. _disableOutHandler: function() {
  88860. this._outHandler && $(document).off(POINTER_ACTION, this._outHandler);
  88861. this._outHandler = null
  88862. },
  88863. _pointerOut: function() {
  88864. this._clearHover();
  88865. this._tooltip.isEnabled() && this._hideTooltip(this.pointAtShownTooltip)
  88866. },
  88867. _inCanvas: function(canvas, x, y) {
  88868. return x >= canvas.left && x <= canvas.right && y >= canvas.top && y <= canvas.bottom
  88869. },
  88870. dispose: function() {
  88871. var that = this;
  88872. that._disableOutHandler();
  88873. _each(that, function(k) {
  88874. that[k] = null
  88875. })
  88876. }
  88877. };
  88878. charts.ChartTracker = function(options) {
  88879. this.ctor(options)
  88880. };
  88881. $.extend(charts.ChartTracker.prototype, baseTrackerPrototype, {
  88882. ctor: function(options) {
  88883. var that = this;
  88884. baseTrackerPrototype.ctor.call(that, options)
  88885. },
  88886. _pointClick: function(point, event) {
  88887. var that = this,
  88888. eventTrigger = that._eventTrigger,
  88889. series = point.series;
  88890. eventTrigger(POINT_CLICK, {
  88891. target: point,
  88892. jQueryEvent: event
  88893. }, function() {
  88894. !eventCanceled(event, series) && eventTrigger(SERIES_CLICK, {
  88895. target: series,
  88896. jQueryEvent: event
  88897. })
  88898. })
  88899. },
  88900. __trackerDelay: DELAY,
  88901. _legendClick: function(series, event) {
  88902. var that = this,
  88903. evetArgs = {
  88904. target: series,
  88905. jQueryEvent: event
  88906. },
  88907. eventTrigger = that._eventTrigger;
  88908. eventTrigger(LEGEND_CLICK, evetArgs, function() {
  88909. !eventCanceled(event, series) && eventTrigger(SERIES_CLICK, evetArgs)
  88910. })
  88911. },
  88912. update: function(options) {
  88913. var that = this;
  88914. that._zoomingMode = (options.zoomingMode + '').toLowerCase();
  88915. that._scrollingMode = (options.scrollingMode + '').toLowerCase();
  88916. baseTrackerPrototype.update.call(this, options);
  88917. that._argumentAxis = getNonVirtualAxis(options.argumentAxis || []);
  88918. that._axisHoverEnabled = that._argumentAxis && processMode(that._argumentAxis.getOptions().hoverMode) === ALL_ARGUMENTS_POINTS_MODE;
  88919. that._chart = options.chart;
  88920. that._rotated = options.rotated;
  88921. that._crosshair = options.crosshair
  88922. },
  88923. _getAxisArgument: function(event) {
  88924. var $target = $(event.target);
  88925. return event.target.tagName === "tspan" ? $target.parent().data('argument') : $target.data('argument')
  88926. },
  88927. _getCanvas: function(x, y) {
  88928. var that = this,
  88929. canvases = that._canvases || [];
  88930. for (var i = 0; i < canvases.length; i++) {
  88931. var c = canvases[i];
  88932. if (that._inCanvas(c, x, y))
  88933. return c
  88934. }
  88935. return null
  88936. },
  88937. _focusOnCanvas: function(canvas) {
  88938. if (!canvas && this._stickedSeries)
  88939. this._pointerOut()
  88940. },
  88941. _resetHoveredArgument: function() {
  88942. if (isDefined(this.hoveredArgument)) {
  88943. this._toAllArgumentPoints(this.hoveredArgument, 'releasePointHoverState');
  88944. this.hoveredArgument = null
  88945. }
  88946. },
  88947. _hideCrosshair: function() {
  88948. this._crosshair && this._crosshair.hide()
  88949. },
  88950. _moveCrosshair: function(point, x, y) {
  88951. if (point && this._crosshair && point.isVisible()) {
  88952. var coords = point.getCrosshairCoords(x, y),
  88953. r = point.getPointRadius();
  88954. this._crosshair.shift(coords.x, coords.y, r)
  88955. }
  88956. },
  88957. _prepare: function(root) {
  88958. var that = this,
  88959. touchScrollingEnabled = that._scrollingMode === 'all' || that._scrollingMode === 'touch',
  88960. touchZoomingEnabled = that._zoomingMode === 'all' || that._zoomingMode === 'touch',
  88961. cssValue = (!touchScrollingEnabled ? "pan-x pan-y " : '') + (!touchZoomingEnabled ? "pinch-zoom" : '') || "none",
  88962. rootStyles = {
  88963. 'touch-action': cssValue,
  88964. '-ms-touch-action': cssValue
  88965. },
  88966. wheelzoomingEnabled = that._zoomingMode === "all" || that._zoomingMode === "mouse";
  88967. root.off("dxmousewheel dxc-scroll-start dxc-scroll-move");
  88968. baseTrackerPrototype._prepare.call(that, root);
  88969. if (!that._gestureEndHandler) {
  88970. that._gestureEndHandler = function() {
  88971. that._gestureEnd && that._gestureEnd()
  88972. };
  88973. $(document).on("dxpointerup", that._gestureEndHandler)
  88974. }
  88975. wheelzoomingEnabled && root.on("dxmousewheel", function(e) {
  88976. var rootOffset = that._renderer.getRootOffset(),
  88977. x = that._rotated ? e.pageY - rootOffset.top : e.pageX - rootOffset.left,
  88978. scale = that._argumentAxis.getTranslator().getMinScale(e.delta > 0),
  88979. translate = x - x * scale,
  88980. zoom = that._argumentAxis.getTranslator().zoom(-translate, scale);
  88981. that._pointerOut();
  88982. that._chart.zoomArgument(zoom.min, zoom.max, true);
  88983. e.preventDefault();
  88984. e.stopPropagation()
  88985. });
  88986. root.on("dxc-scroll-start", function(e) {
  88987. that._gestureStart(that._getGestureParams(e, {
  88988. left: 0,
  88989. top: 0
  88990. }))
  88991. }).on("dxc-scroll-move", function(e) {
  88992. that._gestureChange(that._getGestureParams(e, {
  88993. left: 0,
  88994. top: 0
  88995. })) && e.preventDefault()
  88996. });
  88997. root.css(rootStyles)
  88998. },
  88999. _getGestureParams: function(e, offset) {
  89000. var that = this,
  89001. x1,
  89002. x2,
  89003. touches = e.pointers.length,
  89004. left,
  89005. right,
  89006. eventCoordField = that._rotated ? "pageY" : "pageX";
  89007. offset = that._rotated ? offset.top : offset.left;
  89008. if (touches === 2)
  89009. x1 = e.pointers[0][eventCoordField] - offset,
  89010. x2 = e.pointers[1][eventCoordField] - offset;
  89011. else if (touches === 1)
  89012. x1 = x2 = e.pointers[0][eventCoordField] - offset;
  89013. left = math.min(x1, x2);
  89014. right = math.max(x1, x2);
  89015. return {
  89016. center: left + (right - left) / 2,
  89017. distance: right - left,
  89018. touches: touches,
  89019. scale: 1,
  89020. pointerType: e.pointerType
  89021. }
  89022. },
  89023. _gestureStart: function(gestureParams) {
  89024. var that = this;
  89025. that._startGesture = that._startGesture || gestureParams;
  89026. if (that._startGesture.touches !== gestureParams.touches)
  89027. that._startGesture = gestureParams
  89028. },
  89029. _gestureChange: function(gestureParams) {
  89030. var that = this,
  89031. startGesture = that._startGesture,
  89032. gestureChanged = false,
  89033. scrollingEnabled = that._scrollingMode === 'all' || that._scrollingMode !== 'none' && that._scrollingMode === gestureParams.pointerType,
  89034. zoommingEnabled = that._zoomingMode === 'all' || that._zoomingMode === 'touch';
  89035. if (!startGesture)
  89036. return gestureChanged;
  89037. if (startGesture.touches === 1 && math.abs(startGesture.center - gestureParams.center) < 3) {
  89038. that._gestureStart(gestureParams);
  89039. return gestureChanged
  89040. }
  89041. if (startGesture.touches === 2 && zoommingEnabled) {
  89042. gestureChanged = true;
  89043. startGesture.scale = gestureParams.distance / startGesture.distance;
  89044. startGesture.scroll = gestureParams.center - startGesture.center + (startGesture.center - startGesture.center * startGesture.scale)
  89045. }
  89046. else if (startGesture.touches === 1 && scrollingEnabled) {
  89047. gestureChanged = true;
  89048. startGesture.scroll = gestureParams.center - startGesture.center
  89049. }
  89050. if (gestureChanged) {
  89051. startGesture.changed = gestureChanged;
  89052. that._chart._transformArgument(startGesture.scroll, startGesture.scale)
  89053. }
  89054. return gestureChanged
  89055. },
  89056. _gestureEnd: function() {
  89057. var that = this,
  89058. startGesture = that._startGesture,
  89059. zoom,
  89060. renderer = that._renderer;
  89061. that._startGesture = null;
  89062. function complete() {
  89063. that._chart.zoomArgument(zoom.min, zoom.max, true)
  89064. }
  89065. if (startGesture && startGesture.changed) {
  89066. zoom = that._argumentAxis._translator.zoom(-startGesture.scroll, startGesture.scale);
  89067. if (renderer.animationEnabled() && (-startGesture.scroll !== zoom.translate || startGesture.scale !== zoom.scale)) {
  89068. var translateDelta = -(startGesture.scroll + zoom.translate),
  89069. scaleDelta = startGesture.scale - zoom.scale;
  89070. renderer.root.animate({_: 0}, {
  89071. step: function(pos) {
  89072. var translateValue = -startGesture.scroll - translateDelta * pos;
  89073. var scaleValue = startGesture.scale - scaleDelta * pos;
  89074. that._chart._transformArgument(-translateValue, scaleValue)
  89075. },
  89076. complete: complete,
  89077. duration: 250
  89078. })
  89079. }
  89080. else
  89081. complete()
  89082. }
  89083. },
  89084. _clean: function() {
  89085. var that = this;
  89086. baseTrackerPrototype._clean.call(that);
  89087. that._resetTimer();
  89088. that._stickedSeries = null
  89089. },
  89090. _getSeriesForShared: function(x, y) {
  89091. var that = this,
  89092. points = [],
  89093. point = null,
  89094. distance = Infinity;
  89095. if (that._tooltip.isShared() && !that.hoveredSeries) {
  89096. _each(that._storedSeries, function(_, series) {
  89097. var point = series.getNeighborPoint(x, y);
  89098. point && points.push(point)
  89099. });
  89100. _each(points, function(_, p) {
  89101. var coords = p.getCrosshairCoords(x, y),
  89102. d = math.sqrt((x - coords.x) * (x - coords.x) + (y - coords.y) * (y - coords.y));
  89103. if (d < distance) {
  89104. point = p;
  89105. distance = d
  89106. }
  89107. })
  89108. }
  89109. return point && point.series
  89110. },
  89111. _setTimeout: function(callback, keeper) {
  89112. var that = this;
  89113. if (that._timeoutKeeper !== keeper) {
  89114. that._resetTimer();
  89115. that._hoverTimeout = setTimeout(function() {
  89116. callback();
  89117. that._timeoutKeeper = null
  89118. }, DELAY);
  89119. that._timeoutKeeper = keeper
  89120. }
  89121. },
  89122. _resetTimer: function() {
  89123. clearTimeout(this._hoverTimeout);
  89124. this._timeoutKeeper = this._hoverTimeout = null
  89125. },
  89126. _pointerHandler: function(e) {
  89127. var that = e.data.tracker,
  89128. rootOffset = that._renderer.getRootOffset(),
  89129. x = _floor(e.pageX - rootOffset.left),
  89130. y = _floor(e.pageY - rootOffset.top),
  89131. canvas = that._getCanvas(x, y),
  89132. series = $(e.target).data("series"),
  89133. point = $(e.target).data("point") || series && series.getPointByCoord(x, y);
  89134. that._enableOutHandler();
  89135. that._x = x;
  89136. that._y = y;
  89137. if (e.type === "dxpointerdown")
  89138. canvas && that._gestureStart(that._getGestureParams(e, rootOffset));
  89139. else if (that._startGesture && canvas)
  89140. if (that._gestureChange(that._getGestureParams(e, rootOffset))) {
  89141. that._pointerOut();
  89142. e.preventDefault();
  89143. return
  89144. }
  89145. if (that._legend.coordsIn(x, y)) {
  89146. var item = that._legend.getItemByCoord(x, y);
  89147. if (item) {
  89148. series = that._storedSeries[item.id];
  89149. that._setHoveredSeries(series, that._legend._options.hoverMode);
  89150. that._stickedSeries = series
  89151. }
  89152. else
  89153. that._clearHover();
  89154. that._hideCrosshair();
  89155. return
  89156. }
  89157. if (that._axisHoverEnabled && that._argumentAxis.coordsIn(x, y)) {
  89158. var argument = that._getAxisArgument(e),
  89159. argumentDefined = isDefined(argument);
  89160. if (argumentDefined && that.hoveredArgument !== argument) {
  89161. that._clearHover();
  89162. that._resetHoveredArgument();
  89163. that._toAllArgumentPoints(argument, "setPointHoverState");
  89164. that.hoveredArgument = argument
  89165. }
  89166. else if (!argumentDefined)
  89167. that._resetHoveredArgument();
  89168. return
  89169. }
  89170. that._resetHoveredArgument();
  89171. that._focusOnCanvas(canvas);
  89172. if (!canvas && !point)
  89173. return;
  89174. if (!series && !point)
  89175. that._stickedSeries = that._stickedSeries || that._getSeriesForShared(x, y);
  89176. if (series && !point) {
  89177. point = series.getNeighborPoint(x, y);
  89178. if (series !== that.hoveredSeries) {
  89179. that._setTimeout(function() {
  89180. that._setHoveredSeries(series, series.getOptions().hoverMode);
  89181. that._stickedSeries = series;
  89182. that._pointerComplete(point)
  89183. }, series);
  89184. return
  89185. }
  89186. }
  89187. else if (point) {
  89188. if (that.hoveredSeries)
  89189. that._setTimeout(function() {
  89190. that._pointerOnPoint(point)
  89191. }, point);
  89192. else
  89193. that._pointerOnPoint(point);
  89194. return
  89195. }
  89196. else if (that._stickedSeries) {
  89197. series = that._stickedSeries;
  89198. point = series.getNeighborPoint(x, y);
  89199. that.hoveredSeries && that._releaseHoveredSeries();
  89200. point && that._setHoveredPoint(point)
  89201. }
  89202. that._pointerComplete(point)
  89203. },
  89204. _pointerOnPoint: function(point) {
  89205. var that = this;
  89206. that._stickedSeries = point.series;
  89207. that._setHoveredPoint(point);
  89208. that.hoveredSeries && that._releaseHoveredSeries();
  89209. that._pointerComplete(point)
  89210. },
  89211. _pointerComplete: function(point) {
  89212. var that = this;
  89213. that.hoveredSeries && that.hoveredSeries.updateHover(that._x, that._y);
  89214. that._resetTimer();
  89215. that._moveCrosshair(point, that._x, that._y);
  89216. that.pointAtShownTooltip !== point && that._tooltip.isEnabled() && that._showTooltip(point)
  89217. },
  89218. _pointerOut: function() {
  89219. var that = this;
  89220. that._stickedSeries = null;
  89221. that._hideCrosshair();
  89222. that._resetHoveredArgument();
  89223. that._resetTimer();
  89224. baseTrackerPrototype._pointerOut.call(that)
  89225. },
  89226. _clickHandler: function(e) {
  89227. var that = e.data.tracker,
  89228. rootOffset = that._renderer.getRootOffset(),
  89229. x = _floor(e.pageX - rootOffset.left),
  89230. y = _floor(e.pageY - rootOffset.top),
  89231. point = $(e.target).data("point"),
  89232. series = that._stickedSeries || $(e.target).data("series") || point && point.series,
  89233. axis = that._argumentAxis;
  89234. if (that._legend.coordsIn(x, y)) {
  89235. var item = that._legend.getItemByCoord(x, y);
  89236. if (item) {
  89237. series = that._storedSeries[item.id];
  89238. that._legendClick(series, e)
  89239. }
  89240. return
  89241. }
  89242. if (axis && axis.coordsIn(x, y)) {
  89243. var argument = that._getAxisArgument(e);
  89244. if (isDefined(argument)) {
  89245. that._eventTrigger("argumentAxisClick", {
  89246. argument: argument,
  89247. jQueryEvent: e
  89248. });
  89249. return
  89250. }
  89251. }
  89252. if (series) {
  89253. point = point || series.getPointByCoord(x, y);
  89254. if (point)
  89255. that._pointClick(point, e);
  89256. else
  89257. $(e.target).data("series") && that._eventTrigger(SERIES_CLICK, {
  89258. target: series,
  89259. jQueryEvent: e
  89260. })
  89261. }
  89262. },
  89263. dispose: function() {
  89264. this._gestureEndHandler && $(document).off("dxpointerup", this._gestureEndHandler);
  89265. this._resetTimer();
  89266. baseTrackerPrototype.dispose.call(this)
  89267. }
  89268. });
  89269. charts.PieTracker = function(options) {
  89270. this.ctor(options)
  89271. };
  89272. $.extend(charts.PieTracker.prototype, baseTrackerPrototype, {
  89273. _legendClick: function(point, event) {
  89274. var that = this,
  89275. eventArg = {
  89276. target: point,
  89277. jQueryEvent: event
  89278. },
  89279. eventTrigger = that._eventTrigger;
  89280. eventTrigger(LEGEND_CLICK, eventArg, function() {
  89281. !eventCanceled(event, point) && eventTrigger(POINT_CLICK, eventArg)
  89282. })
  89283. },
  89284. _pointerHandler: function(e) {
  89285. var that = e.data.tracker,
  89286. rootOffset = that._renderer.getRootOffset(),
  89287. x = _floor(e.pageX - rootOffset.left),
  89288. y = _floor(e.pageY - rootOffset.top),
  89289. series = that._storedSeries[0],
  89290. point = $(e.target).data("point") || series && series.getPointByCoord(x, y),
  89291. item,
  89292. mode;
  89293. that._enableOutHandler();
  89294. if (that._legend.coordsIn(x, y)) {
  89295. item = that._legend.getItemByCoord(x, y);
  89296. if (item) {
  89297. point = series.getPoints()[item.id];
  89298. mode = that._legend._options.hoverMode
  89299. }
  89300. }
  89301. if (point && point !== that.hoveredPoint) {
  89302. that._tooltip.isEnabled() && that._showTooltip(point);
  89303. that._setHoveredPoint(point, mode)
  89304. }
  89305. else if (!point)
  89306. that._pointerOut()
  89307. },
  89308. _clickHandler: function(e) {
  89309. var that = e.data.tracker,
  89310. rootOffset = that._renderer.getRootOffset(),
  89311. x = _floor(e.pageX - rootOffset.left),
  89312. y = _floor(e.pageY - rootOffset.top),
  89313. storedSeries = that._storedSeries[0],
  89314. point;
  89315. if (that._legend.coordsIn(x, y)) {
  89316. var item = that._legend.getItemByCoord(x, y);
  89317. if (item) {
  89318. point = storedSeries.getPoints()[item.id];
  89319. that._legendClick(point, e)
  89320. }
  89321. }
  89322. else {
  89323. point = $(e.target).data("point") || storedSeries && storedSeries.getPointByCoord(x, y);
  89324. point && that._eventTrigger(POINT_CLICK, {
  89325. target: point,
  89326. jQueryEvent: e
  89327. })
  89328. }
  89329. }
  89330. })
  89331. })(jQuery, DevExpress, Math);
  89332. /*! Module viz-charts, file crosshair.js */
  89333. (function($, DX, undefined) {
  89334. var _math = Math,
  89335. mathAbs = _math.abs,
  89336. mathMin = _math.min,
  89337. mathMax = _math.max,
  89338. _round = _math.round,
  89339. HORIZONTAL = "horizontal",
  89340. VERTICAL = "vertical",
  89341. LABEL_BACKGROUND_PADDING_X = 8,
  89342. LABEL_BACKGROUND_PADDING_Y = 4,
  89343. CENTER = "center",
  89344. RIGHT = "right",
  89345. LEFT = "left",
  89346. TOP = "top",
  89347. BOTTOM = "bottom",
  89348. _isDefined = DX.utils.isDefined;
  89349. function Crosshair() {
  89350. this.ctor.apply(this, arguments)
  89351. }
  89352. DX.viz.charts.Crosshair = Crosshair;
  89353. Crosshair.prototype = {
  89354. ctor: function(renderer, options, params, group) {
  89355. var that = this;
  89356. that._renderer = renderer;
  89357. that._crosshairGroup = group;
  89358. that._options = {};
  89359. that._init(options, params)
  89360. },
  89361. update: function(options, params) {
  89362. this._init(options, params)
  89363. },
  89364. dispose: function() {
  89365. var that = this;
  89366. that._renderer = null;
  89367. that._crosshairGroup = null;
  89368. that._options = null;
  89369. that._axes = null;
  89370. that._canvas = null;
  89371. that._horizontalGroup = null;
  89372. that._verticalGroup = null;
  89373. that._horizontal = null;
  89374. that._vertical = null;
  89375. that._circle = null;
  89376. that._panes = null
  89377. },
  89378. _init: function(options, params) {
  89379. var that = this,
  89380. canvas = params.canvas;
  89381. that._canvas = {
  89382. top: canvas.top,
  89383. bottom: canvas.height - canvas.bottom,
  89384. left: canvas.left,
  89385. right: canvas.width - canvas.right,
  89386. width: canvas.width,
  89387. height: canvas.height
  89388. };
  89389. that._axes = params.axes;
  89390. that._panes = params.panes;
  89391. that._prepareOptions(options, HORIZONTAL);
  89392. that._prepareOptions(options, VERTICAL)
  89393. },
  89394. _prepareOptions: function(options, direction) {
  89395. this._options[direction] = {
  89396. visible: options[direction + "Line"].visible,
  89397. line: {
  89398. stroke: options[direction + "Line"].color || options.color,
  89399. "stroke-width": options[direction + "Line"].width || options.width,
  89400. dashStyle: options[direction + "Line"].dashStyle || options.dashStyle,
  89401. opacity: options[direction + "Line"].opacity || options.opacity,
  89402. "stroke-linecap": "butt"
  89403. },
  89404. label: $.extend(true, {}, options.label, options[direction + "Line"].label)
  89405. }
  89406. },
  89407. _createLines: function(options, sharpParam, group) {
  89408. var lines = [],
  89409. canvas = this._canvas,
  89410. points = [canvas.left, canvas.top, canvas.left, canvas.top];
  89411. for (var i = 0; i < 2; i++)
  89412. lines.push(this._renderer.path(points, "line").attr(options).sharp(sharpParam).append(group));
  89413. return lines
  89414. },
  89415. render: function() {
  89416. var that = this,
  89417. renderer = that._renderer,
  89418. options = that._options,
  89419. verticalOptions = options.vertical,
  89420. horizontalOptions = options.horizontal,
  89421. extraOptions = horizontalOptions.visible ? horizontalOptions.line : verticalOptions.line,
  89422. circleOptions = {
  89423. stroke: extraOptions.stroke,
  89424. "stroke-width": extraOptions["stroke-width"],
  89425. dashStyle: extraOptions.dashStyle,
  89426. opacity: extraOptions.opacity
  89427. },
  89428. canvas = that._canvas;
  89429. that._horizontal = {};
  89430. that._vertical = {};
  89431. that._horizontalGroup = renderer.g().append(that._crosshairGroup);
  89432. that._verticalGroup = renderer.g().append(that._crosshairGroup);
  89433. if (verticalOptions.visible) {
  89434. that._vertical.lines = that._createLines(verticalOptions.line, "h", that._verticalGroup);
  89435. that._vertical.labels = that._createLabels(that._axes[0], verticalOptions, false, that._verticalGroup)
  89436. }
  89437. if (horizontalOptions.visible) {
  89438. that._horizontal.lines = that._createLines(horizontalOptions.line, "v", that._horizontalGroup);
  89439. that._horizontal.labels = that._createLabels(that._axes[1], horizontalOptions, true, that._horizontalGroup)
  89440. }
  89441. that._circle = renderer.circle(canvas.left, canvas.top, 0).attr(circleOptions).append(that._crosshairGroup)
  89442. },
  89443. _createLabels: function(axes, options, isHorizontal, group) {
  89444. var that = this,
  89445. canvas = that._canvas,
  89446. renderer = that._renderer,
  89447. x,
  89448. y,
  89449. text,
  89450. labels = [],
  89451. background,
  89452. curentLabelPos,
  89453. bbox;
  89454. if (!options.label || !options.label.visible)
  89455. return;
  89456. $.each(axes, function(_, axis) {
  89457. var axisOptions = axis.getOptions(),
  89458. position = axisOptions.position;
  89459. if (axis._virtual || axisOptions.stubData)
  89460. return;
  89461. curentLabelPos = axis.getCurrentLabelPos();
  89462. if (isHorizontal) {
  89463. y = canvas.top;
  89464. x = curentLabelPos
  89465. }
  89466. else {
  89467. x = canvas.left;
  89468. y = curentLabelPos
  89469. }
  89470. text = renderer.text("0", x, y).css(DX.viz.core.utils.patchFontOptions(options.label.font)).attr({align: position === TOP || position === BOTTOM ? CENTER : position === RIGHT ? LEFT : RIGHT}).append(group);
  89471. bbox = text.getBBox();
  89472. text.attr({y: isHorizontal ? 2 * y - bbox.y - bbox.height / 2 : position === BOTTOM ? 2 * y - bbox.y : 2 * y - (bbox.y + bbox.height)});
  89473. background = renderer.rect(0, 0, 0, 0).attr({fill: options.label.backgroundColor || options.line.stroke}).append(group).toBackground();
  89474. labels.push({
  89475. text: text,
  89476. background: background,
  89477. axis: axis,
  89478. pos: {
  89479. coord: curentLabelPos,
  89480. side: position
  89481. }
  89482. })
  89483. });
  89484. return labels
  89485. },
  89486. _updateText: function(coord, labels) {
  89487. var that = this,
  89488. bbox,
  89489. text,
  89490. textElement,
  89491. backgroundElement;
  89492. if (!labels)
  89493. return;
  89494. $.each(labels, function(i, label) {
  89495. textElement = label.text;
  89496. backgroundElement = label.background;
  89497. if (!textElement)
  89498. return;
  89499. text = label.axis.getUntranslatedValue(coord);
  89500. if (_isDefined(text)) {
  89501. textElement.attr({text: text});
  89502. bbox = textElement.getBBox();
  89503. that._updateLinesCanvas(label.pos.side, label.pos.coord);
  89504. backgroundElement.attr({
  89505. x: bbox.x - LABEL_BACKGROUND_PADDING_X,
  89506. y: bbox.y - LABEL_BACKGROUND_PADDING_Y,
  89507. width: bbox.width + LABEL_BACKGROUND_PADDING_X * 2,
  89508. height: bbox.height + LABEL_BACKGROUND_PADDING_Y * 2
  89509. })
  89510. }
  89511. else {
  89512. textElement.attr({text: ""});
  89513. backgroundElement.attr({
  89514. x: 0,
  89515. y: 0,
  89516. width: 0,
  89517. height: 0
  89518. })
  89519. }
  89520. })
  89521. },
  89522. show: function() {
  89523. this._crosshairGroup.attr({visibility: "visible"})
  89524. },
  89525. hide: function() {
  89526. this._crosshairGroup.attr({visibility: "hidden"})
  89527. },
  89528. _updateLinesCanvas: function(position, labelPosition) {
  89529. var coords = this._linesCanvas,
  89530. canvas = this._canvas;
  89531. coords[position] = coords[position] !== canvas[position] && mathAbs(coords[position] - canvas[position]) < mathAbs(labelPosition - canvas[position]) ? coords[position] : labelPosition
  89532. },
  89533. _updateLines: function(lines, x, y, r, isHorizontal) {
  89534. var coords = this._linesCanvas,
  89535. canvas = this._canvas,
  89536. points = isHorizontal ? [[mathMin(x - r, coords.left), canvas.top, x - r, canvas.top], [x + r, canvas.top, mathMax(coords.right, x + r), canvas.top]] : [[canvas.left, mathMin(coords.top, y - r), canvas.left, y - r], [canvas.left, y + r, canvas.left, mathMax(coords.bottom, y + r)]];
  89537. for (var i = 0; i < 2; i++)
  89538. lines[i].attr({points: points[i]})
  89539. },
  89540. _resetLinesCanvas: function() {
  89541. var canvas = this._canvas;
  89542. this._linesCanvas = {
  89543. left: canvas.left,
  89544. right: canvas.right,
  89545. top: canvas.top,
  89546. bottom: canvas.bottom
  89547. }
  89548. },
  89549. _getClipRectForPane: function(x, y) {
  89550. var panes = this._panes,
  89551. i,
  89552. coords;
  89553. for (i = 0; i < panes.length; i++) {
  89554. coords = panes[i].coords;
  89555. if (coords.left <= x && coords.right >= x && coords.top <= y && coords.bottom >= y)
  89556. return panes[i].clipRect
  89557. }
  89558. return {id: null}
  89559. },
  89560. shift: function(x, y, r) {
  89561. var that = this,
  89562. horizontal = that._horizontal,
  89563. vertical = that._vertical,
  89564. clipRect,
  89565. rad = !r ? 0 : r + 3,
  89566. canvas = that._canvas;
  89567. x = _round(x);
  89568. y = _round(y);
  89569. if (x >= canvas.left && x <= canvas.right && y >= canvas.top && y <= canvas.bottom) {
  89570. that.show();
  89571. that._resetLinesCanvas();
  89572. clipRect = that._getClipRectForPane(x, y);
  89573. that._circle.attr({
  89574. cx: x,
  89575. cy: y,
  89576. r: rad,
  89577. clipId: clipRect.id
  89578. });
  89579. if (horizontal.lines) {
  89580. that._updateText(y, horizontal.labels);
  89581. that._updateLines(horizontal.lines, x, y, rad, true);
  89582. that._horizontalGroup.attr({translateY: y - canvas.top})
  89583. }
  89584. if (vertical.lines) {
  89585. that._updateText(x, vertical.labels);
  89586. that._updateLines(vertical.lines, x, y, rad, false);
  89587. that._verticalGroup.attr({translateX: x - canvas.left})
  89588. }
  89589. }
  89590. else
  89591. that.hide()
  89592. }
  89593. }
  89594. })(jQuery, DevExpress);
  89595. DevExpress.MOD_VIZ_CHARTS = true
  89596. }
  89597. if (!DevExpress.MOD_VIZ_GAUGES) {
  89598. if (!DevExpress.MOD_VIZ_CORE)
  89599. throw Error('Required module is not referenced: viz-core');
  89600. /*! Module viz-gauges, file namespaces.js */
  89601. (function(DX) {
  89602. DX.viz.gauges = {__internals: {
  89603. circularNeedles: {},
  89604. circularMarkers: {},
  89605. linearNeedles: {},
  89606. linearMarkers: {}
  89607. }};
  89608. DX.viz.gauges.__tests = {}
  89609. })(DevExpress);
  89610. /*! Module viz-gauges, file factory.js */
  89611. (function(DX, $, undefined) {
  89612. var internals = DX.viz.gauges.__internals,
  89613. circularNeedles = internals.circularNeedles,
  89614. circularMarkers = internals.circularMarkers,
  89615. linearNeedles = internals.linearNeedles,
  89616. linearMarkers = internals.linearMarkers,
  89617. _String = String;
  89618. DX.viz.gauges.__factory = {
  89619. createCircularIndicator: function(parameters, type, _strict) {
  89620. var indicatorType;
  89621. switch (_String(type).toLowerCase()) {
  89622. case'rectangleneedle':
  89623. indicatorType = circularNeedles.RectangleNeedle;
  89624. break;
  89625. case'triangleneedle':
  89626. indicatorType = circularNeedles.TriangleNeedle;
  89627. break;
  89628. case'twocolorneedle':
  89629. indicatorType = circularNeedles.TwoColorRectangleNeedle;
  89630. break;
  89631. case'rangebar':
  89632. indicatorType = internals.CircularRangeBar;
  89633. break;
  89634. case'trianglemarker':
  89635. indicatorType = circularMarkers.TriangleMarker;
  89636. break;
  89637. case'textcloud':
  89638. indicatorType = circularMarkers.TextCloudMarker;
  89639. break;
  89640. default:
  89641. indicatorType = _strict ? null : circularNeedles.RectangleNeedle;
  89642. break
  89643. }
  89644. return indicatorType ? new indicatorType(parameters) : null
  89645. },
  89646. createLinearIndicator: function(parameters, type, _strict) {
  89647. var indicatorType = internals.LinearRangeBar;
  89648. switch (_String(type).toLowerCase()) {
  89649. case'rectangle':
  89650. indicatorType = linearNeedles.RectangleNeedle;
  89651. break;
  89652. case'rhombus':
  89653. indicatorType = linearNeedles.RhombusNeedle;
  89654. break;
  89655. case'circle':
  89656. indicatorType = linearNeedles.CircleNeedle;
  89657. break;
  89658. case'rangebar':
  89659. indicatorType = internals.LinearRangeBar;
  89660. break;
  89661. case'trianglemarker':
  89662. indicatorType = linearMarkers.TriangleMarker;
  89663. break;
  89664. case'textcloud':
  89665. indicatorType = linearMarkers.TextCloudMarker;
  89666. break;
  89667. default:
  89668. indicatorType = _strict ? null : internals.LinearRangeBar;
  89669. break
  89670. }
  89671. return indicatorType ? new indicatorType(parameters) : null
  89672. },
  89673. createCircularScale: function(parameters) {
  89674. return new internals.CircularScale(parameters)
  89675. },
  89676. createLinearScale: function(parameters) {
  89677. return new internals.LinearScale(parameters)
  89678. },
  89679. createCircularRangeContainer: function(parameters) {
  89680. return new internals.CircularRangeContainer(parameters)
  89681. },
  89682. createLinearRangeContainer: function(parameters) {
  89683. return new internals.LinearRangeContainer(parameters)
  89684. },
  89685. createTitle: function(parameters) {
  89686. return new internals.Title(parameters)
  89687. },
  89688. createIndicator: function() {
  89689. return internals.Indicator && new internals.Indicator || null
  89690. },
  89691. createLayoutManager: function() {
  89692. return new internals.LayoutManager
  89693. },
  89694. createThemeManager: function(options) {
  89695. return new internals.ThemeManager(options)
  89696. },
  89697. createTracker: function(parameters) {
  89698. return new internals.Tracker(parameters)
  89699. }
  89700. };
  89701. var _isFunction = DX.utils.isFunction,
  89702. _extend = $.extend;
  89703. var _formatHelper = DX.formatHelper;
  89704. internals.formatValue = function(value, options, extra) {
  89705. options = options || {};
  89706. var text = _formatHelper.format(value, options.format, options.precision),
  89707. context;
  89708. if (_isFunction(options.customizeText)) {
  89709. context = _extend({
  89710. value: value,
  89711. valueText: text
  89712. }, extra);
  89713. return _String(options.customizeText.call(context, context))
  89714. }
  89715. return text
  89716. };
  89717. internals.getSampleText = function(translator, options) {
  89718. var text1 = internals.formatValue(translator.getDomainStart(), options),
  89719. text2 = internals.formatValue(translator.getDomainEnd(), options);
  89720. return text1.length >= text2.length ? text1 : text2
  89721. }
  89722. })(DevExpress, jQuery);
  89723. /*! Module viz-gauges, file baseIndicator.js */
  89724. (function(DX, $, undefined) {
  89725. var _isFinite = isFinite,
  89726. _Number = Number;
  89727. DX.viz.gauges.__internals.BaseElement = DX.Class.inherit({
  89728. ctor: function(parameters) {
  89729. var that = this;
  89730. $.each(parameters, function(name, value) {
  89731. that["_" + name] = value
  89732. });
  89733. that._init()
  89734. },
  89735. dispose: function() {
  89736. var that = this;
  89737. $.each(that, function(name) {
  89738. that[name] = null
  89739. });
  89740. return that
  89741. },
  89742. getOffset: function() {
  89743. return _Number(this._options.offset) || 0
  89744. }
  89745. });
  89746. DX.viz.gauges.__internals.BaseIndicator = DX.viz.gauges.__internals.BaseElement.inherit({
  89747. _init: function() {
  89748. this._rootElement = this._createRoot();
  89749. this._trackerElement = this._createTracker()
  89750. },
  89751. _setupAnimation: function() {
  89752. var that = this;
  89753. if (that._options.animation)
  89754. that._animation = {
  89755. step: function(pos) {
  89756. that._actualValue = that._animation.start + that._animation.delta * pos;
  89757. that._actualPosition = that._translator.translate(that._actualValue);
  89758. that._move()
  89759. },
  89760. duration: that._options.animation.duration > 0 ? _Number(that._options.animation.duration) : 0,
  89761. easing: that._options.animation.easing
  89762. }
  89763. },
  89764. _runAnimation: function(value, notifyReady) {
  89765. var that = this,
  89766. animation = that._animation;
  89767. animation.start = that._actualValue;
  89768. animation.delta = value - that._actualValue;
  89769. that._rootElement.animate({_: 0}, {
  89770. step: animation.step,
  89771. duration: animation.duration,
  89772. easing: animation.easing,
  89773. complete: notifyReady
  89774. })
  89775. },
  89776. _createRoot: function() {
  89777. return this._renderer.g().attr({'class': this._className})
  89778. },
  89779. _createTracker: function() {
  89780. return this._renderer.path([], "area")
  89781. },
  89782. _getTrackerSettings: $.noop,
  89783. clean: function() {
  89784. var that = this;
  89785. that._animation && that._rootElement.stopAnimation();
  89786. that._rootElement.remove();
  89787. that._rootElement.clear();
  89788. that._clear();
  89789. that._tracker.detach(that._trackerElement);
  89790. that._options = that.enabled = that._animation = null;
  89791. return that
  89792. },
  89793. render: function(options) {
  89794. var that = this;
  89795. that.type = options.type;
  89796. that._options = options;
  89797. that._actualValue = that._currentValue = that._translator.adjust(that._options.currentValue);
  89798. that.enabled = that._isEnabled();
  89799. if (that.enabled) {
  89800. that._setupAnimation();
  89801. that._rootElement.attr({fill: that._options.color}).append(that._owner);
  89802. that._tracker.attach(that._trackerElement, that, that._trackerInfo)
  89803. }
  89804. return that
  89805. },
  89806. resize: function(layout) {
  89807. var that = this;
  89808. that._rootElement.clear();
  89809. that._clear();
  89810. that.visible = that._isVisible(layout);
  89811. if (that.visible) {
  89812. $.extend(that._options, layout);
  89813. that._actualPosition = that._translator.translate(that._actualValue);
  89814. that._render();
  89815. that._trackerElement.attr(that._getTrackerSettings());
  89816. that._move()
  89817. }
  89818. return that
  89819. },
  89820. value: function(arg, _noAnimation) {
  89821. var that = this,
  89822. immediateReady = true,
  89823. val;
  89824. if (arg !== undefined) {
  89825. val = that._translator.adjust(arg);
  89826. that._notifiers.dirty();
  89827. if (that._currentValue !== val && _isFinite(val)) {
  89828. that._currentValue = val;
  89829. if (that.visible)
  89830. if (that._animation && !_noAnimation) {
  89831. immediateReady = false;
  89832. that._runAnimation(val, that._notifiers.ready)
  89833. }
  89834. else {
  89835. that._actualValue = val;
  89836. that._actualPosition = that._translator.translate(val);
  89837. that._move()
  89838. }
  89839. }
  89840. immediateReady && that._notifiers.ready();
  89841. return that
  89842. }
  89843. return that._currentValue
  89844. },
  89845. _isEnabled: null,
  89846. _isVisible: null,
  89847. _render: null,
  89848. _clear: null,
  89849. _move: null
  89850. })
  89851. })(DevExpress, jQuery);
  89852. /*! Module viz-gauges, file baseMarker.js */
  89853. (function(DX, undefined) {
  89854. var viz = DX.viz,
  89855. core = viz.core,
  89856. _min = Math.min,
  89857. _round = Math.round,
  89858. _formatValue = viz.gauges.__internals.formatValue,
  89859. _getSampleText = viz.gauges.__internals.getSampleText,
  89860. COEFFICIENTS_MAP = {};
  89861. COEFFICIENTS_MAP['right-bottom'] = COEFFICIENTS_MAP['rb'] = [0, -1, -1, 0, 0, 1, 1, 0];
  89862. COEFFICIENTS_MAP['bottom-right'] = COEFFICIENTS_MAP['br'] = [-1, 0, 0, -1, 1, 0, 0, 1];
  89863. COEFFICIENTS_MAP['left-bottom'] = COEFFICIENTS_MAP['lb'] = [0, -1, 1, 0, 0, 1, -1, 0];
  89864. COEFFICIENTS_MAP['bottom-left'] = COEFFICIENTS_MAP['bl'] = [1, 0, 0, -1, -1, 0, 0, 1];
  89865. COEFFICIENTS_MAP['left-top'] = COEFFICIENTS_MAP['lt'] = [0, 1, 1, 0, 0, -1, -1, 0];
  89866. COEFFICIENTS_MAP['top-left'] = COEFFICIENTS_MAP['tl'] = [1, 0, 0, 1, -1, 0, 0, -1];
  89867. COEFFICIENTS_MAP['right-top'] = COEFFICIENTS_MAP['rt'] = [0, 1, -1, 0, 0, -1, 1, 0];
  89868. COEFFICIENTS_MAP['top-right'] = COEFFICIENTS_MAP['tr'] = [-1, 0, 0, 1, 1, 0, 0, -1];
  89869. function getTextCloudInfo(options) {
  89870. var x = options.x,
  89871. y = options.y,
  89872. type = COEFFICIENTS_MAP[options.type],
  89873. cloudWidth = options.textWidth + 2 * options.horMargin,
  89874. cloudHeight = options.textHeight + 2 * options.verMargin,
  89875. tailWidth,
  89876. tailHeight,
  89877. cx = x,
  89878. cy = y;
  89879. tailWidth = tailHeight = options.tailLength;
  89880. if (type[0] & 1)
  89881. tailHeight = _min(tailHeight, cloudHeight / 3);
  89882. else
  89883. tailWidth = _min(tailWidth, cloudWidth / 3);
  89884. return {
  89885. cx: _round(cx + type[0] * tailWidth + (type[0] + type[2]) * cloudWidth / 2),
  89886. cy: _round(cy + type[1] * tailHeight + (type[1] + type[3]) * cloudHeight / 2),
  89887. points: [_round(x), _round(y), _round(x += type[0] * (cloudWidth + tailWidth)), _round(y += type[1] * (cloudHeight + tailHeight)), _round(x += type[2] * cloudWidth), _round(y += type[3] * cloudHeight), _round(x += type[4] * cloudWidth), _round(y += type[5] * cloudHeight), _round(x += type[6] * (cloudWidth - tailWidth)), _round(y += type[7] * (cloudHeight - tailHeight))]
  89888. }
  89889. }
  89890. viz.gauges.__tests.getTextCloudInfo = getTextCloudInfo;
  89891. viz.gauges.__internals.BaseTextCloudMarker = viz.gauges.__internals.BaseIndicator.inherit({
  89892. _move: function() {
  89893. var that = this,
  89894. bbox,
  89895. info,
  89896. textCloudOptions = that._getTextCloudOptions();
  89897. that._text.attr({text: _formatValue(that._actualValue, that._options.text)});
  89898. bbox = that._text.getBBox();
  89899. info = getTextCloudInfo({
  89900. x: textCloudOptions.x,
  89901. y: textCloudOptions.y,
  89902. textWidth: bbox.width,
  89903. textHeight: bbox.height,
  89904. horMargin: that._options.horizontalOffset,
  89905. verMargin: that._options.verticalOffset,
  89906. tailLength: that._options.arrowLength,
  89907. type: textCloudOptions.type
  89908. });
  89909. that._text.attr({
  89910. x: info.cx,
  89911. y: info.cy + that._textVerticalOffset
  89912. });
  89913. that._cloud.attr({points: info.points});
  89914. that._trackerElement && that._trackerElement.attr({points: info.points})
  89915. },
  89916. _measureText: function() {
  89917. var that = this,
  89918. root,
  89919. text,
  89920. bbox;
  89921. if (!that._textVerticalOffset) {
  89922. root = that._createRoot().append(that._owner);
  89923. text = that._renderer.text(_getSampleText(that._translator, that._options.text), 0, 0).attr({align: "center"}).css(core.utils.patchFontOptions(that._options.text.font)).append(root);
  89924. bbox = text.getBBox();
  89925. root.remove();
  89926. that._textVerticalOffset = -bbox.y - bbox.height / 2;
  89927. that._textWidth = bbox.width;
  89928. that._textHeight = bbox.height;
  89929. that._textFullWidth = that._textWidth + 2 * that._options.horizontalOffset;
  89930. that._textFullHeight = that._textHeight + 2 * that._options.verticalOffset
  89931. }
  89932. },
  89933. _render: function() {
  89934. var that = this;
  89935. that._measureText();
  89936. that._cloud = that._cloud || that._renderer.path([], "area").append(that._rootElement);
  89937. that._text = that._text || that._renderer.text().append(that._rootElement);
  89938. that._text.attr({align: "center"}).css(core.utils.patchFontOptions(that._options.text.font))
  89939. },
  89940. _clear: function() {
  89941. delete this._cloud;
  89942. delete this._text
  89943. },
  89944. getTooltipParameters: function() {
  89945. var position = this._getTextCloudOptions();
  89946. return {
  89947. x: position.x,
  89948. y: position.y,
  89949. value: this._currentValue,
  89950. color: this._options.color
  89951. }
  89952. }
  89953. })
  89954. })(DevExpress);
  89955. /*! Module viz-gauges, file baseRangeBar.js */
  89956. (function(DX, $, undefined) {
  89957. var viz = DX.viz,
  89958. core = viz.core,
  89959. $extend = $.extend,
  89960. formatValue = viz.gauges.__internals.formatValue,
  89961. getSampleText = viz.gauges.__internals.getSampleText;
  89962. viz.gauges.__internals.BaseRangeBar = viz.gauges.__internals.BaseIndicator.inherit({
  89963. _measureText: function() {
  89964. var that = this,
  89965. root,
  89966. text,
  89967. bbox;
  89968. that._hasText = that._isTextVisible();
  89969. if (that._hasText && !that._textVerticalOffset) {
  89970. root = that._createRoot().append(that._owner);
  89971. text = that._renderer.text(getSampleText(that._translator, that._options.text), 0, 0).attr({
  89972. 'class': 'dxg-text',
  89973. align: 'center'
  89974. }).css(core.utils.patchFontOptions(that._options.text.font)).append(root);
  89975. bbox = text.getBBox();
  89976. root.remove();
  89977. that._textVerticalOffset = -bbox.y - bbox.height / 2;
  89978. that._textWidth = bbox.width;
  89979. that._textHeight = bbox.height
  89980. }
  89981. },
  89982. _move: function() {
  89983. var that = this;
  89984. that._updateBarItemsPositions();
  89985. if (that._hasText) {
  89986. that._text.attr({text: formatValue(that._actualValue, that._options.text)});
  89987. that._updateTextPosition();
  89988. that._updateLinePosition()
  89989. }
  89990. },
  89991. _updateBarItems: function() {
  89992. var that = this,
  89993. options = that._options,
  89994. backgroundColor,
  89995. spaceColor,
  89996. translator = that._translator;
  89997. that._setBarSides();
  89998. that._startPosition = translator.translate(translator.getDomainStart());
  89999. that._endPosition = translator.translate(translator.getDomainEnd());
  90000. that._basePosition = translator.translate(options.baseValue);
  90001. that._space = that._getSpace();
  90002. backgroundColor = options.backgroundColor || 'none';
  90003. if (backgroundColor !== 'none' && that._space > 0)
  90004. spaceColor = options.containerBackgroundColor || 'none';
  90005. else {
  90006. that._space = 0;
  90007. spaceColor = 'none'
  90008. }
  90009. that._backItem1.attr({fill: backgroundColor});
  90010. that._backItem2.attr({fill: backgroundColor});
  90011. that._spaceItem1.attr({fill: spaceColor});
  90012. that._spaceItem2.attr({fill: spaceColor})
  90013. },
  90014. _getSpace: function() {
  90015. return 0
  90016. },
  90017. _updateTextItems: function() {
  90018. var that = this;
  90019. if (that._hasText) {
  90020. that._line = that._line || that._renderer.path([], "line").attr({
  90021. 'class': 'dxg-main-bar',
  90022. "stroke-linecap": "square"
  90023. }).append(that._rootElement);
  90024. that._text = that._text || that._renderer.text('', 0, 0).attr({'class': 'dxg-text'}).append(that._rootElement);
  90025. that._text.attr({align: that._getTextAlign()}).css(that._getFontOptions());
  90026. that._setTextItemsSides()
  90027. }
  90028. else {
  90029. if (that._line) {
  90030. that._line.remove();
  90031. delete that._line
  90032. }
  90033. if (that._text) {
  90034. that._text.remove();
  90035. delete that._text
  90036. }
  90037. }
  90038. },
  90039. _isTextVisible: function() {
  90040. return false
  90041. },
  90042. _getTextAlign: function() {
  90043. return 'center'
  90044. },
  90045. _getFontOptions: function() {
  90046. var options = this._options,
  90047. font = options.text.font;
  90048. if (!font || !font.color)
  90049. font = $extend({}, font, {color: options.color});
  90050. return core.utils.patchFontOptions(font)
  90051. },
  90052. _updateBarItemsPositions: function() {
  90053. var that = this,
  90054. positions = that._getPositions();
  90055. that._backItem1.attr(that._buildItemSettings(positions.start, positions.back1));
  90056. that._backItem2.attr(that._buildItemSettings(positions.back2, positions.end));
  90057. that._spaceItem1.attr(that._buildItemSettings(positions.back1, positions.main1));
  90058. that._spaceItem2.attr(that._buildItemSettings(positions.main2, positions.back2));
  90059. that._mainItem.attr(that._buildItemSettings(positions.main1, positions.main2));
  90060. that._trackerElement && that._trackerElement.attr(that._buildItemSettings(positions.main1, positions.main2))
  90061. },
  90062. _render: function() {
  90063. var that = this;
  90064. that._measureText();
  90065. if (!that._backItem1) {
  90066. that._backItem1 = that._createBarItem();
  90067. that._backItem1.attr({'class': 'dxg-back-bar'})
  90068. }
  90069. if (!that._backItem2) {
  90070. that._backItem2 = that._createBarItem();
  90071. that._backItem2.attr({'class': 'dxg-back-bar'})
  90072. }
  90073. if (!that._spaceItem1) {
  90074. that._spaceItem1 = that._createBarItem();
  90075. that._spaceItem1.attr({'class': 'dxg-space-bar'})
  90076. }
  90077. if (!that._spaceItem2) {
  90078. that._spaceItem2 = that._createBarItem();
  90079. that._spaceItem2.attr({'class': 'dxg-space-bar'})
  90080. }
  90081. if (!that._mainItem) {
  90082. that._mainItem = that._createBarItem();
  90083. that._mainItem.attr({'class': 'dxg-main-bar'})
  90084. }
  90085. that._updateBarItems();
  90086. that._updateTextItems()
  90087. },
  90088. _clear: function() {
  90089. var that = this;
  90090. delete that._backItem1;
  90091. delete that._backItem2;
  90092. delete that._spaceItem1;
  90093. delete that._spaceItem2;
  90094. delete that._mainItem;
  90095. delete that._hasText;
  90096. delete that._line;
  90097. delete that._text
  90098. },
  90099. getTooltipParameters: function() {
  90100. var position = this._getTooltipPosition();
  90101. return {
  90102. x: position.x,
  90103. y: position.y,
  90104. value: this._currentValue,
  90105. color: this._options.color,
  90106. offset: 0
  90107. }
  90108. }
  90109. })
  90110. })(DevExpress, jQuery);
  90111. /*! Module viz-gauges, file circularNeedle.js */
  90112. (function(DX, undefined) {
  90113. var circularNeedles = DX.viz.gauges.__internals.circularNeedles,
  90114. _Number = Number;
  90115. circularNeedles.SimpleIndicator = DX.viz.gauges.__internals.BaseIndicator.inherit({
  90116. _move: function() {
  90117. var that = this,
  90118. options = that._options,
  90119. angle = DX.utils.convertAngleToRendererSpace(that._actualPosition);
  90120. that._rootElement.rotate(angle, options.x, options.y);
  90121. that._trackerElement && that._trackerElement.rotate(angle, options.x, options.y)
  90122. },
  90123. _isEnabled: function() {
  90124. return this._options.width > 0
  90125. },
  90126. _isVisible: function(layout) {
  90127. return layout.radius - _Number(this._options.indentFromCenter) > 0
  90128. },
  90129. _getTrackerSettings: function() {
  90130. var options = this._options,
  90131. x = options.x,
  90132. y = options.y - (options.radius + _Number(options.indentFromCenter)) / 2,
  90133. width = options.width / 2,
  90134. length = (options.radius - _Number(options.indentFromCenter)) / 2;
  90135. width > 10 || (width = 10);
  90136. length > 10 || (length = 10);
  90137. return {points: [x - width, y - length, x - width, y + length, x + width, y + length, x + width, y - length]}
  90138. },
  90139. _renderSpindle: function() {
  90140. var that = this,
  90141. options = that._options,
  90142. gapSize;
  90143. if (options.spindleSize > 0) {
  90144. gapSize = _Number(options.spindleGapSize) || 0;
  90145. if (gapSize > 0)
  90146. gapSize = gapSize <= options.spindleSize ? gapSize : _Number(options.spindleSize);
  90147. that._spindleOuter = that._spindleOuter || that._renderer.circle().append(that._rootElement);
  90148. that._spindleInner = that._spindleInner || that._renderer.circle().append(that._rootElement);
  90149. that._spindleOuter.attr({
  90150. 'class': 'dxg-spindle-border',
  90151. cx: options.x,
  90152. cy: options.y,
  90153. r: options.spindleSize / 2
  90154. });
  90155. that._spindleInner.attr({
  90156. 'class': 'dxg-spindle-hole',
  90157. cx: options.x,
  90158. cy: options.y,
  90159. r: gapSize / 2,
  90160. fill: options.containerBackgroundColor
  90161. })
  90162. }
  90163. },
  90164. _render: function() {
  90165. var that = this;
  90166. that._renderPointer();
  90167. that._renderSpindle()
  90168. },
  90169. _clearSpindle: function() {
  90170. delete this._spindleOuter;
  90171. delete this._spindleInner
  90172. },
  90173. _clearPointer: function() {
  90174. delete this._element
  90175. },
  90176. _clear: function() {
  90177. this._clearPointer();
  90178. this._clearSpindle()
  90179. },
  90180. measure: function(layout) {
  90181. var result = {max: layout.radius};
  90182. if (this._options.indentFromCenter < 0)
  90183. result.inverseHorizontalOffset = result.inverseVerticalOffset = -_Number(this._options.indentFromCenter);
  90184. return result
  90185. },
  90186. getTooltipParameters: function() {
  90187. var options = this._options,
  90188. cossin = DX.utils.getCosAndSin(this._actualPosition),
  90189. r = (options.radius + _Number(options.indentFromCenter)) / 2;
  90190. return {
  90191. x: options.x + cossin.cos * r,
  90192. y: options.y - cossin.sin * r,
  90193. value: this._currentValue,
  90194. color: options.color,
  90195. offset: options.width / 2
  90196. }
  90197. }
  90198. });
  90199. circularNeedles.RectangleNeedle = circularNeedles.SimpleIndicator.inherit({_renderPointer: function() {
  90200. var that = this,
  90201. options = that._options,
  90202. y2 = options.y - options.radius,
  90203. y1 = options.y - _Number(options.indentFromCenter),
  90204. x1 = options.x - options.width / 2,
  90205. x2 = x1 + _Number(options.width);
  90206. that._element = that._element || that._renderer.path([], "area").append(that._rootElement);
  90207. that._element.attr({points: [x1, y1, x1, y2, x2, y2, x2, y1]})
  90208. }});
  90209. circularNeedles.TriangleNeedle = circularNeedles.SimpleIndicator.inherit({_renderPointer: function() {
  90210. var that = this,
  90211. options = that._options,
  90212. y2 = options.y - options.radius,
  90213. y1 = options.y - _Number(options.indentFromCenter),
  90214. x1 = options.x - options.width / 2,
  90215. x2 = options.x + options.width / 2;
  90216. that._element = that._element || that._renderer.path([], "area").append(that._rootElement);
  90217. that._element.attr({points: [x1, y1, options.x, y2, x2, y1]})
  90218. }});
  90219. circularNeedles.TwoColorRectangleNeedle = circularNeedles.SimpleIndicator.inherit({
  90220. _renderPointer: function() {
  90221. var that = this,
  90222. options = that._options,
  90223. x1 = options.x - options.width / 2,
  90224. x2 = options.x + options.width / 2,
  90225. y4 = options.y - options.radius,
  90226. y1 = options.y - _Number(options.indentFromCenter),
  90227. fraction = _Number(options.secondFraction) || 0,
  90228. y2,
  90229. y3;
  90230. if (fraction >= 1)
  90231. y2 = y3 = y1;
  90232. else if (fraction <= 0)
  90233. y2 = y3 = y4;
  90234. else {
  90235. y3 = y4 + (y1 - y4) * fraction;
  90236. y2 = y3 + _Number(options.space)
  90237. }
  90238. that._firstElement = that._firstElement || that._renderer.path([], "area").append(that._rootElement);
  90239. that._spaceElement = that._spaceElement || that._renderer.path([], "area").append(that._rootElement);
  90240. that._secondElement = that._secondElement || that._renderer.path([], "area").append(that._rootElement);
  90241. that._firstElement.attr({points: [x1, y1, x1, y2, x2, y2, x2, y1]});
  90242. that._spaceElement.attr({
  90243. points: [x1, y2, x1, y3, x2, y3, x2, y2],
  90244. 'class': 'dxg-hole',
  90245. fill: options.containerBackgroundColor
  90246. });
  90247. that._secondElement.attr({
  90248. points: [x1, y3, x1, y4, x2, y4, x2, y3],
  90249. 'class': 'dxg-part',
  90250. fill: options.secondColor
  90251. })
  90252. },
  90253. _clearPointer: function() {
  90254. delete this._firstElement;
  90255. delete this._secondElement;
  90256. delete this._spaceElement
  90257. }
  90258. })
  90259. })(DevExpress);
  90260. /*! Module viz-gauges, file linearNeedle.js */
  90261. (function(DX, undefined) {
  90262. var linearNeedles = DX.viz.gauges.__internals.linearNeedles;
  90263. linearNeedles.SimpleIndicator = DX.viz.gauges.__internals.BaseIndicator.inherit({
  90264. _move: function() {
  90265. var that = this,
  90266. delta = that._actualPosition - that._zeroPosition;
  90267. that._rootElement.move(that.vertical ? 0 : delta, that.vertical ? delta : 0);
  90268. that._trackerElement && that._trackerElement.move(that.vertical ? 0 : delta, that.vertical ? delta : 0)
  90269. },
  90270. _isEnabled: function() {
  90271. this.vertical = this._options.vertical;
  90272. return this._options.length > 0 && this._options.width > 0
  90273. },
  90274. _isVisible: function() {
  90275. return true
  90276. },
  90277. _getTrackerSettings: function() {
  90278. var options = this._options,
  90279. x1,
  90280. x2,
  90281. y1,
  90282. y2,
  90283. width = options.width / 2,
  90284. length = options.length / 2,
  90285. p = this._zeroPosition;
  90286. width > 10 || (width = 10);
  90287. length > 10 || (length = 10);
  90288. if (this.vertical) {
  90289. x1 = options.x - length;
  90290. x2 = options.x + length;
  90291. y1 = p + width;
  90292. y2 = p - width
  90293. }
  90294. else {
  90295. x1 = p - width;
  90296. x2 = p + width;
  90297. y1 = options.y + length;
  90298. y2 = options.y - length
  90299. }
  90300. return {points: [x1, y1, x1, y2, x2, y2, x2, y1]}
  90301. },
  90302. _render: function() {
  90303. var that = this;
  90304. that._zeroPosition = that._translator.getCodomainStart()
  90305. },
  90306. _clear: function() {
  90307. delete this._element
  90308. },
  90309. measure: function(layout) {
  90310. var p = this.vertical ? layout.x : layout.y;
  90311. return {
  90312. min: p - this._options.length / 2,
  90313. max: p + this._options.length / 2
  90314. }
  90315. },
  90316. getTooltipParameters: function() {
  90317. var that = this,
  90318. options = that._options,
  90319. p = that._actualPosition,
  90320. parameters = {
  90321. x: p,
  90322. y: p,
  90323. value: that._currentValue,
  90324. color: options.color,
  90325. offset: options.width / 2
  90326. };
  90327. that.vertical ? parameters.x = options.x : parameters.y = options.y;
  90328. return parameters
  90329. }
  90330. });
  90331. linearNeedles.RectangleNeedle = linearNeedles.SimpleIndicator.inherit({_render: function() {
  90332. var that = this,
  90333. options = that._options,
  90334. p,
  90335. x1,
  90336. x2,
  90337. y1,
  90338. y2;
  90339. that.callBase();
  90340. p = that._zeroPosition;
  90341. if (that.vertical) {
  90342. x1 = options.x - options.length / 2;
  90343. x2 = options.x + options.length / 2;
  90344. y1 = p + options.width / 2;
  90345. y2 = p - options.width / 2
  90346. }
  90347. else {
  90348. x1 = p - options.width / 2;
  90349. x2 = p + options.width / 2;
  90350. y1 = options.y + options.length / 2;
  90351. y2 = options.y - options.length / 2
  90352. }
  90353. that._element = that._element || that._renderer.path([], "area").append(that._rootElement);
  90354. that._element.attr({points: [x1, y1, x1, y2, x2, y2, x2, y1]})
  90355. }});
  90356. linearNeedles.RhombusNeedle = linearNeedles.SimpleIndicator.inherit({_render: function() {
  90357. var that = this,
  90358. options = that._options,
  90359. x,
  90360. y,
  90361. dx,
  90362. dy;
  90363. that.callBase();
  90364. if (that.vertical) {
  90365. x = options.x;
  90366. y = that._zeroPosition;
  90367. dx = options.length / 2 || 0;
  90368. dy = options.width / 2 || 0
  90369. }
  90370. else {
  90371. x = that._zeroPosition;
  90372. y = options.y;
  90373. dx = options.width / 2 || 0;
  90374. dy = options.length / 2 || 0
  90375. }
  90376. that._element = that._element || that._renderer.path([], "area").append(that._rootElement);
  90377. that._element.attr({points: [x - dx, y, x, y - dy, x + dx, y, x, y + dy]})
  90378. }});
  90379. linearNeedles.CircleNeedle = linearNeedles.SimpleIndicator.inherit({_render: function() {
  90380. var that = this,
  90381. options = that._options,
  90382. x,
  90383. y,
  90384. r;
  90385. that.callBase();
  90386. if (that.vertical) {
  90387. x = options.x;
  90388. y = that._zeroPosition
  90389. }
  90390. else {
  90391. x = that._zeroPosition;
  90392. y = options.y
  90393. }
  90394. r = options.length / 2 || 0;
  90395. that._element = that._element || that._renderer.circle().append(that._rootElement);
  90396. that._element.attr({
  90397. cx: x,
  90398. cy: y,
  90399. r: r
  90400. })
  90401. }})
  90402. })(DevExpress);
  90403. /*! Module viz-gauges, file circularMarker.js */
  90404. (function(DX, undefined) {
  90405. var circularMarkers = DX.viz.gauges.__internals.circularMarkers,
  90406. _Number = Number;
  90407. circularMarkers.TriangleMarker = DX.viz.gauges.__internals.circularNeedles.SimpleIndicator.inherit({
  90408. _isEnabled: function() {
  90409. return this._options.length > 0 && this._options.width > 0
  90410. },
  90411. _isVisible: function(layout) {
  90412. return layout.radius > 0
  90413. },
  90414. _render: function() {
  90415. var that = this,
  90416. options = that._options,
  90417. x = options.x,
  90418. y1 = options.y - options.radius,
  90419. dx = options.width / 2 || 0,
  90420. y2 = y1 - _Number(options.length),
  90421. settings;
  90422. that._element = that._element || that._renderer.path([], "area").append(that._rootElement);
  90423. settings = {
  90424. points: [x, y1, x - dx, y2, x + dx, y2],
  90425. stroke: "none",
  90426. "stroke-width": 0,
  90427. "stroke-linecap": "square"
  90428. };
  90429. if (options.space > 0) {
  90430. settings["stroke-width"] = Math.min(options.space, options.width / 4) || 0;
  90431. settings.stroke = settings["stroke-width"] > 0 ? options.containerBackgroundColor || "none" : "none"
  90432. }
  90433. that._element.attr(settings).sharp()
  90434. },
  90435. _clear: function() {
  90436. delete this._element
  90437. },
  90438. _getTrackerSettings: function() {
  90439. var options = this._options,
  90440. x = options.x,
  90441. y = options.y - options.radius - options.length / 2,
  90442. width = options.width / 2,
  90443. length = options.length / 2;
  90444. width > 10 || (width = 10);
  90445. length > 10 || (length = 10);
  90446. return {points: [x - width, y - length, x - width, y + length, x + width, y + length, x + width, y - length]}
  90447. },
  90448. measure: function(layout) {
  90449. return {
  90450. min: layout.radius,
  90451. max: layout.radius + _Number(this._options.length)
  90452. }
  90453. },
  90454. getTooltipParameters: function() {
  90455. var options = this._options,
  90456. cossin = DX.utils.getCosAndSin(this._actualPosition),
  90457. r = options.radius + options.length / 2,
  90458. parameters = this.callBase();
  90459. parameters.x = options.x + cossin.cos * r;
  90460. parameters.y = options.y - cossin.sin * r;
  90461. parameters.offset = options.length / 2;
  90462. return parameters
  90463. }
  90464. });
  90465. circularMarkers.TextCloudMarker = DX.viz.gauges.__internals.BaseTextCloudMarker.inherit({
  90466. _isEnabled: function() {
  90467. return true
  90468. },
  90469. _isVisible: function(layout) {
  90470. return layout.radius > 0
  90471. },
  90472. _getTextCloudOptions: function() {
  90473. var that = this,
  90474. cossin = DX.utils.getCosAndSin(that._actualPosition),
  90475. nangle = DX.utils.normalizeAngle(that._actualPosition);
  90476. return {
  90477. x: that._options.x + cossin.cos * that._options.radius,
  90478. y: that._options.y - cossin.sin * that._options.radius,
  90479. type: nangle > 270 ? "left-top" : nangle > 180 ? "top-right" : nangle > 90 ? "right-bottom" : "bottom-left"
  90480. }
  90481. },
  90482. measure: function(layout) {
  90483. var that = this,
  90484. arrowLength = _Number(that._options.arrowLength) || 0,
  90485. verticalOffset,
  90486. horizontalOffset;
  90487. that._measureText();
  90488. verticalOffset = that._textFullHeight + arrowLength;
  90489. horizontalOffset = that._textFullWidth + arrowLength;
  90490. return {
  90491. min: layout.radius,
  90492. max: layout.radius,
  90493. horizontalOffset: horizontalOffset,
  90494. verticalOffset: verticalOffset,
  90495. inverseHorizontalOffset: horizontalOffset,
  90496. inverseVerticalOffset: verticalOffset
  90497. }
  90498. }
  90499. })
  90500. })(DevExpress);
  90501. /*! Module viz-gauges, file linearMarker.js */
  90502. (function(DX, undefined) {
  90503. var linearMarkers = DX.viz.gauges.__internals.linearMarkers,
  90504. _Number = Number,
  90505. _String = String;
  90506. linearMarkers.TriangleMarker = DX.viz.gauges.__internals.linearNeedles.SimpleIndicator.inherit({
  90507. _isEnabled: function() {
  90508. var that = this;
  90509. that.vertical = that._options.vertical;
  90510. that._inverted = that.vertical ? _String(that._options.horizontalOrientation).toLowerCase() === 'right' : _String(that._options.verticalOrientation).toLowerCase() === 'bottom';
  90511. return that._options.length > 0 && that._options.width > 0
  90512. },
  90513. _isVisible: function() {
  90514. return true
  90515. },
  90516. _render: function() {
  90517. var that = this,
  90518. options = that._options,
  90519. x1,
  90520. x2,
  90521. y1,
  90522. y2,
  90523. settings = {
  90524. stroke: 'none',
  90525. "stroke-width": 0,
  90526. "stroke-linecap": "square"
  90527. };
  90528. that.callBase();
  90529. if (that.vertical) {
  90530. x1 = options.x;
  90531. y1 = that._zeroPosition;
  90532. x2 = x1 + _Number(that._inverted ? options.length : -options.length);
  90533. settings.points = [x1, y1, x2, y1 - options.width / 2, x2, y1 + options.width / 2]
  90534. }
  90535. else {
  90536. y1 = options.y;
  90537. x1 = that._zeroPosition;
  90538. y2 = y1 + _Number(that._inverted ? options.length : -options.length);
  90539. settings.points = [x1, y1, x1 - options.width / 2, y2, x1 + options.width / 2, y2]
  90540. }
  90541. if (options.space > 0) {
  90542. settings["stroke-width"] = Math.min(options.space, options.width / 4) || 0;
  90543. settings.stroke = settings["stroke-width"] > 0 ? options.containerBackgroundColor || 'none' : 'none'
  90544. }
  90545. that._element = that._element || that._renderer.path([], "area").append(that._rootElement);
  90546. that._element.attr(settings).sharp()
  90547. },
  90548. _getTrackerSettings: function() {
  90549. var that = this,
  90550. options = that._options,
  90551. width = options.width / 2,
  90552. length = _Number(options.length),
  90553. x1,
  90554. x2,
  90555. y1,
  90556. y2,
  90557. result;
  90558. width > 10 || (width = 10);
  90559. length > 20 || (length = 20);
  90560. if (that.vertical) {
  90561. x1 = x2 = options.x;
  90562. x2 = x1 + (that._inverted ? length : -length);
  90563. y1 = that._zeroPosition + width;
  90564. y2 = that._zeroPosition - width;
  90565. result = [x1, y1, x2, y1, x2, y2, x1, y2]
  90566. }
  90567. else {
  90568. y1 = options.y;
  90569. y2 = y1 + (that._inverted ? length : -length);
  90570. x1 = that._zeroPosition - width;
  90571. x2 = that._zeroPosition + width;
  90572. result = [x1, y1, x1, y2, x2, y2, x2, y1]
  90573. }
  90574. return {points: result}
  90575. },
  90576. measure: function(layout) {
  90577. var that = this,
  90578. length = _Number(that._options.length),
  90579. minbound,
  90580. maxbound;
  90581. if (that.vertical) {
  90582. minbound = maxbound = layout.x;
  90583. if (that._inverted)
  90584. maxbound = minbound + length;
  90585. else
  90586. minbound = maxbound - length
  90587. }
  90588. else {
  90589. minbound = maxbound = layout.y;
  90590. if (that._inverted)
  90591. maxbound = minbound + length;
  90592. else
  90593. minbound = maxbound - length
  90594. }
  90595. return {
  90596. min: minbound,
  90597. max: maxbound,
  90598. indent: that._options.width / 2
  90599. }
  90600. },
  90601. getTooltipParameters: function() {
  90602. var that = this,
  90603. options = that._options,
  90604. s = (that._inverted ? options.length : -options.length) / 2,
  90605. parameters = that.callBase();
  90606. that.vertical ? parameters.x += s : parameters.y += s;
  90607. parameters.offset = options.length / 2;
  90608. return parameters
  90609. }
  90610. });
  90611. linearMarkers.TextCloudMarker = DX.viz.gauges.__internals.BaseTextCloudMarker.inherit({
  90612. _isEnabled: function() {
  90613. var that = this;
  90614. that.vertical = that._options.vertical;
  90615. that._inverted = that.vertical ? _String(that._options.horizontalOrientation).toLowerCase() === 'right' : _String(that._options.verticalOrientation).toLowerCase() === 'bottom';
  90616. return true
  90617. },
  90618. _isVisible: function() {
  90619. return true
  90620. },
  90621. _getTextCloudOptions: function() {
  90622. var that = this,
  90623. x = that._actualPosition,
  90624. y = that._actualPosition,
  90625. type;
  90626. if (that.vertical) {
  90627. x = that._options.x;
  90628. type = that._inverted ? 'top-left' : 'top-right'
  90629. }
  90630. else {
  90631. y = that._options.y;
  90632. type = that._inverted ? 'right-top' : 'right-bottom'
  90633. }
  90634. return {
  90635. x: x,
  90636. y: y,
  90637. type: type
  90638. }
  90639. },
  90640. measure: function(layout) {
  90641. var that = this,
  90642. minbound,
  90643. maxbound,
  90644. arrowLength = _Number(that._options.arrowLength) || 0,
  90645. indent;
  90646. that._measureText();
  90647. if (that.vertical) {
  90648. indent = that._textFullHeight;
  90649. if (that._inverted) {
  90650. minbound = layout.x;
  90651. maxbound = layout.x + arrowLength + that._textFullWidth
  90652. }
  90653. else {
  90654. minbound = layout.x - arrowLength - that._textFullWidth;
  90655. maxbound = layout.x
  90656. }
  90657. }
  90658. else {
  90659. indent = that._textFullWidth;
  90660. if (that._inverted) {
  90661. minbound = layout.y;
  90662. maxbound = layout.y + arrowLength + that._textFullHeight
  90663. }
  90664. else {
  90665. minbound = layout.y - arrowLength - that._textFullHeight;
  90666. maxbound = layout.y
  90667. }
  90668. }
  90669. return {
  90670. min: minbound,
  90671. max: maxbound,
  90672. indent: indent
  90673. }
  90674. }
  90675. })
  90676. })(DevExpress);
  90677. /*! Module viz-gauges, file circularRangeBar.js */
  90678. (function(DX, undefined) {
  90679. var _Number = Number,
  90680. getCosAndSin = DX.utils.getCosAndSin,
  90681. convertAngleToRendererSpace = DX.utils.convertAngleToRendererSpace,
  90682. max = Math.max,
  90683. min = Math.min;
  90684. DX.viz.gauges.__internals.CircularRangeBar = DX.viz.gauges.__internals.BaseRangeBar.inherit({
  90685. _isEnabled: function() {
  90686. return this._options.size > 0
  90687. },
  90688. _isVisible: function(layout) {
  90689. return layout.radius - _Number(this._options.size) > 0
  90690. },
  90691. _createBarItem: function() {
  90692. return this._renderer.arc().attr({"stroke-linejoin": "round"}).append(this._rootElement)
  90693. },
  90694. _createTracker: function() {
  90695. return this._renderer.arc().attr({"stroke-linejoin": "round"})
  90696. },
  90697. _setBarSides: function() {
  90698. var that = this;
  90699. that._maxSide = that._options.radius;
  90700. that._minSide = that._maxSide - _Number(that._options.size)
  90701. },
  90702. _getSpace: function() {
  90703. var options = this._options;
  90704. return options.space > 0 ? options.space * 180 / options.radius / Math.PI : 0
  90705. },
  90706. _isTextVisible: function() {
  90707. var options = this._options.text || {};
  90708. return options.indent > 0
  90709. },
  90710. _setTextItemsSides: function() {
  90711. var that = this,
  90712. options = that._options,
  90713. indent = _Number(options.text.indent);
  90714. that._lineFrom = options.y - options.radius;
  90715. that._lineTo = that._lineFrom - indent;
  90716. that._textRadius = options.radius + indent
  90717. },
  90718. _getPositions: function() {
  90719. var that = this,
  90720. basePosition = that._basePosition,
  90721. actualPosition = that._actualPosition,
  90722. mainPosition1,
  90723. mainPosition2;
  90724. if (basePosition >= actualPosition) {
  90725. mainPosition1 = basePosition;
  90726. mainPosition2 = actualPosition
  90727. }
  90728. else {
  90729. mainPosition1 = actualPosition;
  90730. mainPosition2 = basePosition
  90731. }
  90732. return {
  90733. start: that._startPosition,
  90734. end: that._endPosition,
  90735. main1: mainPosition1,
  90736. main2: mainPosition2,
  90737. back1: min(mainPosition1 + that._space, that._startPosition),
  90738. back2: max(mainPosition2 - that._space, that._endPosition)
  90739. }
  90740. },
  90741. _buildItemSettings: function(from, to) {
  90742. var that = this;
  90743. return {
  90744. x: that._options.x,
  90745. y: that._options.y,
  90746. innerRadius: that._minSide,
  90747. outerRadius: that._maxSide,
  90748. startAngle: to,
  90749. endAngle: from
  90750. }
  90751. },
  90752. _updateTextPosition: function() {
  90753. var that = this,
  90754. cossin = getCosAndSin(that._actualPosition),
  90755. x = that._options.x + that._textRadius * cossin.cos,
  90756. y = that._options.y - that._textRadius * cossin.sin;
  90757. x += cossin.cos * that._textWidth * 0.6;
  90758. y -= cossin.sin * that._textHeight * 0.6;
  90759. that._text.attr({
  90760. x: x,
  90761. y: y + that._textVerticalOffset
  90762. })
  90763. },
  90764. _updateLinePosition: function() {
  90765. var that = this,
  90766. x = that._options.x,
  90767. x1,
  90768. x2;
  90769. if (that._basePosition > that._actualPosition) {
  90770. x1 = x - 2;
  90771. x2 = x
  90772. }
  90773. else if (that._basePosition < that._actualPosition) {
  90774. x1 = x;
  90775. x2 = x + 2
  90776. }
  90777. else {
  90778. x1 = x - 1;
  90779. x2 = x + 1
  90780. }
  90781. that._line.attr({points: [x1, that._lineFrom, x1, that._lineTo, x2, that._lineTo, x2, that._lineFrom]}).rotate(convertAngleToRendererSpace(that._actualPosition), x, that._options.y).sharp()
  90782. },
  90783. _getTooltipPosition: function() {
  90784. var that = this,
  90785. cossin = getCosAndSin((that._basePosition + that._actualPosition) / 2),
  90786. r = (that._minSide + that._maxSide) / 2;
  90787. return {
  90788. x: that._options.x + cossin.cos * r,
  90789. y: that._options.y - cossin.sin * r
  90790. }
  90791. },
  90792. measure: function(layout) {
  90793. var that = this,
  90794. result = {
  90795. min: layout.radius - _Number(that._options.size),
  90796. max: layout.radius
  90797. };
  90798. that._measureText();
  90799. if (that._hasText) {
  90800. result.max += _Number(that._options.text.indent);
  90801. result.horizontalOffset = that._textWidth;
  90802. result.verticalOffset = that._textHeight
  90803. }
  90804. return result
  90805. }
  90806. })
  90807. })(DevExpress);
  90808. /*! Module viz-gauges, file linearRangeBar.js */
  90809. (function(DX, undefined) {
  90810. var _Number = Number,
  90811. _String = String;
  90812. DX.viz.gauges.__internals.LinearRangeBar = DX.viz.gauges.__internals.BaseRangeBar.inherit({
  90813. _isEnabled: function() {
  90814. var that = this;
  90815. that.vertical = that._options.vertical;
  90816. that._inverted = that.vertical ? _String(that._options.horizontalOrientation).toLowerCase() === 'right' : _String(that._options.verticalOrientation).toLowerCase() === 'bottom';
  90817. return that._options.size > 0
  90818. },
  90819. _isVisible: function() {
  90820. return true
  90821. },
  90822. _createBarItem: function() {
  90823. return this._renderer.path([], "area").append(this._rootElement)
  90824. },
  90825. _createTracker: function() {
  90826. return this._renderer.path([], "area")
  90827. },
  90828. _setBarSides: function() {
  90829. var that = this,
  90830. options = that._options,
  90831. size = _Number(options.size),
  90832. minSide,
  90833. maxSide;
  90834. if (that.vertical)
  90835. if (that._inverted) {
  90836. minSide = options.x;
  90837. maxSide = options.x + size
  90838. }
  90839. else {
  90840. minSide = options.x - size;
  90841. maxSide = options.x
  90842. }
  90843. else if (that._inverted) {
  90844. minSide = options.y;
  90845. maxSide = options.y + size
  90846. }
  90847. else {
  90848. minSide = options.y - size;
  90849. maxSide = options.y
  90850. }
  90851. that._minSide = minSide;
  90852. that._maxSide = maxSide;
  90853. that._minBound = minSide;
  90854. that._maxBound = maxSide
  90855. },
  90856. _getSpace: function() {
  90857. var options = this._options;
  90858. return options.space > 0 ? _Number(options.space) : 0
  90859. },
  90860. _isTextVisible: function() {
  90861. var textOptions = this._options.text || {};
  90862. return textOptions.indent > 0 || textOptions.indent < 0
  90863. },
  90864. _getTextAlign: function() {
  90865. return this.vertical ? this._options.text.indent > 0 ? 'left' : 'right' : 'center'
  90866. },
  90867. _setTextItemsSides: function() {
  90868. var that = this,
  90869. indent = _Number(that._options.text.indent);
  90870. if (indent > 0) {
  90871. that._lineStart = that._maxSide;
  90872. that._lineEnd = that._maxSide + indent;
  90873. that._textPosition = that._lineEnd + (that.vertical ? 2 : that._textHeight / 2);
  90874. that._maxBound = that._textPosition + (that.vertical ? that._textWidth : that._textHeight / 2)
  90875. }
  90876. else if (indent < 0) {
  90877. that._lineStart = that._minSide;
  90878. that._lineEnd = that._minSide + indent;
  90879. that._textPosition = that._lineEnd - (that.vertical ? 2 : that._textHeight / 2);
  90880. that._minBound = that._textPosition - (that.vertical ? that._textWidth : that._textHeight / 2)
  90881. }
  90882. },
  90883. _getPositions: function() {
  90884. var that = this,
  90885. startPosition = that._startPosition,
  90886. endPosition = that._endPosition,
  90887. space = that._space,
  90888. basePosition = that._basePosition,
  90889. actualPosition = that._actualPosition,
  90890. mainPosition1,
  90891. mainPosition2,
  90892. backPosition1,
  90893. backPosition2;
  90894. if (startPosition < endPosition) {
  90895. if (basePosition < actualPosition) {
  90896. mainPosition1 = basePosition;
  90897. mainPosition2 = actualPosition
  90898. }
  90899. else {
  90900. mainPosition1 = actualPosition;
  90901. mainPosition2 = basePosition
  90902. }
  90903. backPosition1 = mainPosition1 - space;
  90904. backPosition2 = mainPosition2 + space
  90905. }
  90906. else {
  90907. if (basePosition > actualPosition) {
  90908. mainPosition1 = basePosition;
  90909. mainPosition2 = actualPosition
  90910. }
  90911. else {
  90912. mainPosition1 = actualPosition;
  90913. mainPosition2 = basePosition
  90914. }
  90915. backPosition1 = mainPosition1 + space;
  90916. backPosition2 = mainPosition2 - space
  90917. }
  90918. return {
  90919. start: startPosition,
  90920. end: endPosition,
  90921. main1: mainPosition1,
  90922. main2: mainPosition2,
  90923. back1: backPosition1,
  90924. back2: backPosition2
  90925. }
  90926. },
  90927. _buildItemSettings: function(from, to) {
  90928. var that = this,
  90929. side1 = that._minSide,
  90930. side2 = that._maxSide,
  90931. points = that.vertical ? [side1, from, side1, to, side2, to, side2, from] : [from, side1, from, side2, to, side2, to, side1];
  90932. return {points: points}
  90933. },
  90934. _updateTextPosition: function() {
  90935. var that = this;
  90936. that._text.attr(that.vertical ? {
  90937. x: that._textPosition,
  90938. y: that._actualPosition + that._textVerticalOffset
  90939. } : {
  90940. x: that._actualPosition,
  90941. y: that._textPosition + that._textVerticalOffset
  90942. })
  90943. },
  90944. _updateLinePosition: function() {
  90945. var that = this,
  90946. actualPosition = that._actualPosition,
  90947. side1,
  90948. side2,
  90949. points;
  90950. if (that.vertical) {
  90951. if (that._basePosition >= actualPosition) {
  90952. side1 = actualPosition;
  90953. side2 = actualPosition + 2
  90954. }
  90955. else {
  90956. side1 = actualPosition - 2;
  90957. side2 = actualPosition
  90958. }
  90959. points = [that._lineStart, side1, that._lineStart, side2, that._lineEnd, side2, that._lineEnd, side1]
  90960. }
  90961. else {
  90962. if (that._basePosition <= actualPosition) {
  90963. side1 = actualPosition - 2;
  90964. side2 = actualPosition
  90965. }
  90966. else {
  90967. side1 = actualPosition;
  90968. side2 = actualPosition + 2
  90969. }
  90970. points = [side1, that._lineStart, side1, that._lineEnd, side2, that._lineEnd, side2, that._lineStart]
  90971. }
  90972. that._line.attr({points: points}).sharp()
  90973. },
  90974. _getTooltipPosition: function() {
  90975. var that = this,
  90976. crossCenter = (that._minSide + that._maxSide) / 2,
  90977. alongCenter = (that._basePosition + that._actualPosition) / 2;
  90978. return that.vertical ? {
  90979. x: crossCenter,
  90980. y: alongCenter
  90981. } : {
  90982. x: alongCenter,
  90983. y: crossCenter
  90984. }
  90985. },
  90986. measure: function(layout) {
  90987. var that = this,
  90988. size = _Number(that._options.size),
  90989. textIndent = _Number(that._options.text.indent),
  90990. minbound,
  90991. maxbound,
  90992. indent;
  90993. that._measureText();
  90994. if (that.vertical) {
  90995. minbound = maxbound = layout.x;
  90996. if (that._inverted)
  90997. maxbound = maxbound + size;
  90998. else
  90999. minbound = minbound - size;
  91000. if (that._hasText) {
  91001. indent = that._textHeight / 2;
  91002. if (textIndent > 0)
  91003. maxbound += textIndent + that._textWidth;
  91004. if (textIndent < 0)
  91005. minbound += textIndent - that._textWidth
  91006. }
  91007. }
  91008. else {
  91009. minbound = maxbound = layout.y;
  91010. if (that._inverted)
  91011. maxbound = maxbound + size;
  91012. else
  91013. minbound = minbound - size;
  91014. if (that._hasText) {
  91015. indent = that._textWidth / 2;
  91016. if (textIndent > 0)
  91017. maxbound += textIndent + that._textHeight;
  91018. if (textIndent < 0)
  91019. minbound += textIndent - that._textHeight
  91020. }
  91021. }
  91022. return {
  91023. min: minbound,
  91024. max: maxbound,
  91025. indent: indent
  91026. }
  91027. }
  91028. })
  91029. })(DevExpress);
  91030. /*! Module viz-gauges, file scale.js */
  91031. (function(DX, $, undefined) {
  91032. var viz = DX.viz,
  91033. core = viz.core,
  91034. _Number = Number,
  91035. _String = String,
  91036. _isFinite = isFinite,
  91037. _math = Math,
  91038. _min = _math.min,
  91039. _max = _math.max,
  91040. _abs = _math.abs,
  91041. PI_DIV_180 = _math.PI / 180,
  91042. utils = DX.utils,
  91043. _isFunction = utils.isFunction,
  91044. _isArray = utils.isArray,
  91045. _getCosAndSin = utils.getCosAndSin,
  91046. _convertAngleToRendererSpace = utils.convertAngleToRendererSpace,
  91047. _map = $.map,
  91048. _formatHelper = DX.formatHelper,
  91049. _createTickManager = core.CoreFactory.createTickManager;
  91050. function binarySearch(x, list) {
  91051. var a = 0,
  91052. b = list.length - 1,
  91053. flag = list[a] - list[b] < 0,
  91054. c,
  91055. k = -1;
  91056. if (list[a] === x)
  91057. k = a;
  91058. if (list[b] === x)
  91059. k = b;
  91060. while (k < 0 && a <= b) {
  91061. c = ~~((a + b) / 2);
  91062. if (list[c] === x)
  91063. k = c;
  91064. else if (list[c] - x < 0 === flag)
  91065. a = c + 1;
  91066. else
  91067. b = c - 1
  91068. }
  91069. return k
  91070. }
  91071. function sortAsc(x, y) {
  91072. return x - y
  91073. }
  91074. viz.gauges.__internals.BaseScale = viz.gauges.__internals.BaseElement.inherit({
  91075. _init: function() {
  91076. var that = this;
  91077. that._root = that._renderer.g().attr({'class': 'dxg-scale'});
  91078. that._majorTicks = that._renderer.g().attr({'class': 'dxg-major-ticks'});
  91079. that._minorTicks = that._renderer.g().attr({'class': 'dxg-minor-ticks'});
  91080. that._labels = that._renderer.g().attr({'class': 'dxg-labels'})
  91081. },
  91082. clean: function() {
  91083. var that = this;
  91084. that._root.remove();
  91085. that._majorTicks.remove().clear();
  91086. that._minorTicks.remove().clear();
  91087. that._labels.remove().clear();
  91088. that._majorTicksEnabled = that._minorTicksEnabled = that._labelsEnabled = that._options = that.enabled = null;
  91089. return that
  91090. },
  91091. render: function(options) {
  91092. var that = this;
  91093. that._options = options;
  91094. that._processOptions(options);
  91095. if (that._majorTicksEnabled || that._minorTicksEnabled || that._labelsEnabled) {
  91096. that.enabled = true;
  91097. that._root.append(that._container);
  91098. if (that._majorTicksEnabled)
  91099. that._majorTicks.append(that._root);
  91100. if (that._minorTicksEnabled)
  91101. that._minorTicks.append(that._root);
  91102. if (that._labelsEnabled) {
  91103. that._labels.append(that._root);
  91104. that._measureText()
  91105. }
  91106. }
  91107. return that
  91108. },
  91109. _processOptions: function(options) {
  91110. var that = this;
  91111. that._majorTicksEnabled = options.majorTick.visible && options.majorTick.length > 0 && options.majorTick.width > 0;
  91112. that._minorTicksEnabled = options.minorTick.visible && options.minorTick.length > 0 && options.minorTick.width > 0;
  91113. that._labelsEnabled = options.label.visible && _Number(options.label.indentFromTick) !== 0;
  91114. that._setupOrientation()
  91115. },
  91116. _measureText: function() {
  91117. var that = this,
  91118. domain = that._translator.getDomain(),
  91119. options = that._options,
  91120. tickManager = _createTickManager({}, {
  91121. min: domain[0],
  91122. max: domain[1],
  91123. screenDelta: options.approximateScreenDelta
  91124. }, {
  91125. tickInterval: options.majorTick.tickInterval > 0 ? _Number(options.majorTick.tickInterval) : undefined,
  91126. stick: true,
  91127. textFontStyles: core.utils.patchFontOptions(options.label.font),
  91128. gridSpacingFactor: that._getGridSpacingFactor().majorTicks,
  91129. renderText: function(text, x, y, options) {
  91130. return that._renderer.text(text, x, y, options).append(that._renderer.root)
  91131. },
  91132. getText: function(value) {
  91133. return that._formatValue(value)
  91134. },
  91135. overlappingBehaviorType: that._overlappingBehaviorType
  91136. }),
  91137. maxTextParams = tickManager.getMaxLabelParams();
  91138. that._textVerticalOffset = -maxTextParams.y - maxTextParams.height / 2;
  91139. that._textWidth = maxTextParams.width;
  91140. that._textHeight = maxTextParams.height;
  91141. that._textLength = maxTextParams.length
  91142. },
  91143. _formatValue: function(value) {
  91144. var options = this._options.label,
  91145. text = _formatHelper.format(value, options.format, options.precision);
  91146. if (_isFunction(options.customizeText)) {
  91147. text = {
  91148. value: value,
  91149. valueText: text
  91150. };
  91151. text = _String(options.customizeText.call(text, text))
  91152. }
  91153. return text
  91154. },
  91155. _setupOrientation: null,
  91156. _getCustomValues: function(values, compare) {
  91157. var translator = this._translator,
  91158. result = [];
  91159. if (_isArray(values)) {
  91160. result = _map(values, function(x) {
  91161. return _isFinite(translator.translate(x)) ? _Number(x) : null
  91162. }).sort(compare);
  91163. result = _map(result, function(x, i) {
  91164. return x !== result[i - 1] ? x : null
  91165. })
  91166. }
  91167. return result
  91168. },
  91169. _getLabelPosition: function(layout) {
  91170. return this._getAxisLabelPosition(_Number(this._options.majorTick.length), _Number(this._options.label.indentFromTick), layout)
  91171. },
  91172. _generateTicks: function(layout) {
  91173. var that = this,
  91174. scaleOptions = that._options,
  91175. translatorDomains = that._translator.getDomain(),
  91176. data = {
  91177. min: translatorDomains[0],
  91178. max: translatorDomains[1],
  91179. screenDelta: that._getScreenDelta(layout)
  91180. },
  91181. gridSpacingFactors = that._getGridSpacingFactor(),
  91182. options = {
  91183. tickInterval: scaleOptions.majorTick.tickInterval > 0 ? _Number(scaleOptions.majorTick.tickInterval) : undefined,
  91184. minorTickInterval: scaleOptions.minorTick.tickInterval > 0 ? _Number(scaleOptions.minorTick.tickInterval) : undefined,
  91185. gridSpacingFactor: gridSpacingFactors.majorTicks,
  91186. minorGridSpacingFactor: gridSpacingFactors.minorTicks,
  91187. numberMultipliers: [1, 2, 5],
  91188. textFontStyles: core.utils.patchFontOptions(scaleOptions.label.font),
  91189. labelOptions: scaleOptions.label,
  91190. getText: function(value) {
  91191. return that._formatValue(value)
  91192. },
  91193. isHorizontal: !that.vertical,
  91194. stick: true,
  91195. showMinorTicks: true
  91196. },
  91197. tickManager;
  91198. if (scaleOptions.majorTick.useTicksAutoArrangement) {
  91199. options.useTicksAutoArrangement = true;
  91200. options.renderText = function(text, x, y, options) {
  91201. return that._renderer.text(text, x, y, options).append(that._renderer.root)
  91202. };
  91203. options.translate = that._getTranslateFunction(layout);
  91204. that._applyOverlappingOptions(options, layout)
  91205. }
  91206. tickManager = _createTickManager({}, data, options);
  91207. return {
  91208. majorTicks: tickManager.getTicks(true),
  91209. minorTicks: tickManager.getMinorTicks()
  91210. }
  91211. },
  91212. _getTicks: function(layout) {
  91213. var that = this,
  91214. options = that._options,
  91215. info = that._generateTicks(layout),
  91216. majorValues = options.majorTick.showCalculatedTicks ? info.majorTicks : [],
  91217. customMajorValues = _map(that._getCustomValues(options.majorTick.customTickValues, sortAsc), function(value) {
  91218. return binarySearch(value, majorValues) === -1 ? value : null
  91219. }),
  91220. minorValues = _map(options.minorTick.showCalculatedTicks ? info.minorTicks : [], function(value) {
  91221. return binarySearch(value, customMajorValues) === -1 ? value : null
  91222. }),
  91223. customMinorValues = that._getCustomValues(options.minorTick.customTickValues, sortAsc),
  91224. list = majorValues.concat(minorValues, customMajorValues).sort(sortAsc);
  91225. customMinorValues = _map(customMinorValues, function(value) {
  91226. return binarySearch(value, list) === -1 ? value : null
  91227. });
  91228. return {
  91229. major: _map(majorValues.concat(customMajorValues), function(value) {
  91230. return {
  91231. value: value,
  91232. position: that._translator.translate(value)
  91233. }
  91234. }),
  91235. minor: _map(minorValues.concat(customMinorValues), function(value) {
  91236. return {
  91237. value: value,
  91238. position: that._translator.translate(value)
  91239. }
  91240. })
  91241. }
  91242. },
  91243. _createMajorTicks: function(ticks, layout) {
  91244. var that = this,
  91245. points,
  91246. i = 0,
  91247. ii = ticks.length,
  91248. element;
  91249. that._majorTicks.clear().attr({fill: that._options.majorTick.color});
  91250. points = that._getTickPoints(_Number(that._options.majorTick.length), _Number(that._options.majorTick.width), layout);
  91251. if (points) {
  91252. that._options.hideFirstTick && ++i;
  91253. that._options.hideLastTick && --ii;
  91254. for (; i < ii; ++i) {
  91255. element = that._renderer.path(points, "area");
  91256. that._moveTick(element, ticks[i], layout);
  91257. element.append(that._majorTicks)
  91258. }
  91259. }
  91260. },
  91261. _createMinorTicks: function(ticks, layout) {
  91262. var that = this,
  91263. points,
  91264. i = 0,
  91265. ii = ticks.length,
  91266. element;
  91267. that._minorTicks.clear().attr({fill: that._options.minorTick.color});
  91268. points = that._getTickPoints(_Number(that._options.minorTick.length), _Number(that._options.minorTick.width), layout);
  91269. if (points)
  91270. for (; i < ii; ++i) {
  91271. element = that._renderer.path(points, "area");
  91272. that._moveTick(element, ticks[i], layout);
  91273. element.append(that._minorTicks)
  91274. }
  91275. },
  91276. _createLabels: function(ticks, layout) {
  91277. var that = this,
  91278. indentFromTick = _Number(that._options.label.indentFromTick),
  91279. textPosition,
  91280. i = 0,
  91281. ii = ticks.length,
  91282. points,
  91283. text,
  91284. fontStyles = {},
  91285. rangeContainer;
  91286. that._labels.clear().attr({align: that._getLabelAlign(indentFromTick)}).css(core.utils.patchFontOptions(that._options.label.font));
  91287. textPosition = that._getLabelPosition(layout);
  91288. if (textPosition) {
  91289. rangeContainer = that._options.label.useRangeColors ? that._options.rangeContainer : null;
  91290. that._options.hideFirstLabel && ++i;
  91291. that._options.hideLastLabel && --ii;
  91292. for (; i < ii; ++i) {
  91293. text = that._formatValue(ticks[i].value);
  91294. fontStyles.fill = rangeContainer ? rangeContainer.getColorForValue(ticks[i].value) : null;
  91295. points = that._getLabelOptions(text, textPosition, indentFromTick, ticks[i], layout);
  91296. that._renderer.text(text, points.x, points.y + that._textVerticalOffset).css(fontStyles).append(that._labels)
  91297. }
  91298. }
  91299. },
  91300. resize: function(layout) {
  91301. var that = this,
  91302. ticks = that._getTicks(layout);
  91303. if (that._majorTicksEnabled)
  91304. that._createMajorTicks(ticks.major, layout);
  91305. if (that._minorTicksEnabled)
  91306. that._createMinorTicks(ticks.minor, layout);
  91307. if (that._labelsEnabled)
  91308. that._createLabels(ticks.major, layout);
  91309. return that
  91310. }
  91311. });
  91312. viz.gauges.__internals.CircularScale = viz.gauges.__internals.BaseScale.inherit({
  91313. _getGridSpacingFactor: function() {
  91314. return {
  91315. majorTicks: 17,
  91316. minorTicks: 5
  91317. }
  91318. },
  91319. _getTranslateFunction: function(layout) {
  91320. var that = this,
  91321. indent = _Number(that._options.label.indentFromTick),
  91322. translator = this._translator;
  91323. layout = layout || {
  91324. x: 0,
  91325. y: 0,
  91326. radius: 0
  91327. };
  91328. return function(value) {
  91329. var position = that._getLabelPosition(layout),
  91330. text = that._formatValue(value);
  91331. return that._getLabelOptions(text, position, indent, {position: translator.translate(value)}, layout)
  91332. }
  91333. },
  91334. _overlappingBehaviorType: "circular",
  91335. _getScreenDelta: function(layout) {
  91336. return (this._translator.getCodomainStart() - this._translator.getCodomainEnd()) * layout.radius * PI_DIV_180
  91337. },
  91338. _setupOrientation: function() {
  91339. var that = this;
  91340. that._inner = that._outer = 0;
  91341. switch (that._options.orientation) {
  91342. case'inside':
  91343. that._inner = 1;
  91344. break;
  91345. case'center':
  91346. that._inner = that._outer = 0.5;
  91347. break;
  91348. default:
  91349. that._outer = 1;
  91350. break
  91351. }
  91352. },
  91353. _getTickPoints: function(length, width, layout) {
  91354. var x1 = layout.x - width / 2,
  91355. x2 = layout.x + width / 2,
  91356. y1 = layout.y - layout.radius - length * this._outer,
  91357. y2 = layout.y - layout.radius + length * this._inner;
  91358. return y1 > 0 && y2 > 0 ? [x1, y1, x2, y1, x2, y2, x1, y2] : null
  91359. },
  91360. _moveTick: function(element, tick, layout) {
  91361. element.rotate(_convertAngleToRendererSpace(tick.position), layout.x, layout.y)
  91362. },
  91363. _getAxisLabelPosition: function(tickLength, textIndent, layout) {
  91364. var position = layout.radius + tickLength * (textIndent >= 0 ? this._outer : -this._inner) + textIndent;
  91365. return position > 0 ? position : null
  91366. },
  91367. _getLabelAlign: function() {
  91368. return 'center'
  91369. },
  91370. _applyOverlappingOptions: function(options, layout) {
  91371. options.circularRadius = this._getLabelPosition(layout);
  91372. options.circularStartAngle = this._translator.getCodomainStart();
  91373. options.circularEndAngle = this._translator.getCodomainEnd();
  91374. options.overlappingBehaviorType = "circular"
  91375. },
  91376. _getLabelOptions: function(textValue, textPosition, textIndent, tick, layout) {
  91377. var cossin = _getCosAndSin(tick.position),
  91378. x = layout.x + cossin.cos * textPosition,
  91379. y = layout.y - cossin.sin * textPosition,
  91380. dx = cossin.cos * (textValue.length / this._textLength) * this._textWidth / 2,
  91381. dy = cossin.sin * this._textHeight / 2;
  91382. if (textIndent > 0) {
  91383. x += dx;
  91384. y -= dy
  91385. }
  91386. else {
  91387. x -= dx;
  91388. y += dy
  91389. }
  91390. return {
  91391. x: x,
  91392. y: y
  91393. }
  91394. },
  91395. measure: function(layout) {
  91396. var that = this,
  91397. result = {
  91398. min: layout.radius,
  91399. max: layout.radius
  91400. };
  91401. if (that._majorTicksEnabled) {
  91402. result.min = _min(result.min, layout.radius - that._inner * that._options.majorTick.length);
  91403. result.max = _max(result.max, layout.radius + that._outer * that._options.majorTick.length)
  91404. }
  91405. if (that._minorTicksEnabled) {
  91406. result.min = _min(result.min, layout.radius - that._inner * that._options.minorTick.length);
  91407. result.max = _max(result.max, layout.radius + that._outer * that._options.minorTick.length)
  91408. }
  91409. if (that._labelsEnabled) {
  91410. if (that._options.label.indentFromTick > 0) {
  91411. result.horizontalOffset = _Number(that._options.label.indentFromTick) + that._textWidth;
  91412. result.verticalOffset = _Number(that._options.label.indentFromTick) + that._textHeight
  91413. }
  91414. else {
  91415. result.horizontalOffset = result.verticalOffset = 0;
  91416. result.min -= -_Number(that._options.label.indentFromTick) + _max(that._textWidth, that._textHeight)
  91417. }
  91418. result.inverseHorizontalOffset = that._textWidth / 2;
  91419. result.inverseVerticalOffset = that._textHeight / 2
  91420. }
  91421. return result
  91422. }
  91423. });
  91424. viz.gauges.__internals.LinearScale = viz.gauges.__internals.BaseScale.inherit({
  91425. _getGridSpacingFactor: function() {
  91426. return {
  91427. majorTicks: 25,
  91428. minorTicks: 5
  91429. }
  91430. },
  91431. _getTranslateFunction: function() {
  91432. var tr = this._translator;
  91433. return function(value) {
  91434. return tr.translate(value)
  91435. }
  91436. },
  91437. _overlappingBehaviorType: "linear",
  91438. _getScreenDelta: function() {
  91439. return _abs(this._translator.getCodomainEnd() - this._translator.getCodomainStart())
  91440. },
  91441. _setupOrientation: function() {
  91442. var that = this;
  91443. that.vertical = that._options.vertical;
  91444. that._inner = that._outer = 0;
  91445. if (that.vertical)
  91446. switch (that._options.horizontalOrientation) {
  91447. case'left':
  91448. that._inner = 1;
  91449. break;
  91450. case'center':
  91451. that._inner = that._outer = 0.5;
  91452. break;
  91453. default:
  91454. that._outer = 1;
  91455. break
  91456. }
  91457. else
  91458. switch (that._options.verticalOrientation) {
  91459. case'top':
  91460. that._inner = 1;
  91461. break;
  91462. case'middle':
  91463. that._inner = that._outer = 0.5;
  91464. break;
  91465. default:
  91466. that._outer = 1;
  91467. break
  91468. }
  91469. },
  91470. _getTickPoints: function(length, width, layout) {
  91471. var that = this,
  91472. x1,
  91473. x2,
  91474. y1,
  91475. y2;
  91476. if (that.vertical) {
  91477. x1 = layout.x - length * that._inner;
  91478. x2 = layout.x + length * that._outer;
  91479. y1 = -width / 2;
  91480. y2 = +width / 2
  91481. }
  91482. else {
  91483. x1 = -width / 2;
  91484. x2 = +width / 2;
  91485. y1 = layout.y - length * that._inner;
  91486. y2 = layout.y + length * that._outer
  91487. }
  91488. return [x1, y1, x2, y1, x2, y2, x1, y2]
  91489. },
  91490. _moveTick: function(element, tick) {
  91491. var x = 0,
  91492. y = 0;
  91493. if (this.vertical)
  91494. y = tick.position;
  91495. else
  91496. x = tick.position;
  91497. element.move(x, y)
  91498. },
  91499. _getAxisLabelPosition: function(tickLength, textIndent, layout) {
  91500. var position = tickLength * (textIndent >= 0 ? this._outer : -this._inner) + textIndent;
  91501. if (this.vertical)
  91502. position += layout.x;
  91503. else
  91504. position += layout.y + (textIndent >= 0 ? 1 : -1) * (this._textVerticalOffset || 0);
  91505. return position
  91506. },
  91507. _getLabelAlign: function(textIndent) {
  91508. return this.vertical ? textIndent > 0 ? 'left' : 'right' : 'center'
  91509. },
  91510. _applyOverlappingOptions: function(options) {
  91511. options.overlappingBehaviorType = "linear"
  91512. },
  91513. _getLabelOptions: function(textValue, textPosition, textIndent, tick) {
  91514. var x,
  91515. y;
  91516. if (this.vertical) {
  91517. x = textPosition;
  91518. y = tick.position
  91519. }
  91520. else {
  91521. x = tick.position;
  91522. y = textPosition
  91523. }
  91524. return {
  91525. x: x,
  91526. y: y
  91527. }
  91528. },
  91529. measure: function(layout) {
  91530. var that = this,
  91531. p = layout[that.vertical ? 'x' : 'y'],
  91532. result = {
  91533. min: p,
  91534. max: p
  91535. };
  91536. if (that._majorTicksEnabled) {
  91537. result.min = _min(result.min, p - that._inner * that._options.majorTick.length);
  91538. result.max = _max(result.max, p + that._outer * that._options.majorTick.length)
  91539. }
  91540. if (that._minorTicksEnabled) {
  91541. result.min = _min(result.min, p - that._inner * that._options.minorTick.length);
  91542. result.max = _max(result.max, p + that._outer * that._options.minorTick.length)
  91543. }
  91544. if (that._labelsEnabled) {
  91545. if (that._options.label.indentFromTick > 0)
  91546. result.max += +_Number(that._options.label.indentFromTick) + that[that.vertical ? '_textWidth' : '_textHeight'];
  91547. else
  91548. result.min -= -_Number(that._options.label.indentFromTick) + that[that.vertical ? '_textWidth' : '_textHeight'];
  91549. result.indent = that[that.vertical ? '_textHeight' : '_textWidth'] / 2
  91550. }
  91551. return result
  91552. }
  91553. })
  91554. })(DevExpress, jQuery);
  91555. /*! Module viz-gauges, file rangeContainer.js */
  91556. (function(DX, $, undefined) {
  91557. var _Number = Number,
  91558. _String = String,
  91559. _max = Math.max,
  91560. _abs = Math.abs,
  91561. _isString = DX.utils.isString,
  91562. _isArray = DX.utils.isArray,
  91563. _isFinite = isFinite,
  91564. _each = $.each,
  91565. _map = $.map,
  91566. _Palette = DX.viz.core.Palette;
  91567. DX.viz.gauges.__internals.BaseRangeContainer = DX.viz.gauges.__internals.BaseElement.inherit({
  91568. _init: function() {
  91569. this._root = this._renderer.g().attr({'class': 'dxg-range-container'})
  91570. },
  91571. clean: function() {
  91572. this._root.remove().clear();
  91573. this._options = this.enabled = null;
  91574. return this
  91575. },
  91576. _getRanges: function() {
  91577. var that = this,
  91578. options = that._options,
  91579. translator = that._translator,
  91580. totalStart = translator.getDomain()[0],
  91581. totalEnd = translator.getDomain()[1],
  91582. totalDelta = totalEnd - totalStart,
  91583. isNotEmptySegment = totalDelta >= 0 ? isNotEmptySegmentAsc : isNotEmptySegmentDes,
  91584. subtractSegment = totalDelta >= 0 ? subtractSegmentAsc : subtractSegmentDes,
  91585. list = [],
  91586. ranges = [],
  91587. backgroundRanges = [{
  91588. start: totalStart,
  91589. end: totalEnd
  91590. }],
  91591. threshold = _abs(totalDelta) / 1E4,
  91592. palette = new _Palette(options.palette, {
  91593. type: 'indicatingSet',
  91594. theme: options.themeName
  91595. }),
  91596. backgroundColor = _isString(options.backgroundColor) ? options.backgroundColor : 'none',
  91597. width = options.width || {},
  91598. startWidth = _Number(width > 0 ? width : width.start),
  91599. endWidth = _Number(width > 0 ? width : width.end),
  91600. deltaWidth = endWidth - startWidth;
  91601. if (options.ranges !== undefined && !_isArray(options.ranges))
  91602. return null;
  91603. if (!(startWidth >= 0 && endWidth >= 0 && startWidth + endWidth > 0))
  91604. return null;
  91605. list = _map(_isArray(options.ranges) ? options.ranges : [], function(rangeOptions, i) {
  91606. rangeOptions = rangeOptions || {};
  91607. var start = translator.adjust(rangeOptions.startValue),
  91608. end = translator.adjust(rangeOptions.endValue);
  91609. return _isFinite(start) && _isFinite(end) && isNotEmptySegment(start, end, threshold) ? {
  91610. start: start,
  91611. end: end,
  91612. color: rangeOptions.color,
  91613. classIndex: i
  91614. } : null
  91615. });
  91616. _each(list, function(i, item) {
  91617. var paletteColor = palette.getNextColor();
  91618. item.color = _isString(item.color) && item.color || paletteColor || 'none';
  91619. item.className = 'dxg-range dxg-range-' + item.classIndex;
  91620. delete item.classIndex
  91621. });
  91622. _each(list, function(_, item) {
  91623. var i,
  91624. ii,
  91625. sub,
  91626. subs,
  91627. range,
  91628. newRanges = [],
  91629. newBackgroundRanges = [];
  91630. for (i = 0, ii = ranges.length; i < ii; ++i) {
  91631. range = ranges[i];
  91632. subs = subtractSegment(range.start, range.end, item.start, item.end);
  91633. (sub = subs[0]) && (sub.color = range.color) && (sub.className = range.className) && newRanges.push(sub);
  91634. (sub = subs[1]) && (sub.color = range.color) && (sub.className = range.className) && newRanges.push(sub)
  91635. }
  91636. newRanges.push(item);
  91637. ranges = newRanges;
  91638. for (i = 0, ii = backgroundRanges.length; i < ii; ++i) {
  91639. range = backgroundRanges[i];
  91640. subs = subtractSegment(range.start, range.end, item.start, item.end);
  91641. (sub = subs[0]) && newBackgroundRanges.push(sub);
  91642. (sub = subs[1]) && newBackgroundRanges.push(sub)
  91643. }
  91644. backgroundRanges = newBackgroundRanges
  91645. });
  91646. _each(backgroundRanges, function(_, range) {
  91647. range.color = backgroundColor;
  91648. range.className = 'dxg-range dxg-background-range';
  91649. ranges.push(range)
  91650. });
  91651. _each(ranges, function(_, range) {
  91652. range.startWidth = (range.start - totalStart) / totalDelta * deltaWidth + startWidth;
  91653. range.endWidth = (range.end - totalStart) / totalDelta * deltaWidth + startWidth
  91654. });
  91655. return ranges
  91656. },
  91657. render: function(options) {
  91658. var that = this;
  91659. that._options = options;
  91660. that._processOptions();
  91661. that._ranges = that._getRanges();
  91662. if (that._ranges) {
  91663. that.enabled = true;
  91664. that._root.append(that._container)
  91665. }
  91666. return that
  91667. },
  91668. resize: function(layout) {
  91669. var that = this;
  91670. that._root.clear();
  91671. if (that._isVisible(layout))
  91672. _each(that._ranges, function(_, range) {
  91673. that._createRange(range, layout).attr({
  91674. fill: range.color,
  91675. 'class': range.className
  91676. }).append(that._root)
  91677. });
  91678. return that
  91679. },
  91680. _processOptions: null,
  91681. _isVisible: null,
  91682. _createRange: null,
  91683. getColorForValue: function(value) {
  91684. var color = null;
  91685. _each(this._ranges, function(_, range) {
  91686. if (range.start <= value && value <= range.end || range.start >= value && value >= range.end) {
  91687. color = range.color;
  91688. return false
  91689. }
  91690. });
  91691. return color
  91692. }
  91693. });
  91694. function subtractSegmentAsc(segmentStart, segmentEnd, otherStart, otherEnd) {
  91695. var result;
  91696. if (otherStart > segmentStart && otherEnd < segmentEnd)
  91697. result = [{
  91698. start: segmentStart,
  91699. end: otherStart
  91700. }, {
  91701. start: otherEnd,
  91702. end: segmentEnd
  91703. }];
  91704. else if (otherStart >= segmentEnd || otherEnd <= segmentStart)
  91705. result = [{
  91706. start: segmentStart,
  91707. end: segmentEnd
  91708. }];
  91709. else if (otherStart <= segmentStart && otherEnd >= segmentEnd)
  91710. result = [];
  91711. else if (otherStart > segmentStart)
  91712. result = [{
  91713. start: segmentStart,
  91714. end: otherStart
  91715. }];
  91716. else if (otherEnd < segmentEnd)
  91717. result = [{
  91718. start: otherEnd,
  91719. end: segmentEnd
  91720. }];
  91721. return result
  91722. }
  91723. function subtractSegmentDes(segmentStart, segmentEnd, otherStart, otherEnd) {
  91724. var result;
  91725. if (otherStart < segmentStart && otherEnd > segmentEnd)
  91726. result = [{
  91727. start: segmentStart,
  91728. end: otherStart
  91729. }, {
  91730. start: otherEnd,
  91731. end: segmentEnd
  91732. }];
  91733. else if (otherStart <= segmentEnd || otherEnd >= segmentStart)
  91734. result = [{
  91735. start: segmentStart,
  91736. end: segmentEnd
  91737. }];
  91738. else if (otherStart >= segmentStart && otherEnd <= segmentEnd)
  91739. result = [];
  91740. else if (otherStart < segmentStart)
  91741. result = [{
  91742. start: segmentStart,
  91743. end: otherStart
  91744. }];
  91745. else if (otherEnd > segmentEnd)
  91746. result = [{
  91747. start: otherEnd,
  91748. end: segmentEnd
  91749. }];
  91750. return result
  91751. }
  91752. function isNotEmptySegmentAsc(start, end, threshold) {
  91753. return end - start >= threshold
  91754. }
  91755. function isNotEmptySegmentDes(start, end, threshold) {
  91756. return start - end >= threshold
  91757. }
  91758. DX.viz.gauges.__internals.CircularRangeContainer = DX.viz.gauges.__internals.BaseRangeContainer.inherit({
  91759. _processOptions: function() {
  91760. var that = this;
  91761. that._inner = that._outer = 0;
  91762. switch (_String(that._options.orientation).toLowerCase()) {
  91763. case'inside':
  91764. that._inner = 1;
  91765. break;
  91766. case'center':
  91767. that._inner = that._outer = 0.5;
  91768. break;
  91769. default:
  91770. that._outer = 1;
  91771. break
  91772. }
  91773. },
  91774. _isVisible: function(layout) {
  91775. var width = this._options.width;
  91776. width = _Number(width) || _max(_Number(width.start), _Number(width.end));
  91777. return layout.radius - this._inner * width > 0
  91778. },
  91779. _createRange: function(range, layout) {
  91780. var that = this,
  91781. width = (range.startWidth + range.endWidth) / 2;
  91782. return that._renderer.arc(layout.x, layout.y, layout.radius - that._inner * width, layout.radius + that._outer * width, that._translator.translate(range.end), that._translator.translate(range.start)).attr({"stroke-linejoin": "round"})
  91783. },
  91784. measure: function(layout) {
  91785. var width = this._options.width;
  91786. width = _Number(width) || _max(_Number(width.start), _Number(width.end));
  91787. return {
  91788. min: layout.radius - this._inner * width,
  91789. max: layout.radius + this._outer * width
  91790. }
  91791. }
  91792. });
  91793. DX.viz.gauges.__internals.LinearRangeContainer = DX.viz.gauges.__internals.BaseRangeContainer.inherit({
  91794. _processOptions: function() {
  91795. var that = this;
  91796. that.vertical = that._options.vertical;
  91797. that._inner = that._outer = 0;
  91798. if (that.vertical)
  91799. switch (_String(that._options.horizontalOrientation).toLowerCase()) {
  91800. case'left':
  91801. that._inner = 1;
  91802. break;
  91803. case'center':
  91804. that._inner = that._outer = 0.5;
  91805. break;
  91806. default:
  91807. that._outer = 1;
  91808. break
  91809. }
  91810. else
  91811. switch (_String(that._options.verticalOrientation).toLowerCase()) {
  91812. case'top':
  91813. that._inner = 1;
  91814. break;
  91815. case'middle':
  91816. that._inner = that._outer = 0.5;
  91817. break;
  91818. default:
  91819. that._outer = 1;
  91820. break
  91821. }
  91822. },
  91823. _isVisible: function() {
  91824. return true
  91825. },
  91826. _createRange: function(range, layout) {
  91827. var that = this,
  91828. inner = that._inner,
  91829. outer = that._outer,
  91830. startPosition = that._translator.translate(range.start),
  91831. endPosition = that._translator.translate(range.end),
  91832. points,
  91833. x = layout.x,
  91834. y = layout.y,
  91835. startWidth = range.startWidth,
  91836. endWidth = range.endWidth;
  91837. if (that.vertical)
  91838. points = [x - startWidth * inner, startPosition, x - endWidth * inner, endPosition, x + endWidth * outer, endPosition, x + startWidth * outer, startPosition];
  91839. else
  91840. points = [startPosition, y + startWidth * outer, startPosition, y - startWidth * inner, endPosition, y - endWidth * inner, endPosition, y + endWidth * outer];
  91841. return that._renderer.path(points, "area")
  91842. },
  91843. measure: function(layout) {
  91844. var result = {},
  91845. width;
  91846. result.min = result.max = layout[this.vertical ? 'x' : 'y'];
  91847. width = this._options.width;
  91848. width = _Number(width) || _max(_Number(width.start), _Number(width.end));
  91849. result.min -= this._inner * width;
  91850. result.max += this._outer * width;
  91851. return result
  91852. }
  91853. })
  91854. })(DevExpress, jQuery);
  91855. /*! Module viz-gauges, file title.js */
  91856. (function(DX, $, undefined) {
  91857. var viz = DX.viz,
  91858. core = viz.core,
  91859. _isString = DX.utils.isString,
  91860. _max = Math.max,
  91861. _extend = $.extend;
  91862. viz.gauges.__internals.Title = DX.Class.inherit({
  91863. ctor: function(parameters) {
  91864. this._renderer = parameters.renderer;
  91865. this._container = parameters.container
  91866. },
  91867. dispose: function() {
  91868. this._renderer = this._container = null;
  91869. return this
  91870. },
  91871. clean: function() {
  91872. var that = this;
  91873. if (that._root) {
  91874. that._root.remove().clear();
  91875. that._root = that._layout = null
  91876. }
  91877. return that
  91878. },
  91879. render: function(titleOptions, subtitleOptions) {
  91880. var that = this,
  91881. hasTitle = _isString(titleOptions.text) && titleOptions.text.length > 0,
  91882. hasSubtitle = _isString(subtitleOptions.text) && subtitleOptions.text.length > 0,
  91883. element,
  91884. bbox,
  91885. totalWidth = 0,
  91886. totalHeight = 0,
  91887. y = 0;
  91888. if (!hasTitle && !hasSubtitle)
  91889. return that;
  91890. that._root = that._renderer.g().attr({'class': 'dxg-title'}).append(that._container);
  91891. if (hasTitle) {
  91892. element = that._renderer.text(titleOptions.text, 0, 0).attr({align: 'center'}).css(core.utils.patchFontOptions(titleOptions.font)).append(that._root);
  91893. bbox = element.getBBox();
  91894. y += -bbox.y;
  91895. element.attr({y: y});
  91896. y += bbox.height + bbox.y;
  91897. totalWidth = _max(totalWidth, bbox.width);
  91898. totalHeight += bbox.height
  91899. }
  91900. if (hasSubtitle) {
  91901. element = that._renderer.text(subtitleOptions.text, 0, 0).attr({align: 'center'}).css(core.utils.patchFontOptions(subtitleOptions.font)).append(that._root);
  91902. bbox = element.getBBox();
  91903. y += -bbox.y;
  91904. element.attr({y: y});
  91905. totalWidth = _max(totalWidth, bbox.width);
  91906. totalHeight += bbox.height
  91907. }
  91908. that._layout = _extend({
  91909. position: titleOptions.position,
  91910. width: totalWidth,
  91911. height: totalHeight
  91912. }, titleOptions.layout);
  91913. return that
  91914. },
  91915. getLayoutOptions: function() {
  91916. return this._layout
  91917. },
  91918. locate: function(left, top) {
  91919. this._root.attr({
  91920. translateX: left + this._layout.width / 2,
  91921. translateY: top
  91922. });
  91923. return this
  91924. }
  91925. })
  91926. })(DevExpress, jQuery);
  91927. /*! Module viz-gauges, file layoutManager.js */
  91928. (function(DX, $, undefined) {
  91929. var _Number = Number,
  91930. _String = String,
  91931. _max = Math.max,
  91932. _each = $.each;
  91933. function patchLayoutOptions(options) {
  91934. if (options.position) {
  91935. var position = _String(options.position).toLowerCase().split('-');
  91936. options.verticalAlignment = position[0];
  91937. options.horizontalAlignment = position[1]
  91938. }
  91939. }
  91940. DX.viz.gauges.__internals.LayoutManager = DX.Class.inherit({
  91941. setRect: function(rect) {
  91942. this._currentRect = rect.clone();
  91943. return this
  91944. },
  91945. getRect: function() {
  91946. return this._currentRect.clone()
  91947. },
  91948. beginLayout: function(rect) {
  91949. this._rootRect = rect.clone();
  91950. this._currentRect = rect.clone();
  91951. this._cache = [];
  91952. return this
  91953. },
  91954. applyLayout: function(target) {
  91955. var options = target.getLayoutOptions(),
  91956. currentRect,
  91957. verticalOverlay;
  91958. if (!options)
  91959. return this;
  91960. currentRect = this._currentRect;
  91961. verticalOverlay = _Number(options.overlay) || 0;
  91962. patchLayoutOptions(options);
  91963. switch (_String(options.verticalAlignment).toLowerCase()) {
  91964. case'bottom':
  91965. currentRect.bottom -= _max(options.height - verticalOverlay, 0);
  91966. break;
  91967. default:
  91968. currentRect.top += _max(options.height - verticalOverlay, 0);
  91969. break
  91970. }
  91971. this._cache.push({
  91972. target: target,
  91973. options: options
  91974. });
  91975. return this
  91976. },
  91977. endLayout: function() {
  91978. var that = this,
  91979. rootRect = that._rootRect,
  91980. currentRect = that._currentRect;
  91981. _each(that._cache, function(_, cacheItem) {
  91982. var options = cacheItem.options,
  91983. left,
  91984. top,
  91985. verticalOverlay = _Number(options.overlay) || 0;
  91986. switch (_String(options.verticalAlignment).toLowerCase()) {
  91987. case'bottom':
  91988. top = currentRect.bottom - verticalOverlay;
  91989. currentRect.bottom += _max(options.height - verticalOverlay, 0);
  91990. break;
  91991. default:
  91992. top = currentRect.top - options.height + verticalOverlay;
  91993. currentRect.top -= _max(options.height - verticalOverlay, 0);
  91994. break
  91995. }
  91996. switch (_String(options.horizontalAlignment).toLowerCase()) {
  91997. case'left':
  91998. left = rootRect.left;
  91999. break;
  92000. case'right':
  92001. left = rootRect.right - options.width;
  92002. break;
  92003. default:
  92004. left = rootRect.horizontalMiddle() - options.width / 2;
  92005. break
  92006. }
  92007. cacheItem.target.locate(left, top)
  92008. });
  92009. that._cache = null;
  92010. return that
  92011. },
  92012. selectRectByAspectRatio: function(aspectRatio, margins) {
  92013. var rect = this._currentRect.clone(),
  92014. selfAspectRatio,
  92015. width = 0,
  92016. height = 0;
  92017. margins = margins || {};
  92018. if (aspectRatio > 0) {
  92019. rect.left += margins.left || 0;
  92020. rect.right -= margins.right || 0;
  92021. rect.top += margins.top || 0;
  92022. rect.bottom -= margins.bottom || 0;
  92023. if (rect.width() > 0 && rect.height() > 0) {
  92024. selfAspectRatio = rect.height() / rect.width();
  92025. if (selfAspectRatio > 1)
  92026. aspectRatio < selfAspectRatio ? width = rect.width() : height = rect.height();
  92027. else
  92028. aspectRatio > selfAspectRatio ? height = rect.height() : width = rect.width();
  92029. width > 0 || (width = height / aspectRatio);
  92030. height > 0 || (height = width * aspectRatio);
  92031. width = (rect.width() - width) / 2;
  92032. height = (rect.height() - height) / 2;
  92033. rect.left += width;
  92034. rect.right -= width;
  92035. rect.top += height;
  92036. rect.bottom -= height
  92037. }
  92038. else {
  92039. rect.left = rect.right = rect.horizontalMiddle();
  92040. rect.top = rect.bottom = rect.verticalMiddle()
  92041. }
  92042. }
  92043. return rect
  92044. },
  92045. selectRectBySizes: function(sizes, margins) {
  92046. var rect = this._currentRect.clone(),
  92047. step;
  92048. margins = margins || {};
  92049. if (sizes) {
  92050. rect.left += margins.left || 0;
  92051. rect.right -= margins.right || 0;
  92052. rect.top += margins.top || 0;
  92053. rect.bottom -= margins.bottom || 0;
  92054. if (sizes.width > 0) {
  92055. step = (rect.width() - sizes.width) / 2;
  92056. if (step > 0) {
  92057. rect.left += step;
  92058. rect.right -= step
  92059. }
  92060. }
  92061. if (sizes.height > 0) {
  92062. step = (rect.height() - sizes.height) / 2;
  92063. if (step > 0) {
  92064. rect.top += step;
  92065. rect.bottom -= step
  92066. }
  92067. }
  92068. }
  92069. return rect
  92070. }
  92071. })
  92072. })(DevExpress, jQuery);
  92073. /*! Module viz-gauges, file themeManager.js */
  92074. (function(DX, $, undefined) {
  92075. var _extend = $.extend;
  92076. DX.viz.gauges.__internals.ThemeManager = DX.viz.core.BaseThemeManager.inherit({
  92077. _themeSection: 'gauge',
  92078. _fontFields: ['scale.label.font', 'valueIndicators.rangebar.text.font', 'valueIndicators.textcloud.text.font', 'title.font', 'subtitle.font', 'tooltip.font', 'indicator.text.font', 'loadingIndicator.font'],
  92079. _initializeTheme: function() {
  92080. var that = this,
  92081. subTheme;
  92082. if (that._subTheme) {
  92083. subTheme = _extend(true, {}, that._theme[that._subTheme], that._theme);
  92084. _extend(true, that._theme, subTheme)
  92085. }
  92086. that.callBase.apply(that, arguments)
  92087. }
  92088. })
  92089. })(DevExpress, jQuery);
  92090. /*! Module viz-gauges, file baseGauge.js */
  92091. (function(DX, $, undefined) {
  92092. var _Number = Number,
  92093. _isString = DX.utils.isString,
  92094. _getAppropriateFormat = DX.utils.getAppropriateFormat,
  92095. _extend = $.extend,
  92096. _each = $.each;
  92097. DX.viz.gauges.dxBaseGauge = DX.viz.core.BaseWidget.inherit({
  92098. _rootClassPrefix: "dxg",
  92099. _createThemeManager: function() {
  92100. return this._factory.createThemeManager()
  92101. },
  92102. _initCore: function() {
  92103. var that = this;
  92104. that._root = that._renderer.root;
  92105. that._translator = that._factory.createTranslator();
  92106. that._initNotifiers();
  92107. that._tracker = that._factory.createTracker({
  92108. renderer: that._renderer,
  92109. container: that._root
  92110. });
  92111. that._layoutManager = that._factory.createLayoutManager();
  92112. that._title = that._factory.createTitle({
  92113. renderer: that._renderer,
  92114. container: that._root
  92115. });
  92116. that._deltaIndicator = that._factory.createDeltaIndicator({
  92117. renderer: that._renderer,
  92118. container: that._root
  92119. });
  92120. that._setupDomain();
  92121. that._setTrackerCallbacks()
  92122. },
  92123. _setTrackerCallbacks: function() {
  92124. var that = this,
  92125. renderer = that._renderer,
  92126. tooltip = that._tooltip;
  92127. that._tracker.setCallbacks({
  92128. 'tooltip-show': function(target, info) {
  92129. var tooltipParameters = target.getTooltipParameters(),
  92130. offset = renderer.getRootOffset(),
  92131. formatObject = _extend({
  92132. value: tooltipParameters.value,
  92133. valueText: tooltip.formatValue(tooltipParameters.value),
  92134. color: tooltipParameters.color
  92135. }, info);
  92136. return tooltip.show(formatObject, {
  92137. x: tooltipParameters.x + offset.left,
  92138. y: tooltipParameters.y + offset.top,
  92139. offset: tooltipParameters.offset
  92140. }, {target: info})
  92141. },
  92142. 'tooltip-hide': function() {
  92143. return tooltip.hide()
  92144. }
  92145. });
  92146. that._resetTrackerCallbacks = function() {
  92147. that._resetTrackerCallbacks = that = renderer = tooltip = null
  92148. }
  92149. },
  92150. _initNotifiers: function() {
  92151. var that = this,
  92152. counter = 0;
  92153. that._notifiers = {
  92154. dirty: function() {
  92155. that._resetIsReady();
  92156. ++counter
  92157. },
  92158. ready: function() {
  92159. if (--counter === 0)
  92160. that._drawn()
  92161. }
  92162. }
  92163. },
  92164. _disposeCore: function() {
  92165. var that = this;
  92166. that._themeManager.dispose();
  92167. that._tracker.dispose();
  92168. that._title.dispose();
  92169. that._deltaIndicator && that._deltaIndicator.dispose();
  92170. that._root = that._translator = that._notifiers = that._tracker = that._layoutManager = that._title = null
  92171. },
  92172. _refresh: function() {
  92173. var that = this,
  92174. callBase = that.callBase;
  92175. that._endLoading(function() {
  92176. callBase.call(that)
  92177. })
  92178. },
  92179. _clean: function() {
  92180. this._cleanCore()
  92181. },
  92182. _render: function() {
  92183. var that = this;
  92184. that._setupCodomain();
  92185. that._setupAnimationSettings();
  92186. that._setupDefaultFormat();
  92187. that._renderCore()
  92188. },
  92189. _cleanCore: function() {
  92190. var that = this;
  92191. that._title.clean();
  92192. that._deltaIndicator && that._deltaIndicator.clean();
  92193. that._tracker.deactivate();
  92194. that._cleanContent()
  92195. },
  92196. _renderCore: function() {
  92197. var that = this;
  92198. if (!that._isValidDomain)
  92199. return;
  92200. var theme = that._themeManager.theme(),
  92201. titleTheme = _extend(true, {}, theme.title, processTitleOptions(that.option("title"))),
  92202. subTitleTheme = _extend(true, {}, theme.subtitle, processTitleOptions(that.option("subtitle")));
  92203. that._title.render(titleTheme, subTitleTheme);
  92204. that._deltaIndicator && that._deltaIndicator.render(_extend(true, {}, theme.indicator, that.option("indicator")));
  92205. that._layoutManager.beginLayout(that._rootRect);
  92206. _each([that._deltaIndicator, that._title], function(_, item) {
  92207. item && that._layoutManager.applyLayout(item)
  92208. });
  92209. that._mainRect = that._layoutManager.getRect();
  92210. that._renderContent();
  92211. that._layoutManager.endLayout();
  92212. that._tracker.setTooltipState(that._tooltip.isEnabled());
  92213. that._tracker.activate();
  92214. that._noAnimation = null;
  92215. that.option("debugMode") === true && that._renderDebugInfo();
  92216. that._debug_rendered && that._debug_rendered()
  92217. },
  92218. _setTooltipOptions: function() {
  92219. var that = this;
  92220. that.callBase();
  92221. that._tracker && that._tracker.setTooltipState(that._tooltip.isEnabled())
  92222. },
  92223. _renderDebugInfo: function() {
  92224. var that = this,
  92225. group = that._debugGroup || that._renderer.g().attr({"class": "debug-info"}).append(that._renderer.root),
  92226. rect;
  92227. group.clear();
  92228. rect = that._rootRect;
  92229. that._renderer.rect(rect.left, rect.top, rect.width(), rect.height()).attr({
  92230. stroke: "#000000",
  92231. "stroke-width": 1,
  92232. fill: "none"
  92233. }).append(group);
  92234. rect = that._mainRect;
  92235. that._renderer.rect(rect.left, rect.top, rect.width(), rect.height()).attr({
  92236. stroke: "#0000FF",
  92237. "stroke-width": 1,
  92238. fill: "none"
  92239. }).append(group);
  92240. rect = that._layoutManager.getRect();
  92241. rect && that._renderer.rect(rect.left, rect.top, rect.width(), rect.height()).attr({
  92242. stroke: "#FF0000",
  92243. "stroke-width": 1,
  92244. fill: "none"
  92245. }).append(group);
  92246. rect = that._title.getLayoutOptions() ? that._title._root.getBBox() : null;
  92247. rect && that._renderer.rect(rect.x, rect.y, rect.width, rect.height).attr({
  92248. stroke: "#00FF00",
  92249. "stroke-width": 1,
  92250. fill: "none"
  92251. }).append(group);
  92252. rect = that._deltaIndicator && that._deltaIndicator.getLayoutOptions() ? that._deltaIndicator._root.getBBox() : null;
  92253. rect && that._renderer.rect(rect.x, rect.y, rect.width, rect.height).attr({
  92254. stroke: "#00FF00",
  92255. "stroke-width": 1,
  92256. fill: "none"
  92257. }).append(group)
  92258. },
  92259. _applySize: function() {
  92260. var canvas = this._canvas;
  92261. this._rootRect = new DX.viz.core.Rectangle({
  92262. left: canvas.left,
  92263. top: canvas.top,
  92264. right: canvas.width - canvas.right,
  92265. bottom: canvas.height - canvas.bottom
  92266. });
  92267. this._width = canvas.width;
  92268. this._height = canvas.height
  92269. },
  92270. _resize: function() {
  92271. var that = this;
  92272. that._resizing = that._noAnimation = true;
  92273. that._cleanCore();
  92274. that._renderCore();
  92275. that._resizing = null
  92276. },
  92277. _optionChanged: function(args) {
  92278. var that = this;
  92279. switch (args.name) {
  92280. case"startValue":
  92281. case"endValue":
  92282. that._setupDomain();
  92283. that._invalidate();
  92284. break;
  92285. default:
  92286. that.callBase(args);
  92287. break
  92288. }
  92289. },
  92290. _setupDomain: function() {
  92291. var that = this;
  92292. that._setupDomainCore();
  92293. that._isValidDomain = isFinite(1 / (that._translator.getDomain()[1] - that._translator.getDomain()[0]));
  92294. if (!that._isValidDomain)
  92295. that._incidentOccured("W2301")
  92296. },
  92297. _setupAnimationSettings: function() {
  92298. var that = this,
  92299. option = that.option("animation");
  92300. that._animationSettings = null;
  92301. if (option === undefined || option) {
  92302. option = _extend({
  92303. enabled: true,
  92304. duration: 1000,
  92305. easing: "easeOutCubic"
  92306. }, option);
  92307. if (option.enabled && option.duration > 0)
  92308. that._animationSettings = {
  92309. duration: _Number(option.duration),
  92310. easing: option.easing
  92311. }
  92312. }
  92313. that._containerBackgroundColor = that.option("containerBackgroundColor") || that._themeManager.theme().containerBackgroundColor
  92314. },
  92315. _setupDefaultFormat: function() {
  92316. var domain = this._translator.getDomain();
  92317. this._defaultFormatOptions = _getAppropriateFormat(domain[0], domain[1], this._getApproximateScreenRange())
  92318. },
  92319. _setupDomainCore: null,
  92320. _calculateSize: null,
  92321. _cleanContent: null,
  92322. _renderContent: null,
  92323. _setupCodomain: null,
  92324. _getApproximateScreenRange: null,
  92325. _factory: {
  92326. createTranslator: function() {
  92327. return new DX.viz.core.Translator1D
  92328. },
  92329. createTracker: function(parameters) {
  92330. return new DX.viz.gauges.__internals.Tracker(parameters)
  92331. },
  92332. createLayoutManager: function() {
  92333. return new DX.viz.gauges.__internals.LayoutManager
  92334. },
  92335. createTitle: function(parameters) {
  92336. return new DX.viz.gauges.__internals.Title(parameters)
  92337. },
  92338. createDeltaIndicator: function(parameters) {
  92339. return DX.viz.gauges.__internals.DeltaIndicator ? new DX.viz.gauges.__internals.DeltaIndicator(parameters) : null
  92340. }
  92341. }
  92342. });
  92343. function processTitleOptions(options) {
  92344. return _isString(options) ? {text: options} : options || {}
  92345. }
  92346. })(DevExpress, jQuery);
  92347. /*! Module viz-gauges, file gauge.js */
  92348. (function(DX, $, undefined) {
  92349. var _isDefined = DX.utils.isDefined,
  92350. _isArray = DX.utils.isArray,
  92351. _isNumber = DX.utils.isNumber,
  92352. _isFinite = isFinite,
  92353. _Number = Number,
  92354. _String = String,
  92355. _abs = Math.abs,
  92356. _extend = $.extend,
  92357. _each = $.each,
  92358. _map = $.map,
  92359. _noop = $.noop,
  92360. _factory = DX.viz.gauges.__factory,
  92361. OPTION_VALUE = 'value',
  92362. OPTION_SUBVALUES = 'subvalues';
  92363. function processValue(value, fallbackValue) {
  92364. return _isFinite(value) ? _Number(value) : fallbackValue
  92365. }
  92366. function parseArrayOfNumbers(arg) {
  92367. return _isArray(arg) ? arg : _isNumber(arg) ? [arg] : null
  92368. }
  92369. DX.viz.gauges.dxGauge = DX.viz.gauges.dxBaseGauge.inherit({
  92370. _initCore: function() {
  92371. var that = this;
  92372. that._setupValue(that.option(OPTION_VALUE));
  92373. that.__subvalues = parseArrayOfNumbers(that.option(OPTION_SUBVALUES));
  92374. that._setupSubvalues(that.__subvalues);
  92375. selectMode(that);
  92376. that.callBase.apply(that, arguments);
  92377. that._scale = that._createScale({
  92378. renderer: that._renderer,
  92379. container: that._root,
  92380. translator: that._translator
  92381. });
  92382. that._rangeContainer = that._createRangeContainer({
  92383. renderer: that._renderer,
  92384. container: that._root,
  92385. translator: that._translator
  92386. })
  92387. },
  92388. _disposeCore: function() {
  92389. var that = this;
  92390. that.callBase.apply(that, arguments);
  92391. that._scale.dispose();
  92392. that._rangeContainer.dispose();
  92393. that._disposeValueIndicators();
  92394. that._scale = that._rangeContainer = null
  92395. },
  92396. _disposeValueIndicators: function() {
  92397. var that = this;
  92398. that._valueIndicator && that._valueIndicator.dispose();
  92399. that._subvalueIndicatorsSet && that._subvalueIndicatorsSet.dispose();
  92400. that._valueIndicator = that._subvalueIndicatorsSet = null
  92401. },
  92402. _setupDomainCore: function() {
  92403. var that = this,
  92404. scaleOption = that.option('scale') || {},
  92405. startValue = that.option('startValue'),
  92406. endValue = that.option('endValue');
  92407. startValue = _isNumber(startValue) ? _Number(startValue) : _isNumber(scaleOption.startValue) ? _Number(scaleOption.startValue) : 0;
  92408. endValue = _isNumber(endValue) ? _Number(endValue) : _isNumber(scaleOption.endValue) ? _Number(scaleOption.endValue) : 100;
  92409. that._baseValue = startValue < endValue ? startValue : endValue;
  92410. that._translator.setDomain(startValue, endValue)
  92411. },
  92412. _cleanContent: function() {
  92413. var that = this;
  92414. that._rangeContainer.clean();
  92415. that._scale.clean();
  92416. that._cleanValueIndicators()
  92417. },
  92418. _renderContent: function() {
  92419. var that = this,
  92420. elements;
  92421. that._rangeContainer.render(_extend(that._getOption("rangeContainer"), {
  92422. themeName: that._themeManager.themeName(),
  92423. vertical: that._area.vertical
  92424. }));
  92425. that._scale.render(_extend(that._getOption("scale"), {
  92426. rangeContainer: that._rangeContainer.enabled ? that._rangeContainer : null,
  92427. approximateScreenDelta: that._getApproximateScreenRange(),
  92428. offset: 0,
  92429. vertical: that._area.vertical
  92430. }));
  92431. elements = _map([that._scale, that._rangeContainer].concat(that._prepareValueIndicators()), function(element) {
  92432. return element && element.enabled ? element : null
  92433. });
  92434. that._applyMainLayout(elements);
  92435. _each(elements, function(_, element) {
  92436. element.resize(that._getElementLayout(element.getOffset()))
  92437. });
  92438. that._updateActiveElements()
  92439. },
  92440. _updateIndicatorSettings: function(settings) {
  92441. var that = this;
  92442. settings.currentValue = settings.baseValue = _isFinite(that._translator.translate(settings.baseValue)) ? _Number(settings.baseValue) : that._baseValue;
  92443. settings.vertical = that._area.vertical;
  92444. if (settings.text && !settings.text.format && !settings.text.precision) {
  92445. settings.text.format = that._defaultFormatOptions.format;
  92446. settings.text.precision = that._defaultFormatOptions.precision
  92447. }
  92448. },
  92449. _prepareIndicatorSettings: function(options, defaultTypeField) {
  92450. var that = this,
  92451. theme = that._themeManager.theme("valueIndicators"),
  92452. type = _String(options.type || that._themeManager.theme(defaultTypeField)).toLowerCase(),
  92453. settings = _extend(true, {}, theme._default, theme[type], options);
  92454. settings.type = type;
  92455. settings.animation = that._animationSettings;
  92456. settings.containerBackgroundColor = that._containerBackgroundColor;
  92457. that._updateIndicatorSettings(settings);
  92458. return settings
  92459. },
  92460. _cleanValueIndicators: function() {
  92461. this._valueIndicator && this._valueIndicator.clean();
  92462. this._subvalueIndicatorsSet && this._subvalueIndicatorsSet.clean()
  92463. },
  92464. _prepareValueIndicators: function() {
  92465. var that = this;
  92466. that._prepareValueIndicator();
  92467. that.__subvalues !== null && that._prepareSubvalueIndicators();
  92468. return [that._valueIndicator, that._subvalueIndicatorsSet]
  92469. },
  92470. _updateActiveElements: function() {
  92471. this._updateValueIndicator();
  92472. this._updateSubvalueIndicators()
  92473. },
  92474. _prepareValueIndicator: function() {
  92475. var that = this,
  92476. target = that._valueIndicator,
  92477. settings = that._prepareIndicatorSettings(that.option("valueIndicator") || {}, 'valueIndicatorType');
  92478. if (target && target.type !== settings.type) {
  92479. target.dispose();
  92480. target = null
  92481. }
  92482. if (!target)
  92483. target = that._valueIndicator = that._createIndicator(settings.type, that._root, 'dxg-value-indicator', 'value-indicator');
  92484. target.render(settings)
  92485. },
  92486. _createSubvalueIndicatorsSet: function() {
  92487. var that = this,
  92488. owner = that._renderer.g().attr({'class': 'dxg-subvalue-indicators'});
  92489. return new ValueIndicatorsSet({
  92490. root: owner,
  92491. container: that._root,
  92492. createIndicator: function(type, i) {
  92493. return that._createIndicator(type, owner, 'dxg-subvalue-indicator', 'subvalue-indicator', i)
  92494. }
  92495. })
  92496. },
  92497. _prepareSubvalueIndicators: function() {
  92498. var that = this,
  92499. target = that._subvalueIndicatorsSet,
  92500. settings = that._prepareIndicatorSettings(that.option("subvalueIndicator") || {}, 'subvalueIndicatorType'),
  92501. isRecreate;
  92502. if (!target)
  92503. target = that._subvalueIndicatorsSet = that._createSubvalueIndicatorsSet();
  92504. isRecreate = settings.type !== target.type;
  92505. target.type = settings.type;
  92506. if (that._createIndicator(settings.type))
  92507. target.render(settings, isRecreate)
  92508. },
  92509. _setupValue: function(value) {
  92510. this.__value = processValue(value, this.__value)
  92511. },
  92512. _setupSubvalues: function(subvalues) {
  92513. var vals = subvalues === undefined ? this.__subvalues : parseArrayOfNumbers(subvalues),
  92514. i,
  92515. ii,
  92516. list;
  92517. if (vals === null)
  92518. return;
  92519. for (i = 0, ii = vals.length, list = []; i < ii; ++i)
  92520. list.push(processValue(vals[i], this.__subvalues[i]));
  92521. this.__subvalues = list
  92522. },
  92523. _updateValueIndicator: function() {
  92524. var that = this;
  92525. that._valueIndicator && that._valueIndicator.value(that.__value, that._noAnimation);
  92526. that._resizing || that.hideLoadingIndicator()
  92527. },
  92528. _updateSubvalueIndicators: function() {
  92529. var that = this;
  92530. that._subvalueIndicatorsSet && that._subvalueIndicatorsSet.values(that.__subvalues, that._noAnimation);
  92531. that._resizing || that.hideLoadingIndicator()
  92532. },
  92533. value: function(arg) {
  92534. var that = this;
  92535. if (arg !== undefined) {
  92536. that._setupValue(arg);
  92537. that._updateValueIndicator();
  92538. that.option(OPTION_VALUE, that.__value);
  92539. return that
  92540. }
  92541. return that.__value
  92542. },
  92543. subvalues: function(arg) {
  92544. var that = this;
  92545. if (arg !== undefined) {
  92546. if (that.__subvalues !== null) {
  92547. that._setupSubvalues(arg);
  92548. that._updateSubvalueIndicators();
  92549. that.option(OPTION_SUBVALUES, that.__subvalues)
  92550. }
  92551. return that
  92552. }
  92553. return that.__subvalues !== null ? that.__subvalues.slice() : undefined
  92554. },
  92555. _valueChangedHandler: function(name, val) {
  92556. var that = this;
  92557. switch (name) {
  92558. case OPTION_VALUE:
  92559. that._setupValue(val);
  92560. that._updateValueIndicator();
  92561. that.option(OPTION_VALUE, that.__value);
  92562. return true;
  92563. case OPTION_SUBVALUES:
  92564. if (that.__subvalues !== null) {
  92565. that._setupSubvalues(val);
  92566. that._updateSubvalueIndicators();
  92567. that.option(OPTION_SUBVALUES, that.__subvalues);
  92568. return true
  92569. }
  92570. return false;
  92571. default:
  92572. return false
  92573. }
  92574. },
  92575. _optionChanged: function(args) {
  92576. var that = this;
  92577. if (that._valueChangedHandler(args.name, args.value, args.previousValue))
  92578. return;
  92579. if (args.name === "scale") {
  92580. that._setupDomain();
  92581. that._invalidate()
  92582. }
  92583. else
  92584. that.callBase.apply(that, arguments)
  92585. },
  92586. _optionValuesEqual: function(name, oldValue, newValue) {
  92587. var result;
  92588. switch (name) {
  92589. case OPTION_VALUE:
  92590. result = oldValue === newValue;
  92591. break;
  92592. case OPTION_SUBVALUES:
  92593. result = compareArrays(oldValue, newValue);
  92594. break;
  92595. default:
  92596. result = this.callBase.apply(this, arguments);
  92597. break
  92598. }
  92599. return result
  92600. },
  92601. _applyMainLayout: null,
  92602. _getElementLayout: null,
  92603. _createScale: function(parameters) {
  92604. return _factory[this._factoryMethods.scale](parameters)
  92605. },
  92606. _createRangeContainer: function(parameters) {
  92607. return _factory[this._factoryMethods.rangeContainer](parameters)
  92608. },
  92609. _createIndicator: function(type, owner, className, trackerType, trackerIndex, _strict) {
  92610. var that = this,
  92611. indicator = _factory[that._factoryMethods.indicator]({
  92612. renderer: that._renderer,
  92613. translator: that._translator,
  92614. notifiers: that._notifiers,
  92615. owner: owner,
  92616. tracker: that._tracker,
  92617. className: className
  92618. }, type, _strict);
  92619. if (indicator) {
  92620. indicator.type = type;
  92621. indicator._trackerInfo = {
  92622. type: trackerType,
  92623. index: trackerIndex
  92624. }
  92625. }
  92626. return indicator
  92627. },
  92628. _getApproximateScreenRange: null
  92629. });
  92630. DX.viz.gauges.dxGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.dxBaseGauge.prototype._factory);
  92631. DX.viz.gauges.dxGauge.prototype._factory.createThemeManager = function() {
  92632. return new DX.viz.gauges.__internals.ThemeManager
  92633. };
  92634. function valueGetter(arg) {
  92635. return arg ? arg.value : NaN
  92636. }
  92637. function setupValues(that, fieldName, optionItems) {
  92638. var currentValues = that[fieldName],
  92639. newValues = _isArray(optionItems) ? _map(optionItems, valueGetter) : [],
  92640. i = 0,
  92641. ii = newValues.length,
  92642. list = [];
  92643. for (; i < ii; ++i)
  92644. list.push(processValue(newValues[i], currentValues[i]));
  92645. that[fieldName] = list
  92646. }
  92647. function selectMode(gauge) {
  92648. if (gauge.option(OPTION_VALUE) === undefined && gauge.option(OPTION_SUBVALUES) === undefined)
  92649. if (gauge.option('valueIndicators') !== undefined) {
  92650. disableDefaultMode(gauge);
  92651. selectHardMode(gauge)
  92652. }
  92653. }
  92654. function disableDefaultMode(that) {
  92655. that.value = that.subvalues = _noop;
  92656. that._setupValue = that._setupSubvalues = that._updateValueIndicator = that._updateSubvalueIndicators = null
  92657. }
  92658. function selectHardMode(that) {
  92659. that._indicatorValues = [];
  92660. setupValues(that, '_indicatorValues', that.option('valueIndicators'));
  92661. that._valueIndicators = [];
  92662. that._valueChangedHandler = valueChangedHandler_hardMode;
  92663. that._updateActiveElements = updateActiveElements_hardMode;
  92664. that._prepareValueIndicators = prepareValueIndicators_hardMode;
  92665. that._disposeValueIndicators = disposeValueIndicators_hardMode;
  92666. that._cleanValueIndicators = cleanValueIndicators_hardMode;
  92667. that.indicatorValue = indicatorValue_hardMode
  92668. }
  92669. function valueChangedHandler_hardMode(name, val) {
  92670. if (name === 'valueIndicators') {
  92671. setupValues(this, '_indicatorValues', val);
  92672. this._invalidate();
  92673. return true
  92674. }
  92675. return false
  92676. }
  92677. function updateActiveElements_hardMode() {
  92678. var that = this;
  92679. _each(that._valueIndicators, function(_, valueIndicator) {
  92680. valueIndicator.value(that._indicatorValues[valueIndicator.index], that._noAnimation)
  92681. });
  92682. that._resizing || that.hideLoadingIndicator()
  92683. }
  92684. function prepareValueIndicators_hardMode() {
  92685. var that = this,
  92686. valueIndicators = that._valueIndicators || [],
  92687. userOptions = that.option('valueIndicators'),
  92688. optionList = [],
  92689. i = 0,
  92690. ii;
  92691. for (ii = _isArray(userOptions) ? userOptions.length : 0; i < ii; ++i)
  92692. optionList.push(userOptions[i]);
  92693. for (ii = valueIndicators.length; i < ii; ++i)
  92694. optionList.push(null);
  92695. var newValueIndicators = [];
  92696. _each(optionList, function(i, userSettings) {
  92697. var valueIndicator = valueIndicators[i];
  92698. if (!userSettings) {
  92699. valueIndicator && valueIndicator.dispose();
  92700. return
  92701. }
  92702. var settings = that._prepareIndicatorSettings(userSettings, "valueIndicatorType");
  92703. if (valueIndicator && valueIndicator.type !== settings.type) {
  92704. valueIndicator.dispose();
  92705. valueIndicator = null
  92706. }
  92707. if (!valueIndicator)
  92708. valueIndicator = that._createIndicator(settings.type, that._root, 'dxg-value-indicator', 'value-indicator', i, true);
  92709. if (valueIndicator) {
  92710. valueIndicator.index = i;
  92711. valueIndicator.render(settings);
  92712. newValueIndicators.push(valueIndicator)
  92713. }
  92714. });
  92715. that._valueIndicators = newValueIndicators;
  92716. return that._valueIndicators
  92717. }
  92718. function disposeValueIndicators_hardMode() {
  92719. _each(this._valueIndicators, function(_, valueIndicator) {
  92720. valueIndicator.dispose()
  92721. });
  92722. this._valueIndicators = null
  92723. }
  92724. function cleanValueIndicators_hardMode() {
  92725. _each(this._valueIndicators, function(_, valueIndicator) {
  92726. valueIndicator.clean()
  92727. })
  92728. }
  92729. function indicatorValue_hardMode(index, value) {
  92730. return accessPointerValue(this, this._valueIndicators, this._indicatorValues, index, value)
  92731. }
  92732. function accessPointerValue(that, pointers, values, index, value) {
  92733. if (value !== undefined) {
  92734. if (values[index] !== undefined) {
  92735. values[index] = processValue(value, values[index]);
  92736. pointers[index] && pointers[index].value(values[index]);
  92737. that._resizing || that.hideLoadingIndicator()
  92738. }
  92739. return that
  92740. }
  92741. else
  92742. return values[index]
  92743. }
  92744. function compareArrays(array1, array2) {
  92745. var i,
  92746. ii;
  92747. if (array1 === array2)
  92748. return true;
  92749. if (_isArray(array1) && _isArray(array2) && array1.length === array2.length) {
  92750. for (i = 0, ii = array1.length; i < ii; ++i)
  92751. if (_abs(array1[i] - array2[i]) > 1E-8)
  92752. return false;
  92753. return true
  92754. }
  92755. return false
  92756. }
  92757. function ValueIndicatorsSet(parameters) {
  92758. this._parameters = parameters;
  92759. this._indicators = []
  92760. }
  92761. ValueIndicatorsSet.prototype = {
  92762. costructor: ValueIndicatorsSet,
  92763. dispose: function() {
  92764. var that = this;
  92765. _each(that._indicators, function(_, indicator) {
  92766. indicator.dispose()
  92767. });
  92768. that._parameters = that._options = that._indicators = that._colorPalette = that._palette = null;
  92769. return that
  92770. },
  92771. clean: function() {
  92772. var that = this;
  92773. that._parameters.root.remove();
  92774. that._sample && that._sample.clean().dispose();
  92775. _each(that._indicators, function(_, indicator) {
  92776. indicator.clean()
  92777. });
  92778. that._sample = that._options = that._palette = null;
  92779. return that
  92780. },
  92781. render: function(options, isRecreate) {
  92782. var that = this;
  92783. that._options = options;
  92784. that._sample = that._parameters.createIndicator(that.type);
  92785. that._sample.render(options);
  92786. that.enabled = that._sample.enabled;
  92787. that._palette = _isDefined(options.palette) ? new DX.viz.core.Palette(options.palette) : null;
  92788. if (that.enabled) {
  92789. that._parameters.root.append(that._parameters.container);
  92790. that._generatePalette(that._indicators.length);
  92791. that._indicators = _map(that._indicators, function(indicator, i) {
  92792. if (isRecreate) {
  92793. indicator.dispose();
  92794. indicator = that._parameters.createIndicator(that.type, i)
  92795. }
  92796. indicator.render(that._getIndicatorOptions(i));
  92797. return indicator
  92798. })
  92799. }
  92800. return that
  92801. },
  92802. getOffset: function() {
  92803. return _Number(this._options.offset) || 0
  92804. },
  92805. resize: function(layout) {
  92806. var that = this;
  92807. that._layout = layout;
  92808. _each(that._indicators, function(_, indicator) {
  92809. indicator.resize(layout)
  92810. });
  92811. return that
  92812. },
  92813. measure: function(layout) {
  92814. return this._sample.measure(layout)
  92815. },
  92816. _getIndicatorOptions: function(index) {
  92817. var result = this._options;
  92818. if (this._colorPalette)
  92819. result = _extend({}, result, {color: this._colorPalette[index]});
  92820. return result
  92821. },
  92822. _generatePalette: function(count) {
  92823. var that = this,
  92824. colors = null;
  92825. if (that._palette) {
  92826. colors = [];
  92827. that._palette.reset();
  92828. var i = 0;
  92829. for (; i < count; ++i)
  92830. colors.push(that._palette.getNextColor())
  92831. }
  92832. that._colorPalette = colors
  92833. },
  92834. _adjustIndicatorsCount: function(count) {
  92835. var that = this,
  92836. indicators = that._indicators,
  92837. i,
  92838. ii,
  92839. indicator,
  92840. indicatorsLen = indicators.length;
  92841. if (indicatorsLen > count) {
  92842. for (i = count, ii = indicatorsLen; i < ii; ++i)
  92843. indicators[i].clean().dispose();
  92844. that._indicators = indicators.slice(0, count);
  92845. that._generatePalette(indicators.length)
  92846. }
  92847. else if (indicatorsLen < count) {
  92848. that._generatePalette(count);
  92849. for (i = indicatorsLen, ii = count; i < ii; ++i) {
  92850. indicator = that._parameters.createIndicator(that.type, i);
  92851. indicator.render(that._getIndicatorOptions(i)).resize(that._layout);
  92852. indicators.push(indicator)
  92853. }
  92854. }
  92855. },
  92856. values: function(arg, _noAnimation) {
  92857. var that = this;
  92858. if (!that.enabled)
  92859. return;
  92860. if (arg !== undefined) {
  92861. if (!_isArray(arg))
  92862. arg = _isFinite(arg) ? [Number(arg)] : null;
  92863. if (arg) {
  92864. that._adjustIndicatorsCount(arg.length);
  92865. _each(that._indicators, function(i, indicator) {
  92866. indicator.value(arg[i], _noAnimation)
  92867. })
  92868. }
  92869. return that
  92870. }
  92871. return _map(that._indicators, function(indicator) {
  92872. return indicator.value()
  92873. })
  92874. }
  92875. }
  92876. })(DevExpress, jQuery);
  92877. /*! Module viz-gauges, file circularGauge.js */
  92878. (function(DX, $, undefined) {
  92879. var _isFinite = isFinite,
  92880. _Number = Number,
  92881. _normalizeAngle = DX.utils.normalizeAngle,
  92882. _getCosAndSin = DX.utils.getCosAndSin,
  92883. _abs = Math.abs,
  92884. _max = Math.max,
  92885. _min = Math.min,
  92886. _round = Math.round,
  92887. _each = $.each,
  92888. PI = Math.PI;
  92889. function getSides(startAngle, endAngle) {
  92890. var startCosSin = _getCosAndSin(startAngle),
  92891. endCosSin = _getCosAndSin(endAngle),
  92892. startCos = startCosSin.cos,
  92893. startSin = startCosSin.sin,
  92894. endCos = endCosSin.cos,
  92895. endSin = endCosSin.sin;
  92896. return {
  92897. left: startSin <= 0 && endSin >= 0 || startSin <= 0 && endSin <= 0 && startCos <= endCos || startSin >= 0 && endSin >= 0 && startCos >= endCos ? -1 : _min(startCos, endCos, 0),
  92898. right: startSin >= 0 && endSin <= 0 || startSin >= 0 && endSin >= 0 && startCos >= endCos || startSin <= 0 && endSin <= 0 && startCos <= endCos ? 1 : _max(startCos, endCos, 0),
  92899. up: startCos <= 0 && endCos >= 0 || startCos <= 0 && endCos <= 0 && startSin >= endSin || startCos >= 0 && endCos >= 0 && startSin <= endSin ? -1 : -_max(startSin, endSin, 0),
  92900. down: startCos >= 0 && endCos <= 0 || startCos >= 0 && endCos >= 0 && startSin <= endSin || startCos <= 0 && endCos <= 0 && startSin >= endSin ? 1 : -_min(startSin, endSin, 0)
  92901. }
  92902. }
  92903. DX.registerComponent("dxCircularGauge", DX.viz.gauges, DX.viz.gauges.dxGauge.inherit({
  92904. _rootClass: "dxg-circular-gauge",
  92905. _factoryMethods: {
  92906. scale: 'createCircularScale',
  92907. rangeContainer: 'createCircularRangeContainer',
  92908. indicator: 'createCircularIndicator'
  92909. },
  92910. _setupCodomain: function() {
  92911. var that = this,
  92912. geometry = that.option("geometry") || {},
  92913. startAngle = geometry.startAngle,
  92914. endAngle = geometry.endAngle,
  92915. sides;
  92916. startAngle = _isFinite(startAngle) ? _normalizeAngle(startAngle) : 225;
  92917. endAngle = _isFinite(endAngle) ? _normalizeAngle(endAngle) : -45;
  92918. if (_abs(startAngle - endAngle) < 1) {
  92919. endAngle -= 360;
  92920. sides = {
  92921. left: -1,
  92922. up: -1,
  92923. right: 1,
  92924. down: 1
  92925. }
  92926. }
  92927. else {
  92928. startAngle < endAngle && (endAngle -= 360);
  92929. sides = getSides(startAngle, endAngle)
  92930. }
  92931. that._area = {
  92932. x: 0,
  92933. y: 0,
  92934. radius: 100,
  92935. startCoord: startAngle,
  92936. endCoord: endAngle,
  92937. scaleRadius: geometry.scaleRadius > 0 ? _Number(geometry.scaleRadius) : undefined,
  92938. sides: sides
  92939. };
  92940. that._translator.setCodomain(startAngle, endAngle)
  92941. },
  92942. _measureMainElements: function(elements) {
  92943. var that = this,
  92944. radius = that._area.radius,
  92945. maxRadius = 0,
  92946. minRadius = Infinity,
  92947. maxHorizontalOffset = 0,
  92948. maxVerticalOffset = 0,
  92949. maxInverseHorizontalOffset = 0,
  92950. maxInverseVerticalOffset = 0;
  92951. _each(elements, function(_, element) {
  92952. var bounds = element.measure({radius: radius - element.getOffset()});
  92953. bounds.min > 0 && (minRadius = _min(minRadius, bounds.min));
  92954. bounds.max > 0 && (maxRadius = _max(maxRadius, bounds.max));
  92955. bounds.horizontalOffset > 0 && (maxHorizontalOffset = _max(maxHorizontalOffset, bounds.max + bounds.horizontalOffset));
  92956. bounds.verticalOffset > 0 && (maxVerticalOffset = _max(maxVerticalOffset, bounds.max + bounds.verticalOffset));
  92957. bounds.inverseHorizontalOffset > 0 && (maxInverseHorizontalOffset = _max(maxInverseHorizontalOffset, bounds.inverseHorizontalOffset));
  92958. bounds.inverseVerticalOffset > 0 && (maxInverseVerticalOffset = _max(maxInverseVerticalOffset, bounds.inverseVerticalOffset))
  92959. });
  92960. maxHorizontalOffset = _max(maxHorizontalOffset - maxRadius, 0);
  92961. maxVerticalOffset = _max(maxVerticalOffset - maxRadius, 0);
  92962. return {
  92963. minRadius: minRadius,
  92964. maxRadius: maxRadius,
  92965. horizontalMargin: maxHorizontalOffset,
  92966. verticalMargin: maxVerticalOffset,
  92967. inverseHorizontalMargin: maxInverseHorizontalOffset,
  92968. inverseVerticalMargin: maxInverseVerticalOffset
  92969. }
  92970. },
  92971. _applyMainLayout: function(elements) {
  92972. var that = this,
  92973. measurements = that._measureMainElements(elements),
  92974. area = that._area,
  92975. sides = area.sides,
  92976. margins = {
  92977. left: (sides.left < -0.1 ? measurements.horizontalMargin : measurements.inverseHorizontalMargin) || 0,
  92978. right: (sides.right > 0.1 ? measurements.horizontalMargin : measurements.inverseHorizontalMargin) || 0,
  92979. top: (sides.up < -0.1 ? measurements.verticalMargin : measurements.inverseVerticalMargin) || 0,
  92980. bottom: (sides.down > 0.1 ? measurements.verticalMargin : measurements.inverseVerticalMargin) || 0
  92981. },
  92982. rect = that._layoutManager.selectRectByAspectRatio((sides.down - sides.up) / (sides.right - sides.left), margins),
  92983. radius = _min(rect.width() / (sides.right - sides.left), rect.height() / (sides.down - sides.up)),
  92984. x,
  92985. y,
  92986. scaler = (measurements.maxRadius - area.radius + area.scaleRadius) / radius;
  92987. if (0 < scaler && scaler < 1) {
  92988. rect = rect.scale(scaler);
  92989. radius *= scaler
  92990. }
  92991. radius = radius - measurements.maxRadius + area.radius;
  92992. x = rect.left - rect.width() * sides.left / (sides.right - sides.left);
  92993. y = rect.top - rect.height() * sides.up / (sides.down - sides.up);
  92994. area.x = _round(x);
  92995. area.y = _round(y);
  92996. area.radius = radius;
  92997. rect.left -= margins.left;
  92998. rect.right += margins.right;
  92999. rect.top -= margins.top;
  93000. rect.bottom += margins.bottom;
  93001. that._layoutManager.setRect(rect)
  93002. },
  93003. _getElementLayout: function(offset) {
  93004. return {
  93005. x: this._area.x,
  93006. y: this._area.y,
  93007. radius: _round(this._area.radius - offset)
  93008. }
  93009. },
  93010. _getApproximateScreenRange: function() {
  93011. var that = this,
  93012. area = that._area,
  93013. r = _min(that._canvas.width / (area.sides.right - area.sides.left), that._canvas.height / (area.sides.down - area.sides.up));
  93014. r > area.totalRadius && (r = area.totalRadius);
  93015. r = 0.8 * r;
  93016. return -that._translator.getCodomainRange() * r * PI / 180
  93017. },
  93018. _getDefaultSize: function() {
  93019. return {
  93020. width: 300,
  93021. height: 300
  93022. }
  93023. }
  93024. }));
  93025. DX.viz.gauges.dxCircularGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.dxBaseGauge.prototype._factory);
  93026. DX.viz.gauges.dxCircularGauge.prototype._factory.createThemeManager = function() {
  93027. var themeManager = new DX.viz.gauges.__internals.ThemeManager;
  93028. themeManager._subTheme = "_circular";
  93029. return themeManager
  93030. }
  93031. })(DevExpress, jQuery);
  93032. /*! Module viz-gauges, file linearGauge.js */
  93033. (function(DX, $, undefined) {
  93034. var _String = String,
  93035. _Number = Number,
  93036. _max = Math.max,
  93037. _min = Math.min,
  93038. _round = Math.round,
  93039. _each = $.each;
  93040. DX.registerComponent("dxLinearGauge", DX.viz.gauges, DX.viz.gauges.dxGauge.inherit({
  93041. _rootClass: 'dxg-linear-gauge',
  93042. _factoryMethods: {
  93043. scale: 'createLinearScale',
  93044. rangeContainer: 'createLinearRangeContainer',
  93045. indicator: 'createLinearIndicator'
  93046. },
  93047. _setupCodomain: function() {
  93048. var that = this,
  93049. geometry = that.option('geometry') || {},
  93050. vertical = _String(geometry.orientation).toLowerCase() === 'vertical';
  93051. that._area = {
  93052. vertical: vertical,
  93053. x: 0,
  93054. y: 0,
  93055. startCoord: -100,
  93056. endCoord: 100,
  93057. scaleSize: geometry.scaleSize > 0 ? _Number(geometry.scaleSize) : undefined
  93058. };
  93059. that._scale.vertical = vertical;
  93060. that._rangeContainer.vertical = vertical
  93061. },
  93062. _measureMainElements: function(elements) {
  93063. var that = this,
  93064. x = that._area.x,
  93065. y = that._area.y,
  93066. minBound = 1000,
  93067. maxBound = 0,
  93068. indent = 0;
  93069. _each(elements, function(_, element) {
  93070. var bounds = element.measure({
  93071. x: x + element.getOffset(),
  93072. y: y + element.getOffset()
  93073. });
  93074. maxBound = _max(maxBound, bounds.max);
  93075. minBound = _min(minBound, bounds.min);
  93076. bounds.indent > 0 && (indent = _max(indent, bounds.indent))
  93077. });
  93078. return {
  93079. minBound: minBound,
  93080. maxBound: maxBound,
  93081. indent: indent
  93082. }
  93083. },
  93084. _applyMainLayout: function(elements) {
  93085. var that = this,
  93086. measurements = that._measureMainElements(elements),
  93087. area = that._area,
  93088. rect,
  93089. offset,
  93090. counterSize = area.scaleSize + 2 * measurements.indent;
  93091. if (area.vertical) {
  93092. rect = that._layoutManager.selectRectBySizes({
  93093. width: measurements.maxBound - measurements.minBound,
  93094. height: counterSize
  93095. });
  93096. offset = rect.horizontalMiddle() - (measurements.minBound + measurements.maxBound) / 2;
  93097. area.startCoord = rect.bottom - measurements.indent;
  93098. area.endCoord = rect.top + measurements.indent;
  93099. area.x = _round(area.x + offset)
  93100. }
  93101. else {
  93102. rect = that._layoutManager.selectRectBySizes({
  93103. height: measurements.maxBound - measurements.minBound,
  93104. width: counterSize
  93105. });
  93106. offset = rect.verticalMiddle() - (measurements.minBound + measurements.maxBound) / 2;
  93107. area.startCoord = rect.left + measurements.indent;
  93108. area.endCoord = rect.right - measurements.indent;
  93109. area.y = _round(area.y + offset)
  93110. }
  93111. that._translator.setCodomain(area.startCoord, area.endCoord);
  93112. that._layoutManager.setRect(rect)
  93113. },
  93114. _getElementLayout: function(offset) {
  93115. return {
  93116. x: _round(this._area.x + offset),
  93117. y: _round(this._area.y + offset)
  93118. }
  93119. },
  93120. _getApproximateScreenRange: function() {
  93121. var that = this,
  93122. area = that._area,
  93123. s = area.vertical ? that._canvas.height : that._canvas.width;
  93124. s > area.totalSize && (s = area.totalSize);
  93125. s = s * 0.8;
  93126. return s
  93127. },
  93128. _getDefaultSize: function() {
  93129. var geometry = this.option('geometry') || {};
  93130. if (geometry.orientation === 'vertical')
  93131. return {
  93132. width: 100,
  93133. height: 300
  93134. };
  93135. else
  93136. return {
  93137. width: 300,
  93138. height: 100
  93139. }
  93140. }
  93141. }));
  93142. DX.viz.gauges.dxLinearGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.dxBaseGauge.prototype._factory);
  93143. DX.viz.gauges.dxLinearGauge.prototype._factory.createThemeManager = function() {
  93144. var themeManager = new DX.viz.gauges.__internals.ThemeManager;
  93145. themeManager._subTheme = '_linear';
  93146. return themeManager
  93147. }
  93148. })(DevExpress, jQuery);
  93149. /*! Module viz-gauges, file barGauge.js */
  93150. (function(DX, $, undefined) {
  93151. var PI_DIV_180 = Math.PI / 180,
  93152. _abs = Math.abs,
  93153. _round = Math.round,
  93154. _floor = Math.floor,
  93155. _min = Math.min,
  93156. _max = Math.max,
  93157. _isArray = DX.utils.isArray,
  93158. _convertAngleToRendererSpace = DX.utils.convertAngleToRendererSpace,
  93159. _getCosAndSin = DX.utils.getCosAndSin,
  93160. _patchFontOptions = DX.viz.core.utils.patchFontOptions,
  93161. _Number = Number,
  93162. _isFinite = isFinite,
  93163. _noop = $.noop,
  93164. _extend = $.extend,
  93165. _getSampleText = DX.viz.gauges.__internals.getSampleText,
  93166. _formatValue = DX.viz.gauges.__internals.formatValue,
  93167. _Palette = DX.viz.core.Palette,
  93168. OPTION_VALUES = "values";
  93169. var dxBarGauge = DX.viz.gauges.dxBaseGauge.inherit({
  93170. _rootClass: "dxbg-bar-gauge",
  93171. _initCore: function() {
  93172. var that = this;
  93173. that.callBase.apply(that, arguments);
  93174. that._barsGroup = that._renderer.g().attr({"class": "dxbg-bars"});
  93175. that._values = [];
  93176. that._context = {
  93177. renderer: that._renderer,
  93178. translator: that._translator,
  93179. tracker: that._tracker,
  93180. group: that._barsGroup
  93181. };
  93182. that._animateStep = function(pos) {
  93183. var bars = that._bars,
  93184. i,
  93185. ii;
  93186. for (i = 0, ii = bars.length; i < ii; ++i)
  93187. bars[i].animate(pos)
  93188. };
  93189. that._animateComplete = function() {
  93190. var bars = that._bars,
  93191. i,
  93192. ii;
  93193. for (i = 0, ii = bars.length; i < ii; ++i)
  93194. bars[i].endAnimation();
  93195. that._notifiers.ready()
  93196. }
  93197. },
  93198. _disposeCore: function() {
  93199. var that = this;
  93200. that._barsGroup = that._values = that._context = that._animateStep = that._animateComplete = null;
  93201. that.callBase.apply(that, arguments)
  93202. },
  93203. _setupDomainCore: function() {
  93204. var that = this,
  93205. startValue = that.option("startValue"),
  93206. endValue = that.option("endValue");
  93207. _isFinite(startValue) || (startValue = 0);
  93208. _isFinite(endValue) || (endValue = 100);
  93209. that._translator.setDomain(startValue, endValue);
  93210. that._baseValue = that._translator.adjust(that.option("baseValue"));
  93211. _isFinite(that._baseValue) || (that._baseValue = startValue < endValue ? startValue : endValue)
  93212. },
  93213. _getDefaultSize: function() {
  93214. return {
  93215. width: 300,
  93216. height: 300
  93217. }
  93218. },
  93219. _setupCodomain: DX.viz.gauges.dxCircularGauge.prototype._setupCodomain,
  93220. _getApproximateScreenRange: function() {
  93221. var that = this,
  93222. sides = that._area.sides,
  93223. width = that._canvas.width / (sides.right - sides.left),
  93224. height = that._canvas.height / (sides.down - sides.up),
  93225. r = width < height ? width : height;
  93226. return -that._translator.getCodomainRange() * r * PI_DIV_180
  93227. },
  93228. _setupAnimationSettings: function() {
  93229. var that = this;
  93230. that.callBase.apply(that, arguments);
  93231. if (that._animationSettings) {
  93232. that._animationSettings.step = that._animateStep;
  93233. that._animationSettings.complete = that._animateComplete
  93234. }
  93235. },
  93236. _cleanContent: function() {
  93237. var that = this,
  93238. i,
  93239. ii;
  93240. that._barsGroup.remove();
  93241. that._animationSettings && that._barsGroup.stopAnimation();
  93242. for (i = 0, ii = that._bars ? that._bars.length : 0; i < ii; ++i)
  93243. that._bars[i].dispose();
  93244. that._palette = that._bars = null
  93245. },
  93246. _renderContent: function() {
  93247. var that = this,
  93248. labelOptions = that.option("label"),
  93249. text,
  93250. bbox,
  93251. context = that._context;
  93252. that._barsGroup.append(that._root);
  93253. context.textEnabled = labelOptions === undefined || labelOptions && (!("visible" in labelOptions) || labelOptions.visible);
  93254. if (context.textEnabled) {
  93255. context.textColor = labelOptions && labelOptions.font && labelOptions.font.color || null;
  93256. labelOptions = _extend(true, {}, that._themeManager.theme().label, labelOptions);
  93257. context.formatOptions = {
  93258. format: labelOptions.format !== undefined || labelOptions.precision !== undefined ? labelOptions.format : that._defaultFormatOptions.format,
  93259. precision: labelOptions.format !== undefined || labelOptions.precision !== undefined ? labelOptions.precision : that._defaultFormatOptions.precision,
  93260. customizeText: labelOptions.customizeText
  93261. };
  93262. context.textOptions = {align: "center"};
  93263. context.fontStyles = _patchFontOptions(_extend({}, that._themeManager.theme().label.font, labelOptions.font, {color: null}));
  93264. that._textIndent = labelOptions.indent > 0 ? _Number(labelOptions.indent) : 0;
  93265. context.lineWidth = labelOptions.connectorWidth > 0 ? _Number(labelOptions.connectorWidth) : 0;
  93266. context.lineColor = labelOptions.connectorColor || null;
  93267. text = that._renderer.text(_getSampleText(that._translator, context.formatOptions), 0, 0).attr(context.textOptions).css(context.fontStyles).append(that._barsGroup);
  93268. bbox = text.getBBox();
  93269. text.remove();
  93270. context.textVerticalOffset = -bbox.y - bbox.height / 2;
  93271. context.textWidth = bbox.width;
  93272. context.textHeight = bbox.height
  93273. }
  93274. DX.viz.gauges.dxCircularGauge.prototype._applyMainLayout.call(that);
  93275. that._renderBars()
  93276. },
  93277. _measureMainElements: function() {
  93278. var result = {maxRadius: this._area.radius};
  93279. if (this._context.textEnabled) {
  93280. result.horizontalMargin = this._context.textWidth;
  93281. result.verticalMargin = this._context.textHeight
  93282. }
  93283. return result
  93284. },
  93285. _renderBars: function() {
  93286. var that = this,
  93287. options = _extend({}, that._themeManager.theme(), that.option()),
  93288. relativeInnerRadius,
  93289. radius,
  93290. area = that._area;
  93291. that._palette = new _Palette(options.palette, {
  93292. stepHighlight: 50,
  93293. theme: that._themeManager.themeName()
  93294. });
  93295. relativeInnerRadius = options.relativeInnerRadius > 0 && options.relativeInnerRadius < 1 ? _Number(options.relativeInnerRadius) : 0.1;
  93296. radius = area.radius;
  93297. if (that._context.textEnabled) {
  93298. that._textIndent = _round(_min(that._textIndent, radius / 2));
  93299. radius -= that._textIndent
  93300. }
  93301. that._outerRadius = _floor(radius);
  93302. that._innerRadius = _floor(radius * relativeInnerRadius);
  93303. that._barSpacing = options.barSpacing > 0 ? _Number(options.barSpacing) : 0;
  93304. _extend(that._context, {
  93305. backgroundColor: options.backgroundColor,
  93306. x: area.x,
  93307. y: area.y,
  93308. startAngle: area.startCoord,
  93309. endAngle: area.endCoord,
  93310. baseAngle: that._translator.translate(that._baseValue)
  93311. });
  93312. that._bars = [];
  93313. that._updateValues(that.option(OPTION_VALUES))
  93314. },
  93315. _arrangeBars: function(count) {
  93316. var that = this,
  93317. radius = that._outerRadius - that._innerRadius,
  93318. context = that._context,
  93319. spacing,
  93320. _count,
  93321. unitOffset,
  93322. i;
  93323. context.barSize = count > 0 ? _max((radius - (count - 1) * that._barSpacing) / count, 1) : 0;
  93324. spacing = count > 1 ? _max(_min((radius - count * context.barSize) / (count - 1), that._barSpacing), 0) : 0;
  93325. _count = _min(_floor((radius + spacing) / context.barSize), count);
  93326. that._setBarsCount(_count);
  93327. radius = that._outerRadius;
  93328. context.textRadius = radius + that._textIndent;
  93329. that._palette.reset();
  93330. unitOffset = context.barSize + spacing;
  93331. for (i = 0; i < _count; ++i, radius -= unitOffset)
  93332. that._bars[i].arrange({
  93333. radius: radius,
  93334. color: that._palette.getNextColor()
  93335. })
  93336. },
  93337. _setBarsCount: function(count) {
  93338. var that = this,
  93339. i,
  93340. ii;
  93341. if (that._bars.length > count) {
  93342. for (i = count, ii = that._bars.length; i < ii; ++i)
  93343. that._bars[i].dispose();
  93344. that._bars.splice(count, ii - count)
  93345. }
  93346. else if (that._bars.length < count)
  93347. for (i = that._bars.length, ii = count; i < ii; ++i)
  93348. that._bars.push(new BarWrapper(i, that._context));
  93349. if (that._bars.length > 0) {
  93350. if (that._dummyBackground) {
  93351. that._dummyBackground.dispose();
  93352. that._dummyBackground = null
  93353. }
  93354. }
  93355. else {
  93356. if (!that._dummyBackground)
  93357. that._dummyBackground = that._renderer.arc().attr({"stroke-linejoin": "round"}).append(that._barsGroup);
  93358. that._dummyBackground.attr({
  93359. x: that._context.x,
  93360. y: that._context.y,
  93361. outerRadius: that._outerRadius,
  93362. innerRadius: that._innerRadius,
  93363. startAngle: that._context.endAngle,
  93364. endAngle: that._context.startAngle,
  93365. fill: that._context.backgroundColor
  93366. })
  93367. }
  93368. },
  93369. _updateBars: function(values) {
  93370. var that = this,
  93371. i,
  93372. ii;
  93373. for (i = 0, ii = that._bars.length; i < ii; ++i)
  93374. that._bars[i].setValue(values[i])
  93375. },
  93376. _animateBars: function(values) {
  93377. var that = this,
  93378. i,
  93379. ii = that._bars.length;
  93380. if (ii > 0) {
  93381. for (i = 0; i < ii; ++i)
  93382. that._bars[i].beginAnimation(values[i]);
  93383. that._barsGroup.animate({_: 0}, that._animationSettings)
  93384. }
  93385. },
  93386. _updateValues: function(values) {
  93387. var that = this,
  93388. list = _isArray(values) && values || _isFinite(values) && [values] || [],
  93389. i,
  93390. ii = list.length,
  93391. value,
  93392. barValues = [],
  93393. immediateReady = true;
  93394. that._values.length = ii;
  93395. for (i = 0; i < ii; ++i) {
  93396. value = list[i];
  93397. that._values[i] = value = _Number(_isFinite(value) ? value : that._values[i]);
  93398. if (_isFinite(value))
  93399. barValues.push(value)
  93400. }
  93401. that._notifiers.dirty();
  93402. that._animationSettings && that._barsGroup.stopAnimation();
  93403. if (that._bars) {
  93404. that._arrangeBars(barValues.length);
  93405. if (that._animationSettings && !that._noAnimation) {
  93406. immediateReady = false;
  93407. that._animateBars(barValues)
  93408. }
  93409. else
  93410. that._updateBars(barValues)
  93411. }
  93412. immediateReady && that._notifiers.ready();
  93413. if (!that._resizing) {
  93414. that.option(OPTION_VALUES, that._values);
  93415. that.hideLoadingIndicator()
  93416. }
  93417. },
  93418. values: function(arg) {
  93419. if (arg !== undefined) {
  93420. this._updateValues(arg);
  93421. return this
  93422. }
  93423. else
  93424. return this._values.slice(0)
  93425. },
  93426. _optionChanged: function(args) {
  93427. if (args.name === OPTION_VALUES)
  93428. this._updateValues(args.value);
  93429. else
  93430. this.callBase.apply(this, arguments)
  93431. },
  93432. _optionValuesEqual: function(name, oldValue, newValue) {
  93433. if (name === OPTION_VALUES)
  93434. return compareArrays(oldValue, newValue);
  93435. else
  93436. return this.callBase.apply(this, arguments)
  93437. }
  93438. });
  93439. DX.registerComponent("dxBarGauge", DX.viz.gauges, dxBarGauge);
  93440. var ThemeManager = DX.viz.gauges.__internals.ThemeManager.inherit({
  93441. _themeSection: "barGauge",
  93442. _fontFields: ["label.font", "title.font", "tooltip.font", "loadingIndicator.font"]
  93443. });
  93444. dxBarGauge.prototype._factory = DX.utils.clone(DX.viz.gauges.dxBaseGauge.prototype._factory);
  93445. dxBarGauge.prototype._factory.createThemeManager = function() {
  93446. return new ThemeManager
  93447. };
  93448. var BarWrapper = function(index, context) {
  93449. var that = this;
  93450. that._context = context;
  93451. that._background = context.renderer.arc().attr({
  93452. "stroke-linejoin": "round",
  93453. fill: context.backgroundColor
  93454. }).append(context.group);
  93455. that._bar = context.renderer.arc().attr({"stroke-linejoin": "round"}).append(context.group);
  93456. if (context.textEnabled) {
  93457. that._line = context.renderer.path([], "line").attr({"stroke-width": context.lineWidth}).append(context.group);
  93458. that._text = context.renderer.text("", 0, 0).css(context.fontStyles).attr(context.textOptions).append(context.group)
  93459. }
  93460. that._tracker = context.renderer.arc().attr({"stroke-linejoin": "round"});
  93461. context.tracker.attach(that._tracker, that, {index: index});
  93462. that._index = index;
  93463. that._angle = context.baseAngle;
  93464. that._settings = {
  93465. x: context.x,
  93466. y: context.y,
  93467. startAngle: context.baseAngle,
  93468. endAngle: context.baseAngle
  93469. }
  93470. };
  93471. _extend(BarWrapper.prototype, {
  93472. dispose: function() {
  93473. var that = this;
  93474. that._background.dispose();
  93475. that._bar.dispose();
  93476. if (that._context.textEnabled) {
  93477. that._line.dispose();
  93478. that._text.dispose()
  93479. }
  93480. that._context.tracker.detach(that._tracker);
  93481. that._context = that._settings = that._background = that._bar = that._line = that._text = that._tracker = null;
  93482. return that
  93483. },
  93484. arrange: function(options) {
  93485. var that = this,
  93486. context = that._context;
  93487. that._settings.outerRadius = options.radius;
  93488. that._settings.innerRadius = options.radius - context.barSize;
  93489. that._background.attr(_extend({}, that._settings, {
  93490. startAngle: context.endAngle,
  93491. endAngle: context.startAngle
  93492. }));
  93493. that._bar.attr(that._settings);
  93494. that._tracker.attr(that._settings);
  93495. that._color = options.color;
  93496. that._bar.attr({fill: options.color});
  93497. if (context.textEnabled) {
  93498. that._line.attr({
  93499. points: [context.x, context.y - that._settings.innerRadius, context.x, context.y - context.textRadius],
  93500. stroke: context.lineColor || options.color
  93501. }).sharp();
  93502. that._text.css({fill: context.textColor || options.color})
  93503. }
  93504. return that
  93505. },
  93506. getTooltipParameters: function() {
  93507. var that = this,
  93508. cossin = _getCosAndSin((that._angle + that._context.baseAngle) / 2);
  93509. return {
  93510. x: _round(that._context.x + (that._settings.outerRadius + that._settings.innerRadius) / 2 * cossin.cos),
  93511. y: _round(that._context.y - (that._settings.outerRadius + that._settings.innerRadius) / 2 * cossin.sin),
  93512. offset: 0,
  93513. color: that._color,
  93514. value: that._value
  93515. }
  93516. },
  93517. setAngle: function(angle) {
  93518. var that = this,
  93519. cossin;
  93520. that._angle = angle;
  93521. setAngles(that._settings, that._context.baseAngle, that._angle);
  93522. that._bar.attr(that._settings);
  93523. that._tracker.attr(that._settings);
  93524. if (that._context.textEnabled) {
  93525. that._line.rotate(_convertAngleToRendererSpace(that._angle), that._context.x, that._context.y);
  93526. cossin = _getCosAndSin(that._angle);
  93527. that._text.attr({
  93528. text: _formatValue(that._value, that._context.formatOptions, {index: that._index}),
  93529. x: that._context.x + (that._context.textRadius + that._context.textWidth * 0.6) * cossin.cos,
  93530. y: that._context.y - (that._context.textRadius + that._context.textHeight * 0.6) * cossin.sin + that._context.textVerticalOffset
  93531. })
  93532. }
  93533. return that
  93534. },
  93535. _processValue: function(value) {
  93536. this._value = this._context.translator.adjust(value);
  93537. return this._context.translator.translate(this._value)
  93538. },
  93539. setValue: function(value) {
  93540. return this.setAngle(this._processValue(value))
  93541. },
  93542. beginAnimation: function(value) {
  93543. var that = this,
  93544. angle = this._processValue(value);
  93545. if (!compareFloats(that._angle, angle)) {
  93546. that._start = that._angle;
  93547. that._delta = angle - that._angle;
  93548. that._tracker.attr({visibility: "hidden"});
  93549. if (that._context.textEnabled) {
  93550. that._line.attr({visibility: "hidden"});
  93551. that._text.attr({visibility: "hidden"})
  93552. }
  93553. }
  93554. else {
  93555. that.animate = _noop;
  93556. that.setAngle(that._angle)
  93557. }
  93558. },
  93559. animate: function(pos) {
  93560. var that = this;
  93561. that._angle = that._start + that._delta * pos;
  93562. setAngles(that._settings, that._context.baseAngle, that._angle);
  93563. that._bar.attr(that._settings)
  93564. },
  93565. endAnimation: function() {
  93566. var that = this;
  93567. if (that._delta !== undefined) {
  93568. if (compareFloats(that._angle, that._start + that._delta)) {
  93569. that._tracker.attr({visibility: null});
  93570. if (that._context.textEnabled) {
  93571. that._line.attr({visibility: null});
  93572. that._text.attr({visibility: null})
  93573. }
  93574. that.setAngle(that._angle)
  93575. }
  93576. }
  93577. else
  93578. delete that.animate;
  93579. delete that._start;
  93580. delete that._delta
  93581. }
  93582. });
  93583. function setAngles(target, angle1, angle2) {
  93584. target.startAngle = angle1 < angle2 ? angle1 : angle2;
  93585. target.endAngle = angle1 < angle2 ? angle2 : angle1
  93586. }
  93587. function compareFloats(value1, value2) {
  93588. return _abs(value1 - value2) < 0.0001
  93589. }
  93590. function compareArrays(array1, array2) {
  93591. if (array1 === array2)
  93592. return true;
  93593. if (_isArray(array1) && _isArray(array2) && array1.length === array2.length) {
  93594. for (var i = 0, ii = array1.length; i < ii; ++i)
  93595. if (!compareFloats(array1[i], array2[i]))
  93596. return false;
  93597. return true
  93598. }
  93599. return false
  93600. }
  93601. var __BarWrapper = BarWrapper;
  93602. DX.viz.gauges.__tests.BarWrapper = __BarWrapper;
  93603. DX.viz.gauges.__tests.stubBarWrapper = function(barWrapperType) {
  93604. BarWrapper = barWrapperType
  93605. };
  93606. DX.viz.gauges.__tests.restoreBarWrapper = function() {
  93607. BarWrapper = __BarWrapper
  93608. }
  93609. })(DevExpress, jQuery);
  93610. /*! Module viz-gauges, file tracker.js */
  93611. (function(DX, $, undefined) {
  93612. var _abs = Math.abs,
  93613. TOOLTIP_SHOW_DELAY = 300,
  93614. TOOLTIP_HIDE_DELAY = 300,
  93615. TOOLTIP_TOUCH_SHOW_DELAY = 400,
  93616. TOOLTIP_TOUCH_HIDE_DELAY = 300;
  93617. DX.viz.gauges.__internals.Tracker = DX.Class.inherit({
  93618. ctor: function(parameters) {
  93619. DX.utils.debug.assertParam(parameters, 'parameters');
  93620. DX.utils.debug.assertParam(parameters.renderer, 'parameters.renderer');
  93621. DX.utils.debug.assertParam(parameters.container, 'parameters.container');
  93622. var that = this;
  93623. that._container = parameters.container;
  93624. that._element = parameters.renderer.g().attr({
  93625. 'class': 'dxg-tracker',
  93626. stroke: 'none',
  93627. "stroke-width": 0,
  93628. fill: '#000000',
  93629. opacity: 0.0001
  93630. });
  93631. that._showTooltipCallback = function() {
  93632. that._showTooltipTimeout = null;
  93633. var target = that._tooltipEvent.target,
  93634. data = $(target).data();
  93635. that._targetEvent = null;
  93636. if (that._tooltipTarget !== target && that._callbacks['tooltip-show'](data.target, data.info))
  93637. that._tooltipTarget = target
  93638. };
  93639. that._hideTooltipCallback = function() {
  93640. that._hideTooltipTimeout = null;
  93641. that._targetEvent = null;
  93642. if (that._tooltipTarget) {
  93643. that._callbacks['tooltip-hide']();
  93644. that._tooltipTarget = null
  93645. }
  93646. };
  93647. that._dispose = function() {
  93648. clearTimeout(that._showTooltipTimeout);
  93649. clearTimeout(that._hideTooltipTimeout);
  93650. that._showTooltipCallback = that._hideTooltipCallback = that._dispose = null
  93651. };
  93652. that._DEBUG_showTooltipTimeoutSet = that._DEBUG_showTooltipTimeoutCleared = that._DEBUG_hideTooltipTimeoutSet = that._DEBUG_hideTooltipTimeoutCleared = 0;
  93653. that.TOOLTIP_SHOW_DELAY = TOOLTIP_SHOW_DELAY;
  93654. that.TOOLTIP_HIDE_DELAY = TOOLTIP_HIDE_DELAY;
  93655. that.TOOLTIP_TOUCH_SHOW_DELAY = TOOLTIP_TOUCH_SHOW_DELAY;
  93656. that.TOOLTIP_TOUCH_HIDE_DELAY = TOOLTIP_TOUCH_HIDE_DELAY
  93657. },
  93658. dispose: function() {
  93659. var that = this;
  93660. that._dispose();
  93661. that.deactivate();
  93662. that._element.remove();
  93663. that._container = that._element = that._context = that._callbacks = null;
  93664. return that
  93665. },
  93666. activate: function() {
  93667. this._element.append(this._container);
  93668. return this
  93669. },
  93670. deactivate: function() {
  93671. this._element.remove().clear();
  93672. return this
  93673. },
  93674. attach: function(element, target, info) {
  93675. element.data({
  93676. target: target,
  93677. info: info
  93678. }).append(this._element);
  93679. return this
  93680. },
  93681. detach: function(element) {
  93682. element.remove();
  93683. return this
  93684. },
  93685. setTooltipState: function(state) {
  93686. var that = this,
  93687. data;
  93688. that._element.off(tooltipMouseEvents).off(tooltipTouchEvents).off(tooltipMouseWheelEvents);
  93689. if (state) {
  93690. data = {tracker: that};
  93691. that._element.on(tooltipMouseEvents, data).on(tooltipTouchEvents, data).on(tooltipMouseWheelEvents, data)
  93692. }
  93693. return that
  93694. },
  93695. setCallbacks: function(callbacks) {
  93696. this._callbacks = callbacks;
  93697. return this
  93698. },
  93699. _showTooltip: function(event, delay) {
  93700. var that = this;
  93701. that._hideTooltipTimeout && ++that._DEBUG_hideTooltipTimeoutCleared;
  93702. clearTimeout(that._hideTooltipTimeout);
  93703. that._hideTooltipTimeout = null;
  93704. if (that._tooltipTarget === event.target)
  93705. return;
  93706. clearTimeout(that._showTooltipTimeout);
  93707. that._tooltipEvent = event;
  93708. ++that._DEBUG_showTooltipTimeoutSet;
  93709. that._showTooltipTimeout = setTimeout(that._showTooltipCallback, delay)
  93710. },
  93711. _hideTooltip: function(delay) {
  93712. var that = this;
  93713. that._showTooltipTimeout && ++that._DEBUG_showTooltipTimeoutCleared;
  93714. clearTimeout(that._showTooltipTimeout);
  93715. that._showTooltipTimeout = null;
  93716. clearTimeout(that._hideTooltipTimeout);
  93717. if (delay) {
  93718. ++that._DEBUG_hideTooltipTimeoutSet;
  93719. that._hideTooltipTimeout = setTimeout(that._hideTooltipCallback, delay)
  93720. }
  93721. else
  93722. that._hideTooltipCallback()
  93723. }
  93724. });
  93725. var tooltipMouseEvents = {
  93726. 'mouseover.gauge-tooltip': handleTooltipMouseOver,
  93727. 'mouseout.gauge-tooltip': handleTooltipMouseOut
  93728. };
  93729. var tooltipMouseMoveEvents = {'mousemove.gauge-tooltip': handleTooltipMouseMove};
  93730. var tooltipMouseWheelEvents = {'dxmousewheel.gauge-tooltip': handleTooltipMouseWheel};
  93731. var tooltipTouchEvents = {'touchstart.gauge-tooltip': handleTooltipTouchStart};
  93732. function handleTooltipMouseOver(event) {
  93733. var tracker = event.data.tracker;
  93734. tracker._x = event.pageX;
  93735. tracker._y = event.pageY;
  93736. tracker._element.off(tooltipMouseMoveEvents).on(tooltipMouseMoveEvents, event.data);
  93737. tracker._showTooltip(event, TOOLTIP_SHOW_DELAY)
  93738. }
  93739. function handleTooltipMouseMove(event) {
  93740. var tracker = event.data.tracker;
  93741. if (tracker._showTooltipTimeout && _abs(event.pageX - tracker._x) > 4 || _abs(event.pageY - tracker._y) > 4) {
  93742. tracker._x = event.pageX;
  93743. tracker._y = event.pageY;
  93744. tracker._showTooltip(event, TOOLTIP_SHOW_DELAY)
  93745. }
  93746. }
  93747. function handleTooltipMouseOut(event) {
  93748. var tracker = event.data.tracker;
  93749. tracker._element.off(tooltipMouseMoveEvents);
  93750. tracker._hideTooltip(TOOLTIP_HIDE_DELAY)
  93751. }
  93752. function handleTooltipMouseWheel(event) {
  93753. event.data.tracker._hideTooltip()
  93754. }
  93755. var active_touch_tooltip_tracker = null;
  93756. DX.viz.gauges.__internals.Tracker._DEBUG_reset = function() {
  93757. active_touch_tooltip_tracker = null
  93758. };
  93759. function handleTooltipTouchStart(event) {
  93760. event.preventDefault();
  93761. var tracker = active_touch_tooltip_tracker;
  93762. if (tracker && tracker !== event.data.tracker)
  93763. tracker._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY);
  93764. tracker = active_touch_tooltip_tracker = event.data.tracker;
  93765. tracker._showTooltip(event, TOOLTIP_TOUCH_SHOW_DELAY);
  93766. tracker._touch = true
  93767. }
  93768. function handleTooltipDocumentTouchStart() {
  93769. var tracker = active_touch_tooltip_tracker;
  93770. if (tracker) {
  93771. if (!tracker._touch) {
  93772. tracker._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY);
  93773. active_touch_tooltip_tracker = null
  93774. }
  93775. tracker._touch = null
  93776. }
  93777. }
  93778. function handleTooltipDocumentTouchEnd() {
  93779. var tracker = active_touch_tooltip_tracker;
  93780. if (tracker)
  93781. if (tracker._showTooltipTimeout) {
  93782. tracker._hideTooltip(TOOLTIP_TOUCH_HIDE_DELAY);
  93783. active_touch_tooltip_tracker = null
  93784. }
  93785. }
  93786. $(window.document).on({
  93787. 'touchstart.gauge-tooltip': handleTooltipDocumentTouchStart,
  93788. 'touchend.gauge-tooltip': handleTooltipDocumentTouchEnd
  93789. })
  93790. })(DevExpress, jQuery);
  93791. DevExpress.MOD_VIZ_GAUGES = true
  93792. }
  93793. if (!DevExpress.MOD_VIZ_RANGESELECTOR) {
  93794. if (!DevExpress.MOD_VIZ_CORE)
  93795. throw Error('Required module is not referenced: viz-core');
  93796. /*! Module viz-rangeselector, file namespaces.js */
  93797. (function(DevExpress) {
  93798. DevExpress.viz.rangeSelector = {}
  93799. })(DevExpress);
  93800. /*! Module viz-rangeselector, file utils.js */
  93801. (function($, DX, undefined) {
  93802. var dxUtils = DX.utils;
  93803. var findLessOrEqualValueIndex = function(values, value) {
  93804. if (!values || values.length === 0)
  93805. return -1;
  93806. var minIndex = 0,
  93807. maxIndex = values.length - 1;
  93808. while (maxIndex - minIndex > 1) {
  93809. var index = minIndex + maxIndex >> 1;
  93810. if (values[index] > value)
  93811. maxIndex = index;
  93812. else
  93813. minIndex = index
  93814. }
  93815. return values[maxIndex] <= value ? maxIndex : minIndex
  93816. };
  93817. var findLessOrEqualValue = function(values, value) {
  93818. var index = findLessOrEqualValueIndex(values, value);
  93819. if (values && index >= 0 && index < values.length)
  93820. return values[index];
  93821. return value
  93822. };
  93823. var findNearValue = function(values, value) {
  93824. var index = findLessOrEqualValueIndex(values, value);
  93825. if (values && index >= 0 && index < values.length) {
  93826. if (index + 1 < values.length)
  93827. if (dxUtils.isDate(value)) {
  93828. if (values[index + 1].getTime() - value.getTime() < value.getTime() - values[index].getTime())
  93829. index++
  93830. }
  93831. else if (values[index + 1] - value < value - values[index])
  93832. index++;
  93833. return values[index]
  93834. }
  93835. return value
  93836. };
  93837. var findGreaterOrEqualValue = function(values, value) {
  93838. var index = findLessOrEqualValueIndex(values, value);
  93839. if (values && index >= 0 && index < values.length) {
  93840. if (values[index] < value && index + 1 < values.length)
  93841. index++;
  93842. return values[index]
  93843. }
  93844. return value
  93845. };
  93846. var getEventPageX = function(eventArgs) {
  93847. var result = 0;
  93848. if (eventArgs.pageX)
  93849. result = eventArgs.pageX;
  93850. else if (eventArgs.originalEvent && eventArgs.originalEvent.pageX)
  93851. result = eventArgs.originalEvent.pageX;
  93852. if (eventArgs.originalEvent && eventArgs.originalEvent.touches)
  93853. if (eventArgs.originalEvent.touches.length > 0)
  93854. result = eventArgs.originalEvent.touches[0].pageX;
  93855. else if (eventArgs.originalEvent.changedTouches.length > 0)
  93856. result = eventArgs.originalEvent.changedTouches[0].pageX;
  93857. return result
  93858. };
  93859. var truncateSelectedRange = function(value, scaleOptions) {
  93860. var isDiscrete = scaleOptions.type === 'discrete',
  93861. categories = isDiscrete ? scaleOptions._categoriesInfo.categories : undefined,
  93862. startValue = scaleOptions.startValue,
  93863. endValue = scaleOptions.endValue,
  93864. min,
  93865. max,
  93866. valueIndex;
  93867. if (isDiscrete) {
  93868. valueIndex = $.inArray(value, categories);
  93869. return valueIndex < 0 ? startValue : value
  93870. }
  93871. else
  93872. min = startValue > endValue ? endValue : startValue,
  93873. max = startValue > endValue ? startValue : endValue;
  93874. if (value < min)
  93875. value = min;
  93876. if (value > max)
  93877. value = max;
  93878. return value
  93879. };
  93880. DX.viz.rangeSelector.utils = {
  93881. findLessOrEqualValue: findLessOrEqualValue,
  93882. findNearValue: findNearValue,
  93883. findGreaterOrEqualValue: findGreaterOrEqualValue,
  93884. getEventPageX: getEventPageX,
  93885. truncateSelectedRange: truncateSelectedRange,
  93886. trackerSettings: {
  93887. fill: 'grey',
  93888. stroke: 'grey',
  93889. opacity: 0.0001
  93890. },
  93891. animationSettings: {duration: 250}
  93892. }
  93893. })(jQuery, DevExpress);
  93894. /*! Module viz-rangeselector, file baseVisualElementMethods.js */
  93895. (function(DX) {
  93896. DX.viz.rangeSelector.baseVisualElementMethods = {
  93897. init: function(renderer) {
  93898. this._renderer = renderer;
  93899. this._isDrawn = false
  93900. },
  93901. applyOptions: function(options) {
  93902. this._options = options || {};
  93903. this._applyOptions(this._options)
  93904. },
  93905. _applyOptions: function(){},
  93906. redraw: function(group) {
  93907. var that = this;
  93908. if (!that._isDrawn) {
  93909. that._isDrawn = that._draw(group || that._group) !== false;
  93910. if (group)
  93911. that._group = group
  93912. }
  93913. else
  93914. that._update(group || that._group)
  93915. },
  93916. isDrawn: function() {
  93917. return !!this._isDrawn
  93918. },
  93919. isInitialized: function() {
  93920. return !!this._options
  93921. },
  93922. _draw: function(){},
  93923. _update: function(group) {
  93924. group.clear();
  93925. this._draw(group)
  93926. }
  93927. }
  93928. })(DevExpress);
  93929. /*! Module viz-rangeselector, file rangeSelector.js */
  93930. (function($, DX, undefined) {
  93931. var rangeSelector = DX.viz.rangeSelector,
  93932. utils = DX.utils,
  93933. core = DX.viz.core,
  93934. patchFontOptions = core.utils.patchFontOptions,
  93935. ParseUtils = core.ParseUtils,
  93936. formatHelper = DX.formatHelper,
  93937. SCALE_TEXT_SPACING = 5,
  93938. HEIGHT_COMPACT_MODE = 24,
  93939. POINTER_SIZE = 4,
  93940. EMPTY_SLIDER_MARKER_TEXT = '. . .',
  93941. _isDefined = utils.isDefined,
  93942. _isNumber = utils.isNumber,
  93943. _isDate = utils.isDate,
  93944. _max = Math.max,
  93945. _ceil = Math.ceil,
  93946. START_VALUE = 'startValue',
  93947. END_VALUE = 'endValue',
  93948. DATETIME = 'datetime',
  93949. SELECTED_RANGE = 'selectedRange',
  93950. DISCRETE = 'discrete',
  93951. STRING = 'string',
  93952. SELECTED_RANGE_CHANGED = SELECTED_RANGE + 'Changed',
  93953. CONTAINER_BACKGROUND_COLOR = "containerBackgroundColor",
  93954. SLIDER_MARKER = "sliderMarker",
  93955. BACKGROUND = "background",
  93956. LOGARITHMIC = "logarithmic",
  93957. INVISIBLE_POS = -1000,
  93958. logarithmBase = 10;
  93959. rangeSelector.consts = {
  93960. emptySliderMarkerText: EMPTY_SLIDER_MARKER_TEXT,
  93961. pointerSize: POINTER_SIZE
  93962. };
  93963. rangeSelector.HEIGHT_COMPACT_MODE = HEIGHT_COMPACT_MODE;
  93964. rangeSelector.__getTextBBox = getTextBBox;
  93965. function cloneSelectedRange(arg) {
  93966. return {
  93967. startValue: arg.startValue,
  93968. endValue: arg.endValue
  93969. }
  93970. }
  93971. var formatValue = rangeSelector.formatValue = function(value, formatOptions) {
  93972. var formatObject = {
  93973. value: value,
  93974. valueText: formatHelper.format(value, formatOptions.format, formatOptions.precision)
  93975. };
  93976. return String(utils.isFunction(formatOptions.customizeText) ? formatOptions.customizeText.call(formatObject, formatObject) : formatObject.valueText)
  93977. };
  93978. var createRangeContainer = function(rangeContainerOptions) {
  93979. return rangeSelector.rangeSelectorFactory.createRangeContainer(rangeContainerOptions)
  93980. };
  93981. var createTranslator = function(range, canvas) {
  93982. return {
  93983. x: core.CoreFactory.createTranslator2D(range.arg, canvas, {direction: "horizontal"}),
  93984. y: core.CoreFactory.createTranslator2D(range.val, canvas)
  93985. }
  93986. };
  93987. var createTranslatorCanvas = function(sizeOptions, rangeContainerCanvas, scaleLabelsAreaHeight) {
  93988. return {
  93989. left: rangeContainerCanvas.left,
  93990. top: rangeContainerCanvas.top,
  93991. right: sizeOptions.width - rangeContainerCanvas.width - rangeContainerCanvas.left,
  93992. bottom: sizeOptions.height - rangeContainerCanvas.height - rangeContainerCanvas.top + scaleLabelsAreaHeight,
  93993. width: sizeOptions.width,
  93994. height: sizeOptions.height
  93995. }
  93996. };
  93997. var calculateMarkerHeight = function(renderer, value, sliderMarkerOptions) {
  93998. var formattedText = value === undefined ? EMPTY_SLIDER_MARKER_TEXT : formatValue(value, sliderMarkerOptions),
  93999. textBBox = getTextBBox(renderer, formattedText, sliderMarkerOptions.font);
  94000. return _ceil(textBBox.height) + 2 * sliderMarkerOptions.paddingTopBottom + POINTER_SIZE
  94001. };
  94002. var calculateScaleLabelHalfWidth = function(renderer, value, scaleOptions) {
  94003. var formattedText = formatValue(value, scaleOptions.label),
  94004. textBBox = getTextBBox(renderer, formattedText, scaleOptions.label.font);
  94005. return _ceil(textBBox.width / 2)
  94006. };
  94007. var calculateRangeContainerCanvas = function(size, indents, scaleLabelsAreaHeight, isCompactMode) {
  94008. var canvas = {
  94009. left: size.left + indents.left,
  94010. top: size.top + indents.top,
  94011. width: size.width - size.left - size.right - indents.left - indents.right,
  94012. height: !isCompactMode ? size.height - size.top - size.bottom - indents.top : HEIGHT_COMPACT_MODE + scaleLabelsAreaHeight
  94013. };
  94014. if (canvas.width <= 0)
  94015. canvas.width = 1;
  94016. return canvas
  94017. };
  94018. var parseSliderMarkersPlaceholderSize = function(placeholderSize) {
  94019. var placeholderWidthLeft,
  94020. placeholderWidthRight,
  94021. placeholderHeight;
  94022. if (_isNumber(placeholderSize))
  94023. placeholderWidthLeft = placeholderWidthRight = placeholderHeight = placeholderSize;
  94024. else if (placeholderSize) {
  94025. if (_isNumber(placeholderSize.height))
  94026. placeholderHeight = placeholderSize.height;
  94027. if (_isNumber(placeholderSize.width))
  94028. placeholderWidthLeft = placeholderWidthRight = placeholderSize.width;
  94029. else if (placeholderSize.width) {
  94030. if (_isNumber(placeholderSize.width.left))
  94031. placeholderWidthLeft = placeholderSize.width.left;
  94032. if (_isNumber(placeholderSize.width.right))
  94033. placeholderWidthRight = placeholderSize.width.right
  94034. }
  94035. }
  94036. else
  94037. return null;
  94038. return {
  94039. widthLeft: placeholderWidthLeft,
  94040. widthRight: placeholderWidthRight,
  94041. height: placeholderHeight
  94042. }
  94043. };
  94044. var calculateIndents = function(renderer, size, scale, sliderMarkerOptions, indentOptions) {
  94045. var leftMarkerHeight,
  94046. leftScaleLabelWidth = 0,
  94047. rightScaleLabelWidth = 0,
  94048. rightMarkerHeight,
  94049. placeholderWidthLeft = 0,
  94050. placeholderWidthRight = 0,
  94051. placeholderHeight,
  94052. parsedPlaceholderSize;
  94053. indentOptions = indentOptions || {};
  94054. parsedPlaceholderSize = parseSliderMarkersPlaceholderSize(sliderMarkerOptions.placeholderSize);
  94055. if (parsedPlaceholderSize && indentOptions.left === undefined && indentOptions.right === undefined) {
  94056. placeholderWidthLeft = parsedPlaceholderSize.widthLeft;
  94057. placeholderWidthRight = parsedPlaceholderSize.widthRight
  94058. }
  94059. else {
  94060. placeholderWidthLeft = indentOptions.left;
  94061. placeholderWidthRight = indentOptions.right
  94062. }
  94063. if (parsedPlaceholderSize && sliderMarkerOptions.placeholderHeight === undefined)
  94064. placeholderHeight = parsedPlaceholderSize.height;
  94065. else
  94066. placeholderHeight = sliderMarkerOptions.placeholderHeight;
  94067. if (sliderMarkerOptions.visible) {
  94068. leftMarkerHeight = calculateMarkerHeight(renderer, scale.startValue, sliderMarkerOptions);
  94069. rightMarkerHeight = calculateMarkerHeight(renderer, scale.endValue, sliderMarkerOptions);
  94070. if (placeholderHeight === undefined)
  94071. placeholderHeight = _max(leftMarkerHeight, rightMarkerHeight)
  94072. }
  94073. if (scale.label.visible) {
  94074. leftScaleLabelWidth = calculateScaleLabelHalfWidth(renderer, scale.startValue, scale);
  94075. rightScaleLabelWidth = calculateScaleLabelHalfWidth(renderer, scale.endValue, scale)
  94076. }
  94077. placeholderWidthLeft = placeholderWidthLeft !== undefined ? placeholderWidthLeft : leftScaleLabelWidth;
  94078. placeholderWidthRight = (placeholderWidthRight !== undefined ? placeholderWidthRight : rightScaleLabelWidth) || 1;
  94079. return {
  94080. left: placeholderWidthLeft,
  94081. right: placeholderWidthRight,
  94082. top: placeholderHeight || 0,
  94083. bottom: 0
  94084. }
  94085. };
  94086. var calculateValueType = function(firstValue, secondValue) {
  94087. var typeFirstValue = $.type(firstValue),
  94088. typeSecondValue = $.type(secondValue),
  94089. validType = function(type) {
  94090. return typeFirstValue === type || typeSecondValue === type
  94091. };
  94092. return validType('date') ? DATETIME : validType('number') ? 'numeric' : validType(STRING) ? STRING : ''
  94093. };
  94094. var showScaleMarkers = function(scaleOptions) {
  94095. return scaleOptions.valueType === DATETIME && scaleOptions.marker.visible
  94096. };
  94097. var updateTranslatorRangeInterval = function(translatorRange, scaleOptions) {
  94098. var intervalX = scaleOptions.minorTickInterval || scaleOptions.majorTickInterval;
  94099. if (scaleOptions.valueType === "datetime")
  94100. intervalX = utils.dateToMilliseconds(intervalX);
  94101. translatorRange = translatorRange.arg.addRange({interval: intervalX})
  94102. };
  94103. var createRange = function(options) {
  94104. return new core.Range(options)
  94105. };
  94106. var checkLogarithmicOptions = function(options, defaultLogarithmBase, incidentOccured) {
  94107. var logarithmBase;
  94108. if (!options)
  94109. return;
  94110. logarithmBase = options.logarithmBase;
  94111. if (options.type === LOGARITHMIC && logarithmBase <= 0 || logarithmBase && !_isNumber(logarithmBase)) {
  94112. options.logarithmBase = defaultLogarithmBase;
  94113. incidentOccured('E2104')
  94114. }
  94115. else if (options.type !== LOGARITHMIC)
  94116. options.logarithmBase = undefined
  94117. };
  94118. var calculateScaleAreaHeight = function(renderer, scaleOptions, visibleMarkers) {
  94119. var textBBox,
  94120. value = "0",
  94121. formatObject = {
  94122. value: 0,
  94123. valueText: value
  94124. },
  94125. labelScaleOptions = scaleOptions.label,
  94126. markerScaleOPtions = scaleOptions.marker,
  94127. customizeText = labelScaleOptions.customizeText,
  94128. placeholderHeight = scaleOptions.placeholderHeight,
  94129. text = utils.isFunction(customizeText) ? customizeText.call(formatObject, formatObject) : value,
  94130. visibleLabels = labelScaleOptions.visible;
  94131. if (placeholderHeight)
  94132. return placeholderHeight;
  94133. else {
  94134. textBBox = getTextBBox(renderer, text, labelScaleOptions.font);
  94135. return (visibleLabels ? labelScaleOptions.topIndent + textBBox.height : 0) + (visibleMarkers ? markerScaleOPtions.topIndent + markerScaleOPtions.separatorHeight : 0)
  94136. }
  94137. };
  94138. var updateTickIntervals = function(scaleOptions, screenDelta, incidentOccured, stick, min, max) {
  94139. var categoriesInfo = scaleOptions._categoriesInfo,
  94140. tickManager = core.CoreFactory.createTickManager({
  94141. axisType: scaleOptions.type,
  94142. dataType: scaleOptions.valueType
  94143. }, {
  94144. min: min,
  94145. max: max,
  94146. screenDelta: screenDelta,
  94147. customTicks: categoriesInfo && categoriesInfo.categories
  94148. }, {
  94149. labelOptions: {},
  94150. boundCoef: 1,
  94151. minorTickInterval: scaleOptions.minorTickInterval,
  94152. tickInterval: scaleOptions.majorTickInterval,
  94153. incidentOccured: incidentOccured,
  94154. base: scaleOptions.logarithmBase,
  94155. showMinorTicks: true,
  94156. withMinorCorrection: true,
  94157. stick: stick !== false
  94158. });
  94159. tickManager.getTicks(true);
  94160. return {
  94161. majorTickInterval: tickManager.getTickInterval(),
  94162. minorTickInterval: tickManager.getMinorTickInterval(),
  94163. bounds: tickManager.getTickBounds()
  94164. }
  94165. };
  94166. var calculateTranslatorRange = function(seriesDataSource, scaleOptions) {
  94167. var minValue,
  94168. maxValue,
  94169. inverted = false,
  94170. isEqualDates,
  94171. startValue = scaleOptions.startValue,
  94172. endValue = scaleOptions.endValue,
  94173. categories,
  94174. categoriesInfo,
  94175. translatorRange = seriesDataSource ? seriesDataSource.getBoundRange() : {
  94176. arg: createRange(),
  94177. val: createRange({isValueRange: true})
  94178. },
  94179. rangeForCategories;
  94180. if (scaleOptions.type === DISCRETE) {
  94181. rangeForCategories = createRange({
  94182. categories: scaleOptions.categories || (!seriesDataSource && startValue && endValue ? [startValue, endValue] : undefined),
  94183. minVisible: startValue,
  94184. maxVisible: endValue
  94185. });
  94186. rangeForCategories.addRange(translatorRange.arg);
  94187. translatorRange.arg = rangeForCategories;
  94188. categories = rangeForCategories.categories || [];
  94189. scaleOptions._categoriesInfo = categoriesInfo = utils.getCategoriesInfo(categories, startValue || categories[0], endValue || categories[categories.length - 1])
  94190. }
  94191. if (_isDefined(startValue) && _isDefined(endValue)) {
  94192. inverted = scaleOptions.inverted = categoriesInfo ? categoriesInfo.inverted : startValue > endValue;
  94193. minValue = categoriesInfo ? categoriesInfo.start : inverted ? endValue : startValue;
  94194. maxValue = categoriesInfo ? categoriesInfo.end : inverted ? startValue : endValue
  94195. }
  94196. else if (_isDefined(startValue) || _isDefined(endValue)) {
  94197. minValue = startValue;
  94198. maxValue = endValue
  94199. }
  94200. else if (categoriesInfo) {
  94201. minValue = categoriesInfo.start;
  94202. maxValue = categoriesInfo.end
  94203. }
  94204. isEqualDates = _isDate(minValue) && _isDate(maxValue) && minValue.getTime() === maxValue.getTime();
  94205. if (minValue !== maxValue && !isEqualDates)
  94206. translatorRange.arg.addRange({
  94207. invert: inverted,
  94208. min: minValue,
  94209. max: maxValue,
  94210. minVisible: minValue,
  94211. maxVisible: maxValue,
  94212. dataType: scaleOptions.valueType
  94213. });
  94214. translatorRange.arg.addRange({
  94215. base: scaleOptions.logarithmBase,
  94216. axisType: scaleOptions.type
  94217. });
  94218. if (!translatorRange.arg.isDefined()) {
  94219. if (isEqualDates)
  94220. scaleOptions.valueType = 'numeric';
  94221. translatorRange.arg.setStubData(scaleOptions.valueType)
  94222. }
  94223. return translatorRange
  94224. };
  94225. var startEndNotDefined = function(start, end) {
  94226. return !_isDefined(start) || !_isDefined(end)
  94227. };
  94228. function getTextBBox(renderer, text, fontOptions) {
  94229. var textElement = renderer.text(text, INVISIBLE_POS, INVISIBLE_POS).css(patchFontOptions(fontOptions)).append(renderer.root);
  94230. var textBBox = textElement.getBBox();
  94231. textElement.remove();
  94232. return textBBox
  94233. }
  94234. function processValue(selectedRangeOptions, scaleOptions, entity, incidentOccured) {
  94235. var parsedValue,
  94236. value = selectedRangeOptions[entity],
  94237. parser = scaleOptions.parser || function() {
  94238. return null
  94239. },
  94240. resultValue = scaleOptions[entity];
  94241. if (_isDefined(value))
  94242. parsedValue = parser(value);
  94243. if (!_isDefined(parsedValue))
  94244. incidentOccured("E2203", [entity]);
  94245. else
  94246. resultValue = parsedValue;
  94247. return rangeSelector.utils.truncateSelectedRange(resultValue, scaleOptions)
  94248. }
  94249. DX.registerComponent("dxRangeSelector", rangeSelector, core.BaseWidget.inherit({
  94250. _eventsMap: $.extend({}, core.BaseWidget.prototype._eventsMap, {
  94251. onSelectedRangeChanged: {
  94252. name: SELECTED_RANGE_CHANGED,
  94253. deprecated: SELECTED_RANGE_CHANGED,
  94254. deprecatedContext: function() {
  94255. return null
  94256. },
  94257. deprecatedArgs: function(arg) {
  94258. return [cloneSelectedRange(arg)]
  94259. }
  94260. },
  94261. selectedRangeChanged: {newName: "onSelectedRangeChanged"}
  94262. }),
  94263. _setDeprecatedOptions: function() {
  94264. this.callBase();
  94265. $.extend(this._deprecatedOptions, {
  94266. selectedRangeChanged: {
  94267. since: "14.2",
  94268. message: "Use the 'onSelectedRangeChanged' option instead"
  94269. },
  94270. "sliderMarker.padding": {
  94271. since: "15.1",
  94272. message: "Use the 'paddingTopBottom' and 'paddingLeftRight' options instead"
  94273. },
  94274. "sliderMarker.placeholderSize": {
  94275. since: "15.1",
  94276. message: "Use the 'placeholderHeight' and 'indent' options instead"
  94277. }
  94278. })
  94279. },
  94280. _rootClassPrefix: "dxrs",
  94281. _rootClass: "dxrs-range-selector",
  94282. _dataSourceOptions: function() {
  94283. return {paginate: false}
  94284. },
  94285. _dataIsReady: function() {
  94286. return this._isDataSourceReady()
  94287. },
  94288. _initCore: function() {
  94289. var that = this;
  94290. that.rangeContainer = createRangeContainer(that._renderer);
  94291. that._reinitDataSource();
  94292. that._renderer.root.css({
  94293. "touch-action": "pan-y",
  94294. "-ms-touch-action": "pan-y"
  94295. })
  94296. },
  94297. _initTooltip: $.noop,
  94298. _setTooltipRendererOptions: $.noop,
  94299. _setTooltipOptions: $.noop,
  94300. _getDefaultSize: function() {
  94301. return {
  94302. width: 400,
  94303. height: 160
  94304. }
  94305. },
  94306. _handleLoadingIndicatorShown: $.noop,
  94307. _reinitDataSource: function() {
  94308. this._refreshDataSource()
  94309. },
  94310. _disposeCore: function() {
  94311. var that = this,
  94312. disposeObject = function(propName) {
  94313. that[propName] && that[propName].dispose(),
  94314. that[propName] = null
  94315. };
  94316. that.callBase();
  94317. disposeObject("renderer");
  94318. that.translators = null;
  94319. disposeObject("rangeContainer")
  94320. },
  94321. _createThemeManager: function() {
  94322. return rangeSelector.rangeSelectorFactory.createThemeManager()
  94323. },
  94324. _refresh: function() {
  94325. var that = this,
  94326. callBase = that.callBase;
  94327. that._endLoading(function() {
  94328. callBase.call(that)
  94329. })
  94330. },
  94331. _render: function(isResizing) {
  94332. var that = this,
  94333. currentAnimationEnabled,
  94334. renderer = that._renderer;
  94335. isResizing = isResizing || that.__isResizing;
  94336. that._applyOptions();
  94337. if (isResizing) {
  94338. currentAnimationEnabled = renderer.animationEnabled();
  94339. renderer.updateAnimationOptions({enabled: false});
  94340. that.rangeContainer.redraw();
  94341. renderer.updateAnimationOptions({enabled: currentAnimationEnabled})
  94342. }
  94343. else
  94344. that.rangeContainer.redraw();
  94345. !isResizing && (!that._dataSource || that._dataSource && that._dataSource.isLoaded()) && that.hideLoadingIndicator();
  94346. that._drawn();
  94347. that.__rendered && that.__rendered()
  94348. },
  94349. _optionChanged: function(args) {
  94350. var that = this,
  94351. name = args.name;
  94352. if (name === "dataSource")
  94353. that._reinitDataSource();
  94354. else if (name === SELECTED_RANGE)
  94355. that.setSelectedRange(that.option(SELECTED_RANGE));
  94356. else
  94357. that.callBase(args)
  94358. },
  94359. _applySize: $.noop,
  94360. _resize: function() {
  94361. this._render(true)
  94362. },
  94363. _dataSourceChangedHandler: function() {
  94364. var that = this;
  94365. that._endLoading(function() {
  94366. if (that._renderer.drawn)
  94367. that._render()
  94368. })
  94369. },
  94370. _applyOptions: function() {
  94371. var that = this,
  94372. rangeContainerCanvas,
  94373. seriesDataSource,
  94374. translatorRange,
  94375. scaleLabelsAreaHeight,
  94376. sizeOptions = that._canvas,
  94377. indents,
  94378. sliderMarkerOptions,
  94379. selectedRange,
  94380. chartOptions = that.option('chart'),
  94381. shutterOptions = that._getOption("shutter"),
  94382. background = that._getOption(BACKGROUND),
  94383. isCompactMode,
  94384. scaleOptions,
  94385. chartThemeManager;
  94386. that._isUpdating = true;
  94387. seriesDataSource = that._createSeriesDataSource(chartOptions);
  94388. isCompactMode = !(seriesDataSource && seriesDataSource.isShowChart() || background && background.image && background.image.url);
  94389. if (seriesDataSource) {
  94390. chartThemeManager = seriesDataSource.getThemeManager();
  94391. checkLogarithmicOptions(chartOptions && chartOptions.valueAxis, chartThemeManager.getOptions("valueAxis").logarithmBase, that._incidentOccured)
  94392. }
  94393. scaleOptions = that._scaleOptions = that._prepareScaleOptions(seriesDataSource);
  94394. translatorRange = calculateTranslatorRange(seriesDataSource, scaleOptions);
  94395. that._updateScaleOptions(seriesDataSource, translatorRange.arg, sizeOptions.width);
  94396. updateTranslatorRangeInterval(translatorRange, scaleOptions);
  94397. sliderMarkerOptions = that._prepareSliderMarkersOptions(sizeOptions.width);
  94398. selectedRange = that._initSelection();
  94399. indents = calculateIndents(that._renderer, sizeOptions, scaleOptions, sliderMarkerOptions, that.option("indent"));
  94400. scaleLabelsAreaHeight = calculateScaleAreaHeight(that._renderer, scaleOptions, showScaleMarkers(scaleOptions));
  94401. rangeContainerCanvas = calculateRangeContainerCanvas(sizeOptions, indents, scaleLabelsAreaHeight, isCompactMode);
  94402. that.translators = createTranslator(translatorRange, createTranslatorCanvas(sizeOptions, rangeContainerCanvas, scaleLabelsAreaHeight));
  94403. scaleOptions.ticksInfo = that._getTicksInfo(rangeContainerCanvas.width);
  94404. that._testTicksInfo = scaleOptions.ticksInfo;
  94405. that._selectedRange = selectedRange;
  94406. if (seriesDataSource)
  94407. seriesDataSource.adjustSeriesDimensions(that.translators);
  94408. shutterOptions.color = shutterOptions.color || that._getOption(CONTAINER_BACKGROUND_COLOR, true);
  94409. that.rangeContainer.applyOptions({
  94410. canvas: rangeContainerCanvas,
  94411. isCompactMode: isCompactMode,
  94412. scaleLabelsAreaHeight: scaleLabelsAreaHeight,
  94413. indents: indents,
  94414. translators: that.translators,
  94415. selectedRange: selectedRange,
  94416. scale: scaleOptions,
  94417. behavior: that._getOption('behavior'),
  94418. background: background,
  94419. chart: chartOptions,
  94420. seriesDataSource: seriesDataSource,
  94421. sliderMarker: sliderMarkerOptions,
  94422. sliderHandle: that._getOption('sliderHandle'),
  94423. shutter: shutterOptions,
  94424. selectedRangeColor: that._getOption("selectedRangeColor", true),
  94425. selectedRangeChanged: function(selectedRange, blockSelectedRangeChanged) {
  94426. that.option(SELECTED_RANGE, selectedRange);
  94427. if (!blockSelectedRangeChanged)
  94428. that._eventTrigger(SELECTED_RANGE_CHANGED, cloneSelectedRange(selectedRange))
  94429. },
  94430. setSelectedRange: function(selectedRange) {
  94431. that.setSelectedRange(selectedRange)
  94432. }
  94433. });
  94434. that._isUpdating = false;
  94435. chartThemeManager && chartThemeManager.dispose()
  94436. },
  94437. _initSelection: function() {
  94438. var that = this,
  94439. scaleOptions = that._scaleOptions,
  94440. selectedRangeOptions = that.option(SELECTED_RANGE),
  94441. incidentOccured = that._incidentOccured;
  94442. if (!selectedRangeOptions)
  94443. return cloneSelectedRange(scaleOptions);
  94444. else
  94445. return {
  94446. startValue: processValue(selectedRangeOptions, scaleOptions, START_VALUE, incidentOccured),
  94447. endValue: processValue(selectedRangeOptions, scaleOptions, END_VALUE, incidentOccured)
  94448. }
  94449. },
  94450. _createSeriesDataSource: function(chartOptions) {
  94451. var that = this,
  94452. seriesDataSource,
  94453. dataSource = that._dataSource && that._dataSource.items(),
  94454. scaleOptions = that._getOption('scale'),
  94455. valueType = scaleOptions.valueType,
  94456. backgroundOption = that.option(BACKGROUND);
  94457. if (!valueType)
  94458. valueType = calculateValueType(scaleOptions.startValue, scaleOptions.endValue);
  94459. if (dataSource || chartOptions && chartOptions.series) {
  94460. chartOptions = $.extend({}, chartOptions, {theme: that.option("theme")});
  94461. seriesDataSource = new rangeSelector.SeriesDataSource({
  94462. renderer: that._renderer,
  94463. dataSource: dataSource,
  94464. valueType: (valueType || '').toLowerCase(),
  94465. axisType: scaleOptions.type,
  94466. chart: chartOptions,
  94467. dataSourceField: that.option('dataSourceField'),
  94468. backgroundColor: backgroundOption && backgroundOption.color,
  94469. incidentOccured: that._incidentOccured,
  94470. categories: scaleOptions.categories
  94471. })
  94472. }
  94473. return seriesDataSource
  94474. },
  94475. _prepareScaleOptions: function(seriesDataSource) {
  94476. var that = this,
  94477. scaleOptions = that._getOption('scale'),
  94478. parsedValue = 0,
  94479. parseUtils = new ParseUtils,
  94480. valueType = parseUtils.correctValueType((scaleOptions.valueType || '').toLowerCase()),
  94481. parser,
  94482. validateStartEndValues = function(field, parser) {
  94483. var messageToIncidentOccured = field === START_VALUE ? 'start' : 'end';
  94484. if (_isDefined(scaleOptions[field])) {
  94485. parsedValue = parser(scaleOptions[field]);
  94486. if (_isDefined(parsedValue))
  94487. scaleOptions[field] = parsedValue;
  94488. else {
  94489. scaleOptions[field] = undefined;
  94490. that._incidentOccured("E2202", [messageToIncidentOccured])
  94491. }
  94492. }
  94493. };
  94494. if (seriesDataSource)
  94495. valueType = seriesDataSource.getCalculatedValueType() || valueType;
  94496. if (!valueType)
  94497. valueType = calculateValueType(scaleOptions.startValue, scaleOptions.endValue) || 'numeric';
  94498. if (valueType === STRING || scaleOptions.categories) {
  94499. scaleOptions.type = DISCRETE;
  94500. valueType = STRING
  94501. }
  94502. scaleOptions.valueType = valueType;
  94503. parser = parseUtils.getParser(valueType, 'scale');
  94504. validateStartEndValues(START_VALUE, parser);
  94505. validateStartEndValues(END_VALUE, parser);
  94506. checkLogarithmicOptions(scaleOptions, logarithmBase, that._incidentOccured);
  94507. if (!scaleOptions.type)
  94508. scaleOptions.type = 'continuous';
  94509. scaleOptions.parser = parser;
  94510. return scaleOptions
  94511. },
  94512. _prepareSliderMarkersOptions: function(screenDelta) {
  94513. var that = this,
  94514. scaleOptions = that._scaleOptions,
  94515. minorTickInterval = scaleOptions.minorTickInterval,
  94516. majorTickInterval = scaleOptions.majorTickInterval,
  94517. endValue = scaleOptions.endValue,
  94518. startValue = scaleOptions.startValue,
  94519. sliderMarkerOptions = that._getOption(SLIDER_MARKER),
  94520. businessInterval,
  94521. sliderMarkerUserOption = that.option(SLIDER_MARKER) || {};
  94522. sliderMarkerOptions.borderColor = that._getOption(CONTAINER_BACKGROUND_COLOR, true);
  94523. if (!sliderMarkerOptions.format) {
  94524. if (!that._getOption('behavior').snapToTicks && _isNumber(scaleOptions.startValue)) {
  94525. businessInterval = Math.abs(endValue - startValue);
  94526. sliderMarkerOptions.format = 'fixedPoint';
  94527. sliderMarkerOptions.precision = utils.getSignificantDigitPosition(businessInterval / screenDelta)
  94528. }
  94529. if (scaleOptions.valueType === DATETIME)
  94530. if (!scaleOptions.marker.visible) {
  94531. if (_isDefined(startValue) && _isDefined(endValue))
  94532. sliderMarkerOptions.format = formatHelper.getDateFormatByTickInterval(startValue, endValue, minorTickInterval !== 0 ? minorTickInterval : majorTickInterval)
  94533. }
  94534. else
  94535. sliderMarkerOptions.format = utils.getDateUnitInterval(_isDefined(minorTickInterval) && minorTickInterval !== 0 ? minorTickInterval : majorTickInterval)
  94536. }
  94537. if (sliderMarkerUserOption.padding !== undefined && sliderMarkerUserOption.paddingLeftRight === undefined && sliderMarkerUserOption.paddingTopBottom === undefined)
  94538. sliderMarkerOptions.paddingLeftRight = sliderMarkerOptions.paddingTopBottom = sliderMarkerUserOption.padding;
  94539. return sliderMarkerOptions
  94540. },
  94541. _updateScaleOptions: function(seriesDataSource, translatorRange, screenDelta) {
  94542. var scaleOptions = this._scaleOptions,
  94543. min = _isDefined(translatorRange.minVisible) ? translatorRange.minVisible : translatorRange.min,
  94544. max = _isDefined(translatorRange.maxVisible) ? translatorRange.maxVisible : translatorRange.max,
  94545. tickIntervalsInfo = updateTickIntervals(scaleOptions, screenDelta, this._incidentOccured, translatorRange.stick, min, max),
  94546. bounds,
  94547. isEmptyInterval,
  94548. categoriesInfo = scaleOptions._categoriesInfo;
  94549. if (seriesDataSource && !seriesDataSource.isEmpty() && !translatorRange.stubData) {
  94550. bounds = tickIntervalsInfo.bounds;
  94551. translatorRange.addRange(bounds);
  94552. scaleOptions.startValue = scaleOptions.inverted ? bounds.maxVisible : bounds.minVisible;
  94553. scaleOptions.endValue = scaleOptions.inverted ? bounds.minVisible : bounds.maxVisible
  94554. }
  94555. if (categoriesInfo) {
  94556. scaleOptions.startValue = categoriesInfo.start;
  94557. scaleOptions.endValue = categoriesInfo.end
  94558. }
  94559. isEmptyInterval = _isDate(scaleOptions.startValue) && _isDate(scaleOptions.endValue) && scaleOptions.startValue.getTime() === scaleOptions.endValue.getTime() || scaleOptions.startValue === scaleOptions.endValue;
  94560. scaleOptions.isEmpty = startEndNotDefined(scaleOptions.startValue, scaleOptions.endValue) || isEmptyInterval;
  94561. if (scaleOptions.isEmpty)
  94562. scaleOptions.startValue = scaleOptions.endValue = undefined;
  94563. else {
  94564. scaleOptions.minorTickInterval = tickIntervalsInfo.minorTickInterval;
  94565. scaleOptions.majorTickInterval = tickIntervalsInfo.majorTickInterval;
  94566. if (scaleOptions.valueType === DATETIME && !_isDefined(scaleOptions.label.format))
  94567. if (!scaleOptions.marker.visible)
  94568. scaleOptions.label.format = formatHelper.getDateFormatByTickInterval(scaleOptions.startValue, scaleOptions.endValue, scaleOptions.majorTickInterval);
  94569. else
  94570. scaleOptions.label.format = utils.getDateUnitInterval(scaleOptions.majorTickInterval)
  94571. }
  94572. },
  94573. _getStubTicks: function(scaleOptions) {
  94574. scaleOptions.isEmpty = true;
  94575. return ["canvas_position_left", "canvas_position_center", "canvas_position_right"]
  94576. },
  94577. _getTickManagerOptions: function(scaleOptions, isEmpty, startValue, endValue) {
  94578. var that = this;
  94579. return {
  94580. labelOptions: {},
  94581. minorTickInterval: isEmpty ? 0 : that._getOption('scale').minorTickInterval,
  94582. tickInterval: scaleOptions.majorTickInterval,
  94583. addMinMax: scaleOptions.showCustomBoundaryTicks ? {
  94584. min: true,
  94585. max: true
  94586. } : undefined,
  94587. minorTickCount: scaleOptions.minorTickCount,
  94588. textOptions: {
  94589. align: 'center',
  94590. font: scaleOptions.label.font
  94591. },
  94592. textFontStyles: patchFontOptions(scaleOptions.label.font),
  94593. incidentOccured: that._incidentOccured,
  94594. isHorizontal: true,
  94595. renderText: function(text, x, y, options) {
  94596. return that._renderer.text(text, x, y, options).append(that._renderer.root)
  94597. },
  94598. getText: startEndNotDefined(startValue, endValue) ? function(value) {
  94599. return value
  94600. } : function(value) {
  94601. return formatValue(value, scaleOptions.label)
  94602. },
  94603. translate: function(value) {
  94604. return that.translators.x.translate(value)
  94605. },
  94606. textSpacing: SCALE_TEXT_SPACING,
  94607. setTicksAtUnitBeginning: scaleOptions.setTicksAtUnitBeginning,
  94608. useTicksAutoArrangement: scaleOptions.useTicksAutoArrangement,
  94609. base: scaleOptions.logarithmBase,
  94610. stick: true,
  94611. showMinorTicks: true,
  94612. withMinorCorrection: true
  94613. }
  94614. },
  94615. _getTicksInfo: function(screenDelta) {
  94616. var that = this,
  94617. scaleOptions = that._scaleOptions,
  94618. translators = that.translators,
  94619. isEmpty = scaleOptions.isEmpty,
  94620. businessRange = translators.x.getBusinessRange(),
  94621. categoriesInfo = scaleOptions._categoriesInfo,
  94622. tickManagerTypes = {
  94623. axisType: scaleOptions.type,
  94624. dataType: scaleOptions.valueType
  94625. },
  94626. tickManagerData,
  94627. startValue = scaleOptions.startValue,
  94628. endValue = scaleOptions.endValue,
  94629. tickManagerOptions = that._getTickManagerOptions(scaleOptions, isEmpty, startValue, endValue),
  94630. majorTicks,
  94631. customBoundaryTicks,
  94632. tickManager,
  94633. fullTicks,
  94634. noInfoFromMinMax;
  94635. tickManagerData = {
  94636. min: isEmpty ? businessRange.min : startValue,
  94637. max: isEmpty ? businessRange.max : endValue,
  94638. screenDelta: screenDelta,
  94639. customTicks: categoriesInfo && categoriesInfo.categories
  94640. };
  94641. tickManager = core.CoreFactory.createTickManager(tickManagerTypes, tickManagerData, tickManagerOptions);
  94642. if (scaleOptions.type === DISCRETE)
  94643. noInfoFromMinMax = !_isDefined(tickManagerData.min) || !_isDefined(tickManagerData.max);
  94644. else
  94645. noInfoFromMinMax = !_isDefined(tickManagerData.min) && !_isDefined(tickManagerData.max);
  94646. majorTicks = noInfoFromMinMax && !_isDefined(tickManagerData.customTicks) ? that._getStubTicks(scaleOptions) : tickManager.getTicks(true);
  94647. customBoundaryTicks = tickManager.getBoundaryTicks();
  94648. fullTicks = tickManager.getFullTicks();
  94649. if (customBoundaryTicks.length) {
  94650. if (majorTicks[0].valueOf() === customBoundaryTicks[0].valueOf())
  94651. majorTicks.splice(0, 1);
  94652. if (majorTicks[majorTicks.length - 1].valueOf() === customBoundaryTicks[customBoundaryTicks.length - 1].valueOf())
  94653. majorTicks.pop()
  94654. }
  94655. return {
  94656. majorTicks: majorTicks,
  94657. minorTicks: tickManager.getMinorTicks(),
  94658. majorTickInterval: tickManager.getTickInterval(),
  94659. fullTicks: fullTicks,
  94660. customBoundaryTicks: customBoundaryTicks
  94661. }
  94662. },
  94663. getSelectedRange: function() {
  94664. return cloneSelectedRange(this.rangeContainer.slidersContainer.getSelectedRange())
  94665. },
  94666. setSelectedRange: function(selectedRange) {
  94667. var that = this;
  94668. if (that._isUpdating || !selectedRange)
  94669. return;
  94670. var oldSelectedRange = that.rangeContainer.slidersContainer.getSelectedRange();
  94671. if (oldSelectedRange && oldSelectedRange.startValue === selectedRange.startValue && oldSelectedRange.endValue === selectedRange.endValue)
  94672. return;
  94673. that.rangeContainer.slidersContainer.setSelectedRange(selectedRange)
  94674. },
  94675. resetSelectedRange: function(blockSelectedRangeChanged) {
  94676. var data = cloneSelectedRange(this._scaleOptions);
  94677. data.blockSelectedRangeChanged = blockSelectedRangeChanged;
  94678. this.setSelectedRange(data)
  94679. },
  94680. render: function(isResizing) {
  94681. var that = this;
  94682. that.__isResizing = isResizing;
  94683. that.callBase.apply(that, arguments);
  94684. that.__isResizing = null;
  94685. return that
  94686. }
  94687. }).include(DX.ui.DataHelperMixin))
  94688. })(jQuery, DevExpress);
  94689. /*! Module viz-rangeselector, file rangeContainer.js */
  94690. (function($, DX, undefined) {
  94691. var rangeSelector = DX.viz.rangeSelector,
  94692. baseVisualElementMethods = rangeSelector.baseVisualElementMethods,
  94693. RangeContainer;
  94694. var createSlidersContainer = function(options) {
  94695. return rangeSelector.rangeSelectorFactory.createSlidersContainer(options)
  94696. };
  94697. var createScale = function(options) {
  94698. return rangeSelector.rangeSelectorFactory.createScale(options)
  94699. };
  94700. var createRangeView = function(options) {
  94701. return rangeSelector.rangeSelectorFactory.createRangeView(options)
  94702. };
  94703. var _createClipRectCanvas = function(canvas, indents) {
  94704. return {
  94705. left: canvas.left - indents.left,
  94706. top: canvas.top - indents.top,
  94707. width: canvas.width + indents.right + indents.left,
  94708. height: canvas.height + indents.bottom + indents.top
  94709. }
  94710. };
  94711. function canvasOptionsToRenderOptions(canvasOptions) {
  94712. return {
  94713. x: canvasOptions.left,
  94714. y: canvasOptions.top,
  94715. width: canvasOptions.width,
  94716. height: canvasOptions.height
  94717. }
  94718. }
  94719. RangeContainer = function(renderer) {
  94720. baseVisualElementMethods.init.apply(this, arguments);
  94721. this.slidersContainer = createSlidersContainer(renderer);
  94722. this.rangeView = createRangeView(renderer);
  94723. this.scale = createScale(renderer)
  94724. };
  94725. RangeContainer.prototype = $.extend({}, baseVisualElementMethods, {
  94726. constructor: RangeContainer,
  94727. dispose: function() {
  94728. this.slidersContainer.dispose();
  94729. this.slidersContainer = null
  94730. },
  94731. _applyOptions: function(options) {
  94732. var that = this,
  94733. scaleLabelsAreaHeight = options.scaleLabelsAreaHeight,
  94734. canvas = options.canvas,
  94735. isCompactMode = options.isCompactMode,
  94736. viewCanvas = {
  94737. left: canvas.left,
  94738. top: canvas.top,
  94739. width: canvas.width,
  94740. height: canvas.height >= scaleLabelsAreaHeight ? canvas.height - scaleLabelsAreaHeight : 0
  94741. };
  94742. that._viewCanvas = viewCanvas;
  94743. that.slidersContainer.applyOptions({
  94744. isCompactMode: isCompactMode,
  94745. canvas: viewCanvas,
  94746. selectedRangeColor: options.selectedRangeColor,
  94747. translator: options.translators.x,
  94748. scale: options.scale,
  94749. selectedRange: options.selectedRange,
  94750. sliderMarker: options.sliderMarker,
  94751. sliderHandle: options.sliderHandle,
  94752. shutter: options.shutter,
  94753. behavior: options.behavior,
  94754. selectedRangeChanged: options.selectedRangeChanged
  94755. });
  94756. that.rangeView.applyOptions({
  94757. isCompactMode: isCompactMode,
  94758. canvas: viewCanvas,
  94759. translators: options.translators,
  94760. background: options.background,
  94761. chart: options.chart,
  94762. seriesDataSource: options.seriesDataSource,
  94763. behavior: options.behavior,
  94764. isEmpty: options.scale.isEmpty
  94765. });
  94766. that.scale.applyOptions({
  94767. isCompactMode: isCompactMode,
  94768. canvas: canvas,
  94769. translator: options.translators.x,
  94770. scale: options.scale,
  94771. scaleLabelsAreaHeight: scaleLabelsAreaHeight,
  94772. setSelectedRange: options.setSelectedRange
  94773. })
  94774. },
  94775. _draw: function() {
  94776. var that = this,
  94777. containerGroup,
  94778. rangeViewGroup,
  94779. slidersContainerGroup,
  94780. scaleGroup,
  94781. trackersGroup,
  94782. options = that._options,
  94783. clipRectCanvas = _createClipRectCanvas(options.canvas, options.indents),
  94784. viewCanvas = that._viewCanvas,
  94785. renderer = that._renderer,
  94786. slidersContainer = that.slidersContainer;
  94787. that._clipRect = renderer.clipRect(clipRectCanvas.left, clipRectCanvas.top, clipRectCanvas.width, clipRectCanvas.height);
  94788. that._viewClipRect = renderer.clipRect(viewCanvas.left, viewCanvas.top, viewCanvas.width, viewCanvas.height);
  94789. containerGroup = renderer.g().attr({
  94790. 'class': 'rangeContainer',
  94791. clipId: that._clipRect.id
  94792. }).append(renderer.root);
  94793. rangeViewGroup = renderer.g().attr({
  94794. 'class': 'view',
  94795. clipId: that._viewClipRect.id
  94796. });
  94797. that._slidersGroup = slidersContainerGroup = renderer.g().attr({'class': 'slidersContainer'});
  94798. scaleGroup = renderer.g().attr({'class': 'scale'});
  94799. trackersGroup = renderer.g().attr({'class': 'trackers'});
  94800. rangeViewGroup.append(containerGroup);
  94801. if (!options.isCompactMode) {
  94802. slidersContainerGroup.append(containerGroup);
  94803. scaleGroup.append(containerGroup)
  94804. }
  94805. else {
  94806. scaleGroup.append(containerGroup);
  94807. slidersContainerGroup.append(containerGroup)
  94808. }
  94809. trackersGroup.append(containerGroup);
  94810. that.rangeView.redraw(rangeViewGroup);
  94811. slidersContainer.redraw(slidersContainerGroup);
  94812. that.scale.redraw(scaleGroup);
  94813. that._trackersGroup = trackersGroup;
  94814. slidersContainer.appendTrackers(trackersGroup)
  94815. },
  94816. _update: function() {
  94817. var that = this,
  94818. options = that._options,
  94819. slidersContainer = that.slidersContainer;
  94820. that._clipRect.attr(canvasOptionsToRenderOptions(_createClipRectCanvas(options.canvas, options.indents)));
  94821. that._viewClipRect.attr(canvasOptionsToRenderOptions(that._viewCanvas));
  94822. that.rangeView.redraw();
  94823. slidersContainer.redraw(that._slidersGroup);
  94824. slidersContainer.appendTrackers(that._trackersGroup);
  94825. that.scale.redraw()
  94826. },
  94827. createSlidersContainer: createSlidersContainer,
  94828. createScale: createScale
  94829. });
  94830. rangeSelector.RangeContainer = RangeContainer
  94831. })(jQuery, DevExpress);
  94832. /*! Module viz-rangeselector, file scale.js */
  94833. (function($, DX, undefined) {
  94834. var viz = DX.viz,
  94835. rangeSelector = viz.rangeSelector,
  94836. formatHelper = DX.formatHelper,
  94837. rangeSelectorUtils = rangeSelector.utils,
  94838. utils = DX.utils,
  94839. _isDefined = utils.isDefined,
  94840. HALF_TICK_LENGTH = 6,
  94841. MINOR_TICK_OPACITY_COEF = 0.6,
  94842. Scale,
  94843. baseVisualElementMethods = rangeSelector.baseVisualElementMethods,
  94844. _extend = $.extend;
  94845. function calculateRangeByMarkerPosition(posX, markerDatePositions, scaleOptions) {
  94846. var selectedRange = {},
  94847. position,
  94848. i;
  94849. for (i = 0; i < markerDatePositions.length; i++) {
  94850. position = markerDatePositions[i];
  94851. if (!scaleOptions.inverted) {
  94852. if (posX >= position.posX)
  94853. selectedRange.startValue = position.date;
  94854. else if (!selectedRange.endValue)
  94855. selectedRange.endValue = position.date
  94856. }
  94857. else if (posX < position.posX)
  94858. selectedRange.endValue = position.date;
  94859. else if (!selectedRange.startValue)
  94860. selectedRange.startValue = position.date
  94861. }
  94862. selectedRange.startValue = selectedRange.startValue || scaleOptions.startValue;
  94863. selectedRange.endValue = selectedRange.endValue || scaleOptions.endValue;
  94864. return selectedRange
  94865. }
  94866. var dateSetters = {};
  94867. dateSetters.millisecond = function(date) {
  94868. date.setMilliseconds(0)
  94869. };
  94870. dateSetters.second = function(date) {
  94871. date.setSeconds(0, 0)
  94872. };
  94873. dateSetters.minute = function(date) {
  94874. date.setMinutes(0, 0, 0)
  94875. };
  94876. dateSetters.hour = function(date) {
  94877. date.setHours(0, 0, 0, 0)
  94878. };
  94879. dateSetters.week = dateSetters.day = function(date) {
  94880. date.setDate(1);
  94881. dateSetters.hour(date)
  94882. };
  94883. dateSetters.month = function(date) {
  94884. date.setMonth(0);
  94885. dateSetters.day(date)
  94886. };
  94887. dateSetters.quarter = function(date) {
  94888. date.setMonth(formatHelper.getFirstQuarterMonth(date.getMonth()));
  94889. dateSetters.day(date)
  94890. };
  94891. function getMarkerDate(date, tickInterval) {
  94892. var markerDate = new Date(date.getTime()),
  94893. setter = dateSetters[tickInterval];
  94894. setter && setter(markerDate);
  94895. return markerDate
  94896. }
  94897. function prepareDatesDifferences(datesDifferences, tickInterval) {
  94898. var deleteDifferent = tickInterval,
  94899. dateUnitInterval,
  94900. i;
  94901. if (deleteDifferent === 'week')
  94902. deleteDifferent = 'day';
  94903. if (deleteDifferent === 'quarter')
  94904. deleteDifferent = 'month';
  94905. if (datesDifferences[deleteDifferent])
  94906. for (i = 0; i < utils.dateUnitIntervals.length; i++) {
  94907. dateUnitInterval = utils.dateUnitIntervals[i];
  94908. if (datesDifferences[dateUnitInterval]) {
  94909. datesDifferences[dateUnitInterval] = false;
  94910. datesDifferences.count--
  94911. }
  94912. if (dateUnitInterval === deleteDifferent)
  94913. break
  94914. }
  94915. }
  94916. function getLabel(value, options) {
  94917. var formatObject = {
  94918. value: value,
  94919. valueText: formatHelper.format(value, options.format, options.precision)
  94920. };
  94921. return String(utils.isFunction(options.customizeText) ? options.customizeText.call(formatObject, formatObject) : formatObject.valueText)
  94922. }
  94923. Scale = function() {
  94924. baseVisualElementMethods.init.apply(this, arguments)
  94925. };
  94926. Scale.prototype = _extend({}, baseVisualElementMethods, {
  94927. constructor: Scale,
  94928. _setupDateUnitInterval: function(scaleOptions) {
  94929. var key,
  94930. millisecTickInterval,
  94931. majorTickInterval = scaleOptions.ticksInfo.majorTickInterval,
  94932. majorTicks = scaleOptions.ticksInfo.majorTicks;
  94933. if (scaleOptions.valueType === 'datetime') {
  94934. if (majorTicks && majorTicks.autoArrangementStep > 1) {
  94935. if (utils.isString(majorTickInterval))
  94936. majorTickInterval = utils.getDateIntervalByString(majorTickInterval);
  94937. for (key in majorTickInterval)
  94938. if (majorTickInterval.hasOwnProperty(key)) {
  94939. majorTickInterval[key] *= majorTicks.autoArrangementStep;
  94940. millisecTickInterval = utils.dateToMilliseconds(majorTickInterval)
  94941. }
  94942. majorTickInterval = utils.convertMillisecondsToDateUnits(millisecTickInterval)
  94943. }
  94944. this.dateUnitInterval = utils.getDateUnitInterval(majorTickInterval)
  94945. }
  94946. },
  94947. _getDrawnDateMarker: function(date, options) {
  94948. var that = this,
  94949. labelPosX,
  94950. labelPosY,
  94951. scaleOptions = that._options.scale,
  94952. textElement,
  94953. textElementWidth,
  94954. textIndent,
  94955. pathElement;
  94956. if (options.x === null)
  94957. return;
  94958. that.textOptions.align = "left";
  94959. pathElement = that._renderer.path([options.x, options.y, options.x, options.y + scaleOptions.marker.separatorHeight], "line").attr(that._majorTickStyle).append(options.group);
  94960. textElement = that._renderer.text(getLabel(date, options.label), 0, 0).attr(that.textOptions).css(that.fontOptions).append(options.group);
  94961. textElementWidth = textElement.getBBox().width;
  94962. textIndent = scaleOptions.tick.width + scaleOptions.marker.textLeftIndent;
  94963. labelPosX = scaleOptions.inverted ? options.x - textIndent - textElementWidth : options.x + textIndent;
  94964. labelPosY = options.y + scaleOptions.marker.textTopIndent + that.fontOptions["font-size"];
  94965. textElement.move(labelPosX, labelPosY);
  94966. return {
  94967. x1: labelPosX,
  94968. x2: labelPosX + textElementWidth,
  94969. path: pathElement,
  94970. text: textElement
  94971. }
  94972. },
  94973. _deleteDrawnDateMarker: function(marker) {
  94974. marker.path.dispose();
  94975. marker.path = null;
  94976. marker.text.dispose();
  94977. marker.text = null
  94978. },
  94979. _drawDateMarkers: function(dates, group) {
  94980. var that = this,
  94981. i,
  94982. options = that._options,
  94983. datesLength = dates.length,
  94984. datesDifferences,
  94985. markerDate,
  94986. posX,
  94987. markerDatePositions = [],
  94988. prevDateMarker,
  94989. dateMarker;
  94990. if (options.scale.valueType !== 'datetime' || !that.visibleMarkers)
  94991. return;
  94992. if (dates.length > 1) {
  94993. for (i = 1; i < datesLength; i++) {
  94994. datesDifferences = utils.getDatesDifferences(dates[i - 1], dates[i]);
  94995. prepareDatesDifferences(datesDifferences, that.dateUnitInterval);
  94996. if (datesDifferences.count > 0) {
  94997. markerDate = getMarkerDate(dates[i], that.dateUnitInterval);
  94998. that.markerDates = that.markerDates || [];
  94999. that.markerDates.push(markerDate);
  95000. posX = that.translator.translate(markerDate);
  95001. dateMarker = that._getDrawnDateMarker(markerDate, {
  95002. group: group,
  95003. y: options.canvas.top + options.canvas.height - that.markersAreaHeight + options.scale.marker.topIndent,
  95004. x: posX,
  95005. label: that._getLabelFormatOptions(formatHelper.getDateFormatByDifferences(datesDifferences))
  95006. });
  95007. if (prevDateMarker === undefined || dateMarker.x1 > prevDateMarker.x2 || dateMarker.x2 < prevDateMarker.x1) {
  95008. posX !== null && markerDatePositions.push({
  95009. date: markerDate,
  95010. posX: posX
  95011. });
  95012. prevDateMarker = dateMarker
  95013. }
  95014. else
  95015. that._deleteDrawnDateMarker(dateMarker)
  95016. }
  95017. }
  95018. that._initializeMarkersEvents(markerDatePositions, group)
  95019. }
  95020. },
  95021. _getLabelFormatOptions: function(formatString) {
  95022. if (!_isDefined(this._options.scale.marker.label.format))
  95023. return _extend({}, this._options.scale.marker.label, {format: formatString});
  95024. return this._options.scale.marker.label
  95025. },
  95026. _initializeMarkersEvents: function(markerDatePositions, group) {
  95027. var that = this,
  95028. options = that._options,
  95029. markersAreaTop = options.canvas.top + options.canvas.height - this.markersAreaHeight + options.scale.marker.topIndent,
  95030. markersTracker,
  95031. svgOffsetLeft,
  95032. posX,
  95033. selectedRange;
  95034. if (markerDatePositions.length > 0) {
  95035. markersTracker = that._renderer.rect(options.canvas.left, markersAreaTop, options.canvas.width, options.scale.marker.separatorHeight).attr(rangeSelectorUtils.trackerSettings).append(group);
  95036. markersTracker.on(rangeSelector.events.start, function(e) {
  95037. svgOffsetLeft = that._renderer.getRootOffset().left;
  95038. posX = rangeSelectorUtils.getEventPageX(e) - svgOffsetLeft;
  95039. selectedRange = calculateRangeByMarkerPosition(posX, markerDatePositions, options.scale);
  95040. options.setSelectedRange(selectedRange)
  95041. });
  95042. that._markersTracker = markersTracker
  95043. }
  95044. },
  95045. _drawLabel: function(text, group) {
  95046. var that = this,
  95047. options = that._options,
  95048. canvas = options.canvas,
  95049. textY = canvas.top + canvas.height - that.markersAreaHeight,
  95050. textElements = that._renderer.text(getLabel(text, options.scale.label), that.translator.translate(text), textY).attr(that.textOptions).css(that.fontOptions).append(group);
  95051. that.textElements = that.textElements || [];
  95052. that.textElements.push(textElements)
  95053. },
  95054. _drawTicks: function(ticks, group, directionOffset, coords, style, labelsGroup) {
  95055. var that = this,
  95056. i,
  95057. posX,
  95058. tickElement;
  95059. for (i = 0; i < ticks.length; i++) {
  95060. if (labelsGroup)
  95061. that._drawLabel(ticks[i], labelsGroup);
  95062. posX = that.translator.translate(ticks[i], directionOffset);
  95063. tickElement = that._createLine([posX, coords[0], posX, coords[1]], group, style);
  95064. that.tickElements = that.tickElements || [];
  95065. that.tickElements.push(tickElement)
  95066. }
  95067. },
  95068. _createLine: function(points, group, options) {
  95069. return this._renderer.path(points, "line").attr(options).append(group)
  95070. },
  95071. _redraw: function(group) {
  95072. var that = this,
  95073. options = that._options,
  95074. scaleOptions = options.scale,
  95075. renderer = that._renderer,
  95076. labelsGroup = renderer.g().append(group),
  95077. ticksGroup = renderer.g(),
  95078. ticksInfo = scaleOptions.ticksInfo,
  95079. majorTicks = ticksInfo.majorTicks,
  95080. minorTicks = ticksInfo.minorTicks,
  95081. customBoundaryTicks = ticksInfo.customBoundaryTicks,
  95082. hideLabels = scaleOptions.isEmpty || !scaleOptions.label.visible,
  95083. isDiscrete = scaleOptions.type === "discrete",
  95084. directionOffset = isDiscrete ? -1 : 0,
  95085. isCompactMode = options.isCompactMode,
  95086. canvas = options.canvas,
  95087. bottom = canvas.top + canvas.height - that.scaleLabelsAreaHeight,
  95088. center = canvas.top + (bottom - canvas.top) / 2,
  95089. coords = isCompactMode ? [center - HALF_TICK_LENGTH, center + HALF_TICK_LENGTH] : [canvas.top, bottom],
  95090. categoriesInfo = scaleOptions._categoriesInfo,
  95091. majorTickStyle = that._majorTickStyle;
  95092. that._drawTicks(majorTicks, ticksGroup, directionOffset, coords, majorTickStyle, !hideLabels && labelsGroup);
  95093. if (scaleOptions.showMinorTicks || isDiscrete)
  95094. that._drawTicks(minorTicks, ticksGroup, directionOffset, coords, that._minorTickStyle);
  95095. that._drawTicks(customBoundaryTicks, ticksGroup, 0, coords, majorTickStyle);
  95096. isDiscrete && categoriesInfo && _isDefined(categoriesInfo.end) && that._drawTicks([categoriesInfo.end], ticksGroup, 1, coords, majorTickStyle);
  95097. if (isCompactMode)
  95098. that._createLine([canvas.left, center, canvas.width + canvas.left, center], group, _extend({}, majorTickStyle, {sharp: "v"}));
  95099. ticksGroup.append(group);
  95100. that._drawDateMarkers(majorTicks, labelsGroup)
  95101. },
  95102. _applyOptions: function(options) {
  95103. var that = this,
  95104. scaleOptions = options.scale,
  95105. labelsAreaHeight,
  95106. tick = scaleOptions.tick;
  95107. that.textOptions = {align: 'center'};
  95108. that.fontOptions = viz.core.utils.patchFontOptions(scaleOptions.label.font);
  95109. that._majorTickStyle = {
  95110. "stroke-width": tick.width,
  95111. stroke: tick.color,
  95112. "stroke-opacity": tick.opacity,
  95113. sharp: "h"
  95114. };
  95115. that._minorTickStyle = _extend({}, that._majorTickStyle, {"stroke-opacity": tick.opacity * MINOR_TICK_OPACITY_COEF});
  95116. that._setupDateUnitInterval(scaleOptions);
  95117. that.visibleMarkers = scaleOptions.marker.visible === undefined ? true : scaleOptions.marker.visible;
  95118. labelsAreaHeight = scaleOptions.label.visible ? scaleOptions.label.topIndent + that.fontOptions["font-size"] : 0;
  95119. that.scaleLabelsAreaHeight = options.scaleLabelsAreaHeight;
  95120. that.markersAreaHeight = that.scaleLabelsAreaHeight - labelsAreaHeight;
  95121. that.translator = options.translator
  95122. },
  95123. _draw: function(group) {
  95124. this._redraw(group)
  95125. },
  95126. _update: function() {
  95127. if (this._markersTracker)
  95128. this._markersTracker.off(rangeSelector.events.start, '**');
  95129. baseVisualElementMethods._update.apply(this, arguments)
  95130. }
  95131. });
  95132. Scale.prototype._calculateRangeByMarkerPosition = calculateRangeByMarkerPosition;
  95133. Scale.prototype._prepareDatesDifferences = prepareDatesDifferences;
  95134. rangeSelector.Scale = Scale
  95135. })(jQuery, DevExpress);
  95136. /*! Module viz-rangeselector, file rangeFactory.js */
  95137. (function($, DX, undefined) {
  95138. var rangeSelector = DX.viz.rangeSelector;
  95139. rangeSelector.rangeSelectorFactory = function() {
  95140. return {
  95141. createRangeContainer: function(rangeContainerOptions) {
  95142. return new rangeSelector.RangeContainer(rangeContainerOptions)
  95143. },
  95144. createSlidersContainer: function(options) {
  95145. return new rangeSelector.SlidersContainer(options)
  95146. },
  95147. createScale: function(options) {
  95148. return new rangeSelector.Scale(options)
  95149. },
  95150. createSliderMarker: function(options) {
  95151. return new rangeSelector.SliderMarker(options)
  95152. },
  95153. createRangeView: function(options) {
  95154. return new rangeSelector.RangeView(options)
  95155. },
  95156. createThemeManager: function(options) {
  95157. return new rangeSelector.ThemeManager(options)
  95158. },
  95159. createSlider: function(renderer, sliderIndex) {
  95160. return new rangeSelector.Slider(renderer, sliderIndex)
  95161. },
  95162. createSlidersEventsManager: function(renderer, slidersController, processSelectionChanged) {
  95163. return new rangeSelector.SlidersEventsManager(renderer, slidersController, processSelectionChanged)
  95164. },
  95165. createSlidersController: function(sliders) {
  95166. return new rangeSelector.SlidersController(sliders)
  95167. }
  95168. }
  95169. }()
  95170. })(jQuery, DevExpress);
  95171. /*! Module viz-rangeselector, file slidersContainer.js */
  95172. (function($, DX, undefined) {
  95173. var rangeSelector = DX.viz.rangeSelector,
  95174. utils = DX.utils,
  95175. msPointerEnabled = DX.support.pointer,
  95176. isNumber = utils.isNumber,
  95177. isDate = utils.isDate,
  95178. isString = utils.isString,
  95179. rangeSelectorUtils = rangeSelector.utils,
  95180. baseVisualElementMethods = rangeSelector.baseVisualElementMethods,
  95181. rangeSelectorFactory = rangeSelector.rangeSelectorFactory,
  95182. trackerAttributes = rangeSelectorUtils.trackerSettings;
  95183. function SlidersContainer() {
  95184. var that = this;
  95185. baseVisualElementMethods.init.apply(that, arguments);
  95186. that._controller = rangeSelectorFactory.createSlidersController(that._renderer);
  95187. that._eventsManager = rangeSelectorFactory.createSlidersEventsManager(that._renderer, that._controller, function(moving) {
  95188. that._processSelectionChanged(moving)
  95189. });
  95190. that._lastSelectedRange = {}
  95191. }
  95192. SlidersContainer.prototype = $.extend({}, baseVisualElementMethods, {
  95193. constructor: SlidersContainer,
  95194. _drawAreaTracker: function(group) {
  95195. var that = this,
  95196. areaTracker,
  95197. selectedAreaTracker,
  95198. canvas = that._options.canvas,
  95199. renderer = that._renderer;
  95200. areaTracker = renderer.rect(canvas.left, canvas.top, canvas.width, canvas.height).attr(trackerAttributes).append(group);
  95201. selectedAreaTracker = renderer.rect(canvas.left, canvas.top, canvas.width, canvas.height).attr(trackerAttributes).css({cursor: 'pointer'}).append(group);
  95202. that._controller.setAreaTrackers(areaTracker, selectedAreaTracker)
  95203. },
  95204. dispose: function() {
  95205. this._eventsManager.dispose();
  95206. this._controller.dispose();
  95207. this._eventManager = null
  95208. },
  95209. _processSelectionChanged: function(moving, blockSelectedRangeChanged) {
  95210. var that = this,
  95211. equalLastSelectedRange = function(selectedRange) {
  95212. return selectedRange && that._lastSelectedRange.startValue === selectedRange.startValue && that._lastSelectedRange.endValue === selectedRange.endValue
  95213. },
  95214. selectedRange = that.getSelectedRange();
  95215. if ((!moving || (that._options.behavior.callSelectedRangeChanged || '').toLowerCase() === "onmoving") && that._options.selectedRangeChanged && !equalLastSelectedRange(selectedRange)) {
  95216. that._updateLastSelectedRange(selectedRange);
  95217. if (utils.isFunction(that._options.selectedRangeChanged))
  95218. that._options.selectedRangeChanged.call(null, selectedRange, blockSelectedRangeChanged);
  95219. if (!moving && !equalLastSelectedRange(selectedRange))
  95220. that.setSelectedRange(selectedRange)
  95221. }
  95222. },
  95223. _updateLastSelectedRange: function(selectedRange) {
  95224. selectedRange = selectedRange || this._options.selectedRange;
  95225. this._lastSelectedRange = {
  95226. startValue: selectedRange.startValue,
  95227. endValue: selectedRange.endValue
  95228. }
  95229. },
  95230. getSelectedRange: function() {
  95231. return this._controller.getSelectedRange()
  95232. },
  95233. setSelectedRange: function(selectedRange) {
  95234. var that = this,
  95235. scale = that._options.scale,
  95236. startValue,
  95237. endValue,
  95238. currentSelectedRange = that._options.selectedRange,
  95239. checkTypes = function(valueName, value) {
  95240. var valueFromScale = scale[valueName];
  95241. if (isNumber(valueFromScale) && isNumber(value) || isDate(valueFromScale) && isDate(value) || isString(valueFromScale) && isString(value))
  95242. currentSelectedRange[valueName] = value
  95243. };
  95244. if (selectedRange) {
  95245. startValue = selectedRange.startValue;
  95246. endValue = selectedRange.endValue
  95247. }
  95248. checkTypes('startValue', startValue);
  95249. checkTypes('endValue', endValue);
  95250. currentSelectedRange.startValue = rangeSelectorUtils.truncateSelectedRange(currentSelectedRange.startValue, scale);
  95251. currentSelectedRange.endValue = rangeSelectorUtils.truncateSelectedRange(currentSelectedRange.endValue, scale);
  95252. that._controller.applySelectedRange(currentSelectedRange);
  95253. that._controller.applyPosition();
  95254. that._processSelectionChanged(false, selectedRange && selectedRange.blockSelectedRangeChanged)
  95255. },
  95256. appendTrackers: function(group) {
  95257. this._controller.appendTrackers(group)
  95258. },
  95259. _applyOptions: function(options) {
  95260. var that = this;
  95261. that._controller.applyOptions({
  95262. isCompactMode: options.isCompactMode,
  95263. translator: options.translator,
  95264. canvas: options.canvas,
  95265. sliderMarker: options.sliderMarker,
  95266. sliderHandle: options.sliderHandle,
  95267. shutter: options.shutter,
  95268. scale: options.scale,
  95269. behavior: options.behavior
  95270. });
  95271. that._eventsManager.applyOptions({behavior: options.behavior})
  95272. },
  95273. _draw: function(group) {
  95274. var that = this,
  95275. rootElement;
  95276. if (msPointerEnabled) {
  95277. rootElement = that._renderer.root;
  95278. rootElement && rootElement.css({msTouchAction: "pinch-zoom"})
  95279. }
  95280. that._controller.redraw(group);
  95281. that._drawAreaTracker(group);
  95282. that._eventsManager.initialize();
  95283. that._update(group)
  95284. },
  95285. _updateSelectedView: function(group) {
  95286. var that = this,
  95287. options = that._options,
  95288. canvas = options.canvas,
  95289. lineOptions = {
  95290. "stroke-width": 3,
  95291. stroke: options.selectedRangeColor,
  95292. sharp: "v"
  95293. },
  95294. center = canvas.top + canvas.height / 2,
  95295. selectedView = that._selectedView,
  95296. selectedViewAppended = that._selectedViewAppended,
  95297. controller = that._controller;
  95298. if (!options.isCompactMode) {
  95299. if (selectedView && selectedViewAppended) {
  95300. selectedView.remove();
  95301. that._selectedViewAppended = false
  95302. }
  95303. controller.createShutters()
  95304. }
  95305. else {
  95306. if (!selectedView) {
  95307. that._selectedView = selectedView = that._renderer.path([canvas.left, center, canvas.left, center], "line").attr(lineOptions);
  95308. controller.setSelectedView(selectedView)
  95309. }
  95310. else
  95311. selectedView.attr(lineOptions);
  95312. if (!selectedViewAppended) {
  95313. selectedView.append(group);
  95314. controller.removeShutters();
  95315. that._selectedViewAppended = true
  95316. }
  95317. }
  95318. },
  95319. _update: function(group) {
  95320. var that = this,
  95321. isEmpty = that._options.scale.isEmpty,
  95322. controller = that._controller;
  95323. that._eventsManager.setEnabled(!isEmpty);
  95324. !isEmpty && that._updateSelectedView(group);
  95325. controller.applySelectedRange(isEmpty ? {} : that._options.selectedRange);
  95326. controller.applyPosition(that.isDrawn());
  95327. that._updateLastSelectedRange();
  95328. controller.redraw()
  95329. },
  95330. getController: function() {
  95331. return this._controller
  95332. }
  95333. });
  95334. rangeSelector.SlidersContainer = SlidersContainer
  95335. })(jQuery, DevExpress);
  95336. /*! Module viz-rangeselector, file slidersController.js */
  95337. (function($, DX, undefined) {
  95338. var rangeSelector = DX.viz.rangeSelector,
  95339. createSlider = rangeSelector.rangeSelectorFactory.createSlider,
  95340. utils = DX.utils,
  95341. rangeSelectorUtils = rangeSelector.utils,
  95342. _SliderController,
  95343. START_VALUE_INDEX = 0,
  95344. END_VALUE_INDEX = 1,
  95345. DISCRETE = 'discrete';
  95346. _SliderController = rangeSelector.SlidersController = function(renderer) {
  95347. var sliders = [createSlider(renderer, START_VALUE_INDEX), createSlider(renderer, END_VALUE_INDEX)];
  95348. sliders[START_VALUE_INDEX].setAnotherSlider(sliders[END_VALUE_INDEX]);
  95349. sliders[END_VALUE_INDEX].setAnotherSlider(sliders[START_VALUE_INDEX]);
  95350. this._sliders = sliders
  95351. };
  95352. _SliderController.prototype = {
  95353. constructor: _SliderController,
  95354. setAreaTrackers: function(areaTracker, selectedAreaTracker) {
  95355. this._areaTracker = areaTracker;
  95356. this._selectedAreaTracker = selectedAreaTracker
  95357. },
  95358. applyOptions: function(options) {
  95359. var that = this,
  95360. values = null,
  95361. startSlider = that.getSlider(START_VALUE_INDEX),
  95362. endSlider = that.getSlider(END_VALUE_INDEX),
  95363. scaleOptions = options.scale;
  95364. that._options = options;
  95365. startSlider.applyOptions(options);
  95366. endSlider.applyOptions(options);
  95367. if (options.behavior.snapToTicks && scaleOptions.type !== DISCRETE) {
  95368. values = scaleOptions.ticksInfo.fullTicks;
  95369. if (values.length > 1 && values[0] > values[values.length - 1])
  95370. values = values.reverse()
  95371. }
  95372. startSlider.setAvailableValues(values);
  95373. endSlider.setAvailableValues(values)
  95374. },
  95375. processDocking: function(sliderIndex) {
  95376. var that = this;
  95377. if (sliderIndex !== undefined)
  95378. that.getSlider(sliderIndex).processDocking();
  95379. else {
  95380. that.getSlider(START_VALUE_INDEX).processDocking();
  95381. that.getSlider(END_VALUE_INDEX).processDocking()
  95382. }
  95383. that.setTrackersCursorStyle('default');
  95384. that.applyAreaTrackersPosition();
  95385. that._applySelectedRangePosition()
  95386. },
  95387. _applySelectedRangePosition: function(disableAnimation) {
  95388. var that = this,
  95389. options = that._options,
  95390. canvas = options.canvas,
  95391. center = canvas.top + canvas.height / 2,
  95392. isAnimation = options.behavior.animationEnabled && !disableAnimation,
  95393. startSliderPos = that.getSlider(START_VALUE_INDEX).getPosition(),
  95394. interval = that.getSelectedRangeInterval(),
  95395. points = [startSliderPos, center, startSliderPos + interval, center],
  95396. selectedView = that._selectedView;
  95397. if (!selectedView || !options.isCompactMode)
  95398. return;
  95399. if (isAnimation)
  95400. selectedView.animate({points: points}, rangeSelectorUtils.animationSettings);
  95401. else
  95402. selectedView.stopAnimation().attr({points: points})
  95403. },
  95404. setSelectedView: function(selectedView) {
  95405. this._selectedView = selectedView
  95406. },
  95407. getSelectedRangeInterval: function() {
  95408. var that = this;
  95409. return that.getSlider(END_VALUE_INDEX).getPosition() - that.getSlider(START_VALUE_INDEX).getPosition()
  95410. },
  95411. moveSliders: function(postitionDelta, selectedRangeInterval) {
  95412. var startSlider = this.getSlider(START_VALUE_INDEX);
  95413. startSlider.setPosition(startSlider.getPosition() + postitionDelta, false, selectedRangeInterval);
  95414. this.applyPosition(true)
  95415. },
  95416. moveSlider: function(sliderIndex, fastSwap, position, offsetPosition, startOffsetPosition, startOffsetPositionChangedCallback) {
  95417. var that = this,
  95418. slider = that.getSlider(sliderIndex),
  95419. anotherSlider = slider.getAnotherSlider(),
  95420. anotherSliderPosition = anotherSlider.getPosition(),
  95421. doSwap;
  95422. if (slider.canSwap())
  95423. if (sliderIndex === START_VALUE_INDEX ? position > anotherSliderPosition : position < anotherSliderPosition) {
  95424. doSwap = fastSwap;
  95425. if (!fastSwap)
  95426. if (Math.abs(offsetPosition) >= Math.abs(startOffsetPosition)) {
  95427. doSwap = true;
  95428. if (offsetPosition * startOffsetPosition < 0) {
  95429. position += 2 * startOffsetPosition;
  95430. startOffsetPositionChangedCallback(-startOffsetPosition)
  95431. }
  95432. else {
  95433. position -= 2 * startOffsetPosition;
  95434. startOffsetPositionChangedCallback(startOffsetPosition)
  95435. }
  95436. }
  95437. if (doSwap) {
  95438. that.swapSliders();
  95439. anotherSlider.applyPosition(true)
  95440. }
  95441. }
  95442. slider.setPosition(position, true);
  95443. slider.applyPosition(true);
  95444. that.applyAreaTrackersPosition();
  95445. that._applySelectedRangePosition(true);
  95446. that.setTrackersCursorStyle('w-resize')
  95447. },
  95448. applySelectedAreaCenterPosition: function(pos) {
  95449. var that = this,
  95450. startSlider = that.getSlider(START_VALUE_INDEX),
  95451. slidersContainerHalfWidth = (that.getSlider(END_VALUE_INDEX).getPosition() - startSlider.getPosition()) / 2,
  95452. selectedRangeInterval = that.getSelectedRangeInterval();
  95453. startSlider.setPosition(pos - slidersContainerHalfWidth, false, selectedRangeInterval);
  95454. that.applyPosition();
  95455. that.processDocking()
  95456. },
  95457. endSelection: function() {
  95458. var startSlider = this.getSlider(START_VALUE_INDEX),
  95459. endSlider = this.getSlider(END_VALUE_INDEX),
  95460. cloudSpacing = startSlider.getCloudBorder() - endSlider.getCloudBorder(),
  95461. overlappedState;
  95462. if (cloudSpacing > 0)
  95463. overlappedState = true;
  95464. else
  95465. overlappedState = false;
  95466. startSlider.setOverlapped(overlappedState);
  95467. endSlider.setOverlapped(overlappedState)
  95468. },
  95469. processManualSelection: function(startPosition, endPosition, eventArgs) {
  95470. var that = this,
  95471. animateSliderIndex,
  95472. movingSliderIndex,
  95473. positionRange = [Math.min(startPosition, endPosition), Math.max(startPosition, endPosition)],
  95474. movingSlider,
  95475. animatedSlider;
  95476. animateSliderIndex = startPosition < endPosition ? START_VALUE_INDEX : END_VALUE_INDEX;
  95477. movingSliderIndex = startPosition < endPosition ? END_VALUE_INDEX : START_VALUE_INDEX;
  95478. movingSlider = that.getSlider(movingSliderIndex);
  95479. animatedSlider = that.getSlider(animateSliderIndex);
  95480. movingSlider.setPosition(positionRange[movingSliderIndex]);
  95481. animatedSlider.setPosition(positionRange[animateSliderIndex]);
  95482. movingSlider.setPosition(positionRange[movingSliderIndex], true);
  95483. movingSlider.startEventHandler(eventArgs);
  95484. animatedSlider.processDocking();
  95485. movingSlider.applyPosition(true)
  95486. },
  95487. applySelectedRange: function(selectedRange) {
  95488. utils.debug.assertParam(selectedRange, 'selectedRange not passed');
  95489. var that = this,
  95490. scaleoptions = that._options.scale,
  95491. inverted = scaleoptions.inverted,
  95492. startSlider = that.getSlider(START_VALUE_INDEX),
  95493. endSlider = that.getSlider(END_VALUE_INDEX),
  95494. startValue = selectedRange.startValue,
  95495. endValue = selectedRange.endValue,
  95496. categoriesInfo,
  95497. setValues = function(startValue, endValue, isInverted) {
  95498. (isInverted ? endSlider : startSlider).setValue(startValue);
  95499. (isInverted ? startSlider : endSlider).setValue(endValue)
  95500. };
  95501. if (scaleoptions.type !== DISCRETE)
  95502. if (!inverted && startValue > endValue || inverted && startValue < endValue)
  95503. setValues(startValue, endValue, true);
  95504. else
  95505. setValues(startValue, endValue);
  95506. else {
  95507. categoriesInfo = utils.getCategoriesInfo(scaleoptions._categoriesInfo.categories, startValue, endValue);
  95508. setValues(categoriesInfo.start, categoriesInfo.end, categoriesInfo.inverted ^ scaleoptions.inverted)
  95509. }
  95510. },
  95511. getSelectedRange: function() {
  95512. return {
  95513. startValue: this.getSlider(START_VALUE_INDEX).getValue(),
  95514. endValue: this.getSlider(END_VALUE_INDEX).getValue()
  95515. }
  95516. },
  95517. swapSliders: function() {
  95518. var that = this;
  95519. that._sliders.reverse();
  95520. that.getSlider(START_VALUE_INDEX).changeLocation();
  95521. that.getSlider(END_VALUE_INDEX).changeLocation()
  95522. },
  95523. applyAreaTrackersPosition: function() {
  95524. var that = this,
  95525. selectedRange = that.getSelectedRange(),
  95526. canvas = that._options.canvas,
  95527. scaleOptions = that._options.scale,
  95528. startSlider = that.getSlider(START_VALUE_INDEX),
  95529. width = that.getSlider(END_VALUE_INDEX).getPosition() - startSlider.getPosition(),
  95530. options = {
  95531. x: startSlider.getPosition(),
  95532. width: width < 0 ? 0 : width,
  95533. y: canvas.top,
  95534. height: canvas.height
  95535. },
  95536. style = {cursor: scaleOptions.endValue - scaleOptions.startValue === selectedRange.endValue - selectedRange.startValue ? 'default' : 'pointer'};
  95537. that._selectedAreaTracker.attr(options).css(style);
  95538. that._areaTracker.attr({
  95539. x: canvas.left,
  95540. width: canvas.width,
  95541. y: canvas.top,
  95542. height: canvas.height
  95543. })
  95544. },
  95545. applyPosition: function(disableAnimation) {
  95546. var that = this;
  95547. that.getSlider(START_VALUE_INDEX).applyPosition(disableAnimation);
  95548. that.getSlider(END_VALUE_INDEX).applyPosition(disableAnimation);
  95549. that.applyAreaTrackersPosition();
  95550. that._applySelectedRangePosition(disableAnimation)
  95551. },
  95552. redraw: function(group) {
  95553. var that = this;
  95554. that.getSlider(START_VALUE_INDEX).redraw(group);
  95555. that.getSlider(END_VALUE_INDEX).redraw(group);
  95556. that._foregroundSliderIndex = END_VALUE_INDEX
  95557. },
  95558. toForeground: function(slider) {
  95559. var that = this,
  95560. sliderIndex = slider.getIndex();
  95561. if (that._foregroundSliderIndex !== sliderIndex) {
  95562. slider.toForeground();
  95563. that._foregroundSliderIndex = sliderIndex
  95564. }
  95565. },
  95566. appendTrackers: function(group) {
  95567. var that = this;
  95568. if (that._areaTracker && that._selectedAreaTracker) {
  95569. that._areaTracker.append(group);
  95570. that._selectedAreaTracker.append(group)
  95571. }
  95572. that.getSlider(START_VALUE_INDEX).appendTrackers(group);
  95573. that.getSlider(END_VALUE_INDEX).appendTrackers(group)
  95574. },
  95575. getSlider: function(sliderIndex) {
  95576. return this._sliders[sliderIndex]
  95577. },
  95578. getAreaTracker: function() {
  95579. return this._areaTracker
  95580. },
  95581. getSelectedAreaTracker: function() {
  95582. return this._selectedAreaTracker
  95583. },
  95584. setTrackersCursorStyle: function(style) {
  95585. var that = this;
  95586. that._selectedAreaTracker.css({cursor: style});
  95587. that._areaTracker.css({cursor: style})
  95588. },
  95589. createShutters: function() {
  95590. var sliders = this._sliders;
  95591. sliders[0].createShutter();
  95592. sliders[1].createShutter()
  95593. },
  95594. removeShutters: function() {
  95595. var sliders = this._sliders;
  95596. sliders[0].removeShutter();
  95597. sliders[1].removeShutter()
  95598. },
  95599. dispose: function() {
  95600. var sliders = this._sliders;
  95601. sliders[0].dispose();
  95602. sliders[1].dispose()
  95603. }
  95604. }
  95605. })(jQuery, DevExpress);
  95606. /*! Module viz-rangeselector, file slidersEventsManager.js */
  95607. (function($, DX, undefined) {
  95608. var rangeSelector = DX.viz.rangeSelector,
  95609. MIN_MANUAL_SELECTING_WIDTH = 10,
  95610. START_VALUE_INDEX = 0,
  95611. END_VALUE_INDEX = 1,
  95612. addNamespace = DX.ui.events.addNamespace,
  95613. _SlidersEventManager,
  95614. rangeSelectorUtils = rangeSelector.utils,
  95615. getEventPageX = rangeSelectorUtils.getEventPageX,
  95616. rangeSelectorCount = 0;
  95617. rangeSelector.events = {
  95618. start: "dxpointerdown",
  95619. move: "dxpointermove",
  95620. end: "dxpointerup"
  95621. };
  95622. var isLeftButtonPressed = function(event) {
  95623. var e = event || window.event,
  95624. originalEvent = e.originalEvent,
  95625. touches = e.touches,
  95626. pointerType = originalEvent ? originalEvent.pointerType : false,
  95627. eventTouches = originalEvent ? originalEvent.touches : false,
  95628. isIE8LeftClick = e.which === undefined && e.button === 1,
  95629. isMSPointerLeftClick = originalEvent && pointerType !== undefined && (pointerType === (originalEvent.MSPOINTER_TYPE_TOUCH || 'touch') || pointerType === (originalEvent.MSPOINTER_TYPE_MOUSE || 'mouse') && originalEvent.buttons === 1),
  95630. isLeftClick = isIE8LeftClick || e.which === 1,
  95631. isTouches = touches && touches.length > 0 || eventTouches && eventTouches.length > 0;
  95632. return isLeftClick || isMSPointerLeftClick || isTouches
  95633. };
  95634. var isMultiTouches = function(event) {
  95635. var originalEvent = event.originalEvent,
  95636. touches = event.touches,
  95637. eventTouches = originalEvent ? originalEvent.touches : false;
  95638. return touches && touches.length > 1 || eventTouches && eventTouches.length > 1 || null
  95639. };
  95640. var isTouchEventArgs = function(e) {
  95641. return e && e.type && e.type.indexOf('touch') === 0
  95642. };
  95643. _SlidersEventManager = rangeSelector.SlidersEventsManager = function(renderer, slidersController, processSelectionChanged) {
  95644. var that = this,
  95645. uniqueNS = that._uniqueNS = 'dx-range-selector_' + rangeSelectorCount++,
  95646. rangeSelectorEvents = rangeSelector.events;
  95647. that._renderer = renderer;
  95648. that._slidersController = slidersController;
  95649. that._processSelectionChanged = processSelectionChanged;
  95650. that._enabled = true;
  95651. that._eventsNames = {
  95652. start: addNamespace(rangeSelectorEvents.start, uniqueNS),
  95653. move: addNamespace(rangeSelectorEvents.move, uniqueNS),
  95654. end: addNamespace(rangeSelectorEvents.end, uniqueNS)
  95655. }
  95656. };
  95657. _SlidersEventManager.prototype = {
  95658. constructor: _SlidersEventManager,
  95659. _initializeSliderEvents: function(sliderIndex) {
  95660. var that = this,
  95661. isTouchEvent,
  95662. slidersController = that._slidersController,
  95663. processSelectionChanged = that._processSelectionChanged,
  95664. slider = slidersController.getSlider(sliderIndex),
  95665. fastSwap,
  95666. startOffsetPosition,
  95667. splitterMoving,
  95668. sliderEndHandler = function() {
  95669. if (splitterMoving) {
  95670. splitterMoving = false;
  95671. slidersController.endSelection();
  95672. slidersController.processDocking();
  95673. processSelectionChanged(false)
  95674. }
  95675. },
  95676. sliderMoveHandler = function(e) {
  95677. var pageX,
  95678. offsetPosition,
  95679. svgOffsetLeft = that._renderer.getRootOffset().left,
  95680. position,
  95681. sliderIndex = slider.getIndex();
  95682. if (isTouchEvent !== isTouchEventArgs(e))
  95683. return;
  95684. if (!isLeftButtonPressed(e, true) && splitterMoving) {
  95685. splitterMoving = false;
  95686. slidersController.processDocking();
  95687. processSelectionChanged(false)
  95688. }
  95689. else if (splitterMoving) {
  95690. if (!isMultiTouches(e)) {
  95691. this.preventedDefault = true;
  95692. e.preventDefault()
  95693. }
  95694. pageX = getEventPageX(e);
  95695. position = pageX - startOffsetPosition - svgOffsetLeft;
  95696. offsetPosition = pageX - slider.getPosition() - svgOffsetLeft;
  95697. slidersController.moveSlider(sliderIndex, fastSwap, position, offsetPosition, startOffsetPosition, function(newStartOffsetPosition) {
  95698. startOffsetPosition = newStartOffsetPosition
  95699. });
  95700. processSelectionChanged(true)
  95701. }
  95702. slidersController.endSelection()
  95703. },
  95704. eventsNames = that._eventsNames;
  95705. slider.startEventHandler = function(e) {
  95706. if (!that._enabled || !isLeftButtonPressed(e) || splitterMoving)
  95707. return;
  95708. fastSwap = this === slider.getSliderTracker().element;
  95709. splitterMoving = true;
  95710. isTouchEvent = isTouchEventArgs(e);
  95711. startOffsetPosition = getEventPageX(e) - slider.getPosition() - that._renderer.getRootOffset().left;
  95712. if (!isMultiTouches(e)) {
  95713. this.preventedDefault = true;
  95714. e.stopPropagation();
  95715. e.preventDefault()
  95716. }
  95717. };
  95718. slider.on(eventsNames.move, function() {
  95719. slidersController.toForeground(slider)
  95720. });
  95721. slider.on(eventsNames.start, slider.startEventHandler);
  95722. $(document).on(eventsNames.end, sliderEndHandler).on(eventsNames.move, sliderMoveHandler);
  95723. slider.__moveEventHandler = sliderMoveHandler
  95724. },
  95725. _initializeAreaEvents: function() {
  95726. var that = this,
  95727. isTouchEvent,
  95728. slidersController = that._slidersController,
  95729. processSelectionChanged = that._processSelectionChanged,
  95730. areaTracker = slidersController.getAreaTracker(),
  95731. unselectedAreaProcessing = false,
  95732. startPageX,
  95733. areaEndHandler = function(e) {
  95734. var pageX;
  95735. if (unselectedAreaProcessing) {
  95736. pageX = getEventPageX(e);
  95737. if (that._options.behavior.moveSelectedRangeByClick && Math.abs(startPageX - pageX) < MIN_MANUAL_SELECTING_WIDTH)
  95738. slidersController.applySelectedAreaCenterPosition(pageX - that._renderer.getRootOffset().left);
  95739. unselectedAreaProcessing = false;
  95740. slidersController.endSelection();
  95741. processSelectionChanged(false)
  95742. }
  95743. },
  95744. areaMoveHandler = function(e) {
  95745. var pageX,
  95746. startPosition,
  95747. endPosition,
  95748. svgOffsetLeft = that._renderer.getRootOffset().left;
  95749. if (isTouchEvent !== isTouchEventArgs(e))
  95750. return;
  95751. if (unselectedAreaProcessing && !isLeftButtonPressed(e)) {
  95752. unselectedAreaProcessing = false;
  95753. processSelectionChanged(false)
  95754. }
  95755. if (unselectedAreaProcessing) {
  95756. pageX = getEventPageX(e);
  95757. if (that._options.behavior.manualRangeSelectionEnabled && Math.abs(startPageX - pageX) >= MIN_MANUAL_SELECTING_WIDTH) {
  95758. startPosition = startPageX - svgOffsetLeft;
  95759. endPosition = pageX - svgOffsetLeft;
  95760. slidersController.processManualSelection(startPosition, endPosition, e);
  95761. unselectedAreaProcessing = false;
  95762. processSelectionChanged(true)
  95763. }
  95764. }
  95765. },
  95766. eventsNames = that._eventsNames;
  95767. areaTracker.on(eventsNames.start, function(e) {
  95768. if (!that._enabled || !isLeftButtonPressed(e) || unselectedAreaProcessing)
  95769. return;
  95770. unselectedAreaProcessing = true;
  95771. isTouchEvent = isTouchEventArgs(e);
  95772. startPageX = getEventPageX(e)
  95773. });
  95774. $(document).on(eventsNames.end, areaEndHandler).on(eventsNames.move, areaMoveHandler);
  95775. that.__areaMoveEventHandler = areaMoveHandler
  95776. },
  95777. _initializeSelectedAreaEvents: function() {
  95778. var that = this,
  95779. isTouchEvent,
  95780. slidersController = that._slidersController,
  95781. processSelectionChanged = that._processSelectionChanged,
  95782. selectedAreaTracker = slidersController.getSelectedAreaTracker(),
  95783. selectedAreaMoving = false,
  95784. offsetStartPosition,
  95785. selectedRangeInterval,
  95786. selectedAreaEndHandler = function() {
  95787. if (selectedAreaMoving) {
  95788. selectedAreaMoving = false;
  95789. slidersController.processDocking();
  95790. processSelectionChanged(false)
  95791. }
  95792. },
  95793. selectedAreaMoveHandler = function(e) {
  95794. var positionDelta,
  95795. pageX;
  95796. if (isTouchEvent !== isTouchEventArgs(e))
  95797. return;
  95798. if (selectedAreaMoving && !isLeftButtonPressed(e)) {
  95799. selectedAreaMoving = false;
  95800. slidersController.processDocking();
  95801. processSelectionChanged(false)
  95802. }
  95803. if (selectedAreaMoving) {
  95804. if (!isMultiTouches(e)) {
  95805. this.preventedDefault = true;
  95806. e.preventDefault()
  95807. }
  95808. pageX = getEventPageX(e);
  95809. positionDelta = pageX - slidersController.getSlider(START_VALUE_INDEX).getPosition() - offsetStartPosition;
  95810. slidersController.moveSliders(positionDelta, selectedRangeInterval);
  95811. processSelectionChanged(true)
  95812. }
  95813. slidersController.endSelection()
  95814. },
  95815. eventsNames = that._eventsNames;
  95816. selectedAreaTracker.on(eventsNames.start, function(e) {
  95817. if (!that._enabled || !isLeftButtonPressed(e) || selectedAreaMoving)
  95818. return;
  95819. selectedAreaMoving = true;
  95820. isTouchEvent = isTouchEventArgs(e);
  95821. offsetStartPosition = getEventPageX(e) - slidersController.getSlider(START_VALUE_INDEX).getPosition();
  95822. selectedRangeInterval = slidersController.getSelectedRangeInterval();
  95823. if (!isMultiTouches(e)) {
  95824. this.preventedDefault = true;
  95825. e.stopPropagation();
  95826. e.preventDefault()
  95827. }
  95828. });
  95829. $(document).on(eventsNames.end, selectedAreaEndHandler).on(eventsNames.move, selectedAreaMoveHandler);
  95830. that.__selectedAreaMoveEventHandler = selectedAreaMoveHandler
  95831. },
  95832. applyOptions: function(options) {
  95833. this._options = options
  95834. },
  95835. dispose: function() {
  95836. $(document).off('.' + this._uniqueNS)
  95837. },
  95838. initialize: function() {
  95839. var that = this;
  95840. that._initializeSelectedAreaEvents(that);
  95841. that._initializeAreaEvents();
  95842. that._initializeSliderEvents(START_VALUE_INDEX);
  95843. that._initializeSliderEvents(END_VALUE_INDEX)
  95844. },
  95845. setEnabled: function(enabled) {
  95846. this._enabled = enabled
  95847. }
  95848. }
  95849. })(jQuery, DevExpress);
  95850. /*! Module viz-rangeselector, file slider.js */
  95851. (function($, DX, undefined) {
  95852. var rangeSelector = DX.viz.rangeSelector,
  95853. utils = DX.utils,
  95854. rangeSelectorUtils = rangeSelector.utils,
  95855. _inArray = $.inArray,
  95856. dxSupport = DX.support,
  95857. touchSupport = dxSupport.touchEvents,
  95858. msPointerEnabled = dxSupport.pointer,
  95859. SPLITTER_WIDTH = 8,
  95860. TOUCH_SPLITTER_WIDTH = 20,
  95861. START_VALUE_INDEX = 0,
  95862. END_VALUE_INDEX = 1,
  95863. DISCRETE = 'discrete',
  95864. baseVisualElementMethods = rangeSelector.baseVisualElementMethods;
  95865. function checkItemsSpacing(firstSliderPosition, secondSliderPosition, distance) {
  95866. return Math.abs(secondSliderPosition - firstSliderPosition) < distance
  95867. }
  95868. function getValidCategories(categories, curValue, anotherSliderValue, offset) {
  95869. var curValueindex = _inArray(curValue, categories);
  95870. if (curValueindex === 0 || curValueindex === categories.length - 1)
  95871. return anotherSliderValue;
  95872. return categories[curValueindex - offset]
  95873. }
  95874. function Slider(renderer, index) {
  95875. baseVisualElementMethods.init.apply(this, arguments);
  95876. this._index = index
  95877. }
  95878. Slider.prototype = $.extend({}, baseVisualElementMethods, {
  95879. getText: function() {
  95880. if (this._marker)
  95881. return this._marker.getText()
  95882. },
  95883. getAvailableValues: function() {
  95884. return this._values
  95885. },
  95886. getShutter: function() {
  95887. return this._shutter
  95888. },
  95889. getMarker: function() {
  95890. return this._marker
  95891. },
  95892. constructor: Slider,
  95893. _createSlider: function(group) {
  95894. var that = this,
  95895. sliderHandle,
  95896. sliderGroup,
  95897. sliderHandleOptions = that._options.sliderHandle,
  95898. canvas = that._options.canvas,
  95899. renderer = that._renderer;
  95900. sliderGroup = renderer.g().attr({
  95901. 'class': 'slider',
  95902. translateX: canvas.left,
  95903. translateY: canvas.top
  95904. }).append(group);
  95905. sliderHandle = renderer.path([0, 0, 0, canvas.height], "line").attr({
  95906. "stroke-width": sliderHandleOptions.width,
  95907. stroke: sliderHandleOptions.color,
  95908. "stroke-opacity": sliderHandleOptions.opacity,
  95909. sharp: "h"
  95910. }).append(sliderGroup);
  95911. sliderGroup.setValid = function(correct) {
  95912. sliderHandle.attr({stroke: correct ? that._options.sliderHandle.color : that._options.sliderMarker.invalidRangeColor})
  95913. };
  95914. sliderGroup.updateHeight = function() {
  95915. sliderHandle.attr({points: [0, 0, 0, that._options.canvas.height]})
  95916. };
  95917. sliderGroup.applyOptions = function(options) {
  95918. sliderHandle.attr(options)
  95919. };
  95920. sliderGroup.__line = sliderHandle;
  95921. return sliderGroup
  95922. },
  95923. _createSliderTracker: function(group) {
  95924. var that = this,
  95925. sliderHandleWidth = that._options.sliderHandle.width,
  95926. splitterWidth = SPLITTER_WIDTH < sliderHandleWidth ? sliderHandleWidth : SPLITTER_WIDTH,
  95927. sliderWidth = touchSupport || msPointerEnabled ? TOUCH_SPLITTER_WIDTH : splitterWidth,
  95928. sliderTracker,
  95929. canvas = that._options.canvas,
  95930. renderer = that._renderer,
  95931. sliderTrackerGroup = renderer.g().attr({
  95932. 'class': 'sliderTracker',
  95933. translateX: 0,
  95934. translateY: canvas.top
  95935. }).append(group);
  95936. sliderTracker = renderer.rect(-sliderWidth / 2, 0, sliderWidth, canvas.height).attr(rangeSelectorUtils.trackerSettings).css({cursor: 'w-resize'}).append(sliderTrackerGroup);
  95937. sliderTrackerGroup.updateHeight = function() {
  95938. sliderTracker.attr({height: that._options.canvas.height})
  95939. };
  95940. sliderTrackerGroup.__rect = sliderTracker;
  95941. return sliderTrackerGroup
  95942. },
  95943. _setPosition: function(position, correctByMinMaxRange) {
  95944. var that = this,
  95945. correctedPosition = that._correctPosition(position),
  95946. value = that._options.translator.untranslate(correctedPosition, that._getValueDirection());
  95947. that.setValue(value, correctByMinMaxRange, false);
  95948. that._position = correctedPosition
  95949. },
  95950. _getValueDirection: function() {
  95951. return this._options.scale.type === DISCRETE ? this.getIndex() === START_VALUE_INDEX ? -1 : 1 : 0
  95952. },
  95953. _setPositionForBothSliders: function(startPosition, interval) {
  95954. var that = this,
  95955. anotherSlider = that.getAnotherSlider(),
  95956. startValue,
  95957. endValue,
  95958. endPosition,
  95959. options = that._options,
  95960. scale = options.scale,
  95961. canvas = options.canvas,
  95962. rightBorderCoords = canvas.left + canvas.width,
  95963. translator = options.translator,
  95964. valueDirection = that._getValueDirection(),
  95965. valueDirectionAnotherSlider = anotherSlider._getValueDirection(),
  95966. getNextValue = function(value, isNegative, reverseValueDirection) {
  95967. var curValueDirection = !reverseValueDirection ? valueDirection : valueDirectionAnotherSlider,
  95968. curAnotherValueDirection = reverseValueDirection ? valueDirection : valueDirectionAnotherSlider;
  95969. return translator.untranslate(that._correctBounds(utils.addInterval(translator.translate(value, curValueDirection), interval, isNegative)), curAnotherValueDirection)
  95970. };
  95971. startPosition = that._correctBounds(startPosition);
  95972. startValue = translator.untranslate(startPosition, valueDirection);
  95973. endValue = getNextValue(startValue);
  95974. endPosition = startPosition + interval;
  95975. if (endPosition > rightBorderCoords) {
  95976. endValue = scale.endValue;
  95977. endPosition = rightBorderCoords;
  95978. startValue = getNextValue(endValue, true, true);
  95979. startPosition = that._correctBounds(endPosition - interval)
  95980. }
  95981. else
  95982. endPosition = that._correctBounds(endPosition);
  95983. if (that._values)
  95984. if (!scale.inverted ? startValue < that._values[0] : startValue > that._values[that._values.length - 1]) {
  95985. startValue = that._correctByAvailableValues(startValue, false);
  95986. endValue = getNextValue(startValue)
  95987. }
  95988. else {
  95989. endValue = that._correctByAvailableValues(endValue, false);
  95990. startValue = getNextValue(endValue, true)
  95991. }
  95992. anotherSlider.setValue(endValue, undefined, false);
  95993. that.setValue(startValue, undefined, false);
  95994. that._position = startPosition;
  95995. anotherSlider._position = endPosition
  95996. },
  95997. _correctPosition: function(position) {
  95998. return this._correctBounds(this._correctInversion(position))
  95999. },
  96000. _correctInversion: function(position) {
  96001. var that = this,
  96002. correctedPosition = position,
  96003. anotherSliderPosition = that.getAnotherSlider().getPosition(),
  96004. slidersInverted = that.getIndex() === START_VALUE_INDEX ? position > anotherSliderPosition : position < anotherSliderPosition;
  96005. if (slidersInverted)
  96006. correctedPosition = anotherSliderPosition;
  96007. return correctedPosition
  96008. },
  96009. _correctBounds: function(position) {
  96010. var that = this,
  96011. correctedPosition = position,
  96012. canvas = that._options.canvas;
  96013. if (position < canvas.left)
  96014. correctedPosition = canvas.left;
  96015. if (position > canvas.left + canvas.width)
  96016. correctedPosition = canvas.left + canvas.width;
  96017. return correctedPosition
  96018. },
  96019. _correctValue: function(businessValue, correctByMinMaxRange, skipCorrection) {
  96020. var that = this,
  96021. result = that._correctByAvailableValues(businessValue, skipCorrection);
  96022. if (correctByMinMaxRange)
  96023. result = that._correctByMinMaxRange(result);
  96024. if (that._options.scale.type !== DISCRETE)
  96025. result = that.correctByMinRange(result);
  96026. return result
  96027. },
  96028. _correctByAvailableValues: function(businessValue, skipCorrection) {
  96029. var values = this._values;
  96030. if (!skipCorrection && values)
  96031. return rangeSelectorUtils.findNearValue(values, businessValue);
  96032. return businessValue
  96033. },
  96034. _correctByMinMaxRange: function(businessValue) {
  96035. var that = this,
  96036. result = businessValue,
  96037. scale = that._options.scale,
  96038. values = that._values,
  96039. sliderIndex = that.getIndex(),
  96040. anotherSlider = that.getAnotherSlider(),
  96041. anotherBusinessValue = anotherSlider.getValue(),
  96042. isValid = true,
  96043. minValue,
  96044. maxValue,
  96045. maxRange = scale.maxRange,
  96046. minRange = scale.minRange,
  96047. categoriesInfo;
  96048. if (scale.type === DISCRETE) {
  96049. categoriesInfo = scale._categoriesInfo;
  96050. if (checkItemsSpacing(that.getPosition(), anotherSlider.getPosition(), that._options.translator.getInterval() / 2)) {
  96051. isValid = false;
  96052. result = getValidCategories(categoriesInfo.categories, businessValue, anotherSlider.getValue(), sliderIndex === START_VALUE_INDEX ? 1 : -1)
  96053. }
  96054. }
  96055. else {
  96056. if (!scale.inverted && sliderIndex === START_VALUE_INDEX || scale.inverted && sliderIndex === END_VALUE_INDEX) {
  96057. if (maxRange)
  96058. minValue = that._addInterval(anotherBusinessValue, maxRange, true);
  96059. if (minRange)
  96060. maxValue = that._addInterval(anotherBusinessValue, minRange, true)
  96061. }
  96062. else {
  96063. if (maxRange)
  96064. maxValue = that._addInterval(anotherBusinessValue, maxRange);
  96065. if (minRange)
  96066. minValue = that._addInterval(anotherBusinessValue, minRange)
  96067. }
  96068. if (maxValue !== undefined && result > maxValue) {
  96069. result = values ? rangeSelectorUtils.findLessOrEqualValue(values, maxValue) : maxValue;
  96070. isValid = false
  96071. }
  96072. else if (minValue !== undefined && result < minValue) {
  96073. result = values ? rangeSelectorUtils.findGreaterOrEqualValue(values, minValue) : minValue;
  96074. isValid = false
  96075. }
  96076. }
  96077. that._setValid(isValid);
  96078. return result
  96079. },
  96080. _addInterval: function(value, interval, isNegative) {
  96081. var result,
  96082. type = this._options.scale.type,
  96083. base = type === "logarithmic" && this._options.scale.logarithmBase,
  96084. power;
  96085. if (base) {
  96086. power = utils.addInterval(utils.getLog(value, base), interval, isNegative);
  96087. result = Math.pow(base, power)
  96088. }
  96089. else
  96090. result = utils.addInterval(value, interval, isNegative);
  96091. return result
  96092. },
  96093. correctByMinRange: function(businessValue) {
  96094. var that = this,
  96095. startValue,
  96096. endValue,
  96097. scale = that._options.scale,
  96098. result = businessValue;
  96099. if (scale.minRange)
  96100. if (that.getIndex() === END_VALUE_INDEX) {
  96101. startValue = that._addInterval(scale.startValue, scale.minRange, scale.inverted);
  96102. if (!scale.inverted && result < startValue || scale.inverted && result > startValue)
  96103. result = startValue
  96104. }
  96105. else if (that.getIndex() === START_VALUE_INDEX) {
  96106. endValue = that._addInterval(scale.endValue, scale.minRange, !scale.inverted);
  96107. if (!scale.inverted && result > endValue || scale.inverted && result < endValue)
  96108. result = endValue
  96109. }
  96110. return result
  96111. },
  96112. _applySliderPosition: function(position, disableAnimation) {
  96113. var that = this,
  96114. options = that._options,
  96115. isAnimation = options.behavior.animationEnabled && !disableAnimation,
  96116. slider = that._slider,
  96117. sliderTracker = that._sliderTracker,
  96118. attrs = {
  96119. translateX: position,
  96120. translateY: options.canvas.top
  96121. },
  96122. animationSettings = rangeSelectorUtils.animationSettings;
  96123. that._marker && that._marker.setPosition(position);
  96124. if (isAnimation) {
  96125. slider.animate(attrs, animationSettings);
  96126. sliderTracker.animate(attrs, animationSettings)
  96127. }
  96128. else {
  96129. slider.stopAnimation().attr(attrs);
  96130. sliderTracker.stopAnimation().attr(attrs)
  96131. }
  96132. sliderTracker.updateHeight();
  96133. slider.updateHeight()
  96134. },
  96135. _applyShutterPosition: function(position, disableAnimation) {
  96136. var that = this,
  96137. shutterSettings,
  96138. options = that._options,
  96139. shutter = that._shutter,
  96140. isAnimation = options.behavior.animationEnabled && !disableAnimation,
  96141. sliderIndex = that.getIndex(),
  96142. canvas = options.canvas,
  96143. halfSliderHandleWidth = options.sliderHandle.width / 2,
  96144. width;
  96145. if (!shutter)
  96146. return;
  96147. if (sliderIndex === START_VALUE_INDEX) {
  96148. width = position - canvas.left - Math.floor(halfSliderHandleWidth);
  96149. if (width < 0)
  96150. width = 0;
  96151. shutterSettings = {
  96152. x: canvas.left,
  96153. y: canvas.top,
  96154. width: width,
  96155. height: canvas.height
  96156. }
  96157. }
  96158. else if (sliderIndex === END_VALUE_INDEX)
  96159. shutterSettings = {
  96160. x: position + Math.ceil(halfSliderHandleWidth),
  96161. y: canvas.top,
  96162. width: canvas.left + canvas.width - position,
  96163. height: canvas.height
  96164. };
  96165. if (isAnimation)
  96166. shutter.animate(shutterSettings, rangeSelectorUtils.animationSettings);
  96167. else
  96168. shutter.stopAnimation().attr(shutterSettings)
  96169. },
  96170. _setValid: function(isValid) {
  96171. this._marker && this._marker.setValid(isValid);
  96172. this._slider.setValid(isValid)
  96173. },
  96174. _setText: function(text) {
  96175. this._marker && this._marker.setText(text)
  96176. },
  96177. _update: function() {
  96178. var that = this,
  96179. options = that._options,
  96180. shutterOptions = options.shutter,
  96181. sliderHandleOptions = options.sliderHandle,
  96182. marker = that._marker;
  96183. if (marker) {
  96184. marker.applyOptions(options.sliderMarker);
  96185. marker.setCanvas(that._options.canvas)
  96186. }
  96187. that._shutter && that._shutter.attr({
  96188. fill: shutterOptions.color,
  96189. "fill-opacity": shutterOptions.opacity
  96190. });
  96191. that._slider && that._slider.applyOptions({
  96192. "stroke-width": sliderHandleOptions.width,
  96193. stroke: sliderHandleOptions.color,
  96194. "stroke-opacity": sliderHandleOptions.opacity
  96195. })
  96196. },
  96197. _draw: function(group) {
  96198. var that = this,
  96199. slider,
  96200. marker,
  96201. sliderAreaGroup,
  96202. options = that._options,
  96203. renderer = that._renderer;
  96204. that._container = sliderAreaGroup = renderer.g().attr({'class': 'sliderArea'}).append(group);
  96205. slider = that._createSlider(sliderAreaGroup);
  96206. if (options.sliderMarker.visible) {
  96207. marker = rangeSelector.rangeSelectorFactory.createSliderMarker({
  96208. renderer: renderer,
  96209. isLeftPointer: that.getIndex() === END_VALUE_INDEX,
  96210. sliderMarkerOptions: options.sliderMarker
  96211. });
  96212. marker.setCanvas(options.canvas);
  96213. marker.draw(slider)
  96214. }
  96215. that._slider = slider;
  96216. that._marker = marker;
  96217. that._sliderTracker = that._createSliderTracker(group)
  96218. },
  96219. toForeground: function() {
  96220. this._container.toForeground()
  96221. },
  96222. _applyOptions: function() {
  96223. this._lastPosition = null
  96224. },
  96225. getIndex: function() {
  96226. return this._index
  96227. },
  96228. setAvailableValues: function(values) {
  96229. this._values = values
  96230. },
  96231. setAnotherSlider: function(slider) {
  96232. this._anotherSlider = slider
  96233. },
  96234. getAnotherSlider: function() {
  96235. return this._anotherSlider
  96236. },
  96237. appendTrackers: function(group) {
  96238. this._sliderTracker && this._sliderTracker.append(group)
  96239. },
  96240. getSliderTracker: function() {
  96241. return this._sliderTracker
  96242. },
  96243. changeLocation: function() {
  96244. var that = this;
  96245. that._marker && that._marker.changeLocation();
  96246. that._index = that._index === START_VALUE_INDEX ? END_VALUE_INDEX : START_VALUE_INDEX;
  96247. if (that._options.scale.type === DISCRETE)
  96248. that.setPosition(that._position);
  96249. that._lastPosition = null
  96250. },
  96251. setPosition: function(position, correctByMinMaxRange, selectedRangeInterval) {
  96252. var that = this,
  96253. slider;
  96254. if (selectedRangeInterval !== undefined) {
  96255. slider = that.getIndex() === START_VALUE_INDEX ? that : that.getAnotherSlider();
  96256. slider._setPositionForBothSliders(position, selectedRangeInterval)
  96257. }
  96258. else
  96259. that._setPosition(position, correctByMinMaxRange)
  96260. },
  96261. getPosition: function() {
  96262. return this._position
  96263. },
  96264. setValue: function(value, correctByMinMaxRange, skipCorrection) {
  96265. var that = this,
  96266. options = that._options,
  96267. canvas = options.canvas,
  96268. position,
  96269. text;
  96270. if (value === undefined) {
  96271. that._value = undefined;
  96272. position = that.getIndex() === START_VALUE_INDEX ? canvas.left : canvas.left + canvas.width;
  96273. text = rangeSelector.consts.emptySliderMarkerText
  96274. }
  96275. else {
  96276. that._value = that._correctValue(value, correctByMinMaxRange, utils.isDefined(skipCorrection) ? !!skipCorrection : true);
  96277. position = options.translator.translate(that._value, that._getValueDirection());
  96278. text = rangeSelector.formatValue(that._value, options.sliderMarker)
  96279. }
  96280. that._setText(text);
  96281. that._valuePosition = that._position = position
  96282. },
  96283. setOverlapped: function(isOverlapped) {
  96284. this._marker && this._marker.setOverlapped(isOverlapped)
  96285. },
  96286. getValue: function() {
  96287. return this._value
  96288. },
  96289. canSwap: function() {
  96290. var that = this,
  96291. scale = that._options.scale,
  96292. startValue,
  96293. endValue,
  96294. anotherSliderValue;
  96295. if (that._options.behavior.allowSlidersSwap) {
  96296. if (scale.minRange) {
  96297. anotherSliderValue = that.getAnotherSlider().getValue();
  96298. if (that.getIndex() === START_VALUE_INDEX) {
  96299. endValue = that._addInterval(scale.endValue, scale.minRange, !scale.inverted);
  96300. if (!scale.inverted && anotherSliderValue > endValue || scale.inverted && anotherSliderValue < endValue)
  96301. return false
  96302. }
  96303. else {
  96304. startValue = that._addInterval(scale.startValue, scale.minRange, scale.inverted);
  96305. if (!scale.inverted && anotherSliderValue < startValue || scale.inverted && anotherSliderValue > startValue)
  96306. return false
  96307. }
  96308. }
  96309. return true
  96310. }
  96311. return false
  96312. },
  96313. processDocking: function() {
  96314. var that = this;
  96315. that._position = that._valuePosition;
  96316. that.applyPosition(false);
  96317. that._setValid(true)
  96318. },
  96319. applyPosition: function(disableAnimation) {
  96320. var that = this,
  96321. position = that.getPosition();
  96322. if (that._lastPosition !== position) {
  96323. that._applySliderPosition(position, disableAnimation);
  96324. that._applyShutterPosition(position, disableAnimation);
  96325. that._lastPosition = position
  96326. }
  96327. },
  96328. on: function(event, handler) {
  96329. var that = this,
  96330. marker = that._marker,
  96331. tracker = marker && marker.getTracker(),
  96332. sliderTracker = that._sliderTracker;
  96333. sliderTracker && sliderTracker.on(event, handler);
  96334. tracker && tracker.on(event, handler)
  96335. },
  96336. createShutter: function() {
  96337. var that = this,
  96338. index = that.getIndex(),
  96339. canvas = that._options.canvas,
  96340. renderer = that._renderer,
  96341. shutter = that._shutter;
  96342. if (!shutter) {
  96343. if (index === START_VALUE_INDEX)
  96344. shutter = renderer.rect(canvas.left, canvas.top, 0, canvas.height);
  96345. else if (index === END_VALUE_INDEX)
  96346. shutter = renderer.rect(canvas.left, canvas.top, canvas.width, canvas.height);
  96347. that._shutter = shutter
  96348. }
  96349. shutter.append(that._container)
  96350. },
  96351. removeShutter: function() {
  96352. var shutter = this._shutter;
  96353. shutter && shutter.remove()
  96354. },
  96355. getCloudBorder: function() {
  96356. return this._marker ? this._marker.getBorderPosition() : 0
  96357. },
  96358. dispose: function() {
  96359. var marker = this._marker;
  96360. marker && marker.dispose()
  96361. }
  96362. });
  96363. rangeSelector.Slider = Slider
  96364. })(jQuery, DevExpress);
  96365. /*! Module viz-rangeselector, file sliderMarker.js */
  96366. (function($, DX, undefined) {
  96367. var viz = DX.viz,
  96368. core = viz.core,
  96369. rangeSelector = viz.rangeSelector,
  96370. SliderMarker,
  96371. SLIDER_MARKER_UPDATE_DELAY = 75,
  96372. POINTER_SIZE = rangeSelector.consts.pointerSize;
  96373. var getRectSize = function(that, textSize) {
  96374. var options = that._options;
  96375. return {
  96376. width: Math.round(2 * options.paddingLeftRight + textSize.width),
  96377. height: Math.round(2 * options.paddingTopBottom + textSize.height)
  96378. }
  96379. };
  96380. var getAreaPointsInfo = function(that, textSize) {
  96381. var rectSize = getRectSize(that, textSize),
  96382. rectWidth = rectSize.width,
  96383. rectHeight = rectSize.height,
  96384. rectLeftBorder = -rectWidth,
  96385. rectRightBorder = 0,
  96386. pointerRightPoint = POINTER_SIZE,
  96387. pointerCenterPoint = 0,
  96388. pointerLeftPoint = -POINTER_SIZE,
  96389. position = that._position,
  96390. canvas = that._canvas,
  96391. isLeft = that._isLeftPointer,
  96392. correctCloudBorders = function() {
  96393. rectLeftBorder++;
  96394. rectRightBorder++;
  96395. pointerRightPoint++;
  96396. pointerCenterPoint++;
  96397. pointerLeftPoint++
  96398. },
  96399. checkPointerBorders = function() {
  96400. if (pointerRightPoint > rectRightBorder)
  96401. pointerRightPoint = rectRightBorder;
  96402. else if (pointerLeftPoint < rectLeftBorder)
  96403. pointerLeftPoint = rectLeftBorder;
  96404. isLeft && correctCloudBorders()
  96405. },
  96406. borderPosition = position;
  96407. if (isLeft)
  96408. if (position > canvas.left + canvas.width - rectWidth) {
  96409. rectRightBorder = -position + (canvas.left + canvas.width);
  96410. rectLeftBorder = rectRightBorder - rectWidth;
  96411. checkPointerBorders();
  96412. borderPosition += rectLeftBorder
  96413. }
  96414. else {
  96415. rectLeftBorder = pointerLeftPoint = 0;
  96416. rectRightBorder = rectWidth
  96417. }
  96418. else if (position - canvas.left < rectWidth) {
  96419. rectLeftBorder = -(position - canvas.left);
  96420. rectRightBorder = rectLeftBorder + rectWidth;
  96421. checkPointerBorders();
  96422. borderPosition += rectRightBorder
  96423. }
  96424. else {
  96425. pointerRightPoint = 0;
  96426. correctCloudBorders()
  96427. }
  96428. that._borderPosition = borderPosition;
  96429. return {
  96430. offset: rectLeftBorder,
  96431. isCutted: (!isLeft || pointerCenterPoint !== pointerLeftPoint) && (isLeft || pointerCenterPoint !== pointerRightPoint),
  96432. points: [rectLeftBorder, 0, rectRightBorder, 0, rectRightBorder, rectHeight, pointerRightPoint, rectHeight, pointerCenterPoint, rectHeight + POINTER_SIZE, pointerLeftPoint, rectHeight, rectLeftBorder, rectHeight]
  96433. }
  96434. };
  96435. var getTextSize = function(that) {
  96436. var textSize = that._label.getBBox();
  96437. if (!that._textHeight && isFinite(textSize.height))
  96438. that._textHeight = textSize.height;
  96439. return {
  96440. width: textSize.width,
  96441. height: that._textHeight,
  96442. y: textSize.y
  96443. }
  96444. };
  96445. SliderMarker = rangeSelector.SliderMarker = function(options) {
  96446. var that = this;
  96447. that._renderer = options.renderer;
  96448. that._text = options.text;
  96449. that._isLeftPointer = options.isLeftPointer;
  96450. that._options = $.extend(true, {}, options.sliderMarkerOptions);
  96451. that._options.textFontStyles = core.utils.patchFontOptions(that._options.font);
  96452. that._isValid = true;
  96453. that._isOverlapped = false
  96454. };
  96455. SliderMarker.prototype = {
  96456. constructor: SliderMarker,
  96457. draw: function(group) {
  96458. var that = this,
  96459. options = that._options,
  96460. sliderMarkerGroup = that._sliderMarkerGroup = that._renderer.g().attr({'class': 'sliderMarker'}).append(group);
  96461. that._area = that._renderer.path([], "area").attr({fill: options.color}).append(sliderMarkerGroup);
  96462. that._label = that._renderer.text(that._text, 0, 0).attr({align: 'left'}).css(options.textFontStyles).append(sliderMarkerGroup);
  96463. that._tracker = that._renderer.rect(0, 0, 2 * options.paddingLeftRight, 2 * options.paddingTopBottom + POINTER_SIZE).attr(rangeSelector.utils.trackerSettings).css({cursor: 'pointer'}).append(sliderMarkerGroup);
  96464. that._border = that._renderer.rect(0, 0, 1, 0).attr({fill: options.borderColor});
  96465. that._drawn = true;
  96466. that._update()
  96467. },
  96468. _update: function() {
  96469. var that = this,
  96470. textSize,
  96471. options = that._options,
  96472. currentTextSize,
  96473. rectSize;
  96474. clearTimeout(that._timeout);
  96475. if (!that._drawn)
  96476. return;
  96477. that._label.attr({text: that._text || ""});
  96478. currentTextSize = getTextSize(that);
  96479. rectSize = getRectSize(that, currentTextSize);
  96480. textSize = that._textSize || currentTextSize;
  96481. textSize = that._textSize = currentTextSize.width > textSize.width || currentTextSize.height > textSize.height ? currentTextSize : textSize;
  96482. that._timeout = setTimeout(function() {
  96483. updateSliderMarker(currentTextSize, rectSize);
  96484. that._textSize = currentTextSize
  96485. }, SLIDER_MARKER_UPDATE_DELAY);
  96486. function updateSliderMarker(size, rectSize) {
  96487. var points,
  96488. pointsData,
  96489. offset;
  96490. rectSize = rectSize || getRectSize(that, size);
  96491. that._sliderMarkerGroup.attr({translateY: -(rectSize.height + POINTER_SIZE)});
  96492. pointsData = getAreaPointsInfo(that, size);
  96493. points = pointsData.points;
  96494. offset = pointsData.offset;
  96495. that._area.attr({points: points});
  96496. that._border.attr({
  96497. x: that._isLeftPointer ? points[0] - 1 : points[2],
  96498. height: pointsData.isCutted ? rectSize.height : rectSize.height + POINTER_SIZE
  96499. });
  96500. that._tracker.attr({
  96501. translateX: offset,
  96502. width: rectSize.width,
  96503. height: rectSize.height + POINTER_SIZE
  96504. });
  96505. that._label.attr({
  96506. translateX: options.paddingLeftRight + offset,
  96507. translateY: rectSize.height / 2 - (size.y + size.height / 2)
  96508. })
  96509. }
  96510. updateSliderMarker(textSize)
  96511. },
  96512. setText: function(value) {
  96513. var that = this;
  96514. if (that._text !== value)
  96515. that._text = value
  96516. },
  96517. setPosition: function(position) {
  96518. this._position = position;
  96519. this._update()
  96520. },
  96521. changeLocation: function() {
  96522. var that = this;
  96523. that._isLeftPointer = !that._isLeftPointer;
  96524. that._update()
  96525. },
  96526. applyOptions: function(options) {
  96527. var that = this,
  96528. fontSyles,
  96529. opt = that._options = $.extend(true, {}, options);
  96530. fontSyles = opt.textFontStyles = core.utils.patchFontOptions(opt.font);
  96531. that._textHeight = null;
  96532. that._area.attr({fill: options.color});
  96533. that._border.attr({fill: options.borderColor});
  96534. that._label.css(fontSyles);
  96535. that._update()
  96536. },
  96537. getTracker: function() {
  96538. return this._tracker
  96539. },
  96540. setValid: function(isValid) {
  96541. var that = this,
  96542. options = that._options;
  96543. if (that._isValid !== isValid) {
  96544. that._isValid = isValid;
  96545. that._area.attr({fill: isValid ? options.color : options.invalidRangeColor})
  96546. }
  96547. },
  96548. dispose: function() {
  96549. clearTimeout(this._timeout)
  96550. },
  96551. setOverlapped: function(isOverlapped) {
  96552. var border = this._border,
  96553. currentOverlappedState = this._isOverlapped;
  96554. if (currentOverlappedState === isOverlapped)
  96555. return;
  96556. if (isOverlapped)
  96557. border.append(this._sliderMarkerGroup);
  96558. else
  96559. this._isOverlapped && border.remove();
  96560. this._isOverlapped = isOverlapped
  96561. },
  96562. getBorderPosition: function() {
  96563. return this._borderPosition
  96564. },
  96565. setCanvas: function(canvas) {
  96566. this._canvas = canvas
  96567. }
  96568. };
  96569. SliderMarker.prototype.updateDelay = SLIDER_MARKER_UPDATE_DELAY;
  96570. SliderMarker.prototype.getText = function() {
  96571. return this._text
  96572. }
  96573. })(jQuery, DevExpress);
  96574. /*! Module viz-rangeselector, file rangeView.js */
  96575. (function($, DX, undefined) {
  96576. var rangeSelector = DX.viz.rangeSelector,
  96577. RangeView,
  96578. baseVisualElementMethods = rangeSelector.baseVisualElementMethods;
  96579. RangeView = function() {
  96580. baseVisualElementMethods.init.apply(this, arguments)
  96581. };
  96582. RangeView.prototype = $.extend({}, baseVisualElementMethods, {
  96583. constructor: RangeView,
  96584. _draw: function(group) {
  96585. var that = this,
  96586. series,
  96587. i,
  96588. options = that._options,
  96589. isCompactMode = options.isCompactMode,
  96590. canvas = options.canvas,
  96591. isEmpty = options.isEmpty,
  96592. renderer = that._renderer,
  96593. seriesDataSource = options.seriesDataSource,
  96594. showChart = seriesDataSource && seriesDataSource.isShowChart() && !isEmpty,
  96595. background = options.background,
  96596. backgroundColor = showChart ? seriesDataSource.getBackgroundColor() : background.color,
  96597. backgroundImage = background.image,
  96598. backgroundIsVisible = background.visible;
  96599. if (isCompactMode)
  96600. return;
  96601. if (backgroundIsVisible && !isEmpty && backgroundColor)
  96602. renderer.rect(canvas.left, canvas.top, canvas.width + 1, canvas.height).attr({
  96603. fill: backgroundColor,
  96604. 'class': 'dx-range-selector-background'
  96605. }).append(group);
  96606. if (backgroundIsVisible && backgroundImage && backgroundImage.url)
  96607. renderer.image(canvas.left, canvas.top, canvas.width + 1, canvas.height, backgroundImage.url, backgroundImage.location).append(group);
  96608. if (showChart) {
  96609. series = seriesDataSource.getSeries();
  96610. seriesDataSource.adjustSeriesDimensions(options.translators, options.chart.useAggregation);
  96611. for (i = 0; i < series.length; i++) {
  96612. series[i]._extGroups.seriesGroup = group;
  96613. series[i]._extGroups.labelsGroup = group;
  96614. series[i].draw(options.translators, options.behavior && options.behavior.animationEnabled && renderer.animationEnabled())
  96615. }
  96616. }
  96617. }
  96618. });
  96619. rangeSelector.RangeView = RangeView
  96620. })(jQuery, DevExpress);
  96621. /*! Module viz-rangeselector, file seriesDataSource.js */
  96622. (function($, DX, undefined) {
  96623. var rangeSelector = DX.viz.rangeSelector,
  96624. charts = DX.viz.charts,
  96625. core = DX.viz.core,
  96626. coreFactory = core.CoreFactory,
  96627. utils = DX.utils,
  96628. _SeriesDatasource;
  96629. var createThemeManager = function(chartOptions) {
  96630. return charts.factory.createThemeManager(chartOptions, 'rangeSelector.chart')
  96631. };
  96632. var isArrayOfSimpleTypes = function(data) {
  96633. return $.isArray(data) && data.length > 0 && (utils.isNumber(data[0]) || utils.isDate(data[0]))
  96634. };
  96635. var convertToArrayOfObjects = function(data) {
  96636. return $.map(data, function(item, i) {
  96637. return {
  96638. arg: item,
  96639. val: i
  96640. }
  96641. })
  96642. };
  96643. var processSeriesFamilies = function(series, equalBarWidth, minBubbleSize, maxBubbleSize) {
  96644. var families = [],
  96645. types = [];
  96646. $.each(series, function(i, item) {
  96647. if ($.inArray(item.type, types) === -1)
  96648. types.push(item.type)
  96649. });
  96650. $.each(types, function(_, type) {
  96651. var family = new coreFactory.createSeriesFamily({
  96652. type: type,
  96653. equalBarWidth: equalBarWidth,
  96654. minBubbleSize: minBubbleSize,
  96655. maxBubbleSize: maxBubbleSize
  96656. });
  96657. family.add(series);
  96658. family.adjustSeriesValues();
  96659. families.push(family)
  96660. });
  96661. return families
  96662. };
  96663. var isStickType = function(type) {
  96664. var nonStickTypes = ["bar", "candlestick", "stock", "bubble"],
  96665. stickType = true;
  96666. type = type.toLowerCase();
  96667. $.each(nonStickTypes, function(_, item) {
  96668. if (type.indexOf(item) !== -1) {
  96669. stickType = false;
  96670. return false
  96671. }
  96672. });
  96673. return stickType
  96674. };
  96675. function setTemplateFields(data, templateData, series) {
  96676. $.each(data, function(_, data) {
  96677. $.each(series.getTeamplatedFields(), function(_, field) {
  96678. data[field.teamplateField] = data[field.originalField]
  96679. });
  96680. templateData.push(data)
  96681. });
  96682. series.updateTeamplateFieldNames()
  96683. }
  96684. _SeriesDatasource = rangeSelector.SeriesDataSource = function(options) {
  96685. var that = this,
  96686. templatedSeries,
  96687. seriesTemplate,
  96688. themeManager = that._themeManager = createThemeManager(options.chart),
  96689. topIndent,
  96690. bottomIndent;
  96691. themeManager._fontFields = ["commonSeriesSettings.label.font"];
  96692. themeManager.setTheme(options.chart.theme);
  96693. topIndent = themeManager.getOptions('topIndent');
  96694. bottomIndent = themeManager.getOptions('bottomIndent');
  96695. that._indent = {
  96696. top: topIndent >= 0 && topIndent < 1 ? topIndent : 0,
  96697. bottom: bottomIndent >= 0 && bottomIndent < 1 ? bottomIndent : 0
  96698. };
  96699. that._valueAxis = themeManager.getOptions('valueAxisRangeSelector') || {};
  96700. that._hideChart = false;
  96701. seriesTemplate = themeManager.getOptions('seriesTemplate');
  96702. if (options.dataSource && seriesTemplate)
  96703. templatedSeries = utils.processSeriesTemplate(seriesTemplate, options.dataSource);
  96704. that._series = that._calculateSeries(options, templatedSeries);
  96705. that._seriesFamilies = processSeriesFamilies(that._series, themeManager.getOptions('equalBarWidth'), themeManager.getOptions('minBubbleSize'), themeManager.getOptions('maxBubbleSize'))
  96706. };
  96707. _SeriesDatasource.prototype = {
  96708. constructor: _SeriesDatasource,
  96709. _calculateSeries: function(options, templatedSeries) {
  96710. var that = this,
  96711. series = [],
  96712. particularSeriesOptions,
  96713. seriesTheme,
  96714. data,
  96715. groupSeries,
  96716. parsedData,
  96717. chartThemeManager = that._themeManager,
  96718. hasSeriesTemplate = !!chartThemeManager.getOptions('seriesTemplate'),
  96719. allSeriesOptions = hasSeriesTemplate ? templatedSeries : options.chart.series,
  96720. seriesValueType = options.chart.valueAxis && options.chart.valueAxis.valueType,
  96721. dataSourceField,
  96722. i,
  96723. newSeries,
  96724. particularSeries;
  96725. that.teamplateData = [];
  96726. if (options.dataSource && !allSeriesOptions) {
  96727. if (isArrayOfSimpleTypes(options.dataSource))
  96728. options.dataSource = convertToArrayOfObjects(options.dataSource);
  96729. dataSourceField = options.dataSourceField || 'arg';
  96730. allSeriesOptions = {
  96731. argumentField: dataSourceField,
  96732. valueField: dataSourceField
  96733. };
  96734. that._hideChart = true
  96735. }
  96736. allSeriesOptions = $.isArray(allSeriesOptions) ? allSeriesOptions : allSeriesOptions ? [allSeriesOptions] : [];
  96737. that._backgroundColor = options.backgroundColor;
  96738. for (i = 0; i < allSeriesOptions.length; i++) {
  96739. particularSeriesOptions = $.extend(true, {incidentOccured: options.incidentOccured}, allSeriesOptions[i]);
  96740. particularSeriesOptions.rotated = false;
  96741. data = particularSeriesOptions.data || options.dataSource;
  96742. seriesTheme = chartThemeManager.getOptions("series", particularSeriesOptions);
  96743. seriesTheme.argumentField = seriesTheme.argumentField || options.dataSourceField;
  96744. if (data && data.length > 0) {
  96745. newSeries = coreFactory.createSeries({renderer: options.renderer}, seriesTheme);
  96746. series.push(newSeries)
  96747. }
  96748. if (hasSeriesTemplate)
  96749. setTemplateFields(data, that.teamplateData, newSeries)
  96750. }
  96751. data = hasSeriesTemplate ? that.teamplateData : data;
  96752. groupSeries = [series];
  96753. groupSeries.argumentOptions = {
  96754. categories: options.categories,
  96755. argumentType: options.valueType,
  96756. type: options.axisType
  96757. };
  96758. groupSeries[0].valueOptions = {valueType: dataSourceField ? options.valueType : seriesValueType};
  96759. that._dataValidator = core.CoreFactory.createDataValidator(data, groupSeries, options.incidentOccured, chartThemeManager.getOptions("dataPrepareSettings"));
  96760. parsedData = that._dataValidator.validate();
  96761. for (i = 0; i < series.length; i++) {
  96762. particularSeries = series[i];
  96763. particularSeries.updateData(parsedData)
  96764. }
  96765. return series
  96766. },
  96767. adjustSeriesDimensions: function(translators, useAggregation) {
  96768. var that = this;
  96769. if (useAggregation)
  96770. $.each(that._series || [], function(_, s) {
  96771. s.resamplePoints(translators.x)
  96772. });
  96773. $.each(that._seriesFamilies, function(_, family) {
  96774. family.adjustSeriesDimensions({
  96775. arg: translators.x,
  96776. val: translators.y
  96777. })
  96778. })
  96779. },
  96780. getBoundRange: function() {
  96781. var that = this,
  96782. rangeData,
  96783. valueAxisMin = that._valueAxis.min,
  96784. valueAxisMax = that._valueAxis.max,
  96785. valRange = new core.Range({
  96786. isValueRange: true,
  96787. min: valueAxisMin,
  96788. minVisible: valueAxisMin,
  96789. max: valueAxisMax,
  96790. maxVisible: valueAxisMax,
  96791. axisType: that._valueAxis.type,
  96792. base: that._valueAxis.logarithmBase
  96793. }),
  96794. argRange = new core.Range({}),
  96795. rangeYSize,
  96796. rangeVisibleSizeY,
  96797. minIndent,
  96798. maxIndent;
  96799. $.each(that._series, function(_, series) {
  96800. rangeData = series.getRangeData();
  96801. valRange.addRange(rangeData.val);
  96802. argRange.addRange(rangeData.arg);
  96803. if (!isStickType(series.type))
  96804. argRange.addRange({stick: false})
  96805. });
  96806. if (valRange.isDefined() && argRange.isDefined()) {
  96807. minIndent = that._valueAxis.inverted ? that._indent.top : that._indent.bottom;
  96808. maxIndent = that._valueAxis.inverted ? that._indent.bottom : that._indent.top;
  96809. rangeYSize = valRange.max - valRange.min;
  96810. rangeVisibleSizeY = ($.isNumeric(valRange.maxVisible) ? valRange.maxVisible : valRange.max) - ($.isNumeric(valRange.minVisible) ? valRange.minVisible : valRange.min);
  96811. if (utils.isDate(valRange.min))
  96812. valRange.min = new Date(valRange.min.valueOf() - rangeYSize * minIndent);
  96813. else
  96814. valRange.min -= rangeYSize * minIndent;
  96815. if (utils.isDate(valRange.max))
  96816. valRange.max = new Date(valRange.max.valueOf() + rangeYSize * maxIndent);
  96817. else
  96818. valRange.max += rangeYSize * maxIndent;
  96819. if ($.isNumeric(rangeVisibleSizeY)) {
  96820. valRange.maxVisible = valRange.maxVisible ? valRange.maxVisible + rangeVisibleSizeY * maxIndent : undefined;
  96821. valRange.minVisible = valRange.minVisible ? valRange.minVisible - rangeVisibleSizeY * minIndent : undefined
  96822. }
  96823. valRange.invert = that._valueAxis.inverted
  96824. }
  96825. return {
  96826. arg: argRange,
  96827. val: valRange
  96828. }
  96829. },
  96830. getSeries: function() {
  96831. var that = this;
  96832. return that._series
  96833. },
  96834. getBackgroundColor: function() {
  96835. return this._backgroundColor
  96836. },
  96837. isEmpty: function() {
  96838. var that = this;
  96839. return that.getSeries().length === 0
  96840. },
  96841. isShowChart: function() {
  96842. var that = this;
  96843. return !that.isEmpty() && !that._hideChart
  96844. },
  96845. getCalculatedValueType: function() {
  96846. var that = this,
  96847. result;
  96848. if (that._series.length)
  96849. result = that._series[0].argumentType;
  96850. return result
  96851. },
  96852. getThemeManager: function() {
  96853. return this._themeManager
  96854. }
  96855. }
  96856. })(jQuery, DevExpress);
  96857. /*! Module viz-rangeselector, file themeManager.js */
  96858. (function($, DX, undefined) {
  96859. DX.viz.rangeSelector.ThemeManager = DX.viz.core.BaseThemeManager.inherit({
  96860. _themeSection: 'rangeSelector',
  96861. _fontFields: ['scale.label.font', 'sliderMarker.font', 'loadingIndicator.font']
  96862. })
  96863. })(jQuery, DevExpress);
  96864. DevExpress.MOD_VIZ_RANGESELECTOR = true
  96865. }
  96866. if (!DevExpress.MOD_VIZ_VECTORMAP) {
  96867. if (!DevExpress.MOD_VIZ_CORE)
  96868. throw Error('Required module is not referenced: viz-core');
  96869. /*! Module viz-vectormap, file map.js */
  96870. (function(DX, $, undefined) {
  96871. DX.viz.map = {};
  96872. var _parseScalar = DX.viz.core.utils.parseScalar,
  96873. DEFAULT_WIDTH = 800,
  96874. DEFAULT_HEIGHT = 400,
  96875. TOOLTIP_OFFSET = 12,
  96876. _extend = $.extend,
  96877. nextDataKey = 1;
  96878. function generateDataKey() {
  96879. return "vectormap-data-" + nextDataKey++
  96880. }
  96881. var Map = DX.viz.core.BaseWidget.inherit({
  96882. _eventsMap: _extend({}, DX.viz.core.BaseWidget.prototype._eventsMap, {
  96883. onClick: {
  96884. name: "click",
  96885. deprecated: "click",
  96886. deprecatedContext: function(arg) {
  96887. return arg.component
  96888. },
  96889. deprecatedArgs: function(arg) {
  96890. return [arg.jQueryEvent]
  96891. }
  96892. },
  96893. click: {newName: "onClick"},
  96894. onCenterChanged: {
  96895. name: "centerChanged",
  96896. deprecated: "centerChanged",
  96897. deprecatedContext: function(arg) {
  96898. return arg.component
  96899. },
  96900. deprecatedArgs: function(arg) {
  96901. return [arg.center]
  96902. }
  96903. },
  96904. centerChanged: {newName: "onCenterChanged"},
  96905. onZoomFactorChanged: {
  96906. name: "zoomFactorChanged",
  96907. deprecated: "zoomFactorChanged",
  96908. deprecatedContext: function(arg) {
  96909. return arg.component
  96910. },
  96911. deprecatedArgs: function(arg) {
  96912. return [arg.zoomFactor]
  96913. }
  96914. },
  96915. zoomFactorChanged: {newName: "onZoomFactorChanged"},
  96916. onAreaClick: {
  96917. name: "areaClick",
  96918. deprecated: "areaSettings.click",
  96919. deprecatedContext: function(arg) {
  96920. return arg.target
  96921. },
  96922. deprecatedArgs: function(arg) {
  96923. return [arg.target, arg.jQueryEvent]
  96924. }
  96925. },
  96926. onAreaHoverChanged: {name: "areaHoverChanged"},
  96927. onAreaSelectionChanged: {
  96928. name: "areaSelectionChanged",
  96929. deprecated: "areaSettings.selectionChanged",
  96930. deprecatedContext: function(arg) {
  96931. return arg.target
  96932. },
  96933. deprecatedArgs: function(arg) {
  96934. return [arg.target]
  96935. }
  96936. },
  96937. onMarkerClick: {
  96938. name: "markerClick",
  96939. deprecated: "markerSettings.click",
  96940. deprecatedContext: function(arg) {
  96941. return arg.target
  96942. },
  96943. deprecatedArgs: function(arg) {
  96944. return [arg.target, arg.jQueryEvent]
  96945. }
  96946. },
  96947. onMarkerHoverChanged: {name: "markerHoverChanged"},
  96948. onMarkerSelectionChanged: {
  96949. name: "markerSelectionChanged",
  96950. deprecated: "markerSettings.selectionChanged",
  96951. deprecatedContext: function(arg) {
  96952. return arg.target
  96953. },
  96954. deprecatedArgs: function(arg) {
  96955. return [arg.target]
  96956. }
  96957. }
  96958. }),
  96959. _setDeprecatedOptions: function() {
  96960. this.callBase();
  96961. $.extend(this._deprecatedOptions, {
  96962. click: {
  96963. since: "14.2",
  96964. message: 'Use the "onClick" option instead'
  96965. },
  96966. centerChanged: {
  96967. since: "14.2",
  96968. message: 'Use the "onCenterChanged" option instead'
  96969. },
  96970. zoomFactorChanged: {
  96971. since: "14.2",
  96972. message: 'Use the "onZoomFactorChanged" option instead'
  96973. },
  96974. "areaSettings.click": {
  96975. since: "14.2",
  96976. message: 'Use the "onAreaClick" option instead'
  96977. },
  96978. "areaSettings.selectionChanged": {
  96979. since: "14.2",
  96980. message: 'Use the "onAreaSelectionChanged" option instead'
  96981. },
  96982. "markerSettings.click": {
  96983. since: "14.2",
  96984. message: 'Use the "onMarkerClick" option instead'
  96985. },
  96986. "markerSettings.selectionChanged": {
  96987. since: "14.2",
  96988. message: 'Use the "onMarkerSelectionChanged" option instead'
  96989. },
  96990. "markerSettings.font": {
  96991. since: "14.2",
  96992. message: 'Use the "label.font" option instead'
  96993. }
  96994. })
  96995. },
  96996. _rootClassPrefix: "dxm",
  96997. _rootClass: "dxm-vector-map",
  96998. _createThemeManager: function() {
  96999. return this._factory.createThemeManager()
  97000. },
  97001. _initBackground: function(dataKey) {
  97002. this._background = this._renderer.rect(0, 0, 0, 0).attr({"class": "dxm-background"}).data(dataKey, {type: "background"})
  97003. },
  97004. _initAreasManager: function(dataKey, notifyDirty, notifyReady) {
  97005. var that = this;
  97006. that._areasManager = that._factory.createAreasManager({
  97007. container: that._root,
  97008. renderer: that._renderer,
  97009. projection: that._projection,
  97010. themeManager: that._themeManager,
  97011. tracker: that._tracker,
  97012. dataKey: dataKey,
  97013. eventTrigger: that._eventTrigger,
  97014. dataExchanger: that._dataExchanger,
  97015. notifyDirty: notifyDirty,
  97016. notifyReady: notifyReady
  97017. })
  97018. },
  97019. _initMarkersManager: function(dataKey, notifyDirty, notifyReady) {
  97020. var that = this;
  97021. that._markersManager = that._factory.createMarkersManager({
  97022. container: that._root,
  97023. renderer: that._renderer,
  97024. projection: that._projection,
  97025. themeManager: that._themeManager,
  97026. tracker: that._tracker,
  97027. eventTrigger: that._eventTrigger,
  97028. dataExchanger: that._dataExchanger,
  97029. dataKey: dataKey,
  97030. notifyDirty: notifyDirty,
  97031. notifyReady: notifyReady
  97032. })
  97033. },
  97034. _initLegendsControl: function() {
  97035. var that = this;
  97036. that._legendsControl = that._factory.createLegendsControl({
  97037. container: that._root,
  97038. renderer: that._renderer,
  97039. layoutControl: that._layoutControl,
  97040. dataExchanger: that._dataExchanger
  97041. })
  97042. },
  97043. _initControlBar: function(dataKey) {
  97044. var that = this;
  97045. that._controlBar = that._factory.createControlBar({
  97046. container: that._root,
  97047. renderer: that._renderer,
  97048. layoutControl: that._layoutControl,
  97049. projection: that._projection,
  97050. dataKey: dataKey
  97051. })
  97052. },
  97053. _initElements: function() {
  97054. var that = this,
  97055. dataKey = generateDataKey(),
  97056. notifyCounter = 0;
  97057. that._dataExchanger = new DataExchanger;
  97058. that._initCenterHandler();
  97059. that._projection = that._factory.createProjection();
  97060. that._tracker = that._factory.createTracker({
  97061. root: that._root,
  97062. projection: that._projection,
  97063. dataKey: dataKey
  97064. });
  97065. that._layoutControl = that._factory.createLayoutControl();
  97066. that._initBackground(dataKey);
  97067. that._initAreasManager(dataKey, notifyDirty, notifyReady);
  97068. that._initMarkersManager(dataKey, notifyDirty, notifyReady);
  97069. that._initLegendsControl();
  97070. that._initControlBar(dataKey);
  97071. function notifyDirty() {
  97072. that._resetIsReady();
  97073. ++notifyCounter
  97074. }
  97075. function notifyReady() {
  97076. if (--notifyCounter === 0) {
  97077. that._drawn();
  97078. that.hideLoadingIndicator()
  97079. }
  97080. }
  97081. },
  97082. _initCore: function() {
  97083. var that = this;
  97084. that._root = that._renderer.root;
  97085. that._root.attr({
  97086. align: 'center',
  97087. cursor: 'default'
  97088. });
  97089. that._initElements();
  97090. that._projection.setBounds(that.option("bounds")).setMaxZoom(that.option("maxZoomFactor")).setZoom(that.option("zoomFactor"), true).setCenter(that.option("center"), true);
  97091. that._setTrackerCallbacks();
  97092. that._setControlBarCallbacks();
  97093. that._setProjectionCallbacks()
  97094. },
  97095. _init: function() {
  97096. var that = this;
  97097. that.callBase.apply(that, arguments);
  97098. that._areasManager.setData(that.option("mapData"));
  97099. that._markersManager.setData(that.option("markers"))
  97100. },
  97101. _disposeCore: function() {
  97102. var that = this;
  97103. that._resetProjectionCallbacks();
  97104. that._resetTrackerCallbacks();
  97105. that._resetControlBarCallbacks();
  97106. that._tracker.dispose();
  97107. that._legendsControl.dispose();
  97108. that._areasManager.dispose();
  97109. that._markersManager.dispose();
  97110. that._controlBar.dispose();
  97111. that._layoutControl.dispose();
  97112. that._disposeCenterHandler();
  97113. that._dataExchanger.dispose();
  97114. that._projection.dispose();
  97115. that._dataExchanger = that._projection = that._tracker = that._layoutControl = that._root = that._background = that._areasManager = that._markersManager = that._controlBar = that._legendsControl = null
  97116. },
  97117. _initCenterHandler: function() {
  97118. var that = this,
  97119. xdrag,
  97120. ydrag,
  97121. isCursorChanged = false;
  97122. that._centerHandler = {
  97123. processStart: function(arg) {
  97124. if (that._centeringEnabled) {
  97125. xdrag = arg.x;
  97126. ydrag = arg.y;
  97127. that._noCenterChanged = true
  97128. }
  97129. },
  97130. processMove: function(arg) {
  97131. if (that._centeringEnabled) {
  97132. if (!isCursorChanged) {
  97133. that._root.attr({cursor: "move"});
  97134. isCursorChanged = true
  97135. }
  97136. that._projection.moveCenter(xdrag - arg.x, ydrag - arg.y);
  97137. xdrag = arg.x;
  97138. ydrag = arg.y
  97139. }
  97140. },
  97141. processEnd: function() {
  97142. if (that._centeringEnabled) {
  97143. that._root.attr({cursor: "default"});
  97144. that._noCenterChanged = null;
  97145. isCursorChanged && that._raiseCenterChanged();
  97146. isCursorChanged = false
  97147. }
  97148. }
  97149. }
  97150. },
  97151. _disposeCenterHandler: function() {
  97152. this._centerHandler = null
  97153. },
  97154. _setProjectionCallbacks: function() {
  97155. var that = this;
  97156. that._projection.on({
  97157. center: function() {
  97158. that._raiseCenterChanged()
  97159. },
  97160. zoom: function() {
  97161. that._raiseZoomFactorChanged()
  97162. }
  97163. });
  97164. that._resetProjectionCallbacks = function() {
  97165. that._resetProjectionCallbacks = that = null
  97166. }
  97167. },
  97168. _setTrackerCallbacks: function() {
  97169. var that = this,
  97170. centerHandler = that._centerHandler,
  97171. renderer = that._renderer,
  97172. managers = {
  97173. area: that._areasManager,
  97174. marker: that._markersManager
  97175. },
  97176. controlBar = that._controlBar,
  97177. tooltip = that._tooltip,
  97178. isControlDrag = false;
  97179. that._tracker.setCallbacks({
  97180. click: function(arg) {
  97181. var offset = renderer.getRootOffset(),
  97182. manager;
  97183. arg.$event.x = arg.x - offset.left;
  97184. arg.$event.y = arg.y - offset.top;
  97185. manager = managers[arg.data.type];
  97186. if (manager)
  97187. manager.raiseClick(arg.data.index, arg.$event);
  97188. if (manager || arg.data.type === "background")
  97189. that._eventTrigger("click", {jQueryEvent: arg.$event})
  97190. },
  97191. start: function(arg) {
  97192. isControlDrag = arg.data.type === "control-bar";
  97193. if (isControlDrag) {
  97194. arg.data = arg.data.index;
  97195. controlBar.processStart(arg)
  97196. }
  97197. else
  97198. centerHandler.processStart(arg)
  97199. },
  97200. move: function(arg) {
  97201. if (isControlDrag) {
  97202. arg.data = arg.data.index;
  97203. controlBar.processMove(arg)
  97204. }
  97205. else
  97206. centerHandler.processMove(arg)
  97207. },
  97208. end: function(arg) {
  97209. if (isControlDrag) {
  97210. arg.data = arg.data.index;
  97211. controlBar.processEnd(arg);
  97212. isControlDrag = false
  97213. }
  97214. else
  97215. centerHandler.processEnd()
  97216. },
  97217. zoom: function(arg) {
  97218. controlBar.processZoom(arg)
  97219. },
  97220. "hover-on": function(arg) {
  97221. var manager = managers[arg.data.type];
  97222. if (manager)
  97223. manager.hoverItem(arg.data.index, true)
  97224. },
  97225. "hover-off": function(arg) {
  97226. var manager = managers[arg.data.type];
  97227. if (manager)
  97228. manager.hoverItem(arg.data.index, false)
  97229. },
  97230. "focus-on": function(arg, done) {
  97231. var result = false,
  97232. proxy;
  97233. if (tooltip.isEnabled()) {
  97234. proxy = managers[arg.data.type] ? managers[arg.data.type].getProxyItem(arg.data.index) : null;
  97235. if (proxy && tooltip.show(proxy, {
  97236. x: 0,
  97237. y: 0,
  97238. offset: 0
  97239. }, {target: proxy})) {
  97240. tooltip.move(arg.x, arg.y, TOOLTIP_OFFSET);
  97241. result = true
  97242. }
  97243. }
  97244. done(result)
  97245. },
  97246. "focus-move": function(arg) {
  97247. tooltip.move(arg.x, arg.y, TOOLTIP_OFFSET)
  97248. },
  97249. "focus-off": function() {
  97250. tooltip.hide()
  97251. }
  97252. });
  97253. that._resetTrackerCallbacks = function() {
  97254. that._resetTrackerCallbacks = that = centerHandler = renderer = managers = controlBar = tooltip = null
  97255. }
  97256. },
  97257. _setControlBarCallbacks: function() {
  97258. var that = this,
  97259. projection = that._projection,
  97260. isZoomChanged;
  97261. that._projection.on({zoom: function() {
  97262. isZoomChanged = true
  97263. }});
  97264. that._controlBar.setCallbacks({
  97265. reset: function(isCenter, isZoom) {
  97266. if (isCenter)
  97267. projection.setCenter(null);
  97268. if (isZoom)
  97269. projection.setZoom(null)
  97270. },
  97271. beginMove: function() {
  97272. that._noCenterChanged = true
  97273. },
  97274. endMove: function() {
  97275. that._noCenterChanged = null;
  97276. that._raiseCenterChanged()
  97277. },
  97278. move: function(dx, dy) {
  97279. projection.moveCenter(dx, dy)
  97280. },
  97281. zoom: function(zoom, center) {
  97282. var coords,
  97283. screenPosition;
  97284. if (center) {
  97285. screenPosition = that._renderer.getRootOffset();
  97286. screenPosition = [center[0] - screenPosition.left, center[1] - screenPosition.top];
  97287. coords = projection.fromScreenPoint(screenPosition[0], screenPosition[1])
  97288. }
  97289. isZoomChanged = false;
  97290. projection.setScaledZoom(zoom);
  97291. if (isZoomChanged && center)
  97292. projection.setCenterByPoint(coords, screenPosition)
  97293. }
  97294. });
  97295. that._resetControlBarCallbacks = function() {
  97296. that._resetControlBarCallbacks = that = projection = null
  97297. }
  97298. },
  97299. _setupInteraction: function() {
  97300. var that = this;
  97301. that._centerHandler.processEnd();
  97302. that._centeringEnabled = !!_parseScalar(this._getOption("panningEnabled", true), true);
  97303. that._zoomingEnabled = !!_parseScalar(this._getOption("zoomingEnabled", true), true);
  97304. that._controlBar.setInteraction({
  97305. centeringEnabled: that._centeringEnabled,
  97306. zoomingEnabled: that._zoomingEnabled
  97307. })
  97308. },
  97309. _getDefaultSize: function() {
  97310. return {
  97311. width: DEFAULT_WIDTH,
  97312. height: DEFAULT_HEIGHT
  97313. }
  97314. },
  97315. _applySize: function() {
  97316. var that = this,
  97317. width = that._canvas.width,
  97318. height = that._canvas.height;
  97319. that._projection.setSize(width, height);
  97320. that._layoutControl.setSize(width, height);
  97321. that._background.attr({
  97322. x: 0,
  97323. y: 0,
  97324. width: width,
  97325. height: height
  97326. })
  97327. },
  97328. _resize: $.noop,
  97329. _clean: function() {
  97330. var that = this;
  97331. that._tracker.reset();
  97332. that._layoutControl.stop();
  97333. that._background.remove();
  97334. that._areasManager.clean();
  97335. that._markersManager.clean();
  97336. that._controlBar.clean();
  97337. that._legendsControl.clean()
  97338. },
  97339. _render: function() {
  97340. var that = this;
  97341. that._background.append(that._root);
  97342. that._areasManager.render();
  97343. that._markersManager.render();
  97344. that._controlBar.render();
  97345. that._legendsControl.render();
  97346. that._layoutControl.start()
  97347. },
  97348. _optionChanged: function(args) {
  97349. var that = this,
  97350. value = args.value;
  97351. switch (args.name) {
  97352. case"mapData":
  97353. that._areasManager.setData(value);
  97354. break;
  97355. case"markers":
  97356. that._markersManager.setData(value);
  97357. break;
  97358. case"bounds":
  97359. that._projection.setBounds(value);
  97360. break;
  97361. case"maxZoomFactor":
  97362. that._projection.setMaxZoom(value);
  97363. break;
  97364. case"zoomFactor":
  97365. that._projection.setZoom(value);
  97366. break;
  97367. case"center":
  97368. that._projection.setCenter(value);
  97369. break;
  97370. case"background":
  97371. that._setBackgroundOptions();
  97372. break;
  97373. case"areaSettings":
  97374. that._setAreasManagerOptions();
  97375. break;
  97376. case"markerSettings":
  97377. that._setMarkersManagerOptions();
  97378. break;
  97379. case"controlBar":
  97380. that._setControlBarOptions();
  97381. break;
  97382. case"legends":
  97383. that._setLegendsOptions();
  97384. break;
  97385. case"touchEnabled":
  97386. case"wheelEnabled":
  97387. that._setTrackerOptions();
  97388. break;
  97389. case"panningEnabled":
  97390. case"zoomingEnabled":
  97391. that._setupInteraction();
  97392. break;
  97393. default:
  97394. that.callBase.apply(that, arguments);
  97395. break
  97396. }
  97397. },
  97398. _handleThemeOptionsCore: function() {
  97399. var that = this;
  97400. that._setBackgroundOptions();
  97401. that._setAreasManagerOptions();
  97402. that._setMarkersManagerOptions();
  97403. that._setControlBarOptions();
  97404. that._setLegendsOptions();
  97405. that._setTrackerOptions();
  97406. that._setupInteraction()
  97407. },
  97408. _setBackgroundOptions: function() {
  97409. var settings = this._getOption("background");
  97410. this._background.attr({
  97411. "stroke-width": settings.borderWidth,
  97412. stroke: settings.borderColor,
  97413. fill: settings.color
  97414. })
  97415. },
  97416. _setAreasManagerOptions: function() {
  97417. this._areasManager.setOptions(this.option("areaSettings"));
  97418. this._eventTrigger.update("onAreaClick");
  97419. this._eventTrigger.update("onAreaSelectionChanged")
  97420. },
  97421. _setMarkersManagerOptions: function() {
  97422. this._markersManager.setOptions(this.option("markerSettings"));
  97423. this._eventTrigger.update("onMarkerClick");
  97424. this._eventTrigger.update("onMarkerSelectionChanged")
  97425. },
  97426. _setControlBarOptions: function() {
  97427. this._controlBar.setOptions(this._getOption("controlBar"))
  97428. },
  97429. _setLegendsOptions: function() {
  97430. this._legendsControl.setOptions(this.option("legends"), this._themeManager.theme("legend"))
  97431. },
  97432. _setTrackerOptions: function() {
  97433. this._tracker.setOptions({
  97434. touchEnabled: this._getOption("touchEnabled", true),
  97435. wheelEnabled: this._getOption("wheelEnabled", true)
  97436. })
  97437. },
  97438. _raiseCenterChanged: function() {
  97439. !this._noCenterChanged && this._eventTrigger("centerChanged", {center: this._projection.getCenter()})
  97440. },
  97441. _raiseZoomFactorChanged: function() {
  97442. !this._noZoomFactorChanged && this._eventTrigger("zoomFactorChanged", {zoomFactor: this._projection.getZoom()})
  97443. },
  97444. _refresh: function() {
  97445. var that = this,
  97446. callBase = that.callBase;
  97447. that._endLoading(function() {
  97448. callBase.call(that)
  97449. })
  97450. },
  97451. getAreas: function() {
  97452. return this._areasManager.getProxyItems()
  97453. },
  97454. getMarkers: function() {
  97455. return this._markersManager.getProxyItems()
  97456. },
  97457. clearAreaSelection: function(_noEvent) {
  97458. this._areasManager.clearSelection(_noEvent);
  97459. return this
  97460. },
  97461. clearMarkerSelection: function(_noEvent) {
  97462. this._markersManager.clearSelection(_noEvent);
  97463. return this
  97464. },
  97465. clearSelection: function(_noEvent) {
  97466. return this.clearAreaSelection(_noEvent).clearMarkerSelection(_noEvent)
  97467. },
  97468. center: function(value, _noEvent) {
  97469. var that = this;
  97470. if (value === undefined)
  97471. return that._projection.getCenter();
  97472. else {
  97473. that._noCenterChanged = _noEvent;
  97474. that._projection.setCenter(value);
  97475. that._noCenterChanged = null;
  97476. return that
  97477. }
  97478. },
  97479. zoomFactor: function(value, _noEvent) {
  97480. var that = this;
  97481. if (value === undefined)
  97482. return that._projection.getZoom();
  97483. else {
  97484. that._noZoomFactorChanged = _noEvent;
  97485. that._projection.setZoom(value);
  97486. that._noZoomFactorChanged = null;
  97487. return that
  97488. }
  97489. },
  97490. viewport: function(value, _noEvent) {
  97491. var that = this;
  97492. if (value === undefined)
  97493. return that._projection.getViewport();
  97494. else {
  97495. that._noCenterChanged = that._noZoomFactorChanged = _noEvent;
  97496. that._projection.setViewport(value);
  97497. that._noCenterChanged = that._noZoomFactorChanged = null;
  97498. return that
  97499. }
  97500. },
  97501. convertCoordinates: function(x, y) {
  97502. return this._projection.fromScreenPoint(x, y)
  97503. },
  97504. _factory: {}
  97505. });
  97506. var DataExchanger = function() {
  97507. this._store = {}
  97508. };
  97509. DataExchanger.prototype = {
  97510. constructor: DataExchanger,
  97511. dispose: function() {
  97512. this._store = null;
  97513. return this
  97514. },
  97515. _get: function(category, name) {
  97516. var store = this._store[category] || (this._store[category] = {});
  97517. return store[name] || (store[name] = {})
  97518. },
  97519. set: function(category, name, data) {
  97520. var item = this._get(category, name);
  97521. item.data = data;
  97522. item.callback && item.callback(data);
  97523. return this
  97524. },
  97525. bind: function(category, name, callback) {
  97526. var item = this._get(category, name);
  97527. item.callback = callback;
  97528. item.data && callback(item.data);
  97529. return this
  97530. },
  97531. unbind: function(category, name) {
  97532. var item = this._get(category, name);
  97533. item.data = item.callback = null;
  97534. return this
  97535. }
  97536. };
  97537. DX.registerComponent("dxVectorMap", DX.viz.map, Map);
  97538. DX.viz.map._internal = {};
  97539. DX.viz.map.sources = {};
  97540. DX.viz.map._tests = {};
  97541. DX.viz.map._tests.DataExchanger = DataExchanger;
  97542. DX.viz.map._tests.stubDataExchanger = function(stub) {
  97543. DataExchanger = stub
  97544. }
  97545. })(DevExpress, jQuery);
  97546. /*! Module viz-vectormap, file projection.js */
  97547. (function(DX, $, undefined) {
  97548. var _Number = Number,
  97549. _isArray = DX.utils.isArray,
  97550. _math = Math,
  97551. _min = _math.min,
  97552. _max = _math.max,
  97553. _abs = _math.abs,
  97554. _tan = _math.tan,
  97555. _atan = _math.atan,
  97556. _exp = _math.exp,
  97557. _round = _math.round,
  97558. _ln = _math.log,
  97559. _pow = _math.pow,
  97560. PI = _math.PI,
  97561. QUARTER_PI = PI / 4,
  97562. PI_TO_360 = PI / 360,
  97563. TWO_TO_LN2 = 2 / _math.LN2,
  97564. MIN_BOUNDS_RANGE = 1 / 3600 / 180 / 10,
  97565. DEFAULT_MIN_ZOOM = 1,
  97566. DEFAULT_MAX_ZOOM = 1 << 8,
  97567. MERCATOR_MIN_LON = -180,
  97568. MERCATOR_MAX_LON = 180,
  97569. MERCATOR_MIN_LAT = -85.0511,
  97570. MERCATOR_MAX_LAT = 85.0511;
  97571. var mercator = {
  97572. aspectRatio: 1,
  97573. project: function(coordinates) {
  97574. var lon = coordinates[0],
  97575. lat = coordinates[1];
  97576. return [lon <= MERCATOR_MIN_LON ? -1 : lon >= MERCATOR_MAX_LON ? +1 : lon / 180, lat <= MERCATOR_MIN_LAT ? +1 : lat >= MERCATOR_MAX_LAT ? -1 : -_ln(_tan(QUARTER_PI + lat * PI_TO_360)) / PI]
  97577. },
  97578. unproject: function(coordinates) {
  97579. var x = coordinates[0],
  97580. y = coordinates[1];
  97581. return [x <= -1 ? MERCATOR_MIN_LON : x >= +1 ? MERCATOR_MAX_LON : 180 * x, y <= -1 ? MERCATOR_MAX_LAT : y >= +1 ? MERCATOR_MIN_LAT : (_atan(_exp(-PI * coordinates[1])) - QUARTER_PI) / PI_TO_360]
  97582. }
  97583. };
  97584. function createProjectUnprojectMethods(p1, p2, delta) {
  97585. var x0 = (p1[0] + p2[0]) / 2 - delta / 2,
  97586. y0 = (p1[1] + p2[1]) / 2 - delta / 2,
  97587. k = 2 / delta;
  97588. return {
  97589. project: function(coordinates) {
  97590. var p = mercator.project(coordinates);
  97591. return [-1 + (p[0] - x0) * k, -1 + (p[1] - y0) * k]
  97592. },
  97593. unproject: function(coordinates) {
  97594. var p = [x0 + (coordinates[0] + 1) / k, y0 + (coordinates[1] + 1) / k];
  97595. return mercator.unproject(p)
  97596. }
  97597. }
  97598. }
  97599. function floatsEqual(f1, f2) {
  97600. return _abs(f1 - f2) < 1E-8
  97601. }
  97602. function truncate(value, min, max, fallback) {
  97603. var _value = _Number(value);
  97604. if (_value < min)
  97605. _value = min;
  97606. else if (_value > max)
  97607. _value = max;
  97608. else if (!(min <= _value && _value <= max))
  97609. _value = fallback;
  97610. return _value
  97611. }
  97612. function truncateQuad(quad, min, max) {
  97613. return {
  97614. lt: [truncate(quad[0], min[0], max[0], min[0]), truncate(quad[1], min[1], max[1], min[1])],
  97615. rb: [truncate(quad[2], min[0], max[0], max[0]), truncate(quad[3], min[1], max[1], max[1])]
  97616. }
  97617. }
  97618. function parseBounds(bounds) {
  97619. var p1 = mercator.unproject([-1, -1]),
  97620. p2 = mercator.unproject([+1, +1]),
  97621. min = [_min(p1[0], p2[0]), _min(p1[1], p2[1])],
  97622. max = [_max(p1[0], p2[0]), _max(p1[1], p2[1])],
  97623. quad = bounds;
  97624. if (quad)
  97625. quad = truncateQuad(quad, min, max);
  97626. return {
  97627. min: quad ? [_min(quad.lt[0], quad.rb[0]), _min(quad.lt[1], quad.rb[1])] : min,
  97628. max: quad ? [_max(quad.lt[0], quad.rb[0]), _max(quad.lt[1], quad.rb[1])] : max
  97629. }
  97630. }
  97631. function selectCenterValue(value1, value2, center1, center2) {
  97632. var result;
  97633. if (value1 > -1 && value2 >= +1)
  97634. result = center1;
  97635. else if (value1 <= -1 && value2 < +1)
  97636. result = center2;
  97637. else
  97638. result = (center1 + center2) / 2;
  97639. return result
  97640. }
  97641. function Projection() {
  97642. this._events = {
  97643. project: $.Callbacks(),
  97644. transform: $.Callbacks(),
  97645. center: $.Callbacks(),
  97646. zoom: $.Callbacks(),
  97647. "max-zoom": $.Callbacks()
  97648. };
  97649. this.setBounds(null)
  97650. }
  97651. Projection.prototype = {
  97652. constructor: Projection,
  97653. _minZoom: DEFAULT_MIN_ZOOM,
  97654. _maxZoom: DEFAULT_MAX_ZOOM,
  97655. _zoom: DEFAULT_MIN_ZOOM,
  97656. _center: [NaN, NaN],
  97657. dispose: function() {
  97658. this._events = null;
  97659. return this
  97660. },
  97661. setSize: function(width, height) {
  97662. var that = this;
  97663. that._x0 = width / 2;
  97664. that._y0 = height / 2;
  97665. if (width / height <= mercator.aspectRatio) {
  97666. that._xradius = width / 2;
  97667. that._yradius = width / 2 / mercator.aspectRatio
  97668. }
  97669. else {
  97670. that._xradius = height / 2 * mercator.aspectRatio;
  97671. that._yradius = height / 2
  97672. }
  97673. that._events["transform"].fire(that.getTransform());
  97674. return that
  97675. },
  97676. setBounds: function(bounds) {
  97677. var that = this,
  97678. _bounds = parseBounds(bounds),
  97679. p1,
  97680. p2,
  97681. delta,
  97682. methods;
  97683. that._minBound = _bounds.min;
  97684. that._maxBound = _bounds.max;
  97685. p1 = mercator.project(_bounds.min);
  97686. p2 = mercator.project(_bounds.max);
  97687. delta = [_abs(p2[0] - p1[0]), _abs(p2[1] - p1[1])];
  97688. delta = _min(delta[0] > MIN_BOUNDS_RANGE ? delta[0] : 2, delta[1] > MIN_BOUNDS_RANGE ? delta[1] : 2);
  97689. methods = delta < 2 ? createProjectUnprojectMethods(p1, p2, delta) : mercator;
  97690. that._project = methods.project;
  97691. that._unproject = methods.unproject;
  97692. that._defaultCenter = that._unproject([0, 0]);
  97693. that.setCenter(that._defaultCenter);
  97694. that._events.project.fire();
  97695. return that
  97696. },
  97697. _toScreen: function(coordinates) {
  97698. return [this._x0 + this._xradius * coordinates[0], this._y0 + this._yradius * coordinates[1]]
  97699. },
  97700. _fromScreen: function(coordinates) {
  97701. return [(coordinates[0] - this._x0) / this._xradius, (coordinates[1] - this._y0) / this._yradius]
  97702. },
  97703. _toTransformed: function(coordinates) {
  97704. return [coordinates[0] * this._zoom + this._dxcenter, coordinates[1] * this._zoom + this._dycenter]
  97705. },
  97706. _toTransformedFast: function(coordinates) {
  97707. return [coordinates[0] * this._zoom, coordinates[1] * this._zoom]
  97708. },
  97709. _fromTransformed: function(coordinates) {
  97710. return [(coordinates[0] - this._dxcenter) / this._zoom, (coordinates[1] - this._dycenter) / this._zoom]
  97711. },
  97712. _adjustCenter: function() {
  97713. var that = this,
  97714. center = that._project(that._center);
  97715. that._dxcenter = -center[0] * that._zoom;
  97716. that._dycenter = -center[1] * that._zoom
  97717. },
  97718. projectArea: function(coordinates) {
  97719. var i = 0,
  97720. ii = _isArray(coordinates) ? coordinates.length : 0,
  97721. subcoords,
  97722. j,
  97723. jj,
  97724. subresult,
  97725. result = [];
  97726. for (; i < ii; ++i) {
  97727. subcoords = coordinates[i];
  97728. subresult = [];
  97729. for (j = 0, jj = _isArray(subcoords) ? subcoords.length : 0; j < jj; ++j)
  97730. subresult.push(this._project(subcoords[j]));
  97731. result.push(subresult)
  97732. }
  97733. return result
  97734. },
  97735. projectPoint: function(coordinates) {
  97736. return coordinates ? this._project(coordinates) : []
  97737. },
  97738. getAreaCoordinates: function(data) {
  97739. var k = 0,
  97740. kk = data.length,
  97741. partialData,
  97742. i,
  97743. ii,
  97744. list = [],
  97745. partialPath,
  97746. point;
  97747. for (; k < kk; ++k) {
  97748. partialData = data[k];
  97749. partialPath = [];
  97750. for (i = 0, ii = partialData.length; i < ii; ++i) {
  97751. point = this._toScreen(this._toTransformedFast(partialData[i]));
  97752. partialPath.push(point[0], point[1])
  97753. }
  97754. list.push(partialPath)
  97755. }
  97756. return list
  97757. },
  97758. getPointCoordinates: function(data) {
  97759. var point = this._toScreen(this._toTransformedFast(data));
  97760. return {
  97761. x: _round(point[0]),
  97762. y: _round(point[1])
  97763. }
  97764. },
  97765. getSquareSize: function(size) {
  97766. return [size[0] * this._zoom * this._xradius, size[1] * this._zoom * this._yradius]
  97767. },
  97768. getZoom: function() {
  97769. return this._zoom
  97770. },
  97771. setZoom: function(zoom, _forceEvent) {
  97772. var that = this,
  97773. zoom__ = that._zoom;
  97774. that._zoom = truncate(zoom, that._minZoom, that._maxZoom, that._minZoom);
  97775. that._adjustCenter();
  97776. if (!floatsEqual(zoom__, that._zoom) || _forceEvent)
  97777. that._events.zoom.fire(that.getZoom(), that.getTransform());
  97778. return that
  97779. },
  97780. getScaledZoom: function() {
  97781. return _round((this._scale.length - 1) * _ln(this._zoom) / _ln(this._maxZoom))
  97782. },
  97783. setScaledZoom: function(scaledZoom) {
  97784. return this.setZoom(this._scale[_round(scaledZoom)])
  97785. },
  97786. getZoomScalePartition: function() {
  97787. return this._scale.length - 1
  97788. },
  97789. _setupScaling: function() {
  97790. var that = this,
  97791. k = _round(TWO_TO_LN2 * _ln(that._maxZoom)),
  97792. step,
  97793. zoom,
  97794. i = 1;
  97795. k = k > 4 ? k : 4;
  97796. step = _pow(that._maxZoom, 1 / k);
  97797. zoom = that._minZoom;
  97798. that._scale = [zoom];
  97799. for (; i <= k; ++i)
  97800. that._scale.push(zoom *= step)
  97801. },
  97802. setMaxZoom: function(maxZoom) {
  97803. var that = this;
  97804. that._minZoom = DEFAULT_MIN_ZOOM;
  97805. that._maxZoom = truncate(maxZoom, that._minZoom, _Number.MAX_VALUE, DEFAULT_MAX_ZOOM);
  97806. that._setupScaling();
  97807. if (that._zoom > that._maxZoom)
  97808. that.setZoom(that._maxZoom);
  97809. that._events["max-zoom"].fire(that._maxZoom);
  97810. return that
  97811. },
  97812. getMinZoom: function() {
  97813. return this._minZoom
  97814. },
  97815. getMaxZoom: function() {
  97816. return this._maxZoom
  97817. },
  97818. getCenter: function() {
  97819. return [this._center[0], this._center[1]]
  97820. },
  97821. setCenter: function(center, _forceEvent) {
  97822. var that = this,
  97823. _center = _isArray(center) ? center : [],
  97824. center__ = that._center;
  97825. that._center = [truncate(_center[0], that._minBound[0], that._maxBound[0], that._defaultCenter[0]), truncate(_center[1], that._minBound[1], that._maxBound[1], that._defaultCenter[1])];
  97826. that._adjustCenter();
  97827. if (!floatsEqual(center__[0], that._center[0]) || !floatsEqual(center__[1], that._center[1]) || _forceEvent)
  97828. that._events.center.fire(that.getCenter(), that.getTransform());
  97829. return that
  97830. },
  97831. setCenterByPoint: function(coordinates, screenPosition) {
  97832. var that = this,
  97833. p = that._project(coordinates),
  97834. q = that._fromScreen(screenPosition);
  97835. return that.setCenter(that._unproject([-q[0] / that._zoom + p[0], -q[1] / that._zoom + p[1]]))
  97836. },
  97837. moveCenter: function(screenDx, screenDy) {
  97838. var that = this,
  97839. current = that._toScreen(that._toTransformed(that._project(that._center))),
  97840. center = that._unproject(that._fromTransformed(that._fromScreen([current[0] + screenDx, current[1] + screenDy])));
  97841. return that.setCenter(center)
  97842. },
  97843. getViewport: function() {
  97844. var p1 = this._unproject(this._fromTransformed([-1, -1])),
  97845. p2 = this._unproject(this._fromTransformed([+1, +1]));
  97846. return [p1[0], p1[1], p2[0], p2[1]]
  97847. },
  97848. setViewport: function(viewport) {
  97849. var that = this;
  97850. if (!_isArray(viewport))
  97851. return that.setZoom(that._minZoom).setCenter(that._defaultCenter);
  97852. var _viewport = truncateQuad(viewport, that._minBound, that._maxBound),
  97853. lt = that._project(_viewport.lt),
  97854. rb = that._project(_viewport.rb),
  97855. l = _min(lt[0], rb[0]),
  97856. t = _min(lt[1], rb[1]),
  97857. r = _max(lt[0], rb[0]),
  97858. b = _max(lt[1], rb[1]),
  97859. zoom = 2 / _max(r - l, b - t),
  97860. xc = selectCenterValue(l, r, -1 - zoom * l, +1 - zoom * r),
  97861. yc = selectCenterValue(t, b, -1 - zoom * t, +1 - zoom * b);
  97862. return that.setZoom(zoom).setCenter(that._unproject([-xc / zoom, -yc / zoom]))
  97863. },
  97864. getTransform: function() {
  97865. return {
  97866. translateX: this._dxcenter * this._xradius,
  97867. translateY: this._dycenter * this._yradius
  97868. }
  97869. },
  97870. fromScreenPoint: function(x, y) {
  97871. return this._unproject(this._fromTransformed(this._fromScreen([x, y])))
  97872. },
  97873. on: function(obj) {
  97874. $.each(this._events, function(name, list) {
  97875. obj[name] && list.add(obj[name])
  97876. });
  97877. return this
  97878. }
  97879. };
  97880. DX.viz.map._tests.Projection = Projection;
  97881. DX.viz.map._tests.mercator = mercator;
  97882. DX.viz.map._tests._DEBUG_stubMercator = function(stub) {
  97883. mercator = stub
  97884. };
  97885. DX.viz.map._tests._DEBUG_restoreMercator = function() {
  97886. mercator = DX.viz.map._tests.mercator
  97887. };
  97888. DX.viz.map.dxVectorMap.prototype._factory.createProjection = function() {
  97889. return new Projection
  97890. }
  97891. })(DevExpress, jQuery);
  97892. /*! Module viz-vectormap, file controlBar.js */
  97893. (function(DX, undefined) {
  97894. var _Number = Number,
  97895. _math = Math,
  97896. _round = _math.round,
  97897. _floor = _math.floor,
  97898. _pow = _math.pow,
  97899. _ln = _math.log,
  97900. _LN2 = _math.LN2,
  97901. utils = DX.viz.core.utils,
  97902. _parseScalar = utils.parseScalar,
  97903. parseHorizontalAlignment = utils.enumParser(["left", "center", "right"]),
  97904. parseVerticalAlignment = utils.enumParser(["top", "bottom"]),
  97905. COMMAND_RESET = "command-reset",
  97906. COMMAND_MOVE_UP = "command-move-up",
  97907. COMMAND_MOVE_RIGHT = "command-move-right",
  97908. COMMAND_MOVE_DOWN = "command-move-down",
  97909. COMMAND_MOVE_LEFT = "command-move-left",
  97910. COMMAND_ZOOM_IN = "command-zoom-in",
  97911. COMMAND_ZOOM_OUT = "command-zoom-out",
  97912. COMMAND_ZOOM_DRAG_LINE = "command-zoom-drag-line",
  97913. COMMAND_ZOOM_DRAG = "command-zoom-drag",
  97914. EVENT_TARGET_TYPE = "control-bar",
  97915. FLAG_CENTERING = 1,
  97916. FLAG_ZOOMING = 2,
  97917. SIZE_OPTIONS = {
  97918. bigCircleSize: 58,
  97919. smallCircleSize: 28,
  97920. buttonSize: 10,
  97921. arrowButtonOffset: 20,
  97922. incdecButtonSize: 11,
  97923. incButtonOffset: 66,
  97924. decButtonOffset: 227,
  97925. sliderLineStartOffset: 88.5,
  97926. sliderLineEndOffset: 205.5,
  97927. sliderLength: 20,
  97928. sliderWidth: 8,
  97929. trackerGap: 4
  97930. },
  97931. OFFSET_X = 30.5,
  97932. OFFSET_Y = 30.5,
  97933. TOTAL_WIDTH = 61,
  97934. TOTAL_HEIGHT = 274,
  97935. COMMAND_TO_TYPE_MAP = {};
  97936. COMMAND_TO_TYPE_MAP[COMMAND_RESET] = ResetCommand;
  97937. COMMAND_TO_TYPE_MAP[COMMAND_MOVE_UP] = COMMAND_TO_TYPE_MAP[COMMAND_MOVE_RIGHT] = COMMAND_TO_TYPE_MAP[COMMAND_MOVE_DOWN] = COMMAND_TO_TYPE_MAP[COMMAND_MOVE_LEFT] = MoveCommand;
  97938. COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_IN] = COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_OUT] = ZoomCommand;
  97939. COMMAND_TO_TYPE_MAP[COMMAND_ZOOM_DRAG] = ZoomDragCommand;
  97940. var ControlBar = DX.Class.inherit({
  97941. _flags: 0,
  97942. ctor: function(parameters) {
  97943. var that = this;
  97944. that._params = parameters;
  97945. that._createElements(parameters.renderer, parameters.dataKey);
  97946. parameters.layoutControl.addItem(that);
  97947. that._subscribeToProjection(parameters.projection);
  97948. that._setVisibility(false)
  97949. },
  97950. setCallbacks: function(callbacks) {
  97951. this._callbacks = callbacks;
  97952. return this
  97953. },
  97954. _createElements: function(renderer, dataKey) {
  97955. var that = this,
  97956. buttonsGroups,
  97957. trackersGroup;
  97958. that._root = renderer.g().attr({"class": "dxm-control-bar"});
  97959. buttonsGroups = that._buttonsGroup = renderer.g().attr({"class": "dxm-control-buttons"}).append(that._root);
  97960. trackersGroup = renderer.g().attr({
  97961. stroke: "none",
  97962. "stroke-width": 0,
  97963. fill: "#000000",
  97964. opacity: 0.0001
  97965. }).css({cursor: "pointer"}).append(that._root);
  97966. that._createButtons(renderer, dataKey, buttonsGroups);
  97967. that._createTrackers(renderer, dataKey, trackersGroup)
  97968. },
  97969. _createButtons: function(renderer, dataKey, group) {
  97970. var that = this,
  97971. options = SIZE_OPTIONS,
  97972. size = options.buttonSize / 2,
  97973. offset1 = options.arrowButtonOffset - size,
  97974. offset2 = options.arrowButtonOffset,
  97975. incdecButtonSize = options.incdecButtonSize / 2,
  97976. directionOptions = {
  97977. "stroke-linecap": "square",
  97978. fill: "none"
  97979. },
  97980. line = "line";
  97981. renderer.circle(0, 0, options.bigCircleSize / 2).append(group);
  97982. renderer.circle(0, 0, size).attr({fill: "none"}).append(group);
  97983. renderer.path([-size, -offset1, 0, -offset2, size, -offset1], line).attr(directionOptions).append(group);
  97984. renderer.path([offset1, -size, offset2, 0, offset1, size], line).attr(directionOptions).append(group);
  97985. renderer.path([size, offset1, 0, offset2, -size, offset1], line).attr(directionOptions).append(group);
  97986. renderer.path([-offset1, size, -offset2, 0, -offset1, -size], line).attr(directionOptions).append(group);
  97987. renderer.circle(0, options.incButtonOffset, options.smallCircleSize / 2).append(group);
  97988. renderer.path([[-incdecButtonSize, options.incButtonOffset, incdecButtonSize, options.incButtonOffset], [0, options.incButtonOffset - incdecButtonSize, 0, options.incButtonOffset + incdecButtonSize]], "area").append(group);
  97989. renderer.circle(0, options.decButtonOffset, options.smallCircleSize / 2).append(group);
  97990. renderer.path([-incdecButtonSize, options.decButtonOffset, incdecButtonSize, options.decButtonOffset], "area").append(group);
  97991. that._progressBar = renderer.path([], "area").append(group);
  97992. that._zoomDrag = renderer.rect(_floor(-options.sliderLength / 2), _floor(options.sliderLineEndOffset - options.sliderWidth / 2), options.sliderLength, options.sliderWidth).append(group);
  97993. that._sliderLineLength = options.sliderLineEndOffset - options.sliderLineStartOffset
  97994. },
  97995. _createTrackers: function(renderer, dataKey, group) {
  97996. var options = SIZE_OPTIONS,
  97997. size = _round((options.arrowButtonOffset - options.trackerGap) / 2),
  97998. offset1 = options.arrowButtonOffset - size,
  97999. offset2 = _round(_pow(options.bigCircleSize * options.bigCircleSize / 4 - size * size, 0.5)),
  98000. size2 = offset2 - offset1;
  98001. renderer.rect(-size, -size, size * 2, size * 2).data(dataKey, {
  98002. index: COMMAND_RESET,
  98003. type: EVENT_TARGET_TYPE
  98004. }).append(group);
  98005. renderer.rect(-size, -offset2, size * 2, size2).data(dataKey, {
  98006. index: COMMAND_MOVE_UP,
  98007. type: EVENT_TARGET_TYPE
  98008. }).append(group);
  98009. renderer.rect(offset1, -size, size2, size * 2).data(dataKey, {
  98010. index: COMMAND_MOVE_RIGHT,
  98011. type: EVENT_TARGET_TYPE
  98012. }).append(group);
  98013. renderer.rect(-size, offset1, size * 2, size2).data(dataKey, {
  98014. index: COMMAND_MOVE_DOWN,
  98015. type: EVENT_TARGET_TYPE
  98016. }).append(group);
  98017. renderer.rect(-offset2, -size, size2, size * 2).data(dataKey, {
  98018. index: COMMAND_MOVE_LEFT,
  98019. type: EVENT_TARGET_TYPE
  98020. }).append(group);
  98021. renderer.circle(0, options.incButtonOffset, options.smallCircleSize / 2).data(dataKey, {
  98022. index: COMMAND_ZOOM_IN,
  98023. type: EVENT_TARGET_TYPE
  98024. }).append(group);
  98025. renderer.circle(0, options.decButtonOffset, options.smallCircleSize / 2).data(dataKey, {
  98026. index: COMMAND_ZOOM_OUT,
  98027. type: EVENT_TARGET_TYPE
  98028. }).append(group);
  98029. renderer.rect(-2, options.sliderLineStartOffset - 2, 4, options.sliderLineEndOffset - options.sliderLineStartOffset + 4).css({cursor: "default"}).data(dataKey, {
  98030. index: COMMAND_ZOOM_DRAG_LINE,
  98031. type: EVENT_TARGET_TYPE
  98032. }).append(group);
  98033. this._zoomDragCover = renderer.rect(-options.sliderLength / 2, options.sliderLineEndOffset - options.sliderWidth / 2, options.sliderLength, options.sliderWidth).data(dataKey, {
  98034. index: COMMAND_ZOOM_DRAG,
  98035. type: EVENT_TARGET_TYPE
  98036. }).append(group)
  98037. },
  98038. _subscribeToProjection: function(projection) {
  98039. var that = this;
  98040. projection.on({
  98041. zoom: function() {
  98042. that._adjustZoom(projection.getScaledZoom())
  98043. },
  98044. "max-zoom": function() {
  98045. that._zoomPartition = projection.getZoomScalePartition();
  98046. that._sliderUnitLength = that._sliderLineLength / that._zoomPartition;
  98047. that._adjustZoom(projection.getScaledZoom())
  98048. }
  98049. })
  98050. },
  98051. dispose: function() {
  98052. var that = this;
  98053. that._params.layoutControl.removeItem(that);
  98054. that._root.clear();
  98055. that._params = that._callbacks = that._root = that._buttonsGroup = that._zoomDrag = that._zoomDragCover = that._progressBar = null;
  98056. return that
  98057. },
  98058. resize: function(size) {
  98059. this._setVisibility(size !== null && this._options.enabled && this._flags);
  98060. return this
  98061. },
  98062. _setVisibility: function(state) {
  98063. this._root.attr({visibility: state ? null : "hidden"})
  98064. },
  98065. getLayoutOptions: function() {
  98066. var options = this._options;
  98067. return this._rendered && options.enabled && this._flags ? {
  98068. width: 2 * options.margin + TOTAL_WIDTH,
  98069. height: 2 * options.margin + TOTAL_HEIGHT,
  98070. horizontalAlignment: options.horizontalAlignment,
  98071. verticalAlignment: options.verticalAlignment
  98072. } : null
  98073. },
  98074. locate: function(x, y) {
  98075. this._root.attr({
  98076. translateX: x + this._options.margin + OFFSET_X,
  98077. translateY: y + this._options.margin + OFFSET_Y
  98078. });
  98079. return this
  98080. },
  98081. setInteraction: function(interaction) {
  98082. var that = this;
  98083. that.processEnd();
  98084. if (_parseScalar(interaction.centeringEnabled, true))
  98085. that._flags |= FLAG_CENTERING;
  98086. else
  98087. that._flags &= ~FLAG_CENTERING;
  98088. if (_parseScalar(interaction.zoomingEnabled, true))
  98089. that._flags |= FLAG_ZOOMING;
  98090. else
  98091. that._flags &= ~FLAG_ZOOMING;
  98092. if (that._rendered)
  98093. that._refresh();
  98094. return that
  98095. },
  98096. setOptions: function(options) {
  98097. var that = this;
  98098. that.processEnd();
  98099. that._buttonsGroup.attr({
  98100. "stroke-width": options.borderWidth,
  98101. stroke: options.borderColor,
  98102. fill: options.color,
  98103. "fill-opacity": options.opacity
  98104. });
  98105. that._options = {
  98106. enabled: !!_parseScalar(options.enabled, true),
  98107. margin: options.margin > 0 ? _Number(options.margin) : 0,
  98108. horizontalAlignment: parseHorizontalAlignment(options.horizontalAlignment, "left"),
  98109. verticalAlignment: parseVerticalAlignment(options.verticalAlignment, "top")
  98110. };
  98111. that._rendered && that._refresh();
  98112. return that
  98113. },
  98114. _refresh: function() {
  98115. var isVisible = this._flags && this._options.enabled;
  98116. this._setVisibility(isVisible);
  98117. if (isVisible)
  98118. this.updateLayout()
  98119. },
  98120. clean: function() {
  98121. var that = this;
  98122. that._rendered = null;
  98123. that._root.remove();
  98124. return that
  98125. },
  98126. render: function() {
  98127. var that = this;
  98128. that._rendered = true;
  98129. that._root.append(that._params.container);
  98130. that._refresh();
  98131. return that
  98132. },
  98133. _adjustZoom: function(zoom) {
  98134. var that = this,
  98135. transform,
  98136. y,
  98137. start = SIZE_OPTIONS.sliderLineStartOffset,
  98138. end = SIZE_OPTIONS.sliderLineEndOffset,
  98139. h = SIZE_OPTIONS.sliderWidth;
  98140. that._zoomFactor = _round(zoom);
  98141. that._zoomFactor >= 0 || (that._zoomFactor = 0);
  98142. that._zoomFactor <= that._zoomPartition || (that._zoomFactor = that._zoomPartition);
  98143. transform = {translateY: -that._zoomFactor * that._sliderUnitLength};
  98144. y = end - h / 2 + transform.translateY;
  98145. that._progressBar.attr({points: [[0, start, 0, _math.max(start, y)], [0, _math.min(end, y + h), 0, end]]});
  98146. that._zoomDrag.attr(transform);
  98147. that._zoomDragCover.attr(transform)
  98148. },
  98149. _applyZoom: function(center) {
  98150. this._callbacks.zoom(this._zoomFactor, this._flags & FLAG_CENTERING ? center : undefined)
  98151. },
  98152. processStart: function(arg) {
  98153. var commandType = COMMAND_TO_TYPE_MAP[arg.data];
  98154. this._command = commandType && this._options.enabled && commandType.flags & this._flags ? new commandType(this, arg) : null;
  98155. return this
  98156. },
  98157. processMove: function(arg) {
  98158. this._command && this._command.update(arg);
  98159. return this
  98160. },
  98161. processEnd: function() {
  98162. this._command && this._command.finish();
  98163. this._command = null;
  98164. return this
  98165. },
  98166. processZoom: function(arg) {
  98167. var that = this,
  98168. zoomFactor;
  98169. if (that._flags & FLAG_ZOOMING) {
  98170. if (arg.delta)
  98171. zoomFactor = arg.delta;
  98172. else if (arg.ratio)
  98173. zoomFactor = _ln(arg.ratio) / _LN2;
  98174. that._adjustZoom(that._zoomFactor + zoomFactor);
  98175. that._applyZoom([arg.x, arg.y])
  98176. }
  98177. return that
  98178. }
  98179. });
  98180. function disposeCommand(command) {
  98181. delete command._owner;
  98182. command.update = function(){};
  98183. command.finish = function(){}
  98184. }
  98185. function ResetCommand(owner, arg) {
  98186. this._owner = owner;
  98187. this._command = arg.data
  98188. }
  98189. ResetCommand.flags = FLAG_CENTERING | FLAG_ZOOMING;
  98190. ResetCommand.prototype.update = function(arg) {
  98191. arg.data !== this._command && disposeCommand(this)
  98192. };
  98193. ResetCommand.prototype.finish = function() {
  98194. var flags = this._owner._flags;
  98195. this._owner._callbacks.reset(!!(flags & FLAG_CENTERING), !!(flags & FLAG_ZOOMING));
  98196. if (flags & FLAG_ZOOMING)
  98197. this._owner._adjustZoom(0);
  98198. disposeCommand(this)
  98199. };
  98200. function MoveCommand(owner, arg) {
  98201. this._command = arg.data;
  98202. var timeout = null,
  98203. interval = 100,
  98204. dx = 0,
  98205. dy = 0;
  98206. switch (this._command) {
  98207. case COMMAND_MOVE_UP:
  98208. dy = -10;
  98209. break;
  98210. case COMMAND_MOVE_RIGHT:
  98211. dx = 10;
  98212. break;
  98213. case COMMAND_MOVE_DOWN:
  98214. dy = 10;
  98215. break;
  98216. case COMMAND_MOVE_LEFT:
  98217. dx = -10;
  98218. break
  98219. }
  98220. function callback() {
  98221. owner._callbacks.move(dx, dy);
  98222. timeout = setTimeout(callback, interval)
  98223. }
  98224. this._stop = function() {
  98225. clearTimeout(timeout);
  98226. owner._callbacks.endMove();
  98227. this._stop = owner = null;
  98228. return this
  98229. };
  98230. arg = null;
  98231. owner._callbacks.beginMove();
  98232. callback()
  98233. }
  98234. MoveCommand.flags = FLAG_CENTERING;
  98235. MoveCommand.prototype.update = function(arg) {
  98236. this._command !== arg.data && this.finish()
  98237. };
  98238. MoveCommand.prototype.finish = function() {
  98239. disposeCommand(this._stop())
  98240. };
  98241. function ZoomCommand(owner, arg) {
  98242. this._owner = owner;
  98243. this._command = arg.data;
  98244. var timeout = null,
  98245. interval = 150,
  98246. dzoom = this._command === COMMAND_ZOOM_IN ? 1 : -1;
  98247. function callback() {
  98248. owner._adjustZoom(owner._zoomFactor + dzoom);
  98249. timeout = setTimeout(callback, interval)
  98250. }
  98251. this._stop = function() {
  98252. clearTimeout(timeout);
  98253. this._stop = owner = null;
  98254. return this
  98255. };
  98256. arg = null;
  98257. callback()
  98258. }
  98259. ZoomCommand.flags = FLAG_ZOOMING;
  98260. ZoomCommand.prototype.update = function(arg) {
  98261. this._command !== arg.data && this.finish()
  98262. };
  98263. ZoomCommand.prototype.finish = function() {
  98264. this._owner._applyZoom();
  98265. disposeCommand(this._stop())
  98266. };
  98267. function ZoomDragCommand(owner, arg) {
  98268. this._owner = owner;
  98269. this._zoomFactor = owner._zoomFactor;
  98270. this._pos = arg.y
  98271. }
  98272. ZoomDragCommand.flags = FLAG_ZOOMING;
  98273. ZoomDragCommand.prototype.update = function(arg) {
  98274. var owner = this._owner;
  98275. owner._adjustZoom(this._zoomFactor + owner._zoomPartition * (this._pos - arg.y) / owner._sliderLineLength)
  98276. };
  98277. ZoomDragCommand.prototype.finish = function() {
  98278. this._owner._applyZoom();
  98279. disposeCommand(this)
  98280. };
  98281. DX.viz.map._tests.ControlBar = ControlBar;
  98282. var COMMAND_TO_TYPE_MAP__ORIGINAL = COMMAND_TO_TYPE_MAP;
  98283. DX.viz.map._tests.stubCommandToTypeMap = function(map) {
  98284. COMMAND_TO_TYPE_MAP = map
  98285. };
  98286. DX.viz.map._tests.restoreCommandToTypeMap = function() {
  98287. COMMAND_TO_TYPE_MAP = COMMAND_TO_TYPE_MAP__ORIGINAL
  98288. };
  98289. DX.viz.map.dxVectorMap.prototype._factory.createControlBar = function(parameters) {
  98290. return new ControlBar(parameters)
  98291. }
  98292. })(DevExpress);
  98293. /*! Module viz-vectormap, file tracker.js */
  98294. (function(DX, $, undefined) {
  98295. var _math = Math,
  98296. _abs = _math.abs,
  98297. _sqrt = _math.sqrt,
  98298. _round = _math.round,
  98299. _addNamespace = DX.ui.events.addNamespace,
  98300. _parseScalar = DX.viz.core.utils.parseScalar,
  98301. _now = $.now,
  98302. _NAME = DX.viz.map.dxVectorMap.prototype.NAME,
  98303. EVENTS = {};
  98304. setupEvents();
  98305. var EVENT_START = "start",
  98306. EVENT_MOVE = "move",
  98307. EVENT_END = "end",
  98308. EVENT_ZOOM = "zoom",
  98309. EVENT_HOVER_ON = "hover-on",
  98310. EVENT_HOVER_OFF = "hover-off",
  98311. EVENT_CLICK = "click",
  98312. EVENT_FOCUS_ON = "focus-on",
  98313. EVENT_FOCUS_MOVE = "focus-move",
  98314. EVENT_FOCUS_OFF = "focus-off",
  98315. CLICK_TIME_THRESHOLD = 500,
  98316. CLICK_COORD_THRESHOLD_MOUSE = 5,
  98317. CLICK_COORD_THRESHOLD_TOUCH = 20,
  98318. DRAG_COORD_THRESHOLD_MOUSE = 5,
  98319. DRAG_COORD_THRESHOLD_TOUCH = 10,
  98320. FOCUS_ON_DELAY_MOUSE = 300,
  98321. FOCUS_OFF_DELAY_MOUSE = 300,
  98322. FOCUS_ON_DELAY_TOUCH = 300,
  98323. FOCUS_OFF_DELAY_TOUCH = 400,
  98324. FOCUS_COORD_THRESHOLD_MOUSE = 5,
  98325. WHEEL_COOLDOWN = 50,
  98326. WHEEL_DIRECTION_COOLDOWN = 300;
  98327. function Tracker(parameters) {
  98328. var that = this;
  98329. that._root = parameters.root;
  98330. that._callbacks = {};
  98331. that._createEventHandlers(parameters.dataKey);
  98332. that._createProjectionHandlers(parameters.projection);
  98333. that._focus = new Focus(that._callbacks);
  98334. that._attachHandlers()
  98335. }
  98336. Tracker.prototype = {
  98337. constructor: Tracker,
  98338. dispose: function() {
  98339. var that = this;
  98340. that._detachHandlers();
  98341. that._focus.dispose();
  98342. that._root = that._callbacks = that._focus = that._docHandlers = that._rootHandlers = null;
  98343. return that
  98344. },
  98345. _startClick: function(event, data) {
  98346. if (!data)
  98347. return;
  98348. var coords = getEventCoords(event);
  98349. this._clickState = {
  98350. x: coords.x,
  98351. y: coords.y,
  98352. threshold: isTouchEvent(event) ? CLICK_COORD_THRESHOLD_TOUCH : CLICK_COORD_THRESHOLD_MOUSE,
  98353. time: _now()
  98354. }
  98355. },
  98356. _endClick: function(event, data) {
  98357. var state = this._clickState,
  98358. threshold,
  98359. coords;
  98360. if (!state)
  98361. return;
  98362. if (_now() - state.time <= CLICK_TIME_THRESHOLD) {
  98363. threshold = state.threshold;
  98364. coords = getEventCoords(event);
  98365. if (_abs(coords.x - state.x) <= threshold && _abs(coords.y - state.y) <= threshold)
  98366. this._callbacks[EVENT_CLICK]({
  98367. data: data,
  98368. x: coords.x,
  98369. y: coords.y,
  98370. $event: event
  98371. })
  98372. }
  98373. this._clickState = null
  98374. },
  98375. _startDrag: function(event, data) {
  98376. if (!data)
  98377. return;
  98378. var coords = getEventCoords(event),
  98379. state = this._dragState = {
  98380. x: coords.x,
  98381. y: coords.y,
  98382. data: data
  98383. };
  98384. this._callbacks[EVENT_START]({
  98385. x: state.x,
  98386. y: state.y,
  98387. data: state.data
  98388. })
  98389. },
  98390. _moveDrag: function(event, data) {
  98391. var state = this._dragState,
  98392. coords,
  98393. threshold;
  98394. if (!state)
  98395. return;
  98396. coords = getEventCoords(event);
  98397. threshold = isTouchEvent(event) ? DRAG_COORD_THRESHOLD_TOUCH : DRAG_COORD_THRESHOLD_MOUSE;
  98398. if (state.active || _abs(coords.x - state.x) > threshold || _abs(coords.y - state.y) > threshold) {
  98399. state.x = coords.x;
  98400. state.y = coords.y;
  98401. state.active = true;
  98402. state.data = data || {};
  98403. this._callbacks[EVENT_MOVE]({
  98404. x: state.x,
  98405. y: state.y,
  98406. data: state.data
  98407. })
  98408. }
  98409. },
  98410. _endDrag: function() {
  98411. var state = this._dragState;
  98412. if (!state)
  98413. return;
  98414. this._dragState = null;
  98415. this._callbacks[EVENT_END]({
  98416. x: state.x,
  98417. y: state.y,
  98418. data: state.data
  98419. })
  98420. },
  98421. _wheelZoom: function(event, data) {
  98422. if (!data)
  98423. return;
  98424. var that = this,
  98425. lock = that._wheelLock,
  98426. time = _now(),
  98427. delta,
  98428. coords;
  98429. if (time - lock.time <= WHEEL_COOLDOWN)
  98430. return;
  98431. if (time - lock.dirTime > WHEEL_DIRECTION_COOLDOWN)
  98432. lock.dir = 0;
  98433. delta = adjustWheelDelta(event.originalEvent.wheelDelta / 120 || event.originalEvent.detail / -3 || 0, lock);
  98434. if (delta === 0)
  98435. return;
  98436. coords = getEventCoords(event);
  98437. that._callbacks[EVENT_ZOOM]({
  98438. delta: delta,
  98439. x: coords.x,
  98440. y: coords.y
  98441. });
  98442. lock.time = lock.dirTime = time
  98443. },
  98444. _startZoom: function(event, data) {
  98445. if (!isTouchEvent(event) || !data)
  98446. return;
  98447. var state = this._zoomState = this._zoomState || {},
  98448. coords,
  98449. pointer2;
  98450. if (state.pointer1 && state.pointer2)
  98451. return;
  98452. if (state.pointer1 === undefined) {
  98453. state.pointer1 = getPointerId(event) || 0;
  98454. coords = getMultitouchEventCoords(event, state.pointer1);
  98455. state.x1 = state.x1_0 = coords.x;
  98456. state.y1 = state.y1_0 = coords.y
  98457. }
  98458. if (state.pointer2 === undefined) {
  98459. pointer2 = getPointerId(event) || 1;
  98460. if (pointer2 !== state.pointer1) {
  98461. coords = getMultitouchEventCoords(event, pointer2);
  98462. if (coords) {
  98463. state.x2 = state.x2_0 = coords.x;
  98464. state.y2 = state.y2_0 = coords.y;
  98465. state.pointer2 = pointer2;
  98466. state.ready = true;
  98467. this._endDrag()
  98468. }
  98469. }
  98470. }
  98471. },
  98472. _moveZoom: function(event) {
  98473. var state = this._zoomState,
  98474. coords;
  98475. if (!state || !isTouchEvent(event))
  98476. return;
  98477. if (state.pointer1 !== undefined) {
  98478. coords = getMultitouchEventCoords(event, state.pointer1);
  98479. if (coords) {
  98480. state.x1 = coords.x;
  98481. state.y1 = coords.y
  98482. }
  98483. }
  98484. if (state.pointer2 !== undefined) {
  98485. coords = getMultitouchEventCoords(event, state.pointer2);
  98486. if (coords) {
  98487. state.x2 = coords.x;
  98488. state.y2 = coords.y
  98489. }
  98490. }
  98491. },
  98492. _endZoom: function(event) {
  98493. var state = this._zoomState,
  98494. startDistance,
  98495. currentDistance;
  98496. if (!state || !isTouchEvent(event))
  98497. return;
  98498. if (state.ready) {
  98499. startDistance = getDistance(state.x1_0, state.y1_0, state.x2_0, state.y2_0);
  98500. currentDistance = getDistance(state.x1, state.y1, state.x2, state.y2);
  98501. this._callbacks[EVENT_ZOOM]({
  98502. ratio: currentDistance / startDistance,
  98503. x: (state.x1_0 + state.x2_0) / 2,
  98504. y: (state.y1_0 + state.y2_0) / 2
  98505. })
  98506. }
  98507. this._zoomState = null
  98508. },
  98509. _startHover: function(event, data) {
  98510. this._doHover(event, data, true)
  98511. },
  98512. _moveHover: function(event, data) {
  98513. this._doHover(event, data, false)
  98514. },
  98515. _doHover: function(event, data, isTouch) {
  98516. var that = this;
  98517. if (that._dragState && that._dragState.active || that._zoomState && that._zoomState.ready) {
  98518. that._cancelHover();
  98519. return
  98520. }
  98521. if (isTouchEvent(event) !== isTouch || that._hoverTarget === event.target || that._hoverState && that._hoverState.data === data)
  98522. return;
  98523. that._cancelHover();
  98524. if (data) {
  98525. that._hoverState = {data: data};
  98526. that._callbacks[EVENT_HOVER_ON]({data: data})
  98527. }
  98528. that._hoverTarget = event.target
  98529. },
  98530. _cancelHover: function() {
  98531. var state = this._hoverState;
  98532. this._hoverState = this._hoverTarget = null;
  98533. if (state)
  98534. this._callbacks[EVENT_HOVER_OFF]({data: state.data})
  98535. },
  98536. _startFocus: function(event, data) {
  98537. this._doFocus(event, data, true)
  98538. },
  98539. _moveFocus: function(event, data) {
  98540. this._doFocus(event, data, false)
  98541. },
  98542. _doFocus: function(event, data, isTouch) {
  98543. var that = this;
  98544. if (that._dragState && that._dragState.active || that._zoomState && that._zoomState.ready) {
  98545. that._cancelFocus();
  98546. return
  98547. }
  98548. if (isTouchEvent(event) !== isTouch)
  98549. return;
  98550. that._focus.turnOff(isTouch ? FOCUS_OFF_DELAY_TOUCH : FOCUS_OFF_DELAY_MOUSE);
  98551. data && that._focus.turnOn(data, getEventCoords(event), isTouch ? FOCUS_ON_DELAY_TOUCH : FOCUS_ON_DELAY_MOUSE, isTouch)
  98552. },
  98553. _endFocus: function(event) {
  98554. if (!isTouchEvent(event))
  98555. return;
  98556. this._focus.cancelOn()
  98557. },
  98558. _cancelFocus: function() {
  98559. this._focus.cancel()
  98560. },
  98561. _createEventHandlers: function(DATA_KEY) {
  98562. var that = this;
  98563. that._docHandlers = {};
  98564. that._rootHandlers = {};
  98565. that._docHandlers[EVENTS.start] = function(event) {
  98566. var isTouch = isTouchEvent(event),
  98567. data = $(event.target).data(DATA_KEY);
  98568. if (isTouch && !that._isTouchEnabled)
  98569. return;
  98570. data && event.preventDefault();
  98571. that._startClick(event, data);
  98572. that._startDrag(event, data);
  98573. that._startZoom(event, data);
  98574. that._startHover(event, data);
  98575. that._startFocus(event, data)
  98576. };
  98577. that._docHandlers[EVENTS.move] = function(event) {
  98578. var isTouch = isTouchEvent(event),
  98579. data = $(event.target).data(DATA_KEY);
  98580. if (isTouch && !that._isTouchEnabled)
  98581. return;
  98582. that._moveDrag(event, data);
  98583. that._moveZoom(event, data);
  98584. that._moveHover(event, data);
  98585. that._moveFocus(event, data)
  98586. };
  98587. that._docHandlers[EVENTS.end] = function(event) {
  98588. var isTouch = isTouchEvent(event),
  98589. data = $(event.target).data(DATA_KEY);
  98590. if (isTouch && !that._isTouchEnabled)
  98591. return;
  98592. that._endClick(event, data);
  98593. that._endDrag(event, data);
  98594. that._endZoom(event, data);
  98595. that._endFocus(event, data)
  98596. };
  98597. that._rootHandlers[EVENTS.wheel] = function(event) {
  98598. that._cancelFocus();
  98599. if (!that._isWheelEnabled)
  98600. return;
  98601. var data = $(event.target).data(DATA_KEY);
  98602. if (data) {
  98603. event.preventDefault();
  98604. event.stopPropagation();
  98605. that._wheelZoom(event, data)
  98606. }
  98607. };
  98608. that._wheelLock = {dir: 0}
  98609. },
  98610. _createProjectionHandlers: function(projection) {
  98611. var that = this;
  98612. projection.on({
  98613. center: handler,
  98614. zoom: handler
  98615. });
  98616. function handler() {
  98617. that._cancelFocus()
  98618. }
  98619. },
  98620. reset: function() {
  98621. var that = this;
  98622. that._clickState = null;
  98623. that._endDrag();
  98624. that._cancelHover();
  98625. that._cancelFocus();
  98626. return that
  98627. },
  98628. setCallbacks: function(callbacks) {
  98629. $.extend(this._callbacks, callbacks);
  98630. return this
  98631. },
  98632. setOptions: function(options) {
  98633. var that = this;
  98634. that.reset();
  98635. that._detachHandlers();
  98636. that._isTouchEnabled = !!_parseScalar(options.touchEnabled, true);
  98637. that._isWheelEnabled = !!_parseScalar(options.wheelEnabled, true);
  98638. that._attachHandlers();
  98639. return that
  98640. },
  98641. _detachHandlers: function() {
  98642. var that = this;
  98643. if (that._isTouchEnabled)
  98644. that._root.css({
  98645. "touch-action": "",
  98646. "-ms-touch-action": "",
  98647. "-webkit-user-select": ""
  98648. }).off(_addNamespace("MSHoldVisual", _NAME)).off(_addNamespace("contextmenu", _NAME));
  98649. $(document).off(that._docHandlers);
  98650. that._root.off(that._rootHandlers)
  98651. },
  98652. _attachHandlers: function() {
  98653. var that = this;
  98654. if (that._isTouchEnabled)
  98655. that._root.css({
  98656. "touch-action": "none",
  98657. "-ms-touch-action": "none",
  98658. "-webkit-user-select": "none"
  98659. }).on(_addNamespace("MSHoldVisual", _NAME), function(event) {
  98660. event.preventDefault()
  98661. }).on(_addNamespace("contextmenu", _NAME), function(event) {
  98662. isTouchEvent(event) && event.preventDefault()
  98663. });
  98664. $(document).on(that._docHandlers);
  98665. that._root.on(that._rootHandlers)
  98666. }
  98667. };
  98668. var Focus = function(callbacks) {
  98669. var that = this,
  98670. _activeData = null,
  98671. _data = null,
  98672. _disabled = false,
  98673. _onTimer = null,
  98674. _offTimer = null,
  98675. _x,
  98676. _y;
  98677. that.dispose = function() {
  98678. clearTimeout(_onTimer);
  98679. clearTimeout(_offTimer);
  98680. that.turnOn = that.turnOff = that.cancel = that.cancelOn = that.dispose = that = callbacks = _activeData = _data = _onTimer = _offTimer = null
  98681. };
  98682. that.turnOn = function(data, coords, timeout, forceTimeout) {
  98683. if (data === _data && _disabled)
  98684. return;
  98685. _disabled = false;
  98686. _data = data;
  98687. if (_activeData) {
  98688. _x = coords.x;
  98689. _y = coords.y;
  98690. clearTimeout(_onTimer);
  98691. _onTimer = setTimeout(function() {
  98692. _onTimer = null;
  98693. if (_data === _activeData) {
  98694. callbacks[EVENT_FOCUS_MOVE]({
  98695. data: _data,
  98696. x: _x,
  98697. y: _y
  98698. });
  98699. onCheck(true)
  98700. }
  98701. else
  98702. callbacks[EVENT_FOCUS_ON]({
  98703. data: _data,
  98704. x: _x,
  98705. y: _y
  98706. }, onCheck)
  98707. }, forceTimeout ? timeout : 0)
  98708. }
  98709. else if (!_onTimer || _abs(coords.x - _x) > FOCUS_COORD_THRESHOLD_MOUSE || _abs(coords.y - _y) > FOCUS_COORD_THRESHOLD_MOUSE || forceTimeout) {
  98710. _x = coords.x;
  98711. _y = coords.y;
  98712. clearTimeout(_onTimer);
  98713. _onTimer = setTimeout(function() {
  98714. _onTimer = null;
  98715. callbacks[EVENT_FOCUS_ON]({
  98716. data: _data,
  98717. x: _x,
  98718. y: _y
  98719. }, onCheck)
  98720. }, timeout)
  98721. }
  98722. function onCheck(result) {
  98723. _disabled = !result;
  98724. if (result) {
  98725. _activeData = _data;
  98726. clearTimeout(_offTimer);
  98727. _offTimer = null
  98728. }
  98729. }
  98730. };
  98731. that.turnOff = function(timeout) {
  98732. clearTimeout(_onTimer);
  98733. _onTimer = null;
  98734. _data = null;
  98735. if (_activeData && !_disabled)
  98736. _offTimer = _offTimer || setTimeout(function() {
  98737. _offTimer = null;
  98738. callbacks[EVENT_FOCUS_OFF]({data: _activeData});
  98739. _activeData = null
  98740. }, timeout)
  98741. };
  98742. that.cancel = function() {
  98743. clearTimeout(_onTimer);
  98744. clearTimeout(_offTimer);
  98745. if (_activeData)
  98746. callbacks[EVENT_FOCUS_OFF]({data: _activeData});
  98747. _activeData = _data = _onTimer = _offTimer = null
  98748. };
  98749. that.cancelOn = function() {
  98750. clearTimeout(_onTimer);
  98751. _onTimer = null
  98752. }
  98753. };
  98754. DX.viz.map._tests.Tracker = Tracker;
  98755. DX.viz.map._tests._DEBUG_forceEventMode = function(mode) {
  98756. setupEvents(mode)
  98757. };
  98758. DX.viz.map._tests.Focus = Focus;
  98759. DX.viz.map._tests._DEBUG_stubFocusType = function(focusType) {
  98760. Focus = focusType
  98761. };
  98762. DX.viz.map._tests._DEBUG_restoreFocusType = function() {
  98763. Focus = DX.viz.map._tests.Focus
  98764. };
  98765. DX.viz.map.dxVectorMap.prototype._factory.createTracker = function(parameters) {
  98766. return new Tracker(parameters)
  98767. };
  98768. function getDistance(x1, y1, x2, y2) {
  98769. return _sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
  98770. }
  98771. function isTouchEvent(event) {
  98772. var type = event.originalEvent.type,
  98773. pointerType = event.originalEvent.pointerType;
  98774. return /^touch/.test(type) || /^MSPointer/.test(type) && pointerType !== 4 || /^pointer/.test(type) && pointerType !== "mouse"
  98775. }
  98776. function selectItem(flags, items) {
  98777. var i = 0,
  98778. ii = flags.length,
  98779. item;
  98780. for (; i < ii; ++i)
  98781. if (flags[i]) {
  98782. item = items[i];
  98783. break
  98784. }
  98785. return _addNamespace(item || items[i], _NAME)
  98786. }
  98787. function setupEvents() {
  98788. var flags = [navigator.pointerEnabled, navigator.msPointerEnabled, "ontouchstart" in window];
  98789. if (arguments.length)
  98790. flags = [arguments[0] === "pointer", arguments[0] === "MSPointer", arguments[0] === "touch"];
  98791. EVENTS = {
  98792. start: selectItem(flags, ["pointerdown", "MSPointerDown", "touchstart mousedown", "mousedown"]),
  98793. move: selectItem(flags, ["pointermove", "MSPointerMove", "touchmove mousemove", "mousemove"]),
  98794. end: selectItem(flags, ["pointerup", "MSPointerUp", "touchend mouseup", "mouseup"]),
  98795. wheel: selectItem([], ["mousewheel DOMMouseScroll"])
  98796. }
  98797. }
  98798. function getEventCoords(event) {
  98799. var originalEvent = event.originalEvent,
  98800. touch = originalEvent.touches && originalEvent.touches[0] || {};
  98801. return {
  98802. x: touch.pageX || originalEvent.pageX || event.pageX,
  98803. y: touch.pageY || originalEvent.pageY || event.pageY
  98804. }
  98805. }
  98806. function getPointerId(event) {
  98807. return event.originalEvent.pointerId
  98808. }
  98809. function getMultitouchEventCoords(event, pointerId) {
  98810. var originalEvent = event.originalEvent;
  98811. if (originalEvent.pointerId !== undefined)
  98812. originalEvent = originalEvent.pointerId === pointerId ? originalEvent : null;
  98813. else
  98814. originalEvent = originalEvent.touches[pointerId];
  98815. return originalEvent ? {
  98816. x: originalEvent.pageX || event.pageX,
  98817. y: originalEvent.pageY || event.pageY
  98818. } : null
  98819. }
  98820. function adjustWheelDelta(delta, lock) {
  98821. if (delta === 0)
  98822. return 0;
  98823. var _delta = _abs(delta),
  98824. sign = _round(delta / _delta);
  98825. if (lock.dir && sign !== lock.dir)
  98826. return 0;
  98827. lock.dir = sign;
  98828. if (_delta < 0.1)
  98829. _delta = 0;
  98830. else if (_delta < 1)
  98831. _delta = 1;
  98832. else if (_delta > 4)
  98833. _delta = 4;
  98834. else
  98835. _delta = _round(_delta);
  98836. return sign * _delta
  98837. }
  98838. })(DevExpress, jQuery);
  98839. /*! Module viz-vectormap, file themeManager.js */
  98840. (function(DX, $, undefined) {
  98841. var _Number = Number,
  98842. _extend = $.extend,
  98843. _each = $.each;
  98844. var ThemeManager = DX.viz.core.BaseThemeManager.inherit({
  98845. _themeSection: "map",
  98846. _fontFields: ["areaSettings.label.font", "markerSettings.label.font", "tooltip.font", "legend.font", "loadingIndicator.font"],
  98847. getCommonAreaSettings: function(options) {
  98848. var settings = _extend(true, {}, this._theme.areaSettings, options),
  98849. palette,
  98850. i,
  98851. colors;
  98852. if (settings.paletteSize > 0) {
  98853. palette = new DX.viz.core.GradientPalette(settings.palette, settings.paletteSize);
  98854. for (i = 0, colors = []; i < settings.paletteSize; ++i)
  98855. colors.push(palette.getColor(i));
  98856. settings._colors = colors
  98857. }
  98858. return settings
  98859. },
  98860. getAreaSettings: function(commonSettings, options) {
  98861. var settings = _extend(true, {}, commonSettings, options);
  98862. settings.borderWidth = _Number(settings.borderWidth) || 0;
  98863. settings.borderColor = settings.borderColor || null;
  98864. if (options.color === undefined && options.paletteIndex >= 0)
  98865. settings.color = commonSettings._colors[options.paletteIndex];
  98866. settings.color = settings.color || null;
  98867. settings.hoveredBorderWidth = _Number(settings.hoveredBorderWidth) || settings.borderWidth;
  98868. settings.hoveredBorderColor = settings.hoveredBorderColor || settings.borderColor;
  98869. settings.hoveredColor = settings.hoveredColor || settings.color;
  98870. settings.selectedBorderWidth = _Number(settings.selectedBorderWidth) || settings.borderWidth;
  98871. settings.selectedBorderColor = settings.selectedBorderColor || settings.borderColor;
  98872. settings.selectedColor = settings.selectedColor || settings.color;
  98873. return settings
  98874. },
  98875. getCommonMarkerSettings: function(options) {
  98876. options && !options.label && options.font && (options.label = {font: options.font}) && (options.font = undefined);
  98877. var theme = _extend({}, this._theme.markerSettings),
  98878. _options = _extend({}, options),
  98879. themeParts = {},
  98880. optionsParts = {},
  98881. settings;
  98882. _each(theme, function(name, themePart) {
  98883. if (name[0] === "_") {
  98884. themeParts[name] = themePart;
  98885. optionsParts[name] = _options[name];
  98886. theme[name] = _options[name] = undefined
  98887. }
  98888. });
  98889. settings = _extend(true, {}, theme, _options);
  98890. _each(themeParts, function(name, themePart) {
  98891. settings[name] = _extend(true, {}, theme, themePart, _options, optionsParts[name])
  98892. });
  98893. return settings
  98894. },
  98895. getMarkerSettings: function(commonSettings, options, type) {
  98896. var settings = _extend(true, {}, commonSettings["_" + type], options);
  98897. settings.borderWidth = _Number(settings.borderWidth) || 0;
  98898. settings.borderColor = settings.borderColor || null;
  98899. settings.color = settings.color || null;
  98900. settings.opacity = settings.opacity || null;
  98901. settings.hoveredBorderWidth = _Number(settings.hoveredBorderWidth) || settings.borderWidth;
  98902. settings.hoveredBorderColor = settings.hoveredBorderColor || settings.borderColor;
  98903. settings.hoveredColor = settings.hoveredColor || settings.color;
  98904. settings.hoveredOpacity = settings.hoveredOpacity || settings.opacity;
  98905. settings.selectedBorderWidth = _Number(settings.selectedBorderWidth) || settings.borderWidth;
  98906. settings.selectedBorderColor = settings.selectedBorderColor || settings.borderColor;
  98907. settings.selectedColor = settings.selectedColor || settings.color;
  98908. settings.selectedOpacity = settings.selectedOpacity || settings.opacity;
  98909. return settings
  98910. },
  98911. getPieColors: function(commonSettings, count) {
  98912. var colors = commonSettings._pie._colors || [],
  98913. palette,
  98914. i,
  98915. _count = count > 8 ? count : 8;
  98916. if (colors.length < _count) {
  98917. palette = new DX.viz.core.Palette(commonSettings._pie.palette, {
  98918. stepHighlight: 50,
  98919. theme: this.themeName()
  98920. });
  98921. for (i = 0, colors = []; i < _count; ++i)
  98922. colors.push(palette.getNextColor());
  98923. commonSettings._pie._colors = colors
  98924. }
  98925. return colors
  98926. }
  98927. });
  98928. DX.viz.map._tests.ThemeManager = ThemeManager;
  98929. DX.viz.map.dxVectorMap.prototype._factory.createThemeManager = function() {
  98930. return new ThemeManager
  98931. }
  98932. })(DevExpress, jQuery);
  98933. /*! Module viz-vectormap, file legend.js */
  98934. (function(DX, $, undefined) {
  98935. var _String = String,
  98936. _isArray = DX.utils.isArray,
  98937. _extend = $.extend,
  98938. _each = $.each,
  98939. _BaseLegend = DX.viz.core.Legend;
  98940. function Legend(parameters) {
  98941. var that = this;
  98942. that._params = parameters;
  98943. that._root = parameters.renderer.g().attr({"class": "dxm-legend"});
  98944. parameters.layoutControl.addItem(that);
  98945. _BaseLegend.apply(that, [{
  98946. renderer: parameters.renderer,
  98947. group: that._root,
  98948. backgroundClass: null,
  98949. itemsGroupClass: null,
  98950. textField: "text",
  98951. getFormatObject: function(data) {
  98952. return data
  98953. }
  98954. }]);
  98955. that._onDataChanged = function(items) {
  98956. var itemsForUpdate = $.map(items, function(item) {
  98957. return _extend(true, {states: {normal: {fill: item.color}}}, item)
  98958. });
  98959. that.update(itemsForUpdate, that._options);
  98960. that._refresh()
  98961. }
  98962. }
  98963. var legendPrototype = Legend.prototype = DX.utils.clone(_BaseLegend.prototype);
  98964. legendPrototype.constructor = Legend;
  98965. legendPrototype.dispose = function() {
  98966. var that = this;
  98967. that._params.layoutControl.removeItem(that);
  98968. that._unbindData();
  98969. that._params = that._root = that._onDataChanged = null;
  98970. return _BaseLegend.prototype.dispose.apply(that, arguments)
  98971. };
  98972. legendPrototype.clean = function() {
  98973. this._rendered = false;
  98974. this._root.remove();
  98975. return this
  98976. };
  98977. legendPrototype.render = function() {
  98978. var that = this;
  98979. that._root.append(that._params.container);
  98980. that._rendered = true;
  98981. that._refresh();
  98982. return that
  98983. };
  98984. legendPrototype.resize = function(size) {
  98985. if (size === null)
  98986. this.erase();
  98987. else
  98988. this.setSize(size).draw();
  98989. return this
  98990. };
  98991. legendPrototype.locate = _BaseLegend.prototype.shift;
  98992. legendPrototype._unbindData = function() {
  98993. if (this._dataCategory)
  98994. this._params.dataExchanger.unbind(this._dataCategory, this._dataName)
  98995. };
  98996. legendPrototype._bindData = function(info) {
  98997. this._params.dataExchanger.bind(this._dataCategory = info.category, this._dataName = info.name, this._onDataChanged)
  98998. };
  98999. var sourceMap = {
  99000. areacolorgroups: {
  99001. category: "areas",
  99002. name: "color"
  99003. },
  99004. markercolorgroups: {
  99005. category: "markers",
  99006. name: "color"
  99007. },
  99008. markersizegroups: {
  99009. category: "markers",
  99010. name: "size"
  99011. }
  99012. };
  99013. var unknownSource = {
  99014. category: "UNKNOWN",
  99015. name: "UNKNOWN"
  99016. };
  99017. legendPrototype.setOptions = function(options) {
  99018. var that = this;
  99019. that.update(that._data, options);
  99020. that._unbindData();
  99021. that._bindData(sourceMap[_String(options.source).toLowerCase()] || unknownSource);
  99022. that._refresh();
  99023. return that
  99024. };
  99025. legendPrototype._refresh = function() {
  99026. if (this._rendered)
  99027. this.updateLayout()
  99028. };
  99029. function LegendsControl(parameters) {
  99030. this._parameters = parameters;
  99031. this._items = []
  99032. }
  99033. LegendsControl.prototype = {
  99034. constructor: LegendsControl,
  99035. dispose: function() {
  99036. _each(this._items, function(_, item) {
  99037. item.dispose()
  99038. });
  99039. this._parameters = this._items = null;
  99040. return this
  99041. },
  99042. setOptions: function(options, theme) {
  99043. var optionList = _isArray(options) ? options : [],
  99044. i = 0,
  99045. ii = optionList.length,
  99046. item,
  99047. newItems = [],
  99048. items = this._items;
  99049. for (; i < ii; ++i) {
  99050. item = (items[i] || new Legend(this._parameters)).setOptions(_extend(true, {}, theme, optionList[i]));
  99051. newItems.push(item)
  99052. }
  99053. for (ii = items.length; i < ii; ++i)
  99054. items[i].clean().dispose();
  99055. this._items = newItems
  99056. },
  99057. clean: function() {
  99058. _each(this._items, function(_, item) {
  99059. item.clean()
  99060. });
  99061. return this
  99062. },
  99063. render: function() {
  99064. _each(this._items, function(_, item) {
  99065. item.render()
  99066. });
  99067. return this
  99068. }
  99069. };
  99070. DX.viz.map.dxVectorMap.prototype._factory.createLegendsControl = function(parameters) {
  99071. return new LegendsControl(parameters)
  99072. };
  99073. DX.viz.map._tests.Legend = Legend;
  99074. DX.viz.map._tests.LegendsControl = LegendsControl;
  99075. DX.viz.map._tests.stubLegendType = function(stub) {
  99076. Legend = stub
  99077. };
  99078. DX.viz.map._tests.restoreLegendType = function() {
  99079. Legend = DX.viz.map._tests.Legend
  99080. };
  99081. DX.viz.map._tests.extendLegendSourceMap = function(name, value) {
  99082. sourceMap[name] = value
  99083. }
  99084. })(DevExpress, jQuery);
  99085. /*! Module viz-vectormap, file layout.js */
  99086. (function(DX, $, undefined) {
  99087. var _round = Math.round,
  99088. _min = Math.min,
  99089. _max = Math.max,
  99090. _each = $.each,
  99091. _inArray = $.inArray,
  99092. horizontalAlignmentMap = {
  99093. left: 0,
  99094. center: 1,
  99095. right: 2
  99096. },
  99097. verticalAlignmentMap = {
  99098. top: 0,
  99099. bottom: 1
  99100. };
  99101. function getCellIndex(options) {
  99102. return verticalAlignmentMap[options.verticalAlignment] * 3 + horizontalAlignmentMap[options.horizontalAlignment]
  99103. }
  99104. function createCells(canvas, items) {
  99105. var hstep = (canvas.right - canvas.left) / 3,
  99106. vstep = (canvas.bottom - canvas.top) / 2,
  99107. h1 = canvas.left,
  99108. h2 = _round(h1 + hstep),
  99109. h3 = _round(h1 + hstep + hstep),
  99110. h4 = canvas.right,
  99111. v1 = canvas.top,
  99112. v2 = _round(v1 + vstep),
  99113. v3 = canvas.bottom,
  99114. cells = [{rect: [h1, v1, h2, v2]}, {
  99115. rect: [h2, v1, h3, v2],
  99116. center: true
  99117. }, {
  99118. rect: [h3, v1, h4, v2],
  99119. horInv: true
  99120. }, {
  99121. rect: [h1, v2, h2, v3],
  99122. verInv: true
  99123. }, {
  99124. rect: [h2, v2, h3, v3],
  99125. center: true,
  99126. verInv: true
  99127. }, {
  99128. rect: [h3, v2, h4, v3],
  99129. horInv: true,
  99130. verInv: true
  99131. }],
  99132. itemsList = [[], [], [], [], [], []];
  99133. _each(items, function(_, item) {
  99134. var options = item.getLayoutOptions();
  99135. if (options)
  99136. itemsList[getCellIndex(options)].push({
  99137. item: item,
  99138. width: options.width,
  99139. height: options.height
  99140. })
  99141. });
  99142. _each(cells, function(i, cell) {
  99143. if (itemsList[i].length)
  99144. cell.items = itemsList[i];
  99145. else {
  99146. if (cell.center)
  99147. cell.rect[0] = cell.rect[2] = (cell.rect[0] + cell.rect[2]) / 2;
  99148. else
  99149. cell.rect[cell.horInv ? 0 : 2] = cell.rect[cell.horInv ? 2 : 0];
  99150. cell.rect[cell.verInv ? 1 : 3] = cell.rect[cell.verInv ? 3 : 1]
  99151. }
  99152. });
  99153. return cells
  99154. }
  99155. function adjustCellSizes(cells) {
  99156. _each([0, 1, 2, 3, 4, 5], function(_, index) {
  99157. var cell = cells[index],
  99158. otherCell = cells[(index + 3) % 6];
  99159. if (cell.items)
  99160. if (!otherCell.items) {
  99161. cell.rect[1] = _min(cell.rect[1], otherCell.rect[3]);
  99162. cell.rect[3] = _max(cell.rect[3], otherCell.rect[1])
  99163. }
  99164. });
  99165. _each([1, 4], function(_, index) {
  99166. var cell = cells[index],
  99167. otherCell1 = cells[index - 1],
  99168. otherCell2 = cells[index + 1],
  99169. size1,
  99170. size2;
  99171. if (cell.items) {
  99172. if (!otherCell1.items && !otherCell2.items) {
  99173. size1 = cell.rect[0] - otherCell1.rect[2];
  99174. size2 = otherCell2.rect[0] - cell.rect[2];
  99175. if (size1 > size2)
  99176. if (size1 / size2 >= 2) {
  99177. cell.rect[0] -= size1;
  99178. cell.right = true
  99179. }
  99180. else {
  99181. cell.rect[0] -= size2;
  99182. cell.rect[2] += size2
  99183. }
  99184. else if (size2 / size1 >= 2) {
  99185. cell.rect[2] += size2;
  99186. cell.center = null
  99187. }
  99188. else {
  99189. cell.rect[0] -= size1;
  99190. cell.rect[2] += size1
  99191. }
  99192. }
  99193. }
  99194. else {
  99195. if (otherCell1.items)
  99196. otherCell1.rect[2] = (cell.rect[0] + cell.rect[2]) / 2;
  99197. if (otherCell2.items)
  99198. otherCell2.rect[0] = (cell.rect[0] + cell.rect[2]) / 2
  99199. }
  99200. })
  99201. }
  99202. function adjustCellsAndApplyLayout(cells, forceMode) {
  99203. var hasHiddenItems = false;
  99204. adjustCellSizes(cells);
  99205. _each(cells, function(_, cell) {
  99206. if (cell.items)
  99207. hasHiddenItems = applyCellLayout(cell, forceMode) || hasHiddenItems
  99208. });
  99209. return hasHiddenItems
  99210. }
  99211. function applyCellLayout(cell, forceMode) {
  99212. var cellRect = cell.rect,
  99213. cellWidth = cellRect[2] - cellRect[0],
  99214. cellHeight = cellRect[3] - cellRect[1],
  99215. xoffset = 0,
  99216. yoffset = 0,
  99217. currentHeight = 0,
  99218. totalL = cellRect[2],
  99219. totalT = cellRect[3],
  99220. totalR = cellRect[0],
  99221. totalB = cellRect[1],
  99222. moves = [],
  99223. hasHiddenItems = false;
  99224. _each(cell.items, function(_, item) {
  99225. if (item.width > cellWidth || item.height > cellHeight) {
  99226. moves.push(null);
  99227. hasHiddenItems = true;
  99228. return forceMode || false
  99229. }
  99230. if (xoffset + item.width > cellWidth) {
  99231. yoffset += currentHeight;
  99232. xoffset = currentHeight = 0
  99233. }
  99234. if (yoffset + item.height > cellHeight) {
  99235. moves.push(null);
  99236. hasHiddenItems = true;
  99237. return forceMode || false
  99238. }
  99239. currentHeight = _max(currentHeight, item.height);
  99240. var dx = cell.horInv ? cellRect[2] - item.width - xoffset : cellRect[0] + xoffset,
  99241. dy = cell.verInv ? cellRect[3] - item.height - yoffset : cellRect[1] + yoffset;
  99242. xoffset += item.width;
  99243. totalL = _min(totalL, dx);
  99244. totalT = _min(totalT, dy);
  99245. totalR = _max(totalR, dx + item.width);
  99246. totalB = _max(totalB, dy + item.height);
  99247. moves.push([dx, dy])
  99248. });
  99249. if (forceMode || !hasHiddenItems) {
  99250. xoffset = 0;
  99251. if (cell.right)
  99252. xoffset = cellRect[2] - cellRect[0] - totalR + totalL;
  99253. else if (cell.center)
  99254. xoffset = _round((cellRect[2] - cellRect[0] - totalR + totalL) / 2);
  99255. _each(cell.items, function(i, item) {
  99256. var move = moves[i];
  99257. if (move)
  99258. item.item.locate(move[0] + xoffset, move[1]);
  99259. else
  99260. item.item.resize(null)
  99261. });
  99262. cell.rect = [totalL, totalT, totalR, totalB];
  99263. cell.items = null
  99264. }
  99265. return hasHiddenItems
  99266. }
  99267. function applyLayout(canvas, items) {
  99268. var cells = createCells(canvas, items);
  99269. if (adjustCellsAndApplyLayout(cells))
  99270. adjustCellsAndApplyLayout(cells, true)
  99271. }
  99272. function LayoutControl() {
  99273. var that = this;
  99274. that._items = [];
  99275. that._suspended = true;
  99276. that._updateLayout = function() {
  99277. that._update()
  99278. }
  99279. }
  99280. LayoutControl.prototype = {
  99281. constructor: LayoutControl,
  99282. dispose: function() {
  99283. this._items = this._updateLayout = null;
  99284. return this
  99285. },
  99286. setSize: function(width, height) {
  99287. this._size = {
  99288. width: width,
  99289. height: height
  99290. };
  99291. this._update();
  99292. return this
  99293. },
  99294. stop: function() {
  99295. this._suspended = true;
  99296. return this
  99297. },
  99298. start: function() {
  99299. this._suspended = null;
  99300. this._update();
  99301. return this
  99302. },
  99303. addItem: function(item) {
  99304. this._items.push(item);
  99305. item.updateLayout = this._updateLayout;
  99306. return this
  99307. },
  99308. removeItem: function(item) {
  99309. this._items.splice(_inArray(item, this._items), 1);
  99310. item.updateLayout = null;
  99311. return this
  99312. },
  99313. _update: function() {
  99314. if (this._suspended)
  99315. return;
  99316. var size = this._size;
  99317. _each(this._items, function(_, item) {
  99318. item.resize(size)
  99319. });
  99320. applyLayout({
  99321. left: 0,
  99322. top: 0,
  99323. right: size.width,
  99324. bottom: size.height
  99325. }, this._items)
  99326. }
  99327. };
  99328. DX.viz.map.dxVectorMap.prototype._factory.createLayoutControl = function() {
  99329. return new LayoutControl
  99330. };
  99331. DX.viz.map._tests.LayoutControl = LayoutControl
  99332. })(DevExpress, jQuery);
  99333. /*! Module viz-vectormap, file mapItemsManager.js */
  99334. (function(DX, $, undefined) {
  99335. var _isFinite = isFinite,
  99336. _utils = DX.utils,
  99337. _coreUtils = DX.viz.core.utils,
  99338. _isString = _utils.isString,
  99339. _isArray = _utils.isArray,
  99340. _isFunction = _utils.isFunction,
  99341. _patchFontOptions = _coreUtils.patchFontOptions,
  99342. _parseScalar = _coreUtils.parseScalar,
  99343. _extend = $.extend,
  99344. _each = $.each,
  99345. _map = $.map;
  99346. var SELECTIONS = {
  99347. none: null,
  99348. single: -1,
  99349. multiple: NaN
  99350. };
  99351. function getSelection(selectionMode) {
  99352. var selection = String(selectionMode).toLowerCase();
  99353. selection = selection in SELECTIONS ? SELECTIONS[selection] : SELECTIONS.single;
  99354. if (selection !== null)
  99355. selection = {
  99356. state: {},
  99357. single: selection || null
  99358. };
  99359. return selection
  99360. }
  99361. function createEventTriggers(context, trigger, names) {
  99362. context.raiseHoverChanged = function(handle, state) {
  99363. trigger(names.hoverChanged, {
  99364. target: handle.proxy,
  99365. state: state
  99366. })
  99367. };
  99368. context.raiseSelectionChanged = function(handle) {
  99369. trigger(names.selectionChanged, {target: handle.proxy})
  99370. }
  99371. }
  99372. var MapItemsManager = DX.Class.inherit({
  99373. _rootClass: null,
  99374. ctor: function(parameters) {
  99375. var that = this;
  99376. that._params = parameters;
  99377. that._init();
  99378. parameters.projection.on({
  99379. project: function() {
  99380. that._reproject()
  99381. },
  99382. transform: function(transform) {
  99383. that._transform(transform);
  99384. that._relocate()
  99385. },
  99386. center: function(_, transform) {
  99387. that._transform(transform)
  99388. },
  99389. zoom: function(_, transform) {
  99390. that._transform(transform);
  99391. that._relocate()
  99392. }
  99393. })
  99394. },
  99395. _init: function() {
  99396. var that = this;
  99397. that._context = {
  99398. renderer: that._params.renderer,
  99399. projection: that._params.projection,
  99400. dataKey: that._params.dataKey,
  99401. selection: null,
  99402. getItemSettings: that._createItemSettingsBuilder()
  99403. };
  99404. that._initRoot();
  99405. createEventTriggers(that._context, that._params.eventTrigger, that._eventNames)
  99406. },
  99407. _createItemSettingsBuilder: function() {
  99408. var that = this;
  99409. return function(proxy, settings) {
  99410. var result = {};
  99411. _each(that._grouping, function(settingField, grouping) {
  99412. var value,
  99413. index;
  99414. if (_isFinite(value = grouping.callback(proxy)) && (index = findGroupPosition(value, grouping.groups)) >= 0)
  99415. result[settingField] = grouping.groups[index][settingField]
  99416. });
  99417. return that._getItemSettings(proxy, _extend({}, settings, result))
  99418. }
  99419. },
  99420. _initRoot: function() {
  99421. this._context.root = this._root = this._params.renderer.g().attr({"class": this._rootClass})
  99422. },
  99423. dispose: function() {
  99424. var that = this;
  99425. that._destroyHandles();
  99426. that._params = that._context = that._grouping = null;
  99427. that._disposeRoot();
  99428. return that
  99429. },
  99430. _disposeRoot: function() {
  99431. this._root = null
  99432. },
  99433. clean: function() {
  99434. var that = this;
  99435. that._destroyItems();
  99436. that._removeRoot();
  99437. that._rendered = false;
  99438. return that
  99439. },
  99440. _removeRoot: function() {
  99441. this._root.remove()
  99442. },
  99443. setOptions: function(options) {
  99444. var that = this;
  99445. that._processOptions(options || {});
  99446. that._params.notifyDirty();
  99447. that._destroyItems();
  99448. that._createItems(that._params.notifyReady);
  99449. return that
  99450. },
  99451. render: function() {
  99452. var that = this;
  99453. that._rendered = true;
  99454. that._params.notifyDirty();
  99455. that._appendRoot();
  99456. that._createItems(that._params.notifyReady, true);
  99457. return that
  99458. },
  99459. _processOptions: function(options) {
  99460. var that = this,
  99461. settings = that._commonSettings = that._getCommonSettings(options),
  99462. context = that._context;
  99463. that._customizeCallback = _isFunction(settings.customize) ? settings.customize : $.noop;
  99464. context.hover = !!_parseScalar(settings.hoverEnabled, true);
  99465. if (context.selection)
  99466. _each(context.selection.state, function(_, handle) {
  99467. handle && handle.resetSelected()
  99468. });
  99469. context.selection = getSelection(settings.selectionMode);
  99470. that._grouping = {};
  99471. that._updateGrouping()
  99472. },
  99473. _appendRoot: function() {
  99474. this._root.append(this._params.container)
  99475. },
  99476. _destroyItems: function() {
  99477. var that = this;
  99478. that._clearRoot();
  99479. clearTimeout(that._labelsTimeout);
  99480. that._rendered && that._handles && _each(that._handles, function(_, handle) {
  99481. if (handle.item) {
  99482. handle.item.dispose();
  99483. handle.item = null
  99484. }
  99485. })
  99486. },
  99487. _clearRoot: function() {
  99488. this._root.clear()
  99489. },
  99490. _destroyHandles: function() {
  99491. this._handles && _each(this._handles, function(_, handle) {
  99492. handle.dispose()
  99493. });
  99494. this._handles = null
  99495. },
  99496. _createHandles: function(source) {
  99497. var that = this;
  99498. if (_isArray(source))
  99499. that._handles = _map(source, function(dataItem, i) {
  99500. dataItem = dataItem || {};
  99501. var handle = new MapItemHandle(that._context, that._getItemCoordinates(dataItem), that._getItemAttributes(dataItem), i, that._itemType),
  99502. proxy = handle.proxy;
  99503. that._initProxy(proxy, dataItem);
  99504. handle.settings = that._customizeCallback.call(proxy, proxy) || {};
  99505. if (handle.settings.isSelected)
  99506. proxy.selected(true);
  99507. return handle
  99508. })
  99509. },
  99510. _createItems: function(notifyReady) {
  99511. var that = this,
  99512. selectedItems = [],
  99513. immediateReady = true;
  99514. if (that._rendered && that._handles) {
  99515. _each(that._handles, function(_, handle) {
  99516. handle.item = that._createItem(handle.proxy).init(that._context, handle.proxy).project().update(handle.settings).locate();
  99517. if (handle.proxy.selected())
  99518. selectedItems.push(handle.item)
  99519. });
  99520. _each(selectedItems, function(_, item) {
  99521. item.setSelectedState()
  99522. });
  99523. that._arrangeItems();
  99524. if (that._commonSettings.label.enabled) {
  99525. immediateReady = false;
  99526. clearTimeout(that._labelsTimeout);
  99527. that._labelsTimeout = setTimeout(function() {
  99528. _each(that._handles, function(_, handle) {
  99529. handle.item.createLabel()
  99530. });
  99531. notifyReady()
  99532. })
  99533. }
  99534. }
  99535. immediateReady && notifyReady()
  99536. },
  99537. _processSource: null,
  99538. setData: function(data) {
  99539. var that = this;
  99540. that._params.notifyDirty();
  99541. if (_isString(data))
  99542. $.getJSON(data).done(updateSource).fail(function() {
  99543. updateSource(null)
  99544. });
  99545. else
  99546. updateSource(data);
  99547. return that;
  99548. function updateSource(source) {
  99549. if (that._rendered)
  99550. that._params.tracker.reset();
  99551. that._destroyItems();
  99552. that._destroyHandles();
  99553. that._createHandles(that._processSource(source));
  99554. that._createItems(that._params.notifyReady)
  99555. }
  99556. },
  99557. _transform: function(transform) {
  99558. this._root.attr(transform)
  99559. },
  99560. _reproject: function() {
  99561. this._rendered && this._handles && _each(this._handles, function(_, handle) {
  99562. handle.item.project().locate()
  99563. })
  99564. },
  99565. _relocate: function() {
  99566. this._rendered && this._handles && _each(this._handles, function(_, handle) {
  99567. handle.item.locate()
  99568. })
  99569. },
  99570. hoverItem: function(index, state) {
  99571. this._handles[index].setHovered(state);
  99572. return this
  99573. },
  99574. selectItem: function(index, state, noCallback) {
  99575. this._handles[index].setSelected(state, noCallback);
  99576. return this
  99577. },
  99578. clearSelection: function() {
  99579. var selection = this._context.selection;
  99580. if (selection)
  99581. _each(selection.state, function(_, handle) {
  99582. handle && handle.setSelected(false)
  99583. });
  99584. return this
  99585. },
  99586. raiseClick: function(index, $event) {
  99587. this._params.eventTrigger(this._eventNames.click, {
  99588. target: this._handles[index].proxy,
  99589. jQueryEvent: $event
  99590. });
  99591. return this
  99592. },
  99593. getProxyItems: function() {
  99594. return _map(this._handles, function(handle) {
  99595. return handle.proxy
  99596. })
  99597. },
  99598. getProxyItem: function(index) {
  99599. return this._handles[index].proxy
  99600. },
  99601. _performGrouping: function(partition, settingField, valueCallback, valuesCallback) {
  99602. var groups = createGroups(partition),
  99603. values;
  99604. if (groups) {
  99605. values = valuesCallback(groups.length);
  99606. _each(groups, function(i, group) {
  99607. group.index = i;
  99608. group[settingField] = values[i]
  99609. });
  99610. this._grouping[settingField] = {
  99611. callback: valueCallback,
  99612. groups: groups
  99613. }
  99614. }
  99615. else {
  99616. delete this._grouping[settingField];
  99617. groups = []
  99618. }
  99619. this._params.dataExchanger.set(this._dataCategory, settingField, groups)
  99620. },
  99621. _groupByColor: function(colorGroups, palette, valueCallback) {
  99622. this._performGrouping(colorGroups, "color", valueCallback, function(count) {
  99623. var _palette = new DX.viz.core.GradientPalette(palette, count),
  99624. i = 0,
  99625. list = [];
  99626. for (; i < count; ++i)
  99627. list.push(_palette.getColor(i));
  99628. return list
  99629. })
  99630. }
  99631. });
  99632. MapItemsManager.prototype.TEST_getContext = function() {
  99633. return this._context
  99634. };
  99635. MapItemsManager.prototype.TEST_performGrouping = MapItemsManager.prototype._performGrouping;
  99636. MapItemsManager.prototype.TEST_groupByColor = MapItemsManager.prototype._groupByColor;
  99637. DX.viz.map._internal.mapItemBehavior = {
  99638. init: function(ctx, proxy) {
  99639. var that = this;
  99640. that._ctx = ctx;
  99641. that._data = {
  99642. index: proxy.index,
  99643. type: proxy.type
  99644. };
  99645. that._proxy = proxy;
  99646. that._root = that._createRoot().append(that._ctx.root);
  99647. return that
  99648. },
  99649. dispose: function() {
  99650. disposeItem(this);
  99651. return this
  99652. },
  99653. project: function() {
  99654. var that = this;
  99655. that._coords = that._project(that._ctx.projection, that._proxy.coordinates());
  99656. return this
  99657. },
  99658. locate: function() {
  99659. var that = this;
  99660. that._locate(that._transform(that._ctx.projection, that._coords));
  99661. that._label && that._label.value && that._locateLabel();
  99662. return that
  99663. },
  99664. update: function(settings) {
  99665. var that = this;
  99666. that._settings = that._ctx.getItemSettings(that._proxy, settings);
  99667. that._update(that._settings);
  99668. that._label && that._updateLabel();
  99669. return that
  99670. },
  99671. createLabel: function() {
  99672. var that = this;
  99673. that._label = {
  99674. root: that._createLabelRoot(),
  99675. text: that._ctx.renderer.text(),
  99676. tracker: that._ctx.renderer.rect().attr({
  99677. stroke: "none",
  99678. "stroke-width": 0,
  99679. fill: "#000000",
  99680. opacity: 0.0001
  99681. }).data(that._ctx.dataKey, that._data)
  99682. };
  99683. that._updateLabel();
  99684. return that
  99685. },
  99686. _updateLabel: function() {
  99687. var that = this,
  99688. settings = that._settings.label;
  99689. that._label.value = String(this._proxy.text || this._proxy.attribute(this._settings.label.dataField) || "");
  99690. if (that._label.value) {
  99691. that._label.text.attr({
  99692. text: that._label.value,
  99693. x: 0,
  99694. y: 0
  99695. }).css(_patchFontOptions(settings.font)).attr({
  99696. align: "center",
  99697. stroke: settings.stroke,
  99698. "stroke-width": settings["stroke-width"],
  99699. "stroke-opacity": settings["stroke-opacity"]
  99700. }).append(that._label.root);
  99701. that._label.tracker.append(that._label.root);
  99702. that._adjustLabel();
  99703. that._locateLabel()
  99704. }
  99705. }
  99706. };
  99707. var MapItemHandle = function(context, coordinates, attributes, index, type) {
  99708. var handle = this;
  99709. handle._ctx = context;
  99710. handle._idx = index;
  99711. handle._hovered = handle._selected = false;
  99712. attributes = _extend({}, attributes);
  99713. handle.proxy = {
  99714. index: index,
  99715. type: type,
  99716. coordinates: function() {
  99717. return coordinates
  99718. },
  99719. attribute: function(name, value) {
  99720. if (arguments.length > 1) {
  99721. attributes[name] = value;
  99722. return this
  99723. }
  99724. else
  99725. return arguments.length > 0 ? attributes[name] : attributes
  99726. },
  99727. selected: function(state, _noEvent) {
  99728. if (arguments.length > 0) {
  99729. handle.setSelected(!!state, _noEvent);
  99730. return this
  99731. }
  99732. else
  99733. return handle._selected
  99734. },
  99735. applySettings: function(settings) {
  99736. _extend(true, handle.settings, settings);
  99737. handle.item && handle.item.update(handle.settings);
  99738. return this
  99739. }
  99740. }
  99741. };
  99742. MapItemHandle.prototype = {
  99743. constructor: MapItemHandle,
  99744. dispose: function() {
  99745. disposeItem(this.proxy);
  99746. disposeItem(this);
  99747. return this
  99748. },
  99749. setHovered: function(state) {
  99750. state = !!state;
  99751. var that = this;
  99752. if (that._ctx.hover && that._hovered !== state) {
  99753. that._hovered = state;
  99754. if (that.item) {
  99755. if (that._hovered)
  99756. that.item.onHover();
  99757. if (!that._selected) {
  99758. that.item[that._hovered ? "setHoveredState" : "setDefaultState"]();
  99759. that._ctx.raiseHoverChanged(that, that._hovered)
  99760. }
  99761. }
  99762. }
  99763. return that
  99764. },
  99765. resetSelected: function() {
  99766. this._selected = false;
  99767. return this
  99768. },
  99769. setSelected: function(state, _noEvent) {
  99770. state = !!state;
  99771. var that = this,
  99772. context = that._ctx,
  99773. selection = that._ctx.selection,
  99774. tmp;
  99775. if (selection && that._selected !== state) {
  99776. that._selected = state;
  99777. tmp = selection.state[selection.single];
  99778. selection.state[selection.single] = null;
  99779. if (tmp)
  99780. tmp.setSelected(false);
  99781. selection.state[selection.single || that._idx] = state ? that : null;
  99782. if (that.item) {
  99783. that.item[state ? "setSelectedState" : that._hovered ? "setHoveredState" : "setDefaultState"]();
  99784. if (!_noEvent)
  99785. context.raiseSelectionChanged(that)
  99786. }
  99787. }
  99788. return that
  99789. }
  99790. };
  99791. function disposeItem(item) {
  99792. _each(item, function(name) {
  99793. item[name] = null
  99794. })
  99795. }
  99796. function createGroups(partition) {
  99797. var i,
  99798. ii,
  99799. groups = null;
  99800. if (_isArray(partition) && partition.length > 1) {
  99801. groups = [];
  99802. for (i = 0, ii = partition.length - 1; i < ii; ++i)
  99803. groups.push({
  99804. start: Number(partition[i]),
  99805. end: Number(partition[i + 1])
  99806. })
  99807. }
  99808. return groups
  99809. }
  99810. function findGroupPosition(value, groups) {
  99811. var i = 0,
  99812. ii = groups.length;
  99813. for (; i < ii; ++i)
  99814. if (groups[i].start <= value && value <= groups[i].end)
  99815. return i;
  99816. return -1
  99817. }
  99818. _extend(DX.viz.map._tests, {
  99819. MapItemsManager: MapItemsManager,
  99820. MapItemHandle: MapItemHandle,
  99821. stubMapItemHandle: function(mapItemHandleType) {
  99822. MapItemHandle = mapItemHandleType
  99823. },
  99824. restoreMapItemHandle: function() {
  99825. MapItemHandle = DX.viz.map._tests.MapItemHandle
  99826. }
  99827. });
  99828. DX.viz.map.dxVectorMap.prototype._factory.MapItemsManager = MapItemsManager
  99829. })(DevExpress, jQuery);
  99830. /*! Module viz-vectormap, file areasManager.js */
  99831. (function(DX, $, undefined) {
  99832. var _abs = Math.abs,
  99833. _sqrt = Math.sqrt,
  99834. _noop = $.noop,
  99835. TOLERANCE = 1;
  99836. var AreasManager = DX.viz.map.dxVectorMap.prototype._factory.MapItemsManager.inherit({
  99837. _rootClass: "dxm-areas",
  99838. _dataCategory: "areas",
  99839. _eventNames: {
  99840. click: "areaClick",
  99841. hoverChanged: "areaHoverChanged",
  99842. selectionChanged: "areaSelectionChanged"
  99843. },
  99844. _initRoot: function() {
  99845. var that = this;
  99846. that.callBase.apply(that, arguments);
  99847. that._context.labelRoot = that._labelRoot = that._params.renderer.g().attr({"class": "dxm-area-labels"})
  99848. },
  99849. _disposeRoot: function() {
  99850. this.callBase.apply(this, arguments);
  99851. this._labelRoot = null
  99852. },
  99853. _processSource: function(source) {
  99854. var isGeoJson = source && source.type === "FeatureCollection";
  99855. this._getItemCoordinates = isGeoJson ? getCoordinatesGeoJson : getCoordinatesDefault;
  99856. this._getItemAttributes = isGeoJson ? getAttributesGeoJson : getAttributesDefault;
  99857. return isGeoJson ? source.features : source
  99858. },
  99859. _getCommonSettings: function(options) {
  99860. return this._params.themeManager.getCommonAreaSettings(options)
  99861. },
  99862. _initProxy: _noop,
  99863. _itemType: "area",
  99864. _removeRoot: function() {
  99865. this.callBase.apply(this, arguments);
  99866. this._labelRoot.remove()
  99867. },
  99868. _appendRoot: function() {
  99869. var that = this;
  99870. that.callBase.apply(that, arguments);
  99871. if (that._commonSettings.label.enabled)
  99872. that._labelRoot.append(that._params.container)
  99873. },
  99874. _clearRoot: function() {
  99875. this.callBase.apply(this, arguments);
  99876. this._labelRoot.clear()
  99877. },
  99878. _getItemSettings: function(_, options) {
  99879. return this._params.themeManager.getAreaSettings(this._commonSettings, options)
  99880. },
  99881. _transform: function(transform) {
  99882. this.callBase.apply(this, arguments);
  99883. this._labelRoot.attr(transform)
  99884. },
  99885. _createItem: function() {
  99886. return new Area
  99887. },
  99888. _updateGrouping: function() {
  99889. var commonSettings = this._commonSettings,
  99890. attributeName = commonSettings.colorGroupingField;
  99891. this._groupByColor(commonSettings.colorGroups, commonSettings.palette, function(proxy) {
  99892. return proxy.attribute(attributeName)
  99893. })
  99894. },
  99895. _arrangeItems: _noop
  99896. });
  99897. function getCoordinatesDefault(dataItem) {
  99898. return dataItem.coordinates
  99899. }
  99900. function getCoordinatesGeoJson(dataItem) {
  99901. var coordinates,
  99902. type;
  99903. if (dataItem.geometry) {
  99904. type = dataItem.geometry.type;
  99905. coordinates = dataItem.geometry.coordinates;
  99906. if (coordinates && (type === "Polygon" || type === "MultiPolygon"))
  99907. type === "MultiPolygon" && (coordinates = [].concat.apply([], coordinates));
  99908. else
  99909. coordinates = undefined
  99910. }
  99911. return coordinates
  99912. }
  99913. function getAttributesDefault(dataItem) {
  99914. return dataItem.attributes
  99915. }
  99916. function getAttributesGeoJson(dataItem) {
  99917. return dataItem.properties
  99918. }
  99919. function Area(){}
  99920. $.extend(Area.prototype, DX.viz.map._internal.mapItemBehavior, {
  99921. _project: function(projection, coords) {
  99922. return projection.projectArea(coords)
  99923. },
  99924. _createRoot: function() {
  99925. return this._ctx.renderer.path([], "area").data(this._ctx.dataKey, this._data)
  99926. },
  99927. _update: function(settings) {
  99928. this._styles = {
  99929. normal: {
  99930. "class": "dxm-area",
  99931. stroke: settings.borderColor,
  99932. "stroke-width": settings.borderWidth,
  99933. fill: settings.color
  99934. },
  99935. hovered: {
  99936. "class": "dxm-area dxm-area-hovered",
  99937. stroke: settings.hoveredBorderColor,
  99938. "stroke-width": settings.hoveredBorderWidth,
  99939. fill: settings.hoveredColor
  99940. },
  99941. selected: {
  99942. "class": "dxm-area dxm-area-selected",
  99943. stroke: settings.selectedBorderColor,
  99944. "stroke-width": settings.selectedBorderWidth,
  99945. fill: settings.selectedColor
  99946. }
  99947. };
  99948. this._root.attr(this._styles.normal);
  99949. return this
  99950. },
  99951. _transform: function(projection, coords) {
  99952. return projection.getAreaCoordinates(coords)
  99953. },
  99954. _locate: function(coords) {
  99955. this._root.attr({points: coords})
  99956. },
  99957. onHover: _noop,
  99958. setDefaultState: function() {
  99959. this._root.attr(this._styles.normal).toBackground()
  99960. },
  99961. setHoveredState: function() {
  99962. this._root.attr(this._styles.hovered).toForeground()
  99963. },
  99964. setSelectedState: function() {
  99965. this._root.attr(this._styles.selected).toForeground()
  99966. },
  99967. _createLabelRoot: function() {
  99968. return this._ctx.renderer.g().attr({"class": "dxm-area-label"}).append(this._ctx.labelRoot)
  99969. },
  99970. _adjustLabel: function() {
  99971. var that = this,
  99972. centroid = calculateAreaCentroid(that._coords),
  99973. bbox = that._label.text.getBBox(),
  99974. offset = -bbox.y - bbox.height / 2;
  99975. that._centroid = centroid.coords;
  99976. that._areaSize = _sqrt(centroid.area);
  99977. that._labelSize = [bbox.width, bbox.height];
  99978. that._label.text.attr({y: offset});
  99979. that._label.tracker.attr({
  99980. x: bbox.x,
  99981. y: bbox.y + offset,
  99982. width: bbox.width,
  99983. height: bbox.height
  99984. })
  99985. },
  99986. _locateLabel: function() {
  99987. var that = this,
  99988. coords = that._ctx.projection.getPointCoordinates(that._centroid),
  99989. size = that._ctx.projection.getSquareSize([that._areaSize, that._areaSize]);
  99990. that._label.root.attr({
  99991. translateX: coords.x,
  99992. translateY: coords.y,
  99993. visibility: that._labelSize[0] / size[0] < TOLERANCE && that._labelSize[1] / size[1] < TOLERANCE ? null : "hidden"
  99994. })
  99995. }
  99996. });
  99997. function calculatePolygonCentroid(coordinates) {
  99998. var i = 0,
  99999. ii = coordinates.length,
  100000. v1,
  100001. v2 = coordinates[ii - 1],
  100002. cross,
  100003. cx = 0,
  100004. cy = 0,
  100005. area = 0;
  100006. for (; i < ii; ++i) {
  100007. v1 = v2;
  100008. v2 = coordinates[i];
  100009. cross = v1[0] * v2[1] - v2[0] * v1[1];
  100010. area += cross;
  100011. cx += (v1[0] + v2[0]) * cross;
  100012. cy += (v1[1] + v2[1]) * cross
  100013. }
  100014. area /= 2;
  100015. cx /= 6 * area;
  100016. cy /= 6 * area;
  100017. return {
  100018. coords: [cx, cy],
  100019. area: _abs(area)
  100020. }
  100021. }
  100022. function calculateAreaCentroid(coordinates) {
  100023. var i = 0,
  100024. ii = coordinates.length,
  100025. centroid,
  100026. resultCentroid,
  100027. maxArea = 0;
  100028. for (; i < ii; ++i) {
  100029. centroid = calculatePolygonCentroid(coordinates[i]);
  100030. if (centroid.area > maxArea) {
  100031. maxArea = centroid.area;
  100032. resultCentroid = centroid
  100033. }
  100034. }
  100035. return resultCentroid
  100036. }
  100037. DX.viz.map._internal.AreasManager = AreasManager;
  100038. DX.viz.map._internal.Area = Area;
  100039. DX.viz.map._tests.AreasManager = AreasManager;
  100040. DX.viz.map._tests.Area = Area;
  100041. DX.viz.map.dxVectorMap.prototype._factory.createAreasManager = function(parameters) {
  100042. return new AreasManager(parameters)
  100043. }
  100044. })(DevExpress, jQuery);
  100045. /*! Module viz-vectormap, file markersManager.js */
  100046. (function(DX, $, undefined) {
  100047. var _Number = Number,
  100048. _String = String,
  100049. _isFinite = isFinite,
  100050. _math = Math,
  100051. _round = _math.round,
  100052. _max = _math.max,
  100053. _min = _math.min,
  100054. _extend = $.extend,
  100055. _each = $.each,
  100056. _isArray = DX.utils.isArray,
  100057. CLASS_DEFAULT = "dxm-marker",
  100058. CLASS_HOVERED = "dxm-marker dxm-marker-hovered",
  100059. CLASS_SELECTED = "dxm-marker dxm-marker-selected",
  100060. DOT = "dot",
  100061. BUBBLE = "bubble",
  100062. PIE = "pie",
  100063. IMAGE = "image",
  100064. DEFAULT_MARKER_TYPE = null,
  100065. MARKER_TYPES = {};
  100066. var MarkersManager = DX.viz.map.dxVectorMap.prototype._factory.MapItemsManager.inherit({
  100067. _rootClass: "dxm-markers",
  100068. _dataCategory: "markers",
  100069. _eventNames: {
  100070. click: "markerClick",
  100071. hoverChanged: "markerHoverChanged",
  100072. selectionChanged: "markerSelectionChanged"
  100073. },
  100074. _init: function() {
  100075. var that = this;
  100076. that.callBase.apply(that, arguments);
  100077. that._context.getPieColors = function(count) {
  100078. return that._params.themeManager.getPieColors(that._commonSettings, count)
  100079. };
  100080. that._filter = that._params.renderer.shadowFilter("-40%", "-40%", "180%", "200%", 0, 1, 1, "#000000", 0.2)
  100081. },
  100082. _dispose: function() {
  100083. this.callBase.apply(this, arguments);
  100084. this._filter.dispose();
  100085. this._filter = null
  100086. },
  100087. _getItemCoordinates: function(dataItem) {
  100088. return dataItem.coordinates
  100089. },
  100090. _getItemAttributes: function(dataItem) {
  100091. return dataItem.attributes
  100092. },
  100093. _processSource: function(source) {
  100094. return source
  100095. },
  100096. _getCommonSettings: function(options) {
  100097. return this._params.themeManager.getCommonMarkerSettings(options)
  100098. },
  100099. _processOptions: function(options) {
  100100. var that = this;
  100101. that._commonType = parseMarkerType(options && options.type, DEFAULT_MARKER_TYPE);
  100102. that.callBase.apply(that, arguments);
  100103. that._commonSettings._filter = that._filter.ref
  100104. },
  100105. _arrangeBubbles: function() {
  100106. var markers = this._handles,
  100107. bubbles = [],
  100108. i,
  100109. ii = markers.length,
  100110. marker,
  100111. values = [],
  100112. minValue,
  100113. maxValue,
  100114. deltaValue;
  100115. if (this._commonSettings._bubble.sizeGroups)
  100116. return;
  100117. for (i = 0; i < ii; ++i) {
  100118. marker = markers[i];
  100119. if (marker.item.type === BUBBLE) {
  100120. bubbles.push(marker);
  100121. if (_isFinite(marker.proxy.value))
  100122. values.push(marker.proxy.value)
  100123. }
  100124. }
  100125. minValue = _min.apply(null, values);
  100126. maxValue = _max.apply(null, values);
  100127. deltaValue = maxValue - minValue || 1;
  100128. for (i = 0, ii = bubbles.length; i < ii; ++i) {
  100129. marker = bubbles[i];
  100130. marker.item.setSize(_isFinite(marker.proxy.value) ? (marker.proxy.value - minValue) / deltaValue : 0)
  100131. }
  100132. },
  100133. _itemType: "marker",
  100134. _initProxy: function(proxy, dataItem) {
  100135. _each(dataItem, function(name, value) {
  100136. if (proxy[name] === undefined)
  100137. proxy[name] = value
  100138. });
  100139. proxy._TYPE = parseMarkerType(dataItem.type, null)
  100140. },
  100141. _getItemSettings: function(proxy, options) {
  100142. var type = proxy._TYPE || this._commonType,
  100143. settings = this._params.themeManager.getMarkerSettings(this._commonSettings, _extend({}, proxy.style, options), type);
  100144. proxy.text = proxy.text || settings.text;
  100145. return settings
  100146. },
  100147. _createItem: function(proxy) {
  100148. return new MARKER_TYPES[proxy._TYPE || this._commonType]
  100149. },
  100150. _updateGrouping: function() {
  100151. var that = this,
  100152. markerType = that._commonType,
  100153. colorDataField,
  100154. sizeDataField,
  100155. commonSettings = that._commonSettings["_" + markerType];
  100156. if (markerType === DOT || markerType === BUBBLE) {
  100157. colorDataField = commonSettings.colorGroupingField;
  100158. that._groupByColor(commonSettings.colorGroups, commonSettings.palette, function(proxy) {
  100159. return !proxy._TYPE || proxy._TYPE === markerType ? proxy.attribute(colorDataField) : NaN
  100160. })
  100161. }
  100162. sizeDataField = commonSettings.sizeGroupingField;
  100163. that._performGrouping(commonSettings.sizeGroups, "size", function(proxy) {
  100164. return !proxy._TYPE || proxy._TYPE === markerType ? proxy.value || proxy.attribute(sizeDataField) : NaN
  100165. }, function(count) {
  100166. var minSize = commonSettings.minSize > 0 ? _Number(commonSettings.minSize) : 0,
  100167. maxSize = commonSettings.maxSize >= minSize ? _Number(commonSettings.maxSize) : 0,
  100168. i = 0,
  100169. sizes = [];
  100170. for (i = 0; i < count; ++i)
  100171. sizes.push((minSize * (count - i - 1) + maxSize * i) / (count - 1));
  100172. return sizes
  100173. })
  100174. },
  100175. _updateLegendForPies: function() {
  100176. var count = 0;
  100177. _each(this._handles, function(_, handle) {
  100178. var proxy = handle.proxy,
  100179. values;
  100180. if (!proxy._TYPE || proxy._TYPE === PIE) {
  100181. values = proxy.values;
  100182. if (values && values.length > count)
  100183. count = values.length
  100184. }
  100185. });
  100186. if (count > 0)
  100187. this._params.dataExchanger.set(this._dataCategory, "color", $.map(this._context.getPieColors(count).slice(0, count), function(color, i) {
  100188. return {
  100189. index: i,
  100190. color: color
  100191. }
  100192. }))
  100193. },
  100194. _arrangeItems: function() {
  100195. this._arrangeBubbles();
  100196. this._updateLegendForPies()
  100197. }
  100198. });
  100199. var baseMarkerBehavior = _extend({}, DX.viz.map._internal.mapItemBehavior, {
  100200. _project: function(projection, coords) {
  100201. return projection.projectPoint(coords)
  100202. },
  100203. _createRoot: function() {
  100204. return this._ctx.renderer.g()
  100205. },
  100206. _update: function(settings) {
  100207. var that = this;
  100208. that._root.attr({"class": CLASS_DEFAULT}).clear();
  100209. that._create(settings, that._ctx.renderer, that._root);
  100210. return that
  100211. },
  100212. _transform: function(projection, coords) {
  100213. return projection.getPointCoordinates(coords)
  100214. },
  100215. _locate: function(coords) {
  100216. this._root.attr({
  100217. translateX: coords.x,
  100218. translateY: coords.y
  100219. })
  100220. },
  100221. onHover: function() {
  100222. this._root.toForeground()
  100223. },
  100224. setDefaultState: function() {
  100225. this._root.attr({"class": CLASS_DEFAULT}).toBackground();
  100226. this._applyDefault()
  100227. },
  100228. setHoveredState: function() {
  100229. this._root.attr({"class": CLASS_HOVERED});
  100230. this._applyHovered()
  100231. },
  100232. setSelectedState: function() {
  100233. this._root.attr({"class": CLASS_SELECTED}).toForeground();
  100234. this._applySelected()
  100235. },
  100236. _createLabelRoot: function() {
  100237. return this._root
  100238. },
  100239. _adjustLabel: function() {
  100240. var bbox = this._label.text.getBBox(),
  100241. x = _round(-bbox.x + this._size / 2) + 2,
  100242. y = _round(-bbox.y - bbox.height / 2) - 1;
  100243. this._label.text.attr({
  100244. x: x,
  100245. y: y
  100246. });
  100247. this._label.tracker.attr({
  100248. x: x + bbox.x - 1,
  100249. y: y + bbox.y - 1,
  100250. width: bbox.width + 2,
  100251. height: bbox.height + 2
  100252. })
  100253. },
  100254. _locateLabel: $.noop
  100255. });
  100256. function DotMarker(){}
  100257. _extend(DotMarker.prototype, baseMarkerBehavior, {
  100258. type: DOT,
  100259. _create: function(style, renderer, root) {
  100260. var that = this,
  100261. size = that._size = style.size > 0 ? _Number(style.size) : 0,
  100262. hoveredSize = size,
  100263. selectedSize = size + (style.selectedStep > 0 ? _Number(style.selectedStep) : 0),
  100264. hoveredBackSize = hoveredSize + (style.backStep > 0 ? _Number(style.backStep) : 0),
  100265. selectedBackSize = selectedSize + (style.backStep > 0 ? _Number(style.backStep) : 0),
  100266. r = size / 2;
  100267. that._dotDefault = {
  100268. cx: 0,
  100269. cy: 0,
  100270. r: r,
  100271. stroke: style.borderColor,
  100272. "stroke-width": style.borderWidth,
  100273. fill: style.color,
  100274. filter: style.shadow ? style._filter : null
  100275. };
  100276. that._dotHovered = {
  100277. cx: 0,
  100278. cy: 0,
  100279. r: hoveredSize / 2,
  100280. stroke: style.hoveredBorderColor,
  100281. "stroke-width": style.hoveredBorderWidth,
  100282. fill: style.hoveredColor
  100283. };
  100284. that._dotSelected = {
  100285. cx: 0,
  100286. cy: 0,
  100287. r: selectedSize / 2,
  100288. stroke: style.selectedBorderColor,
  100289. "stroke-width": style.selectedBorderWidth,
  100290. fill: style.selectedColor
  100291. };
  100292. that._backDefault = {
  100293. cx: 0,
  100294. cy: 0,
  100295. r: r,
  100296. stroke: "none",
  100297. "stroke-width": 0,
  100298. fill: style.backColor,
  100299. opacity: style.backOpacity
  100300. };
  100301. that._backHovered = {
  100302. cx: 0,
  100303. cy: 0,
  100304. r: hoveredBackSize / 2,
  100305. stroke: "none",
  100306. "stroke-width": 0,
  100307. fill: style.backColor,
  100308. opacity: style.backOpacity
  100309. };
  100310. that._backSelected = {
  100311. cx: 0,
  100312. cy: 0,
  100313. r: selectedBackSize / 2,
  100314. stroke: "none",
  100315. "stroke-width": 0,
  100316. fill: style.backColor,
  100317. opacity: style.backOpacity
  100318. };
  100319. that._back = renderer.circle().sharp().attr(that._backDefault).data(that._ctx.dataKey, that._data).append(root);
  100320. that._dot = renderer.circle().sharp().attr(that._dotDefault).data(that._ctx.dataKey, that._data).append(root)
  100321. },
  100322. _destroy: function() {
  100323. this._back = this._dot = null
  100324. },
  100325. _applyDefault: function() {
  100326. this._back.attr(this._backDefault);
  100327. this._dot.attr(this._dotDefault)
  100328. },
  100329. _applyHovered: function() {
  100330. this._back.attr(this._backHovered);
  100331. this._dot.attr(this._dotHovered)
  100332. },
  100333. _applySelected: function() {
  100334. this._back.attr(this._backSelected);
  100335. this._dot.attr(this._dotSelected)
  100336. }
  100337. });
  100338. function BubbleMarker(){}
  100339. _extend(BubbleMarker.prototype, baseMarkerBehavior, {
  100340. type: BUBBLE,
  100341. _create: function(style, renderer, root) {
  100342. var that = this;
  100343. that._minSize = style.minSize > 0 ? _Number(style.minSize) : 0;
  100344. that._maxSize = style.maxSize > that._minSize ? _Number(style.maxSize) : that._minSize;
  100345. that.value = _isFinite(that._proxy.value) ? _Number(that._proxy.value) : null;
  100346. that._default = {
  100347. stroke: style.borderColor,
  100348. "stroke-width": style.borderWidth,
  100349. fill: style.color,
  100350. opacity: style.opacity
  100351. };
  100352. that._hovered = {
  100353. stroke: style.hoveredBorderColor,
  100354. "stroke-width": style.hoveredBorderWidth,
  100355. fill: style.hoveredColor,
  100356. opacity: style.hoveredOpacity
  100357. };
  100358. that._selected = {
  100359. stroke: style.selectedBorderColor,
  100360. "stroke-width": style.selectedBorderWidth,
  100361. fill: style.selectedColor,
  100362. opacity: style.selectedOpacity
  100363. };
  100364. that._bubble = renderer.circle(0, 0, 0).sharp().attr(that._default).data(that._ctx.dataKey, that._data).append(root);
  100365. that.setSize(style.size / that._maxSize || 1)
  100366. },
  100367. _applyDefault: function() {
  100368. this._bubble.attr(this._default)
  100369. },
  100370. _applyHovered: function() {
  100371. this._bubble.attr(this._hovered)
  100372. },
  100373. _applySelected: function() {
  100374. this._bubble.attr(this._selected)
  100375. },
  100376. setSize: function(ratio) {
  100377. var that = this,
  100378. r = (that._minSize + ratio * (that._maxSize - that._minSize)) / 2;
  100379. that._default.r = that._hovered.r = that._selected.r = r;
  100380. that._size = 2 * r;
  100381. that._bubble.attr({r: r});
  100382. return that
  100383. }
  100384. });
  100385. function PieMarker(){}
  100386. _extend(PieMarker.prototype, baseMarkerBehavior, {
  100387. type: PIE,
  100388. _create: function(style, renderer, root) {
  100389. var that = this,
  100390. r = (style.size > 0 ? _Number(style.size) : 0) / 2,
  100391. srcValues,
  100392. i = 0,
  100393. ii,
  100394. values,
  100395. value,
  100396. sum = 0,
  100397. translator,
  100398. startAngle,
  100399. endAngle,
  100400. colors;
  100401. that._size = 2 * r;
  100402. that._pieDefault = {opacity: style.opacity};
  100403. that._pieHovered = {opacity: style.hoveredOpacity};
  100404. that._pieSelected = {opacity: style.selectedOpacity};
  100405. that._borderDefault = {
  100406. stroke: style.borderColor,
  100407. "stroke-width": style.borderWidth
  100408. };
  100409. that._borderHovered = {
  100410. stroke: style.hoveredBorderColor,
  100411. "stroke-width": style.hoveredBorderWidth
  100412. };
  100413. that._borderSelected = {
  100414. stroke: style.selectedBorderColor,
  100415. "stroke-width": style.selectedBorderWidth
  100416. };
  100417. srcValues = that._proxy.values;
  100418. ii = _isArray(srcValues) ? srcValues.length : 0;
  100419. values = [];
  100420. for (; i < ii; ++i) {
  100421. value = _Number(srcValues[i]);
  100422. if (_isFinite(value)) {
  100423. values.push(value);
  100424. sum += value
  100425. }
  100426. }
  100427. that._pie = renderer.g().attr(that._pieDefault);
  100428. translator = new DX.viz.core.Translator1D(0, sum, 90, 450);
  100429. startAngle = translator.translate(0);
  100430. colors = that._ctx.getPieColors(values.length);
  100431. for (value = 0, i = 0, ii = values.length; i < ii; ++i) {
  100432. value += values[i];
  100433. endAngle = translator.translate(value);
  100434. renderer.arc(0, 0, 0, r, startAngle, endAngle).attr({
  100435. "stroke-linejoin": "round",
  100436. fill: colors[i]
  100437. }).data(that._ctx.dataKey, that._data).append(that._pie);
  100438. startAngle = endAngle
  100439. }
  100440. that._pie.append(root);
  100441. that._border = renderer.circle(0, 0, r).sharp().attr(that._borderDefault).data(that._ctx.dataKey, that._data).append(root)
  100442. },
  100443. _applyDefault: function() {
  100444. this._pie.attr(this._pieDefault);
  100445. this._border.attr(this._borderDefault)
  100446. },
  100447. _applyHovered: function() {
  100448. this._pie.attr(this._pieHovered);
  100449. this._border.attr(this._borderHovered)
  100450. },
  100451. _applySelected: function() {
  100452. this._pie.attr(this._pieSelected);
  100453. this._border.attr(this._borderSelected)
  100454. }
  100455. });
  100456. function ImageMarker(){}
  100457. _extend(ImageMarker.prototype, baseMarkerBehavior, {
  100458. type: IMAGE,
  100459. _create: function(style, renderer, root) {
  100460. var that = this,
  100461. size = that._size = style.size > 0 ? _Number(style.size) : 0,
  100462. hoveredSize = size + (style.hoveredStep > 0 ? _Number(style.hoveredStep) : 0),
  100463. selectedSize = size + (style.selectedStep > 0 ? _Number(style.selectedStep) : 0);
  100464. that._default = {
  100465. x: -size / 2,
  100466. y: -size / 2,
  100467. width: size,
  100468. height: size
  100469. };
  100470. that._hovered = {
  100471. x: -hoveredSize / 2,
  100472. y: -hoveredSize / 2,
  100473. width: hoveredSize,
  100474. height: hoveredSize
  100475. };
  100476. that._selected = {
  100477. x: -selectedSize / 2,
  100478. y: -selectedSize / 2,
  100479. width: selectedSize,
  100480. height: selectedSize
  100481. };
  100482. that._image = renderer.image().attr(that._default).attr({
  100483. href: that._proxy.url,
  100484. location: "center"
  100485. }).append(root);
  100486. that._tracker = renderer.rect().attr(that._default).attr({
  100487. stroke: "none",
  100488. "stroke-width": 0,
  100489. fill: "#000000",
  100490. opacity: 0.0001
  100491. }).data(that._ctx.dataKey, that._data).append(root)
  100492. },
  100493. _applyDefault: function() {
  100494. this._image.attr(this._default);
  100495. this._tracker.attr(this._default)
  100496. },
  100497. _applyHovered: function() {
  100498. this._image.attr(this._hovered);
  100499. this._tracker.attr(this._hovered)
  100500. },
  100501. _applySelected: function() {
  100502. this._image.attr(this._selected);
  100503. this._tracker.attr(this._selected)
  100504. }
  100505. });
  100506. _each([DotMarker, BubbleMarker, PieMarker, ImageMarker], function(_, markerType) {
  100507. DEFAULT_MARKER_TYPE = DEFAULT_MARKER_TYPE || markerType.prototype.type;
  100508. MARKER_TYPES[markerType.prototype.type] = markerType
  100509. });
  100510. function parseMarkerType(type, defaultType) {
  100511. var _type = _String(type).toLowerCase();
  100512. return MARKER_TYPES[_type] ? _type : defaultType
  100513. }
  100514. var __originalDefaultMarkerType = DEFAULT_MARKER_TYPE,
  100515. __originalMarkerTypes = _extend({}, MARKER_TYPES);
  100516. DX.viz.map._tests.stubMarkerTypes = function(markerTypes, defaultMarkerType) {
  100517. DEFAULT_MARKER_TYPE = defaultMarkerType;
  100518. MARKER_TYPES = markerTypes
  100519. };
  100520. DX.viz.map._tests.restoreMarkerTypes = function() {
  100521. DEFAULT_MARKER_TYPE = __originalDefaultMarkerType;
  100522. MARKER_TYPES = __originalMarkerTypes
  100523. };
  100524. DX.viz.map._tests.baseMarkerBehavior = baseMarkerBehavior;
  100525. DX.viz.map._tests.MarkersManager = MarkersManager;
  100526. DX.viz.map._tests.DotMarker = DotMarker;
  100527. DX.viz.map._tests.BubbleMarker = BubbleMarker;
  100528. DX.viz.map._tests.PieMarker = PieMarker;
  100529. DX.viz.map._tests.ImageMarker = ImageMarker;
  100530. DX.viz.map.dxVectorMap.prototype._factory.createMarkersManager = function(parameters) {
  100531. return new MarkersManager(parameters)
  100532. }
  100533. })(DevExpress, jQuery);
  100534. DevExpress.MOD_VIZ_VECTORMAP = true
  100535. }
  100536. if (!DevExpress.MOD_VIZ_SPARKLINES) {
  100537. if (!DevExpress.MOD_VIZ_CORE)
  100538. throw Error('Required module is not referenced: viz-core');
  100539. /*! Module viz-sparklines, file baseSparkline.js */
  100540. (function($, DX, undefined) {
  100541. var DEFAULT_LINE_SPACING = 2,
  100542. DEFAULT_EVENTS_DELAY = 200,
  100543. TOUCH_EVENTS_DELAY = 1000,
  100544. _extend = $.extend,
  100545. _abs = Math.abs,
  100546. core = DX.viz.core;
  100547. function generateDefaultCustomizeTooltipCallback(fontOptions, rtlEnabled) {
  100548. var lineSpacing = fontOptions.lineSpacing,
  100549. lineHeight = (lineSpacing !== undefined && lineSpacing !== null ? lineSpacing : DEFAULT_LINE_SPACING) + fontOptions.size;
  100550. DX.viz.sparklines.generated_customize_tooltip = function() {
  100551. return {
  100552. lineHeight: lineHeight,
  100553. rtlEnabled: rtlEnabled
  100554. }
  100555. };
  100556. return function(customizeObject) {
  100557. var html = "",
  100558. vt = customizeObject.valueText;
  100559. for (var i = 0; i < vt.length; i += 2)
  100560. html += "<tr><td>" + vt[i] + "</td><td style='width: 15px'></td><td style='text-align: " + (rtlEnabled ? "left" : "right") + "'>" + vt[i + 1] + "</td></tr>";
  100561. return {html: "<table style='border-spacing:0px; line-height: " + lineHeight + "px'>" + html + "</table>"}
  100562. }
  100563. }
  100564. DX.viz.sparklines = {};
  100565. DX.viz.sparklines.BaseSparkline = core.BaseWidget.inherit({
  100566. _setDeprecatedOptions: function() {
  100567. this.callBase();
  100568. $.extend(this._deprecatedOptions, {
  100569. "tooltip.verticalAlignment": {
  100570. since: "15.1",
  100571. message: "Now tootips are aligned automatically"
  100572. },
  100573. "tooltip.horizontalAlignment": {
  100574. since: "15.1",
  100575. message: "Now tootips are aligned automatically"
  100576. }
  100577. })
  100578. },
  100579. _clean: function() {
  100580. var that = this;
  100581. if (that._tooltipShown) {
  100582. that._tooltipShown = false;
  100583. that._tooltip.hide()
  100584. }
  100585. that._cleanWidgetElements();
  100586. that._cleanTranslators()
  100587. },
  100588. _initCore: function() {
  100589. var that = this;
  100590. that._tooltipTracker = that._renderer.root;
  100591. that._tooltipTracker.attr({"pointer-events": "visible"});
  100592. that._createHtmlElements();
  100593. that._initTooltipEvents()
  100594. },
  100595. _initTooltip: function() {
  100596. this._initTooltipBase = this.callBase;
  100597. return
  100598. },
  100599. _getDefaultSize: function() {
  100600. return this._defaultSize
  100601. },
  100602. _isContainerVisible: function() {
  100603. return true
  100604. },
  100605. _disposeCore: function() {
  100606. this._disposeWidgetElements();
  100607. this._disposeTooltipEvents();
  100608. this._ranges = null
  100609. },
  100610. _render: function() {
  100611. this._prepareOptions();
  100612. this._updateWidgetElements();
  100613. this._drawWidgetElements()
  100614. },
  100615. _updateWidgetElements: function() {
  100616. this._updateRange();
  100617. this._updateTranslator()
  100618. },
  100619. _applySize: function() {
  100620. if (this._allOptions)
  100621. this._allOptions.size = {
  100622. width: this._canvas.width,
  100623. height: this._canvas.height
  100624. }
  100625. },
  100626. _cleanTranslators: function() {
  100627. this._translatorX = null;
  100628. this._translatorY = null
  100629. },
  100630. _setupResizeHandler: $.noop,
  100631. _resize: function() {
  100632. var that = this;
  100633. that._redrawWidgetElements();
  100634. if (that._tooltipShown) {
  100635. that._tooltipShown = false;
  100636. that._tooltip.hide()
  100637. }
  100638. that._drawn()
  100639. },
  100640. _prepareOptions: function() {
  100641. return _extend(true, {}, this._themeManager.theme(), this.option())
  100642. },
  100643. _createThemeManager: function() {
  100644. var themeManager = new DX.viz.core.BaseThemeManager;
  100645. themeManager._themeSection = this._widgetType;
  100646. themeManager._fontFields = ["tooltip.font"];
  100647. return themeManager
  100648. },
  100649. _getTooltipCoords: function() {
  100650. var canvas = this._canvas,
  100651. rootOffset = this._renderer.getRootOffset();
  100652. return {
  100653. x: canvas.width / 2 + rootOffset.left,
  100654. y: canvas.height / 2 + rootOffset.top
  100655. }
  100656. },
  100657. _initTooltipEvents: function() {
  100658. var that = this,
  100659. data = {widget: that};
  100660. that._showTooltipCallback = function() {
  100661. var tooltip;
  100662. that._showTooltipTimeout = null;
  100663. if (!that._tooltipShown) {
  100664. that._tooltipShown = true;
  100665. tooltip = that._getTooltip();
  100666. tooltip.isEnabled() && that._tooltip.show(that._getTooltipData(), that._getTooltipCoords(), {})
  100667. }
  100668. that._DEBUG_showCallback && that._DEBUG_showCallback()
  100669. };
  100670. that._hideTooltipCallback = function() {
  100671. var tooltipWasShown = that._tooltipShown;
  100672. that._hideTooltipTimeout = null;
  100673. if (that._tooltipShown) {
  100674. that._tooltipShown = false;
  100675. that._tooltip.hide()
  100676. }
  100677. that._DEBUG_hideCallback && that._DEBUG_hideCallback(tooltipWasShown)
  100678. };
  100679. that._disposeCallbacks = function() {
  100680. that = that._showTooltipCallback = that._hideTooltipCallback = that._disposeCallbacks = null
  100681. };
  100682. that._tooltipTracker.on(mouseEvents, data).on(touchEvents, data).on(mouseWheelEvents, data);
  100683. that._tooltipTracker.on(menuEvents)
  100684. },
  100685. _disposeTooltipEvents: function() {
  100686. var that = this;
  100687. clearTimeout(that._showTooltipTimeout);
  100688. clearTimeout(that._hideTooltipTimeout);
  100689. that._tooltipTracker.off();
  100690. that._disposeCallbacks()
  100691. },
  100692. _updateTranslator: function() {
  100693. var that = this,
  100694. canvas = this._canvas,
  100695. ranges = this._ranges;
  100696. that._translatorX = new core.Translator2D(ranges.arg, canvas, {direction: "horizontal"});
  100697. that._translatorY = new core.Translator2D(ranges.val, canvas)
  100698. },
  100699. _getTooltip: function() {
  100700. var that = this;
  100701. if (!that._tooltip) {
  100702. that._initTooltipBase();
  100703. that._setTooltipRendererOptions(that._tooltipRendererOptions);
  100704. that._tooltipRendererOptions = null;
  100705. that._setTooltipOptions()
  100706. }
  100707. return that._tooltip
  100708. },
  100709. _setTooltipRendererOptions: function(options) {
  100710. if (this._tooltip)
  100711. this._tooltip.setRendererOptions(options);
  100712. else
  100713. this._tooltipRendererOptions = options
  100714. },
  100715. _setTooltipOptions: function() {
  100716. var tooltip = this._tooltip,
  100717. options = tooltip && this._getOption("tooltip");
  100718. tooltip && tooltip.update($.extend({}, options, {
  100719. customizeTooltip: !$.isFunction(options.customizeTooltip) ? generateDefaultCustomizeTooltipCallback(options.font, this.option("rtlEnabled")) : options.customizeTooltip,
  100720. enabled: options.enabled && this._isTooltipEnabled()
  100721. }))
  100722. },
  100723. _showTooltip: function(delay) {
  100724. var that = this;
  100725. ++that._DEBUG_clearHideTooltipTimeout;
  100726. clearTimeout(that._hideTooltipTimeout);
  100727. that._hideTooltipTimeout = null;
  100728. clearTimeout(that._showTooltipTimeout);
  100729. ++that._DEBUG_showTooltipTimeoutSet;
  100730. that._showTooltipTimeout = setTimeout(that._showTooltipCallback, delay)
  100731. },
  100732. _hideTooltip: function(delay) {
  100733. var that = this;
  100734. ++that._DEBUG_clearShowTooltipTimeout;
  100735. clearTimeout(that._showTooltipTimeout);
  100736. that._showTooltipTimeout = null;
  100737. clearTimeout(that._hideTooltipTimeout);
  100738. if (delay) {
  100739. ++that._DEBUG_hideTooltipTimeoutSet;
  100740. that._hideTooltipTimeout = setTimeout(that._hideTooltipCallback, delay)
  100741. }
  100742. else
  100743. that._hideTooltipCallback()
  100744. },
  100745. _initLoadingIndicator: $.noop,
  100746. _disposeLoadingIndicator: $.noop,
  100747. _handleLoadingIndicatorOptionChanged: $.noop,
  100748. showLoadingIndicator: $.noop,
  100749. hideLoadingIndicator: $.noop
  100750. });
  100751. var menuEvents = {
  100752. "contextmenu.sparkline-tooltip": function(event) {
  100753. if (DX.ui.events.isTouchEvent(event) || DX.ui.events.isPointerEvent(event))
  100754. event.preventDefault()
  100755. },
  100756. "MSHoldVisual.sparkline-tooltip": function(event) {
  100757. event.preventDefault()
  100758. }
  100759. };
  100760. var mouseEvents = {
  100761. "mouseover.sparkline-tooltip": function(event) {
  100762. isPointerDownCalled = false;
  100763. var widget = event.data.widget;
  100764. widget._x = event.pageX;
  100765. widget._y = event.pageY;
  100766. widget._tooltipTracker.off(mouseMoveEvents).on(mouseMoveEvents, event.data);
  100767. widget._showTooltip(DEFAULT_EVENTS_DELAY)
  100768. },
  100769. "mouseout.sparkline-tooltip": function(event) {
  100770. if (isPointerDownCalled)
  100771. return;
  100772. var widget = event.data.widget;
  100773. widget._tooltipTracker.off(mouseMoveEvents);
  100774. widget._hideTooltip(DEFAULT_EVENTS_DELAY)
  100775. }
  100776. };
  100777. var mouseWheelEvents = {"dxmousewheel.sparkline-tooltip": function(event) {
  100778. event.data.widget._hideTooltip()
  100779. }};
  100780. var mouseMoveEvents = {"mousemove.sparkline-tooltip": function(event) {
  100781. var widget = event.data.widget;
  100782. if (widget._showTooltipTimeout && (_abs(widget._x - event.pageX) > 3 || _abs(widget._y - event.pageY) > 3)) {
  100783. widget._x = event.pageX;
  100784. widget._y = event.pageY;
  100785. widget._showTooltip(DEFAULT_EVENTS_DELAY)
  100786. }
  100787. }};
  100788. var active_touch_tooltip_widget = null,
  100789. touchstartTooltipProcessing = function(event) {
  100790. event.preventDefault();
  100791. var widget = active_touch_tooltip_widget;
  100792. if (widget && widget !== event.data.widget)
  100793. widget._hideTooltip(DEFAULT_EVENTS_DELAY);
  100794. widget = active_touch_tooltip_widget = event.data.widget;
  100795. widget._showTooltip(TOUCH_EVENTS_DELAY);
  100796. widget._touch = true
  100797. },
  100798. touchstartDocumentProcessing = function() {
  100799. var widget = active_touch_tooltip_widget;
  100800. if (widget) {
  100801. if (!widget._touch) {
  100802. widget._hideTooltip(DEFAULT_EVENTS_DELAY);
  100803. active_touch_tooltip_widget = null
  100804. }
  100805. widget._touch = null
  100806. }
  100807. },
  100808. touchendDocumentProcessing = function() {
  100809. var widget = active_touch_tooltip_widget;
  100810. if (widget)
  100811. if (widget._showTooltipTimeout) {
  100812. widget._hideTooltip(DEFAULT_EVENTS_DELAY);
  100813. active_touch_tooltip_widget = null
  100814. }
  100815. },
  100816. isPointerDownCalled = false;
  100817. var touchEvents = {
  100818. "pointerdown.sparkline-tooltip": touchstartTooltipProcessing,
  100819. "touchstart.sparkline-tooltip": touchstartTooltipProcessing
  100820. };
  100821. $(document).on({
  100822. "pointerdown.sparkline-tooltip": function() {
  100823. isPointerDownCalled = true;
  100824. touchstartDocumentProcessing()
  100825. },
  100826. "touchstart.sparkline-tooltip": touchstartDocumentProcessing,
  100827. "pointerup.sparkline-tooltip": touchendDocumentProcessing,
  100828. "touchend.sparkline-tooltip": touchendDocumentProcessing
  100829. });
  100830. DX.viz.sparklines.BaseSparkline._DEBUG_reset = function() {
  100831. active_touch_tooltip_widget = null
  100832. }
  100833. })(jQuery, DevExpress);
  100834. /*! Module viz-sparklines, file sparkline.js */
  100835. (function($, DX, undefined) {
  100836. var viz = DX.viz,
  100837. core = viz.core,
  100838. MIN_BAR_WIDTH = 1,
  100839. MAX_BAR_WIDTH = 50,
  100840. DEFAULT_BAR_INTERVAL = 4,
  100841. DEFAULT_CANVAS_WIDTH = 250,
  100842. DEFAULT_CANVAS_HEIGHT = 30,
  100843. DEFAULT_HORIZONTAL_MARGIN = 5,
  100844. DEFAULT_VERTICAL_MARGIN = 3,
  100845. ALLOWED_TYPES = {
  100846. line: true,
  100847. spline: true,
  100848. stepline: true,
  100849. area: true,
  100850. steparea: true,
  100851. splinearea: true,
  100852. bar: true,
  100853. winloss: true
  100854. },
  100855. _map = $.map,
  100856. _math = Math,
  100857. _abs = _math.abs,
  100858. _round = _math.round,
  100859. _max = _math.max,
  100860. _min = _math.min,
  100861. _isFinite = isFinite,
  100862. _isDefined = DX.utils.isDefined,
  100863. _Number = Number,
  100864. _String = String;
  100865. DX.registerComponent("dxSparkline", viz.sparklines, viz.sparklines.BaseSparkline.inherit({
  100866. _rootClassPrefix: "dxsl",
  100867. _rootClass: "dxsl-sparkline",
  100868. _widgetType: "sparkline",
  100869. _defaultSize: {
  100870. width: DEFAULT_CANVAS_WIDTH,
  100871. height: DEFAULT_CANVAS_HEIGHT,
  100872. left: DEFAULT_HORIZONTAL_MARGIN,
  100873. right: DEFAULT_HORIZONTAL_MARGIN,
  100874. top: DEFAULT_VERTICAL_MARGIN,
  100875. bottom: DEFAULT_VERTICAL_MARGIN
  100876. },
  100877. _initCore: function() {
  100878. this.callBase();
  100879. this._refreshDataSource();
  100880. this._createSeries()
  100881. },
  100882. _dataSourceChangedHandler: function() {
  100883. if (this._initialized) {
  100884. this._clean();
  100885. this._updateWidgetElements();
  100886. this._drawWidgetElements()
  100887. }
  100888. },
  100889. _updateWidgetElements: function() {
  100890. this._updateSeries();
  100891. this.callBase()
  100892. },
  100893. _dataSourceOptions: function() {
  100894. return {paginate: false}
  100895. },
  100896. _redrawWidgetElements: function() {
  100897. this._updateTranslator();
  100898. this._correctPoints();
  100899. this._series.draw({
  100900. x: this._translatorX,
  100901. y: this._translatorY
  100902. });
  100903. this._seriesGroup.append(this._renderer.root)
  100904. },
  100905. _disposeWidgetElements: function() {
  100906. var that = this;
  100907. delete that._seriesGroup;
  100908. delete that._seriesLabelGroup;
  100909. that._series && that._series.dispose();
  100910. that._series = null
  100911. },
  100912. _cleanWidgetElements: function() {
  100913. this._seriesGroup.remove();
  100914. this._seriesLabelGroup.remove();
  100915. this._seriesGroup.clear();
  100916. this._seriesLabelGroup.clear()
  100917. },
  100918. _drawWidgetElements: function() {
  100919. if (this._isDataSourceReady()) {
  100920. this._drawSeries();
  100921. this._drawn()
  100922. }
  100923. },
  100924. _prepareOptions: function() {
  100925. this._allOptions = this.callBase();
  100926. this._allOptions.type = _String(this._allOptions.type).toLowerCase();
  100927. if (!ALLOWED_TYPES[this._allOptions.type])
  100928. this._allOptions.type = "line"
  100929. },
  100930. _createHtmlElements: function() {
  100931. this._seriesGroup = this._renderer.g().attr({"class": "dxsl-series"});
  100932. this._seriesLabelGroup = this._renderer.g().attr({"class": "dxsl-series-labels"})
  100933. },
  100934. _createSeries: function() {
  100935. this._series = new core.series.Series({
  100936. renderer: this._renderer,
  100937. seriesGroup: this._seriesGroup,
  100938. labelsGroup: this._seriesLabelGroup
  100939. }, {
  100940. widgetType: "chart",
  100941. type: "line"
  100942. })
  100943. },
  100944. getSeriesOptions: function() {
  100945. return this._series.getOptions()
  100946. },
  100947. _updateSeries: function() {
  100948. var that = this,
  100949. groupSeries,
  100950. dataValidator,
  100951. seriesOptions;
  100952. that._prepareDataSource();
  100953. seriesOptions = that._prepareSeriesOptions();
  100954. that._series.updateOptions(seriesOptions);
  100955. groupSeries = [[that._series]];
  100956. groupSeries.argumentOptions = {type: seriesOptions.type === "bar" ? "discrete" : undefined};
  100957. dataValidator = new core.DataValidator(that._simpleDataSource, groupSeries, that._incidentOccured, {
  100958. checkTypeForAllData: false,
  100959. convertToAxisDataType: true,
  100960. sortingMethod: true
  100961. });
  100962. that._simpleDataSource = dataValidator.validate();
  100963. that._series.updateData(that._simpleDataSource)
  100964. },
  100965. _optionChanged: function(args) {
  100966. if (args.name === "dataSource" && this._allOptions)
  100967. this._refreshDataSource();
  100968. else
  100969. this.callBase.apply(this, arguments)
  100970. },
  100971. _parseNumericDataSource: function(data, argField, valField) {
  100972. var ignoreEmptyPoints = this.option("ignoreEmptyPoints");
  100973. return _map(data, function(dataItem, index) {
  100974. var item = null,
  100975. isDataNumber,
  100976. value;
  100977. if (dataItem !== undefined) {
  100978. item = {};
  100979. isDataNumber = _isFinite(dataItem);
  100980. item[argField] = isDataNumber ? _String(index) : dataItem[argField];
  100981. value = isDataNumber ? dataItem : dataItem[valField];
  100982. item[valField] = value === null ? ignoreEmptyPoints ? undefined : value : _Number(value);
  100983. item = item[argField] !== undefined && item[valField] !== undefined ? item : null
  100984. }
  100985. return item
  100986. })
  100987. },
  100988. _parseWinlossDataSource: function(data, argField, valField) {
  100989. var lowBarValue = -1,
  100990. zeroBarValue = 0,
  100991. highBarValue = 1,
  100992. delta = 0.0001,
  100993. target = this._allOptions.winlossThreshold;
  100994. return _map(data, function(dataItem) {
  100995. var item = {};
  100996. item[argField] = dataItem[argField];
  100997. if (_abs(dataItem[valField] - target) < delta)
  100998. item[valField] = zeroBarValue;
  100999. else if (dataItem[valField] > target)
  101000. item[valField] = highBarValue;
  101001. else
  101002. item[valField] = lowBarValue;
  101003. return item
  101004. })
  101005. },
  101006. _prepareDataSource: function() {
  101007. var that = this,
  101008. options = that._allOptions,
  101009. argField = options.argumentField,
  101010. valField = options.valueField,
  101011. dataSource = that._dataSource ? that._dataSource.items() : [],
  101012. data = that._parseNumericDataSource(dataSource, argField, valField);
  101013. if (options.type === "winloss") {
  101014. that._winlossDataSource = data;
  101015. that._simpleDataSource = that._parseWinlossDataSource(data, argField, valField)
  101016. }
  101017. else
  101018. that._simpleDataSource = data
  101019. },
  101020. _prepareSeriesOptions: function() {
  101021. var that = this,
  101022. options = that._allOptions,
  101023. type = options.type === "winloss" ? "bar" : options.type;
  101024. return {
  101025. visible: true,
  101026. argumentField: options.argumentField,
  101027. valueField: options.valueField,
  101028. color: options.lineColor,
  101029. width: options.lineWidth,
  101030. widgetType: "chart",
  101031. type: type,
  101032. opacity: type.indexOf("area") !== -1 ? that._allOptions.areaOpacity : undefined,
  101033. customizePoint: that._getCustomizeFunction(),
  101034. point: {
  101035. size: options.pointSize,
  101036. symbol: options.pointSymbol,
  101037. border: {
  101038. visible: true,
  101039. width: 2
  101040. },
  101041. color: options.pointColor,
  101042. visible: false,
  101043. hoverStyle: {border: {}},
  101044. selectionStyle: {border: {}}
  101045. },
  101046. border: {
  101047. color: options.lineColor,
  101048. width: options.lineWidth,
  101049. visible: type !== "bar"
  101050. }
  101051. }
  101052. },
  101053. _createBarCustomizeFunction: function(pointIndexes) {
  101054. var that = this,
  101055. options = that._allOptions,
  101056. winlossData = that._winlossDataSource;
  101057. return function() {
  101058. var index = this.index,
  101059. isWinloss = options.type === "winloss",
  101060. target = isWinloss ? options.winlossThreshold : 0,
  101061. value = isWinloss ? winlossData[index][options.valueField] : this.value,
  101062. positiveColor = isWinloss ? options.winColor : options.barPositiveColor,
  101063. negativeColor = isWinloss ? options.lossColor : options.barNegativeColor,
  101064. color;
  101065. if (value >= target)
  101066. color = positiveColor;
  101067. else
  101068. color = negativeColor;
  101069. if (index === pointIndexes.first || index === pointIndexes.last)
  101070. color = options.firstLastColor;
  101071. if (index === pointIndexes.min)
  101072. color = options.minColor;
  101073. if (index === pointIndexes.max)
  101074. color = options.maxColor;
  101075. return {color: color}
  101076. }
  101077. },
  101078. _createLineCustomizeFunction: function(pointIndexes) {
  101079. var that = this,
  101080. options = that._allOptions;
  101081. return function() {
  101082. var color,
  101083. index = this.index;
  101084. if (index === pointIndexes.first || index === pointIndexes.last)
  101085. color = options.firstLastColor;
  101086. if (index === pointIndexes.min)
  101087. color = options.minColor;
  101088. if (index === pointIndexes.max)
  101089. color = options.maxColor;
  101090. return color ? {
  101091. visible: true,
  101092. border: {color: color}
  101093. } : {}
  101094. }
  101095. },
  101096. _getCustomizeFunction: function() {
  101097. var that = this,
  101098. options = that._allOptions,
  101099. dataSource = that._winlossDataSource || that._simpleDataSource,
  101100. drawnPointIndexes = that._getExtremumPointsIndexes(dataSource),
  101101. customizeFunction;
  101102. if (options.type === "winloss" || options.type === "bar")
  101103. customizeFunction = that._createBarCustomizeFunction(drawnPointIndexes);
  101104. else
  101105. customizeFunction = that._createLineCustomizeFunction(drawnPointIndexes);
  101106. return customizeFunction
  101107. },
  101108. _getExtremumPointsIndexes: function(data) {
  101109. var that = this,
  101110. options = that._allOptions,
  101111. lastIndex = data.length - 1,
  101112. indexes = {};
  101113. that._minMaxIndexes = that._findMinMax(data);
  101114. if (options.showFirstLast) {
  101115. indexes.first = 0;
  101116. indexes.last = lastIndex
  101117. }
  101118. if (options.showMinMax) {
  101119. indexes.min = that._minMaxIndexes.minIndex;
  101120. indexes.max = that._minMaxIndexes.maxIndex
  101121. }
  101122. return indexes
  101123. },
  101124. _findMinMax: function(data) {
  101125. var that = this,
  101126. valField = that._allOptions.valueField,
  101127. firstItem = data[0] || {},
  101128. firstValue = firstItem[valField] || 0,
  101129. min = firstValue,
  101130. max = firstValue,
  101131. minIndex = 0,
  101132. maxIndex = 0,
  101133. dataLength = data.length,
  101134. value,
  101135. i;
  101136. for (i = 1; i < dataLength; i++) {
  101137. value = data[i][valField];
  101138. if (value < min) {
  101139. min = value;
  101140. minIndex = i
  101141. }
  101142. if (value > max) {
  101143. max = value;
  101144. maxIndex = i
  101145. }
  101146. }
  101147. return {
  101148. minIndex: minIndex,
  101149. maxIndex: maxIndex
  101150. }
  101151. },
  101152. _updateRange: function() {
  101153. var that = this,
  101154. series = that._series,
  101155. type = series.type,
  101156. isBarType = type === "bar",
  101157. isWinlossType = type === "winloss",
  101158. DEFAULT_VALUE_RANGE_MARGIN = 0.15,
  101159. DEFAULT_ARGUMENT_RANGE_MARGIN = 0.1,
  101160. WINLOSS_MAX_RANGE = 1,
  101161. WINLOSS_MIN_RANGE = -1,
  101162. rangeData = series.getRangeData(),
  101163. minValue = that._allOptions.minValue,
  101164. hasMinY = _isDefined(minValue) && _isFinite(minValue),
  101165. maxValue = that._allOptions.maxValue,
  101166. hasMaxY = _isDefined(maxValue) && _isFinite(maxValue),
  101167. valCoef,
  101168. argCoef;
  101169. valCoef = (rangeData.val.max - rangeData.val.min) * DEFAULT_VALUE_RANGE_MARGIN;
  101170. if (isBarType || isWinlossType || type === "area") {
  101171. if (rangeData.val.min !== 0)
  101172. rangeData.val.min -= valCoef;
  101173. if (rangeData.val.max !== 0)
  101174. rangeData.val.max += valCoef
  101175. }
  101176. else {
  101177. rangeData.val.min -= valCoef;
  101178. rangeData.val.max += valCoef
  101179. }
  101180. if (hasMinY || hasMaxY) {
  101181. if (hasMinY && hasMaxY) {
  101182. rangeData.val.minVisible = _min(minValue, maxValue);
  101183. rangeData.val.maxVisible = _max(minValue, maxValue)
  101184. }
  101185. else {
  101186. rangeData.val.minVisible = hasMinY ? _Number(minValue) : undefined;
  101187. rangeData.val.maxVisible = hasMaxY ? _Number(maxValue) : undefined
  101188. }
  101189. if (isWinlossType) {
  101190. rangeData.val.minVisible = hasMinY ? _max(rangeData.val.minVisible, WINLOSS_MIN_RANGE) : undefined;
  101191. rangeData.val.maxVisible = hasMaxY ? _min(rangeData.val.maxVisible, WINLOSS_MAX_RANGE) : undefined
  101192. }
  101193. }
  101194. if (series.getPoints().length > 1)
  101195. if (isBarType) {
  101196. argCoef = (rangeData.arg.max - rangeData.arg.min) * DEFAULT_ARGUMENT_RANGE_MARGIN;
  101197. rangeData.arg.min = rangeData.arg.min - argCoef;
  101198. rangeData.arg.max = rangeData.arg.max + argCoef
  101199. }
  101200. else
  101201. rangeData.arg.stick = true;
  101202. that._ranges = rangeData
  101203. },
  101204. _getBarWidth: function(pointsCount) {
  101205. var that = this,
  101206. canvas = that._canvas,
  101207. intervalWidth = pointsCount * DEFAULT_BAR_INTERVAL,
  101208. rangeWidth = canvas.width - canvas.left - canvas.right - intervalWidth,
  101209. width = _round(rangeWidth / pointsCount);
  101210. if (width < MIN_BAR_WIDTH)
  101211. width = MIN_BAR_WIDTH;
  101212. if (width > MAX_BAR_WIDTH)
  101213. width = MAX_BAR_WIDTH;
  101214. return width
  101215. },
  101216. _correctPoints: function() {
  101217. var that = this,
  101218. seriesType = that._allOptions.type,
  101219. seriesPoints = that._series.getPoints(),
  101220. pointsLength = seriesPoints.length,
  101221. barWidth,
  101222. i;
  101223. if (seriesType === "bar" || seriesType === "winloss") {
  101224. barWidth = that._getBarWidth(pointsLength);
  101225. for (i = 0; i < pointsLength; i++)
  101226. seriesPoints[i].correctCoordinates({
  101227. width: barWidth,
  101228. offset: 0
  101229. })
  101230. }
  101231. },
  101232. _drawSeries: function() {
  101233. var that = this;
  101234. if (that._simpleDataSource.length > 0) {
  101235. that._correctPoints();
  101236. that._series.draw({
  101237. x: that._translatorX,
  101238. y: that._translatorY
  101239. });
  101240. that._seriesGroup.append(that._renderer.root)
  101241. }
  101242. },
  101243. _isTooltipEnabled: function() {
  101244. return !!this._simpleDataSource.length
  101245. },
  101246. _getTooltipData: function() {
  101247. var that = this,
  101248. options = that._allOptions,
  101249. dataSource = that._winlossDataSource || that._simpleDataSource,
  101250. tooltip = that._tooltip;
  101251. if (dataSource.length === 0)
  101252. return {};
  101253. var minMax = that._minMaxIndexes,
  101254. valueField = options.valueField,
  101255. first = dataSource[0][valueField],
  101256. last = dataSource[dataSource.length - 1][valueField],
  101257. min = dataSource[minMax.minIndex][valueField],
  101258. max = dataSource[minMax.maxIndex][valueField],
  101259. formattedFirst = tooltip.formatValue(first),
  101260. formattedLast = tooltip.formatValue(last),
  101261. formattedMin = tooltip.formatValue(min),
  101262. formattedMax = tooltip.formatValue(max),
  101263. customizeObject = {
  101264. firstValue: formattedFirst,
  101265. lastValue: formattedLast,
  101266. minValue: formattedMin,
  101267. maxValue: formattedMax,
  101268. originalFirstValue: first,
  101269. originalLastValue: last,
  101270. originalMinValue: min,
  101271. originalMaxValue: max,
  101272. valueText: ["Start:", formattedFirst, "End:", formattedLast, "Min:", formattedMin, "Max:", formattedMax]
  101273. };
  101274. if (options.type === "winloss") {
  101275. customizeObject.originalThresholdValue = options.winlossThreshold;
  101276. customizeObject.thresholdValue = tooltip.formatValue(options.winlossThreshold)
  101277. }
  101278. return customizeObject
  101279. }
  101280. }).include(DX.ui.DataHelperMixin))
  101281. })(jQuery, DevExpress);
  101282. /*! Module viz-sparklines, file bullet.js */
  101283. (function($, DX, undefined) {
  101284. var TARGET_MIN_Y = 0.02,
  101285. TARGET_MAX_Y = 0.98,
  101286. BAR_VALUE_MIN_Y = 0.1,
  101287. BAR_VALUE_MAX_Y = 0.9,
  101288. DEFAULT_CANVAS_WIDTH = 300,
  101289. DEFAULT_CANVAS_HEIGHT = 30,
  101290. DEFAULT_HORIZONTAL_MARGIN = 1,
  101291. DEFAULT_VERTICAL_MARGIN = 2,
  101292. _Number = Number,
  101293. _isFinite = isFinite;
  101294. DX.registerComponent("dxBullet", DX.viz.sparklines, DX.viz.sparklines.BaseSparkline.inherit({
  101295. _rootClassPrefix: "dxb",
  101296. _rootClass: "dxb-bullet",
  101297. _widgetType: "bullet",
  101298. _defaultSize: {
  101299. width: DEFAULT_CANVAS_WIDTH,
  101300. height: DEFAULT_CANVAS_HEIGHT,
  101301. left: DEFAULT_HORIZONTAL_MARGIN,
  101302. right: DEFAULT_HORIZONTAL_MARGIN,
  101303. top: DEFAULT_VERTICAL_MARGIN,
  101304. bottom: DEFAULT_VERTICAL_MARGIN
  101305. },
  101306. _disposeWidgetElements: function() {
  101307. delete this._zeroLevelPath;
  101308. delete this._targetPath;
  101309. delete this._barValuePath
  101310. },
  101311. _redrawWidgetElements: function() {
  101312. this._updateTranslator();
  101313. this._drawBarValue();
  101314. this._drawTarget();
  101315. this._drawZeroLevel()
  101316. },
  101317. _cleanWidgetElements: function() {
  101318. this._zeroLevelPath.remove();
  101319. this._targetPath.remove();
  101320. this._barValuePath.remove()
  101321. },
  101322. _drawWidgetElements: function() {
  101323. this._drawBullet();
  101324. this._drawn()
  101325. },
  101326. _createHtmlElements: function() {
  101327. var renderer = this._renderer;
  101328. this._zeroLevelPath = renderer.path(undefined, "line").attr({
  101329. "class": "dxb-zero-level",
  101330. "stroke-linecap": "square"
  101331. });
  101332. this._targetPath = renderer.path(undefined, "line").attr({
  101333. "class": "dxb-target",
  101334. "stroke-linecap": "square"
  101335. });
  101336. this._barValuePath = renderer.path(undefined, "line").attr({
  101337. "class": "dxb-bar-value",
  101338. "stroke-linecap": "square"
  101339. })
  101340. },
  101341. _prepareOptions: function() {
  101342. var that = this,
  101343. options,
  101344. startScaleValue,
  101345. endScaleValue,
  101346. level,
  101347. value,
  101348. target,
  101349. isValueUndefined,
  101350. isTargetUndefined;
  101351. that._allOptions = options = that.callBase();
  101352. isValueUndefined = that._allOptions.value === undefined;
  101353. isTargetUndefined = that._allOptions.target === undefined;
  101354. that._tooltipEnabled = !(isValueUndefined && isTargetUndefined);
  101355. if (isValueUndefined)
  101356. that._allOptions.value = 0;
  101357. if (isTargetUndefined)
  101358. that._allOptions.target = 0;
  101359. options.value = value = _Number(options.value);
  101360. options.target = target = _Number(options.target);
  101361. if (that._allOptions.startScaleValue === undefined) {
  101362. that._allOptions.startScaleValue = target < value ? target : value;
  101363. that._allOptions.startScaleValue = that._allOptions.startScaleValue < 0 ? that._allOptions.startScaleValue : 0
  101364. }
  101365. if (that._allOptions.endScaleValue === undefined)
  101366. that._allOptions.endScaleValue = target > value ? target : value;
  101367. options.startScaleValue = startScaleValue = _Number(options.startScaleValue);
  101368. options.endScaleValue = endScaleValue = _Number(options.endScaleValue);
  101369. if (endScaleValue < startScaleValue) {
  101370. level = endScaleValue;
  101371. that._allOptions.endScaleValue = startScaleValue;
  101372. that._allOptions.startScaleValue = level;
  101373. that._allOptions.inverted = true
  101374. }
  101375. },
  101376. _updateRange: function() {
  101377. var that = this,
  101378. options = that._allOptions;
  101379. that._ranges = {
  101380. arg: {
  101381. invert: options.inverted,
  101382. min: options.startScaleValue,
  101383. max: options.endScaleValue,
  101384. axisType: "continuous",
  101385. dataType: "numeric"
  101386. },
  101387. val: {
  101388. min: 0,
  101389. max: 1,
  101390. axisType: "continuous",
  101391. dataType: "numeric"
  101392. }
  101393. }
  101394. },
  101395. _drawBullet: function() {
  101396. var that = this,
  101397. options = that._allOptions,
  101398. isValidBounds = options.startScaleValue !== options.endScaleValue,
  101399. isValidMin = _isFinite(options.startScaleValue),
  101400. isValidMax = _isFinite(options.endScaleValue),
  101401. isValidValue = _isFinite(options.value),
  101402. isValidTarget = _isFinite(options.target);
  101403. if (isValidBounds && isValidMax && isValidMin && isValidTarget && isValidValue) {
  101404. this._drawBarValue();
  101405. this._drawTarget();
  101406. this._drawZeroLevel()
  101407. }
  101408. },
  101409. _getTargetParams: function() {
  101410. var that = this,
  101411. options = that._allOptions,
  101412. translatorY = that._translatorY,
  101413. x = that._translatorX.translate(options.target);
  101414. return {
  101415. points: [x, translatorY.translate(TARGET_MIN_Y), x, translatorY.translate(TARGET_MAX_Y)],
  101416. stroke: options.targetColor,
  101417. "stroke-width": options.targetWidth
  101418. }
  101419. },
  101420. _getBarValueParams: function() {
  101421. var that = this,
  101422. options = that._allOptions,
  101423. translatorX = that._translatorX,
  101424. translatorY = that._translatorY,
  101425. startLevel = options.startScaleValue,
  101426. endLevel = options.endScaleValue,
  101427. value = options.value,
  101428. y2 = translatorY.translate(BAR_VALUE_MIN_Y),
  101429. y1 = translatorY.translate(BAR_VALUE_MAX_Y),
  101430. x1,
  101431. x2;
  101432. if (value > 0) {
  101433. x1 = startLevel <= 0 ? 0 : startLevel;
  101434. x2 = value >= endLevel ? endLevel : value < x1 ? x1 : value
  101435. }
  101436. else {
  101437. x1 = endLevel >= 0 ? 0 : endLevel;
  101438. x2 = value < startLevel ? startLevel : value > x1 ? x1 : value
  101439. }
  101440. x1 = translatorX.translate(x1);
  101441. x2 = translatorX.translate(x2);
  101442. return {
  101443. points: [x1, y1, x2, y1, x2, y2, x1, y2],
  101444. fill: options.color
  101445. }
  101446. },
  101447. _getZeroLevelParams: function() {
  101448. var that = this,
  101449. translatorY = that._translatorY,
  101450. x = that._translatorX.translate(0);
  101451. return {
  101452. points: [x, translatorY.translate(TARGET_MIN_Y), x, translatorY.translate(TARGET_MAX_Y)],
  101453. stroke: that._allOptions.targetColor,
  101454. "stroke-width": 1
  101455. }
  101456. },
  101457. _drawZeroLevel: function() {
  101458. var that = this,
  101459. options = that._allOptions;
  101460. if (0 > options.endScaleValue || 0 < options.startScaleValue || !options.showZeroLevel)
  101461. return;
  101462. that._zeroLevelPath.attr(that._getZeroLevelParams()).sharp().append(that._renderer.root)
  101463. },
  101464. _drawTarget: function() {
  101465. var that = this,
  101466. options = that._allOptions,
  101467. target = options.target;
  101468. if (target > options.endScaleValue || target < options.startScaleValue || !options.showTarget)
  101469. return;
  101470. that._targetPath.attr(that._getTargetParams()).sharp().append(that._renderer.root)
  101471. },
  101472. _drawBarValue: function() {
  101473. this._barValuePath.attr(this._getBarValueParams()).append(this._renderer.root)
  101474. },
  101475. _getTooltipCoords: function() {
  101476. var canvas = this._canvas,
  101477. rootOffset = this._renderer.getRootOffset(),
  101478. bbox = this._barValuePath.getBBox();
  101479. return {
  101480. x: bbox.x + bbox.width / 2 + rootOffset.left,
  101481. y: canvas.height / 2 + rootOffset.top
  101482. }
  101483. },
  101484. _getTooltipData: function() {
  101485. var that = this,
  101486. tooltip = that._tooltip,
  101487. options = that._allOptions,
  101488. value = options.value,
  101489. target = options.target;
  101490. return {
  101491. originalValue: value,
  101492. originalTarget: target,
  101493. value: tooltip.formatValue(value),
  101494. target: tooltip.formatValue(target),
  101495. valueText: ["Actual Value:", value, "Target Value:", target]
  101496. }
  101497. },
  101498. _isTooltipEnabled: function() {
  101499. return this._tooltipEnabled
  101500. }
  101501. }))
  101502. })(jQuery, DevExpress);
  101503. DevExpress.MOD_VIZ_SPARKLINES = true
  101504. }