Dialogs.js 243 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501
  1. /**
  2. * Copyright (c) 2006-2018, JGraph Ltd
  3. * Copyright (c) 2006-2018, Gaudenz Alder
  4. */
  5. var StorageDialog = function(editorUi, fn, rowLimit)
  6. {
  7. rowLimit = (rowLimit != null) ? rowLimit : 2;
  8. var div = document.createElement('div');
  9. div.style.textAlign = 'center';
  10. div.style.whiteSpace = 'nowrap';
  11. div.style.paddingTop = '0px';
  12. div.style.paddingBottom = '20px';
  13. var elt = editorUi.addLanguageMenu(div, true);
  14. var bottom = '28px';
  15. if (elt != null)
  16. {
  17. elt.style.bottom = parseInt(bottom) - 3 + 'px';
  18. }
  19. if (!editorUi.isOffline() && editorUi.getServiceCount() > 1)
  20. {
  21. var help = document.createElement('a');
  22. help.setAttribute('href', 'https://about.draw.io/support/');
  23. help.setAttribute('title', mxResources.get('help'));
  24. help.setAttribute('target', '_blank');
  25. help.style.position = 'absolute';
  26. help.style.textDecoration = 'none';
  27. help.style.cursor = 'pointer';
  28. help.style.fontSize = '12px';
  29. help.style.bottom = bottom;
  30. help.style.left = '26px';
  31. help.style.color = 'gray';
  32. var icon = document.createElement('img');
  33. mxUtils.setOpacity(icon, 50);
  34. icon.style.height = '16px';
  35. icon.style.width = '16px';
  36. icon.setAttribute('border', '0');
  37. icon.setAttribute('valign', 'bottom');
  38. icon.setAttribute('src', Editor.helpImage);
  39. icon.style.marginRight = '2px';
  40. help.appendChild(icon);
  41. mxUtils.write(help, mxResources.get('help'));
  42. div.appendChild(help);
  43. }
  44. var demo = document.createElement('div');
  45. demo.style.position = 'absolute';
  46. demo.style.cursor = 'pointer';
  47. demo.style.fontSize = '12px';
  48. demo.style.bottom = bottom;
  49. demo.style.color = 'gray';
  50. mxUtils.write(demo, mxResources.get('decideLater'));
  51. if (editorUi.isOfflineApp())
  52. {
  53. demo.style.right = '20px';
  54. }
  55. else
  56. {
  57. mxUtils.setPrefixedStyle(demo.style, 'transform', 'translate(-50%,0)');
  58. demo.style.left = '50%';
  59. }
  60. this.init = function()
  61. {
  62. if (mxClient.IS_QUIRKS || document.documentMode == 8)
  63. {
  64. demo.style.marginLeft = -Math.round(demo.clientWidth / 2) + 'px';
  65. }
  66. };
  67. div.appendChild(demo);
  68. mxEvent.addListener(demo, 'click', function()
  69. {
  70. editorUi.hideDialog();
  71. var prev = Editor.useLocalStorage;
  72. editorUi.createFile(editorUi.defaultFilename, null, null, null, null, null, null, true);
  73. Editor.useLocalStorage = prev;
  74. });
  75. var buttons = document.createElement('div');
  76. if (mxClient.IS_QUIRKS)
  77. {
  78. buttons.style.whiteSpace = 'nowrap';
  79. buttons.style.cssFloat = 'left';
  80. }
  81. buttons.style.border = '1px solid #d3d3d3';
  82. buttons.style.borderWidth = '1px 0px 1px 0px';
  83. buttons.style.padding = '12px 0px 12px 0px';
  84. var cb = document.createElement('input');
  85. cb.setAttribute('type', 'checkbox');
  86. cb.setAttribute('checked', 'checked');
  87. cb.defaultChecked = true;
  88. var count = 0;
  89. var p3 = document.createElement('p');
  90. function addLogo(img, title, mode, clientName, labels, clientFn)
  91. {
  92. var button = document.createElement('a');
  93. button.style.overflow = 'hidden';
  94. button.style.display = (mxClient.IS_QUIRKS) ? 'inline' : 'inline-block';
  95. button.className = 'geBaseButton';
  96. button.style.boxSizing = 'border-box';
  97. button.style.fontSize = '11px';
  98. button.style.position = 'relative';
  99. button.style.margin = '4px';
  100. button.style.padding = '8px 10px 12px 10px';
  101. button.style.width = '88px';
  102. button.style.height = '100px';
  103. button.style.whiteSpace = 'nowrap';
  104. button.setAttribute('title', title);
  105. // Workaround for quirks is a vertical list (limited to max 2 items)
  106. if (mxClient.IS_QUIRKS)
  107. {
  108. button.style.cssFloat = 'left';
  109. button.style.zoom = '1';
  110. }
  111. var label = document.createElement('div');
  112. label.style.textOverflow = 'ellipsis';
  113. label.style.overflow = 'hidden';
  114. if (img != null)
  115. {
  116. var logo = document.createElement('img');
  117. logo.setAttribute('src', img);
  118. logo.setAttribute('border', '0');
  119. logo.setAttribute('align', 'absmiddle');
  120. logo.style.width = '60px';
  121. logo.style.height = '60px';
  122. logo.style.paddingBottom = '6px';
  123. button.appendChild(logo);
  124. }
  125. else
  126. {
  127. label.style.paddingTop = '5px';
  128. label.style.whiteSpace = 'normal';
  129. // Handles special case
  130. if (mxClient.IS_IOS)
  131. {
  132. button.style.padding = '0px 10px 20px 10px';
  133. button.style.top = '6px';
  134. }
  135. else if (mxClient.IS_FF)
  136. {
  137. label.style.paddingTop = '0px';
  138. label.style.marginTop = '-2px';
  139. }
  140. }
  141. button.appendChild(label);
  142. mxUtils.write(label, title);
  143. if (labels != null)
  144. {
  145. for (var i = 0; i < labels.length; i++)
  146. {
  147. mxUtils.br(label);
  148. mxUtils.write(label, labels[i]);
  149. }
  150. }
  151. function initButton()
  152. {
  153. mxEvent.addListener(button, 'click', (clientFn != null) ? clientFn : function()
  154. {
  155. // Special case: Redirect all drive users to draw.io pro
  156. if (mode == App.MODE_GOOGLE && !editorUi.isDriveDomain())
  157. {
  158. window.location.hostname = DriveClient.prototype.newAppHostname;
  159. }
  160. else if (mode == App.MODE_GOOGLE && editorUi.spinner.spin(document.body, mxResources.get('authorizing')))
  161. {
  162. // Tries immediate authentication
  163. editorUi.drive.checkToken(mxUtils.bind(this, function()
  164. {
  165. editorUi.spinner.stop();
  166. editorUi.setMode(mode, cb.checked);
  167. fn();
  168. }));
  169. }
  170. else if (mode == App.MODE_ONEDRIVE && editorUi.spinner.spin(document.body, mxResources.get('authorizing')))
  171. {
  172. // Tries immediate authentication
  173. editorUi.oneDrive.checkToken(mxUtils.bind(this, function()
  174. {
  175. editorUi.spinner.stop();
  176. editorUi.setMode(mode, cb.checked);
  177. fn();
  178. }));
  179. }
  180. else
  181. {
  182. editorUi.setMode(mode, cb.checked);
  183. fn();
  184. }
  185. });
  186. };
  187. // Supports lazy loading
  188. if (clientName != null && editorUi[clientName] == null)
  189. {
  190. logo.style.visibility = 'hidden';
  191. mxUtils.setOpacity(label, 10);
  192. var size = 12;
  193. var spinner = new Spinner({
  194. lines: 12, // The number of lines to draw
  195. length: size, // The length of each line
  196. width: 5, // The line thickness
  197. radius: 10, // The radius of the inner circle
  198. rotate: 0, // The rotation offset
  199. color: (uiTheme == 'dark') ? '#c0c0c0' : '#000', // #rgb or #rrggbb
  200. speed: 1.5, // Rounds per second
  201. trail: 60, // Afterglow percentage
  202. shadow: false, // Whether to render a shadow
  203. hwaccel: false, // Whether to use hardware acceleration
  204. top: '40%',
  205. zIndex: 2e9 // The z-index (defaults to 2000000000)
  206. });
  207. spinner.spin(button);
  208. // Timeout after 30 secs
  209. var timeout = window.setTimeout(function()
  210. {
  211. if (editorUi[clientName] == null)
  212. {
  213. spinner.stop();
  214. button.style.display = 'none';
  215. }
  216. }, 30000);
  217. editorUi.addListener('clientLoaded', mxUtils.bind(this, function(sender, evt)
  218. {
  219. if (editorUi[clientName] != null && evt.getProperty('client') == editorUi[clientName])
  220. {
  221. window.clearTimeout(timeout);
  222. mxUtils.setOpacity(label, 100);
  223. logo.style.visibility = '';
  224. spinner.stop();
  225. initButton();
  226. if (clientName == 'drive' && p3.parentNode != null)
  227. {
  228. p3.parentNode.removeChild(p3);
  229. }
  230. }
  231. }));
  232. }
  233. else
  234. {
  235. initButton();
  236. }
  237. buttons.appendChild(button);
  238. if (++count >= rowLimit)
  239. {
  240. mxUtils.br(buttons);
  241. count = 0;
  242. }
  243. };
  244. var hd = document.createElement('p');
  245. hd.style.fontSize = '16pt';
  246. hd.style.padding = '0px';
  247. hd.style.paddingTop = '4px';
  248. hd.style.paddingBottom = '16px';
  249. hd.style.margin = '0px';
  250. hd.style.color = 'gray';
  251. mxUtils.write(hd, mxResources.get('saveDiagramsTo') + ':');
  252. div.appendChild(hd);
  253. if (typeof window.DriveClient === 'function')
  254. {
  255. addLogo(IMAGE_PATH + '/google-drive-logo.svg', mxResources.get('googleDrive'), App.MODE_GOOGLE, 'drive');
  256. }
  257. if (typeof window.OneDriveClient === 'function')
  258. {
  259. addLogo(IMAGE_PATH + '/onedrive-logo.svg', mxResources.get('oneDrive'), App.MODE_ONEDRIVE, 'oneDrive');
  260. }
  261. addLogo(IMAGE_PATH + '/osa_drive-harddisk.png', mxResources.get('device'), App.MODE_DEVICE);
  262. if (isLocalStorage && (urlParams['browser'] == '1' || urlParams['offline'] == '1'))
  263. {
  264. addLogo(IMAGE_PATH + '/osa_database.png', mxResources.get('browser'), App.MODE_BROWSER);
  265. }
  266. div.appendChild(buttons);
  267. var p2 = document.createElement('p');
  268. p2.style.marginTop = '12px';
  269. p2.style.marginBottom = '6px';
  270. p2.appendChild(cb);
  271. var span = document.createElement('span');
  272. span.style.color = 'gray';
  273. span.style.fontSize = '12px';
  274. mxUtils.write(span, ' ' + mxResources.get('rememberThisSetting'));
  275. p2.appendChild(span);
  276. mxUtils.br(p2);
  277. var recent = editorUi.getRecent();
  278. if (recent != null && recent.length > 0)
  279. {
  280. var recentSelect = document.createElement('select');
  281. recentSelect.style.marginTop = '8px';
  282. recentSelect.style.width = '140px';
  283. var titleOption = document.createElement('option');
  284. titleOption.setAttribute('value', '');
  285. titleOption.setAttribute('selected', 'selected');
  286. titleOption.style.textAlign = 'center';
  287. mxUtils.write(titleOption, mxResources.get('openRecent') + '...');
  288. recentSelect.appendChild(titleOption);
  289. for (var i = 0; i < recent.length; i++)
  290. {
  291. (function(entry)
  292. {
  293. var modeKey = entry.mode;
  294. // Google and oneDrive use different keys
  295. if (modeKey == App.MODE_GOOGLE)
  296. {
  297. modeKey = 'googleDrive';
  298. }
  299. else if (modeKey == App.MODE_ONEDRIVE)
  300. {
  301. modeKey = 'oneDrive';
  302. }
  303. var entryOption = document.createElement('option');
  304. entryOption.setAttribute('value', entry.id);
  305. mxUtils.write(entryOption, entry.title + ' (' + mxResources.get(modeKey) + ')');
  306. recentSelect.appendChild(entryOption);
  307. })(recent[i]);
  308. }
  309. p2.appendChild(recentSelect);
  310. mxEvent.addListener(recentSelect, 'change', function(evt)
  311. {
  312. if (recentSelect.value != '')
  313. {
  314. editorUi.loadFile(recentSelect.value);
  315. }
  316. });
  317. }
  318. else
  319. {
  320. p2.style.marginTop = '20px';
  321. buttons.style.padding = '30px 0px 26px 0px';
  322. }
  323. if (Graph.fileSupport && !mxClient.IS_IE && !mxClient.IS_IE11)
  324. {
  325. var link = document.createElement('div');
  326. link.style.cursor = 'pointer';
  327. link.style.padding = '18px 0px 6px 0px';
  328. link.style.fontSize = '12px';
  329. link.style.color = 'gray';
  330. mxUtils.write(link, mxResources.get('import') + ': ' + mxResources.get('gliffy') + ', ' +
  331. mxResources.get('formatVssx') + ', ' + mxResources.get('formatVsdx') + ', ' +
  332. mxResources.get('lucidchart') + '...');
  333. mxEvent.addListener(link, 'click', function()
  334. {
  335. var input = document.createElement('input');
  336. input.setAttribute('type', 'file');
  337. mxEvent.addListener(input, 'change', function()
  338. {
  339. if (input.files != null)
  340. {
  341. // Using null for position will disable crop of input file
  342. editorUi.hideDialog();
  343. editorUi.openFiles(input.files, true);
  344. }
  345. });
  346. input.click();
  347. });
  348. p2.appendChild(link);
  349. buttons.style.paddingBottom = '4px';
  350. }
  351. buttons.appendChild(p2);
  352. mxEvent.addListener(span, 'click', function(evt)
  353. {
  354. cb.checked = !cb.checked;
  355. mxEvent.consume(evt);
  356. });
  357. // Checks if Google Drive is missing after a 5 sec delay
  358. if (mxClient.IS_SVG && isLocalStorage && urlParams['gapi'] != '0' &&
  359. (document.documentMode == null || document.documentMode >= 10))
  360. {
  361. window.setTimeout(function()
  362. {
  363. if (editorUi.drive == null)
  364. {
  365. // To check for Disconnect plugin in chrome use mxClient.IS_GC and check for URL:
  366. // chrome-extension://jeoacafpbcihiomhlakheieifhpjdfeo/scripts/vendor/jquery/jquery-2.0.3.min.map
  367. p3.style.padding = '8px';
  368. p3.style.fontSize = '9pt';
  369. p3.style.marginTop = '-14px';
  370. p3.innerHTML = '<a style="background-color:#dcdcdc;padding:5px;color:black;text-decoration:none;" ' +
  371. 'href="https://plus.google.com/u/0/+DrawIo1/posts/1HTrfsb5wDN" target="_blank">' +
  372. '<img border="0" src="' + mxGraph.prototype.warningImage.src + '" align="top"> ' +
  373. mxResources.get('googleDriveMissingClickHere') + '</a>';
  374. div.appendChild(p3);
  375. }
  376. }, 5000);
  377. }
  378. this.container = div;
  379. };
  380. /**
  381. * Constructs a dialog for creating new files from templates.
  382. */
  383. var SplashDialog = function(editorUi)
  384. {
  385. var div = document.createElement('div');
  386. div.style.textAlign = 'center';
  387. var elt = editorUi.addLanguageMenu(div, true);
  388. if (elt != null)
  389. {
  390. elt.style.bottom = '19px';
  391. }
  392. var help = null;
  393. var serviceCount = editorUi.getServiceCount();
  394. if (!editorUi.isOffline() && serviceCount > 1)
  395. {
  396. help = document.createElement('a');
  397. help.setAttribute('href', 'https://about.draw.io/support/');
  398. help.setAttribute('title', mxResources.get('help'));
  399. help.setAttribute('target', '_blank');
  400. help.style.position = 'absolute';
  401. help.style.fontSize = '12px';
  402. help.style.textDecoration = 'none';
  403. help.style.cursor = 'pointer';
  404. help.style.bottom = '22px';
  405. help.style.left = '26px';
  406. help.style.color = 'gray';
  407. var icon = document.createElement('img');
  408. mxUtils.setOpacity(icon, 50);
  409. icon.style.height = '16px';
  410. icon.style.width = '16px';
  411. icon.setAttribute('border', '0');
  412. icon.setAttribute('valign', 'bottom');
  413. icon.setAttribute('src', Editor.helpImage);
  414. icon.style.marginRight = '2px';
  415. help.appendChild(icon);
  416. mxUtils.write(help, mxResources.get('help'));
  417. div.appendChild(help);
  418. }
  419. var hd = document.createElement('p');
  420. hd.style.fontSize = '16pt';
  421. hd.style.padding = '0px';
  422. hd.style.paddingTop = '2px';
  423. hd.style.margin = '0px';
  424. hd.style.color = 'gray';
  425. var logo = document.createElement('img');
  426. logo.setAttribute('border', '0');
  427. logo.setAttribute('align', 'absmiddle');
  428. logo.style.width = '40px';
  429. logo.style.height = '40px';
  430. logo.style.marginRight = '12px';
  431. logo.style.paddingBottom = '4px';
  432. var service = '';
  433. if (editorUi.mode == App.MODE_GOOGLE)
  434. {
  435. logo.src = IMAGE_PATH + '/google-drive-logo.svg';
  436. service = mxResources.get('googleDrive');
  437. }
  438. else if (editorUi.mode == App.MODE_DROPBOX)
  439. {
  440. logo.src = IMAGE_PATH + '/dropbox-logo.svg';
  441. service = mxResources.get('dropbox');
  442. }
  443. else if (editorUi.mode == App.MODE_ONEDRIVE)
  444. {
  445. logo.src = IMAGE_PATH + '/onedrive-logo.svg';
  446. service = mxResources.get('oneDrive');
  447. }
  448. else if (editorUi.mode == App.MODE_GITHUB)
  449. {
  450. logo.src = IMAGE_PATH + '/github-logo.svg';
  451. service = mxResources.get('github');
  452. }
  453. else if (editorUi.mode == App.MODE_TRELLO)
  454. {
  455. logo.src = IMAGE_PATH + '/trello-logo.svg';
  456. service = mxResources.get('trello');
  457. }
  458. else if (editorUi.mode == App.MODE_BROWSER)
  459. {
  460. logo.src = IMAGE_PATH + '/osa_database.png';
  461. service = mxResources.get('browser');
  462. }
  463. else
  464. {
  465. logo.src = IMAGE_PATH + '/osa_drive-harddisk.png';
  466. service = mxResources.get('device');
  467. }
  468. var buttons = document.createElement('div');
  469. buttons.style.margin = '4px 0px 0px 0px';
  470. var btn = document.createElement('button');
  471. btn.className = 'geBigButton';
  472. btn.style.overflow = 'hidden';
  473. btn.style.width = '340px';
  474. if (!mxClient.IS_CHROMEAPP && !EditorUi.isElectronApp)
  475. {
  476. hd.appendChild(logo);
  477. mxUtils.write(hd, service);
  478. div.appendChild(hd);
  479. buttons.style.border = '1px solid #d3d3d3';
  480. buttons.style.borderWidth = '1px 0px 1px 0px';
  481. buttons.style.padding = '18px 0px 24px 0px';
  482. btn.style.marginBottom = '8px';
  483. }
  484. else
  485. {
  486. buttons.style.padding = '42px 0px 56px 0px';
  487. btn.style.marginBottom = '12px';
  488. }
  489. if (mxClient.IS_QUIRKS)
  490. {
  491. buttons.style.whiteSpace = 'nowrap';
  492. buttons.style.cssFloat = 'left';
  493. }
  494. if (mxClient.IS_QUIRKS)
  495. {
  496. btn.style.width = '340px';
  497. }
  498. mxUtils.write(btn, mxResources.get('createNewDiagram'));
  499. mxEvent.addListener(btn, 'click', function()
  500. {
  501. editorUi.hideDialog();
  502. editorUi.actions.get('new').funct();
  503. });
  504. buttons.appendChild(btn);
  505. mxUtils.br(buttons);
  506. var btn = document.createElement('button');
  507. btn.className = 'geBigButton';
  508. btn.style.marginBottom = '22px';
  509. btn.style.overflow = 'hidden';
  510. btn.style.width = '340px';
  511. if (mxClient.IS_QUIRKS)
  512. {
  513. btn.style.width = '340px';
  514. }
  515. mxUtils.write(btn, mxResources.get('openExistingDiagram'));
  516. mxEvent.addListener(btn, 'click', function()
  517. {
  518. editorUi.actions.get('open').funct();
  519. });
  520. buttons.appendChild(btn);
  521. var storage = 'undefined';
  522. if (editorUi.mode == App.MODE_GOOGLE)
  523. {
  524. storage = mxResources.get('googleDrive');
  525. }
  526. else if (editorUi.mode == App.MODE_DROPBOX)
  527. {
  528. storage = mxResources.get('dropbox');
  529. }
  530. else if (editorUi.mode == App.MODE_ONEDRIVE)
  531. {
  532. storage = mxResources.get('oneDrive');
  533. }
  534. else if (editorUi.mode == App.MODE_GITHUB)
  535. {
  536. storage = mxResources.get('github');
  537. }
  538. else if (editorUi.mode == App.MODE_TRELLO)
  539. {
  540. storage = mxResources.get('trello');
  541. }
  542. else if (editorUi.mode == App.MODE_DEVICE)
  543. {
  544. storage = mxResources.get('device');
  545. }
  546. else if (editorUi.mode == App.MODE_BROWSER)
  547. {
  548. storage = mxResources.get('browser');
  549. }
  550. if (!mxClient.IS_CHROMEAPP && !EditorUi.isElectronApp)
  551. {
  552. var driveUser = (editorUi.drive != null) ? editorUi.drive.getUser() : null;
  553. function addLogout(logout)
  554. {
  555. btn.style.marginBottom = '24px';
  556. var link = document.createElement('a');
  557. link.setAttribute('href', 'javascript:void(0)');
  558. link.style.display = 'inline-block';
  559. link.style.marginTop = '6px';
  560. mxUtils.write(link, mxResources.get('signOut'));
  561. // Makes room after last big buttons
  562. btn.style.marginBottom = '16px';
  563. buttons.style.paddingBottom = '18px';
  564. mxEvent.addListener(link, 'click', function()
  565. {
  566. editorUi.confirm(mxResources.get('areYouSure'), function()
  567. {
  568. logout();
  569. });
  570. });
  571. buttons.appendChild(link);
  572. };
  573. if (editorUi.mode == App.MODE_GOOGLE && driveUser != null)
  574. {
  575. btn.style.marginBottom = '24px';
  576. var link = document.createElement('a');
  577. link.setAttribute('href', 'javascript:void(0)');
  578. link.style.display = 'inline-block';
  579. link.style.marginTop = '6px';
  580. mxUtils.write(link, mxResources.get('changeUser') + ' (' + driveUser.displayName + ')');
  581. // Makes room after last big buttons
  582. btn.style.marginBottom = '16px';
  583. buttons.style.paddingBottom = '18px';
  584. mxEvent.addListener(link, 'click', function()
  585. {
  586. editorUi.hideDialog();
  587. editorUi.drive.clearUserId();
  588. editorUi.drive.setUser(null);
  589. gapi.auth.signOut();
  590. // Restores current dialog after clearing user
  591. editorUi.setMode(App.MODE_GOOGLE);
  592. editorUi.hideDialog();
  593. editorUi.showSplash();
  594. // FIXME: Does not force showing the auth dialog if only one user is logged in
  595. editorUi.drive.authorize(false, mxUtils.bind(this, mxUtils.bind(this, function()
  596. {
  597. editorUi.hideDialog();
  598. editorUi.showSplash();
  599. })), mxUtils.bind(this, function(resp)
  600. {
  601. editorUi.handleError(resp, null, function()
  602. {
  603. editorUi.hideDialog();
  604. editorUi.showSplash();
  605. });
  606. }));
  607. });
  608. buttons.appendChild(link);
  609. }
  610. else if (editorUi.mode == App.MODE_ONEDRIVE && editorUi.oneDrive != null)
  611. {
  612. addLogout(function()
  613. {
  614. editorUi.oneDrive.logout();
  615. });
  616. }
  617. else if (editorUi.mode == App.MODE_GITHUB && editorUi.gitHub != null)
  618. {
  619. addLogout(function()
  620. {
  621. editorUi.gitHub.logout();
  622. editorUi.openLink('https://www.github.com/logout');
  623. });
  624. }
  625. else if (editorUi.mode == App.MODE_TRELLO && editorUi.trello != null)
  626. {
  627. if (editorUi.trello.isAuthorized())
  628. {
  629. addLogout(function()
  630. {
  631. editorUi.trello.logout();
  632. });
  633. }
  634. }
  635. else if (editorUi.mode == App.MODE_DROPBOX && editorUi.dropbox != null)
  636. {
  637. // NOTE: Dropbox has a logout option in the picker
  638. addLogout(function()
  639. {
  640. editorUi.dropbox.logout();
  641. editorUi.openLink('https://www.dropbox.com/logout');
  642. });
  643. }
  644. mxUtils.br(buttons);
  645. var link = document.createElement('a');
  646. link.setAttribute('href', 'javascript:void(0)');
  647. link.style.display = 'inline-block';
  648. link.style.marginTop = '8px';
  649. mxUtils.write(link, mxResources.get('changeStorage'));
  650. mxEvent.addListener(link, 'click', function()
  651. {
  652. editorUi.hideDialog(false);
  653. editorUi.setMode(null);
  654. editorUi.clearMode();
  655. editorUi.showSplash(true);
  656. });
  657. buttons.appendChild(link);
  658. }
  659. div.appendChild(buttons);
  660. this.container = div;
  661. };
  662. /**
  663. * Constructs a new embed dialog
  664. */
  665. var EmbedDialog = function(editorUi, result, timeout, ignoreSize, previewFn, title)
  666. {
  667. var div = document.createElement('div');
  668. var maxSize = 500000;
  669. var maxFbSize = 51200;
  670. var maxTwitterSize = 7168;
  671. // Checks if result is a link
  672. var validUrl = /^https?:\/\//.test(result) || /^mailto:\/\//.test(result);
  673. if (title != null)
  674. {
  675. mxUtils.write(div, title);
  676. }
  677. else
  678. {
  679. mxUtils.write(div, mxResources.get((result.length < maxSize) ?
  680. ((validUrl) ? 'link' : 'mainEmbedNotice') : 'preview') + ':');
  681. }
  682. mxUtils.br(div);
  683. var size = document.createElement('div');
  684. size.style.position = 'absolute';
  685. size.style.top = '30px';
  686. size.style.right = '30px';
  687. size.style.color = 'gray';
  688. mxUtils.write(size, editorUi.formatFileSize(result.length));
  689. div.appendChild(size);
  690. // Using DIV for faster rendering
  691. var text = document.createElement('textarea');
  692. text.setAttribute('autocomplete', 'off');
  693. text.setAttribute('autocorrect', 'off');
  694. text.setAttribute('autocapitalize', 'off');
  695. text.setAttribute('spellcheck', 'false');
  696. text.style.marginTop = '10px';
  697. text.style.resize = 'none';
  698. text.style.height = '150px';
  699. text.style.width = '440px';
  700. text.style.border = '1px solid gray';
  701. text.value = mxResources.get('updatingDocument');
  702. div.appendChild(text);
  703. mxUtils.br(div);
  704. this.init = function()
  705. {
  706. window.setTimeout(function()
  707. {
  708. if (result.length < maxSize)
  709. {
  710. text.value = result;
  711. text.focus();
  712. if (mxClient.IS_GC || mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS)
  713. {
  714. text.select();
  715. }
  716. else
  717. {
  718. document.execCommand('selectAll', false, null);
  719. }
  720. }
  721. else
  722. {
  723. text.setAttribute('readonly', 'true');
  724. text.value = result.substring(0, 340) + '... (' + mxResources.get('drawingTooLarge') + ')';
  725. }
  726. }, 0);
  727. };
  728. var buttons = document.createElement('div');
  729. buttons.style.position = 'absolute';
  730. buttons.style.bottom = '36px';
  731. buttons.style.right = '32px';
  732. var previewBtn = null;
  733. // Loads forever in IE9
  734. if (EmbedDialog.showPreviewOption && (!mxClient.IS_CHROMEAPP || validUrl) && !navigator.standalone && (validUrl ||
  735. (mxClient.IS_SVG && (document.documentMode == null || document.documentMode > 9))))
  736. {
  737. previewBtn = mxUtils.button(mxResources.get((result.length < maxSize) ? 'preview' : 'openInNewWindow'), function()
  738. {
  739. var value = (result.length < maxSize) ? text.value : result;
  740. if (previewFn != null)
  741. {
  742. previewFn(value);
  743. }
  744. else
  745. {
  746. if (validUrl)
  747. {
  748. try
  749. {
  750. var win = editorUi.openLink(value);
  751. if (win != null && (timeout == null || timeout > 0))
  752. {
  753. window.setTimeout(mxUtils.bind(this, function()
  754. {
  755. if (win != null && win.location.href != null &&
  756. win.location.href.substring(0, 8) != value.substring(0, 8))
  757. {
  758. win.close();
  759. editorUi.handleError({message: mxResources.get('drawingTooLarge')});
  760. }
  761. }), timeout || 500);
  762. }
  763. }
  764. catch (e)
  765. {
  766. editorUi.handleError({message: e.message || mxResources.get('drawingTooLarge')});
  767. }
  768. }
  769. else
  770. {
  771. var wnd = window.open();
  772. var doc = (wnd != null) ? wnd.document : null;
  773. if (doc != null)
  774. {
  775. doc.writeln('<html><head><title>' + encodeURIComponent(mxResources.get('preview')) +
  776. '</title><meta charset="utf-8"></head>' +
  777. '<body>' + result + '</body></html>');
  778. doc.close();
  779. }
  780. else
  781. {
  782. editorUi.handleError({message: mxResources.get('errorUpdatingPreview')});
  783. }
  784. }
  785. }
  786. });
  787. previewBtn.className = 'geBtn';
  788. buttons.appendChild(previewBtn);
  789. }
  790. if (!validUrl || result.length > 7500)
  791. {
  792. var downloadBtn = mxUtils.button(mxResources.get('download'), function()
  793. {
  794. editorUi.hideDialog();
  795. editorUi.saveData('embed.txt', 'txt', result, 'text/plain');
  796. });
  797. downloadBtn.className = 'geBtn';
  798. buttons.appendChild(downloadBtn);
  799. }
  800. // Twitter-intent does not allow more characters, must be pasted manually
  801. if (validUrl && (!editorUi.isOffline() || mxClient.IS_CHROMEAPP))
  802. {
  803. if (result.length < maxFbSize)
  804. {
  805. var fbBtn = mxUtils.button('', function()
  806. {
  807. try
  808. {
  809. var url = 'https://www.facebook.com/sharer.php?p[url]=' +
  810. encodeURIComponent(text.value);
  811. editorUi.openLink(url);
  812. }
  813. catch (e)
  814. {
  815. editorUi.handleError({message: e.message || mxResources.get('drawingTooLarge')});
  816. }
  817. });
  818. var img = document.createElement('img');
  819. img.setAttribute('src', Editor.facebookImage);
  820. img.setAttribute('width', '18');
  821. img.setAttribute('height', '18');
  822. img.setAttribute('border', '0');
  823. fbBtn.appendChild(img);
  824. fbBtn.setAttribute('title', mxResources.get('facebook') + ' (' +
  825. editorUi.formatFileSize(maxFbSize) + ' max)');
  826. fbBtn.style.verticalAlign = 'bottom';
  827. fbBtn.style.paddingTop = '4px';
  828. fbBtn.style.minWidth = '46px'
  829. fbBtn.className = 'geBtn';
  830. buttons.appendChild(fbBtn);
  831. }
  832. if (result.length < maxTwitterSize)
  833. {
  834. var tweetBtn = mxUtils.button('', function()
  835. {
  836. try
  837. {
  838. var url = 'https://twitter.com/intent/tweet?text=' +
  839. encodeURIComponent('Check out the diagram I made using @drawio') +
  840. '&url=' + encodeURIComponent(text.value);
  841. editorUi.openLink(url);
  842. }
  843. catch (e)
  844. {
  845. editorUi.handleError({message: e.message || mxResources.get('drawingTooLarge')});
  846. }
  847. });
  848. var img = document.createElement('img');
  849. img.setAttribute('src', Editor.tweetImage);
  850. img.setAttribute('width', '18');
  851. img.setAttribute('height', '18');
  852. img.setAttribute('border', '0');
  853. img.style.marginBottom = '5px'
  854. tweetBtn.appendChild(img);
  855. tweetBtn.setAttribute('title', mxResources.get('twitter') + ' (' +
  856. editorUi.formatFileSize(maxTwitterSize) + ' max)');
  857. tweetBtn.style.verticalAlign = 'bottom';
  858. tweetBtn.style.paddingTop = '4px';
  859. tweetBtn.style.minWidth = '46px'
  860. tweetBtn.className = 'geBtn';
  861. buttons.appendChild(tweetBtn);
  862. }
  863. }
  864. var closeBtn = mxUtils.button(mxResources.get('close'), function()
  865. {
  866. editorUi.hideDialog();
  867. });
  868. buttons.appendChild(closeBtn);
  869. var copyBtn = mxUtils.button(mxResources.get('copy'), function()
  870. {
  871. text.focus();
  872. if (mxClient.IS_GC || mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS)
  873. {
  874. text.select();
  875. }
  876. else
  877. {
  878. document.execCommand('selectAll', false, null);
  879. }
  880. document.execCommand('copy');
  881. editorUi.alert(mxResources.get('copiedToClipboard'));
  882. });
  883. if (result.length < maxSize)
  884. {
  885. // Does not work in Safari and shows annoying dialog for IE11-
  886. if (!mxClient.IS_SF && document.documentMode == null)
  887. {
  888. buttons.appendChild(copyBtn);
  889. copyBtn.className = 'geBtn gePrimaryBtn';
  890. closeBtn.className = 'geBtn';
  891. }
  892. else
  893. {
  894. closeBtn.className = 'geBtn gePrimaryBtn';
  895. }
  896. }
  897. else
  898. {
  899. buttons.appendChild(previewBtn);
  900. closeBtn.className = 'geBtn';
  901. previewBtn.className = 'geBtn gePrimaryBtn';
  902. }
  903. div.appendChild(buttons);
  904. this.container = div;
  905. };
  906. /**
  907. * Add embed dialog option.
  908. */
  909. EmbedDialog.showPreviewOption = true;
  910. /**
  911. * Constructs a dialog for embedding the diagram in Google Sites.
  912. */
  913. var GoogleSitesDialog = function(editorUi, publicUrl)
  914. {
  915. var div = document.createElement('div');
  916. var graph = editorUi.editor.graph;
  917. var bounds = graph.getGraphBounds();
  918. var scale = graph.view.scale;
  919. var x0 = Math.floor(bounds.x / scale - graph.view.translate.x);
  920. var y0 = Math.floor(bounds.y / scale - graph.view.translate.y);
  921. mxUtils.write(div, mxResources.get('googleGadget') + ':');
  922. mxUtils.br(div);
  923. var gadgetInput = document.createElement('input');
  924. gadgetInput.setAttribute('type', 'text');
  925. gadgetInput.style.marginBottom = '8px';
  926. gadgetInput.style.marginTop = '2px';
  927. gadgetInput.style.width = '410px';
  928. div.appendChild(gadgetInput);
  929. mxUtils.br(div);
  930. this.init = function()
  931. {
  932. gadgetInput.focus();
  933. if (mxClient.IS_GC || mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS)
  934. {
  935. gadgetInput.select();
  936. }
  937. else
  938. {
  939. document.execCommand('selectAll', false, null);
  940. }
  941. };
  942. mxUtils.write(div, mxResources.get('top') + ':');
  943. var topInput = document.createElement('input');
  944. topInput.setAttribute('type', 'text');
  945. topInput.setAttribute('size', '4');
  946. topInput.style.marginRight = '16px';
  947. topInput.style.marginLeft = '4px';
  948. topInput.value = x0;
  949. div.appendChild(topInput);
  950. mxUtils.write(div, mxResources.get('height') + ':');
  951. var heightInput = document.createElement('input');
  952. heightInput.setAttribute('type', 'text');
  953. heightInput.setAttribute('size', '4');
  954. heightInput.style.marginLeft = '4px';
  955. heightInput.value = Math.ceil(bounds.height / scale);
  956. div.appendChild(heightInput);
  957. mxUtils.br(div);
  958. var hr = document.createElement('hr');
  959. hr.setAttribute('size', '1');
  960. hr.style.marginBottom = '16px';
  961. hr.style.marginTop = '16px';
  962. div.appendChild(hr);
  963. mxUtils.write(div, mxResources.get('publicDiagramUrl') + ':');
  964. mxUtils.br(div);
  965. var urlInput = document.createElement('input');
  966. urlInput.setAttribute('type', 'text');
  967. urlInput.setAttribute('size', '28');
  968. urlInput.style.marginBottom = '8px';
  969. urlInput.style.marginTop = '2px';
  970. urlInput.style.width = '410px';
  971. urlInput.value = publicUrl || '';
  972. div.appendChild(urlInput);
  973. mxUtils.br(div);
  974. mxUtils.write(div, mxResources.get('borderWidth') + ':');
  975. var borderInput = document.createElement('input');
  976. borderInput.setAttribute('type', 'text');
  977. borderInput.setAttribute('size', '3');
  978. borderInput.style.marginBottom = '8px';
  979. borderInput.style.marginLeft = '4px';
  980. borderInput.value = '0';
  981. div.appendChild(borderInput);
  982. mxUtils.br(div);
  983. var panCheckBox = document.createElement('input');
  984. panCheckBox.setAttribute('type', 'checkbox');
  985. panCheckBox.setAttribute('checked', 'checked');
  986. panCheckBox.defaultChecked = true;
  987. panCheckBox.style.marginLeft = '16px';
  988. div.appendChild(panCheckBox);
  989. mxUtils.write(div, mxResources.get('pan') + ' ');
  990. var zoomCheckBox = document.createElement('input');
  991. zoomCheckBox.setAttribute('type', 'checkbox');
  992. zoomCheckBox.setAttribute('checked', 'checked');
  993. zoomCheckBox.defaultChecked = true;
  994. zoomCheckBox.style.marginLeft = '8px';
  995. div.appendChild(zoomCheckBox);
  996. mxUtils.write(div, mxResources.get('zoom') + ' ');
  997. var editCheckBox = document.createElement('input');
  998. editCheckBox.setAttribute('type', 'checkbox');
  999. editCheckBox.style.marginLeft = '8px';
  1000. editCheckBox.setAttribute('title', window.location.href);
  1001. div.appendChild(editCheckBox);
  1002. mxUtils.write(div, mxResources.get('edit') + ' ');
  1003. var editBlankCheckBox = document.createElement('input');
  1004. editBlankCheckBox.setAttribute('type', 'checkbox');
  1005. editBlankCheckBox.style.marginLeft = '8px';
  1006. div.appendChild(editBlankCheckBox);
  1007. mxUtils.write(div, mxResources.get('asNew') + ' ');
  1008. mxUtils.br(div);
  1009. var resizeCheckBox = document.createElement('input');
  1010. resizeCheckBox.setAttribute('type', 'checkbox');
  1011. resizeCheckBox.setAttribute('checked', 'checked');
  1012. resizeCheckBox.defaultChecked = true;
  1013. resizeCheckBox.style.marginLeft = '16px';
  1014. div.appendChild(resizeCheckBox);
  1015. mxUtils.write(div, mxResources.get('resize') + ' ');
  1016. var fitCheckBox = document.createElement('input');
  1017. fitCheckBox.setAttribute('type', 'checkbox');
  1018. fitCheckBox.style.marginLeft = '8px';
  1019. div.appendChild(fitCheckBox);
  1020. mxUtils.write(div, mxResources.get('fit') + ' ');
  1021. var embedCheckBox = document.createElement('input');
  1022. embedCheckBox.setAttribute('type', 'checkbox');
  1023. embedCheckBox.style.marginLeft = '8px';
  1024. div.appendChild(embedCheckBox);
  1025. mxUtils.write(div, mxResources.get('embed') + ' ');
  1026. var node = null;
  1027. var s = editorUi.getBasenames().join(';');
  1028. var file = editorUi.getCurrentFile();
  1029. function update()
  1030. {
  1031. var title = (file != null && file.getTitle() != null) ? file.getTitle() : this.defaultFilename;
  1032. if (embedCheckBox.checked && urlInput.value != '')
  1033. {
  1034. var encUrl = encodeURIComponent(mxUtils.htmlEntities(urlInput.value));
  1035. var gurl = 'https://www.draw.io/gadget.xml?type=4&diagram=' + encUrl;
  1036. if (title != null)
  1037. {
  1038. gurl += '&title=' + encodeURIComponent(title);
  1039. }
  1040. if (s.length > 0)
  1041. {
  1042. gurl += '&s=' + s;
  1043. }
  1044. if (borderInput.value != '' && borderInput.value != '0')
  1045. {
  1046. gurl += '&border=' + borderInput.value;
  1047. }
  1048. if (heightInput.value != '')
  1049. {
  1050. gurl += '&height=' + heightInput.value;
  1051. }
  1052. gurl += '&pan=' + ((panCheckBox.checked) ? '1': '0');
  1053. gurl += '&zoom=' + ((zoomCheckBox.checked) ? '1': '0');
  1054. gurl += '&fit=' + ((fitCheckBox.checked) ? '1': '0');
  1055. gurl += '&resize=' + ((resizeCheckBox.checked) ? '1': '0');
  1056. gurl += '&x0=' + Number(topInput.value);
  1057. gurl += '&y0=' + y0;
  1058. if (graph.mathEnabled)
  1059. {
  1060. gurl += '&math=1';
  1061. }
  1062. if (editBlankCheckBox.checked)
  1063. {
  1064. gurl += '&edit=_blank';
  1065. }
  1066. else if (editCheckBox.checked)
  1067. {
  1068. gurl += '&edit=' + encodeURIComponent(mxUtils.htmlEntities(window.location.href));
  1069. }
  1070. gadgetInput.value = gurl;
  1071. }
  1072. else if (file.constructor == DriveFile || file.constructor == DropboxFile)
  1073. {
  1074. var gurl = 'https://www.draw.io/gadget.xml?embed=0&diagram=';
  1075. if (urlInput.value != '')
  1076. {
  1077. gurl += encodeURIComponent(mxUtils.htmlEntities(urlInput.value)) + '&type=3';
  1078. }
  1079. else
  1080. {
  1081. gurl += file.getHash().substring(1);
  1082. if (file.constructor == DropboxFile)
  1083. {
  1084. gurl += '&type=2';
  1085. }
  1086. else
  1087. {
  1088. gurl += '&type=1';
  1089. }
  1090. }
  1091. if (title != null)
  1092. {
  1093. gurl += '&title=' + encodeURIComponent(title);
  1094. }
  1095. if (heightInput.value != '')
  1096. {
  1097. var h = parseInt(heightInput.value) + parseInt(topInput.value);
  1098. gurl += '&height=' + h;
  1099. }
  1100. gadgetInput.value = gurl;
  1101. }
  1102. else
  1103. {
  1104. gadgetInput.value = '';
  1105. }
  1106. };
  1107. mxEvent.addListener(panCheckBox, 'change', update);
  1108. mxEvent.addListener(zoomCheckBox, 'change', update);
  1109. mxEvent.addListener(resizeCheckBox, 'change', update);
  1110. mxEvent.addListener(fitCheckBox, 'change', update);
  1111. mxEvent.addListener(editCheckBox, 'change', update);
  1112. mxEvent.addListener(editBlankCheckBox, 'change', update);
  1113. mxEvent.addListener(embedCheckBox, 'change', update);
  1114. mxEvent.addListener(heightInput, 'change', update);
  1115. mxEvent.addListener(topInput, 'change', update);
  1116. mxEvent.addListener(borderInput, 'change', update);
  1117. mxEvent.addListener(urlInput, 'change', update);
  1118. update();
  1119. mxEvent.addListener(gadgetInput, 'click', function()
  1120. {
  1121. gadgetInput.focus();
  1122. if (mxClient.IS_GC || mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS)
  1123. {
  1124. gadgetInput.select();
  1125. }
  1126. else
  1127. {
  1128. document.execCommand('selectAll', false, null);
  1129. }
  1130. });
  1131. var buttons = document.createElement('div');
  1132. buttons.style.paddingTop = '12px';
  1133. buttons.style.textAlign = 'right';
  1134. var closeBtn = mxUtils.button(mxResources.get('close'), function()
  1135. {
  1136. editorUi.hideDialog();
  1137. });
  1138. closeBtn.className = 'geBtn gePrimaryBtn';
  1139. buttons.appendChild(closeBtn);
  1140. div.appendChild(buttons);
  1141. this.container = div;
  1142. };
  1143. /**
  1144. * Constructs a new parse dialog.
  1145. */
  1146. var CreateGraphDialog = function(editorUi, title, type)
  1147. {
  1148. var div = document.createElement('div');
  1149. div.style.textAlign = 'right';
  1150. this.init = function()
  1151. {
  1152. var container = document.createElement('div');
  1153. container.style.position = 'relative';
  1154. container.style.border = '1px solid gray';
  1155. container.style.width = '100%';
  1156. container.style.height = '360px';
  1157. container.style.overflow = 'hidden';
  1158. container.style.marginBottom = '16px';
  1159. mxEvent.disableContextMenu(container);
  1160. div.appendChild(container);
  1161. var graph = new Graph(container);
  1162. graph.setCellsCloneable(true);
  1163. graph.setPanning(true);
  1164. graph.setAllowDanglingEdges(false);
  1165. graph.connectionHandler.select = false;
  1166. graph.view.setTranslate(20, 20);
  1167. graph.border = 20;
  1168. graph.panningHandler.useLeftButtonForPanning = true;
  1169. var vertexStyle = 'rounded=1;';
  1170. var edgeStyle = 'curved=1;';
  1171. var startStyle = 'ellipse';
  1172. // FIXME: Does not work in iPad
  1173. var mxCellRendererInstallCellOverlayListeners = mxCellRenderer.prototype.installCellOverlayListeners;
  1174. graph.cellRenderer.installCellOverlayListeners = function(state, overlay, shape)
  1175. {
  1176. mxCellRenderer.prototype.installCellOverlayListeners.apply(this, arguments);
  1177. mxEvent.addListener(shape.node, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown', function (evt)
  1178. {
  1179. overlay.fireEvent(new mxEventObject('pointerdown', 'event', evt, 'state', state));
  1180. });
  1181. if (!mxClient.IS_POINTER && mxClient.IS_TOUCH)
  1182. {
  1183. mxEvent.addListener(shape.node, 'touchstart', function (evt)
  1184. {
  1185. overlay.fireEvent(new mxEventObject('pointerdown', 'event', evt, 'state', state));
  1186. });
  1187. }
  1188. };
  1189. graph.getAllConnectionConstraints = function()
  1190. {
  1191. return null;
  1192. };
  1193. // Keeps highlight behind overlays
  1194. graph.connectionHandler.marker.highlight.keepOnTop = false;
  1195. graph.connectionHandler.createEdgeState = function(me)
  1196. {
  1197. var edge = graph.createEdge(null, null, null, null, null, edgeStyle);
  1198. return new mxCellState(this.graph.view, edge, this.graph.getCellStyle(edge));
  1199. };
  1200. // Gets the default parent for inserting new cells. This
  1201. // is normally the first child of the root (ie. layer 0).
  1202. var parent = graph.getDefaultParent();
  1203. var addOverlay = mxUtils.bind(this, function(cell)
  1204. {
  1205. // Creates a new overlay with an image and a tooltip
  1206. var overlay = new mxCellOverlay(this.connectImage, 'Add outgoing');
  1207. overlay.cursor = 'hand';
  1208. // Installs a handler for clicks on the overlay
  1209. overlay.addListener(mxEvent.CLICK, function(sender, evt2)
  1210. {
  1211. // TODO: Add menu for picking next shape
  1212. graph.connectionHandler.reset();
  1213. graph.clearSelection();
  1214. var geo = graph.getCellGeometry(cell);
  1215. var v2;
  1216. executeLayout(function()
  1217. {
  1218. v2 = graph.insertVertex(parent, null, 'Entry', geo.x, geo.y, 80, 30, vertexStyle);
  1219. addOverlay(v2);
  1220. graph.view.refresh(v2);
  1221. var e1 = graph.insertEdge(parent, null, '', cell, v2, edgeStyle);
  1222. }, function()
  1223. {
  1224. graph.scrollCellToVisible(v2);
  1225. });
  1226. });
  1227. // FIXME: Does not work in iPad (inserts loop)
  1228. overlay.addListener('pointerdown', function(sender, eo)
  1229. {
  1230. var evt2 = eo.getProperty('event');
  1231. var state = eo.getProperty('state');
  1232. graph.popupMenuHandler.hideMenu();
  1233. graph.stopEditing(false);
  1234. var pt = mxUtils.convertPoint(graph.container,
  1235. mxEvent.getClientX(evt2), mxEvent.getClientY(evt2));
  1236. graph.connectionHandler.start(state, pt.x, pt.y);
  1237. graph.isMouseDown = true;
  1238. graph.isMouseTrigger = mxEvent.isMouseEvent(evt2);
  1239. mxEvent.consume(evt2);
  1240. });
  1241. // Sets the overlay for the cell in the graph
  1242. graph.addCellOverlay(cell, overlay);
  1243. });
  1244. // Adds cells to the model in a single step
  1245. graph.getModel().beginUpdate();
  1246. var v1;
  1247. try
  1248. {
  1249. v1 = graph.insertVertex(parent, null, 'Start', 0, 0, 80, 30, startStyle);
  1250. addOverlay(v1);
  1251. }
  1252. finally
  1253. {
  1254. // Updates the display
  1255. graph.getModel().endUpdate();
  1256. }
  1257. var layout;
  1258. if (type == 'horizontalTree')
  1259. {
  1260. layout = new mxCompactTreeLayout(graph);
  1261. layout.edgeRouting = false;
  1262. layout.levelDistance = 30;
  1263. edgeStyle = 'edgeStyle=elbowEdgeStyle;elbow=horizontal;';
  1264. }
  1265. else if (type == 'verticalTree')
  1266. {
  1267. layout = new mxCompactTreeLayout(graph, false);
  1268. layout.edgeRouting = false;
  1269. layout.levelDistance = 30;
  1270. edgeStyle = 'edgeStyle=elbowEdgeStyle;elbow=vertical;';
  1271. }
  1272. else if (type == 'radialTree')
  1273. {
  1274. layout = new mxRadialTreeLayout(graph, false);
  1275. layout.edgeRouting = false;
  1276. layout.levelDistance = 80;
  1277. }
  1278. else if (type == 'verticalFlow')
  1279. {
  1280. layout = new mxHierarchicalLayout(graph, mxConstants.DIRECTION_NORTH);
  1281. }
  1282. else if (type == 'horizontalFlow')
  1283. {
  1284. layout = new mxHierarchicalLayout(graph, mxConstants.DIRECTION_WEST);
  1285. }
  1286. else if (type == 'organic')
  1287. {
  1288. layout = new mxFastOrganicLayout(graph, false);
  1289. layout.forceConstant = 80;
  1290. }
  1291. else if (type == 'circle')
  1292. {
  1293. layout = new mxCircleLayout(graph);
  1294. }
  1295. if (layout != null)
  1296. {
  1297. var executeLayout = function(change, post)
  1298. {
  1299. graph.getModel().beginUpdate();
  1300. try
  1301. {
  1302. if (change != null)
  1303. {
  1304. change();
  1305. }
  1306. layout.execute(graph.getDefaultParent(), v1);
  1307. }
  1308. catch (e)
  1309. {
  1310. throw e;
  1311. }
  1312. finally
  1313. {
  1314. // New API for animating graph layout results asynchronously
  1315. var morph = new mxMorphing(graph);
  1316. morph.addListener(mxEvent.DONE, mxUtils.bind(this, function()
  1317. {
  1318. graph.getModel().endUpdate();
  1319. if (post != null)
  1320. {
  1321. post();
  1322. }
  1323. }));
  1324. morph.startAnimation();
  1325. }
  1326. };
  1327. var edgeHandleConnect = mxEdgeHandler.prototype.connect;
  1328. mxEdgeHandler.prototype.connect = function(edge, terminal, isSource, isClone, me)
  1329. {
  1330. edgeHandleConnect.apply(this, arguments);
  1331. executeLayout();
  1332. };
  1333. graph.resizeCell = function()
  1334. {
  1335. mxGraph.prototype.resizeCell.apply(this, arguments);
  1336. executeLayout();
  1337. };
  1338. graph.connectionHandler.addListener(mxEvent.CONNECT, function()
  1339. {
  1340. executeLayout();
  1341. });
  1342. }
  1343. var cancelBtn = mxUtils.button(mxResources.get('close'), function()
  1344. {
  1345. editorUi.confirm(mxResources.get('areYouSure'), function()
  1346. {
  1347. if (container.parentNode != null)
  1348. {
  1349. graph.destroy();
  1350. container.parentNode.removeChild(container);
  1351. }
  1352. editorUi.hideDialog();
  1353. });
  1354. })
  1355. cancelBtn.className = 'geBtn';
  1356. if (editorUi.editor.cancelFirst)
  1357. {
  1358. div.appendChild(cancelBtn);
  1359. }
  1360. var okBtn = mxUtils.button(mxResources.get('insert'), function()
  1361. {
  1362. graph.clearCellOverlays();
  1363. // Computes unscaled, untranslated graph bounds
  1364. var pt = editorUi.editor.graph.getFreeInsertPoint();
  1365. var cells = editorUi.editor.graph.importCells(
  1366. graph.getModel().getChildren(graph.getDefaultParent()), pt.x, pt.y);
  1367. var view = editorUi.editor.graph.view;
  1368. var temp = view.getBounds(cells);
  1369. temp.x -= view.translate.x;
  1370. temp.y -= view.translate.y;
  1371. editorUi.editor.graph.scrollRectToVisible(temp);
  1372. editorUi.editor.graph.setSelectionCells(cells);
  1373. if (container.parentNode != null)
  1374. {
  1375. graph.destroy();
  1376. container.parentNode.removeChild(container);
  1377. }
  1378. editorUi.hideDialog();
  1379. });
  1380. div.appendChild(okBtn);
  1381. okBtn.className = 'geBtn gePrimaryBtn';
  1382. if (!editorUi.editor.cancelFirst)
  1383. {
  1384. div.appendChild(cancelBtn);
  1385. }
  1386. };
  1387. this.container = div;
  1388. };
  1389. /**
  1390. *
  1391. */
  1392. CreateGraphDialog.prototype.connectImage = new mxImage((mxClient.IS_SVG) ? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RjQ3OTk0QjMyRDcyMTFFNThGQThGNDVBMjNBMjFDMzkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RjQ3OTk0QjQyRDcyMTFFNThGQThGNDVBMjNBMjFDMzkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyRjA0N0I2MjJENzExMUU1OEZBOEY0NUEyM0EyMUMzOSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpGNDc5OTRCMjJENzIxMUU1OEZBOEY0NUEyM0EyMUMzOSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PjIf+MgAAATlSURBVHjanFZraFxFFD735u4ru3ls0yZG26ShgmJoKK1J2vhIYzBgRdtIURHyw1hQUH9IxIgI2h8iCEUF/1RRlNQYCsYfCTHVhiTtNolpZCEStqSC22xIsrs1bDfu7t37Gs/cO3Ozxs1DBw73zpk555vzmHNGgJ0NYatFgmNLYUHYUoHASMz5ijmgVLmxgfKCUiBxC4ACJAeSG8nb1dVVOTc3dyoSibwWDofPBIPBJzo7O8vpGtvjpDICGztxkciECpF2LS0tvZtOpwNkk5FKpcYXFxffwL1+JuPgllPj8nk1F6RoaGjoKCqZ5ApljZDZO4SMRA0SuG2QUJIQRV8HxMOM9vf3H0ZZH9Nhg20MMl2QkFwjIyNHWlpahtADnuUMwLcRHX5aNSBjCJYEsSSLUeLEbhGe3ytCmQtA1/XY+Pj46dbW1iDuyCJp9BC5ycBj4hoeHq5ra2sbw0Xn1ZgBZ+dVkA1Lc+6p0Ck2p0QS4Ox9EhwpEylYcmBg4LH29vYQLilIOt0u5FhDfevNZDI/u93uw6PLOrwTUtjxrbPYbhD42WgMrF8JmR894ICmCgnQjVe8Xu8pXEkzMJKbuo5oNPomBbm1ZsD7s2kwFA1JZ6QBUXWT1nmGNc/qoMgavDcrQzxjQGFh4aOYIJ0sFAXcEtui4uLiVjr5KpSBVFYDDZVrWUaKRRWSAYeK0fmKykgDXbVoNaPChRuyqdDv97czL5nXxQbq6empQmsaklkDBiNpSwFVrmr2P6UyicD5piI4f8wHh0oEm8/p4h8pyGiEWvVQd3e3nxtjAzU1NR2jP7NRBWQ8GbdEzzJAmc0V3RR4cI8Dvmwuhc8fKUFA0d6/ltHg5p+Kuaejo6OeY0jcNJ/PV00ZS0nFUoZRvvFS1bZFsKHCCQ2Pl8H0chY+C96B6ZUsrCQ1qKtwQVFRURW/QhIXMAzDPAZ6BgOr8tTa8dDxCmiYGApaJbJMxSzV+brE8pdgWkcpY5dbMF1AR9XH8/xu2ilef48bvn92n82ZwHh+8ssqTEXS9p7dHisiiURikd8PbpExNTU1UVNTA3V3Y7lC16n0gpB/NwpNcZjfa7dScC4Qh0kOQCwnlEgi3F/hMVl9fX0zvKrzSk2lfXjRhj0eT/2rvWG4+Pta3oJY7XfC3hInXAv/ldeFLx8shQ+eqQL0UAAz7ylkpej5eNZRVBWL6BU6ef14OYiY1oqyTtmsavr/5koaRucT1pzx+ZpL1+GV5nLutksUgIcmtwTRiuuVZXnU5XId7A2swJkfFsymRWC91hHg1Viw6x23+7vn9sPJ+j20BE1hCXqSWaNSQ8ScbknRZWxub1PGCw/fBV+c3AeijlUbY5bBjEqr9GuYZP4jP41WudGSC6erTRCqdGZm5i1WvXWeDHnbBCZGc2Nj4wBl/hZOwrmBBfgmlID1HmGJutHaF+tKoevp/XCgstDkjo2NtWKLuc6AVN4mNjY+s1XQxoenOoFuDPHGtnRbJj9ej5GvL0dI7+giuRyMk1giazc+DP6vgUDgOJVlOv7R+PJ12QIeL6SyeDz+Kfp8ZrNWjgDTsVjsQ7qXyTjztXJhm9ePxFLfMTg4eG9tbe1RTP9KFFYQfHliYmIS69kCC7jKYmKwxxD5P88tkVkqbPPcIps9t4T/+HjcuJ/s5BFJgf4WYABCtxGuxIZ90gAAAABJRU5ErkJggg==' :
  1393. IMAGE_PATH + '/handle-connect.png', 26, 26);
  1394. /**
  1395. * Constructs a new parse dialog.
  1396. */
  1397. var BackgroundImageDialog = function(editorUi, applyFn)
  1398. {
  1399. var div = document.createElement('div');
  1400. div.style.whiteSpace = 'nowrap';
  1401. var h3 = document.createElement('h2');
  1402. mxUtils.write(h3, mxResources.get('backgroundImage'));
  1403. h3.style.marginTop = '0px';
  1404. div.appendChild(h3);
  1405. mxUtils.write(div, mxResources.get('image') + ' ' + mxResources.get('url') + ':');
  1406. mxUtils.br(div);
  1407. var img = editorUi.editor.graph.backgroundImage;
  1408. var urlInput = document.createElement('input');
  1409. urlInput.setAttribute('type', 'text');
  1410. urlInput.style.marginTop = '4px';
  1411. urlInput.style.marginBottom = '4px';
  1412. urlInput.style.width = '350px';
  1413. urlInput.value = (img != null) ? img.src : '';
  1414. var resetting = false;
  1415. var urlChanged = function()
  1416. {
  1417. if (!resetting && urlInput.value != '' && !editorUi.isOffline())
  1418. {
  1419. editorUi.loadImage(mxUtils.trim(urlInput.value), function(img)
  1420. {
  1421. widthInput.value = img.width;
  1422. heightInput.value = img.height;
  1423. }, function()
  1424. {
  1425. editorUi.showError(mxResources.get('error'), mxResources.get('fileNotFound'), mxResources.get('ok'));
  1426. urlInput.value = '';
  1427. widthInput.value = '';
  1428. heightInput.value = '';
  1429. });
  1430. }
  1431. else
  1432. {
  1433. widthInput.value = '';
  1434. heightInput.value = '';
  1435. }
  1436. };
  1437. this.init = function()
  1438. {
  1439. urlInput.focus();
  1440. // Installs drag and drop handler for local images and links
  1441. if (Graph.fileSupport)
  1442. {
  1443. urlInput.setAttribute('placeholder', mxResources.get('dragImagesHere'));
  1444. // Setup the dnd listeners
  1445. var dlg = div.parentNode;
  1446. var graph = editorUi.editor.graph;
  1447. var dropElt = null;
  1448. mxEvent.addListener(dlg, 'dragleave', function(evt)
  1449. {
  1450. if (dropElt != null)
  1451. {
  1452. dropElt.parentNode.removeChild(dropElt);
  1453. dropElt = null;
  1454. }
  1455. evt.stopPropagation();
  1456. evt.preventDefault();
  1457. });
  1458. mxEvent.addListener(dlg, 'dragover', mxUtils.bind(this, function(evt)
  1459. {
  1460. // IE 10 does not implement pointer-events so it can't have a drop highlight
  1461. if (dropElt == null && (!mxClient.IS_IE || document.documentMode > 10))
  1462. {
  1463. dropElt = editorUi.highlightElement(dlg);
  1464. }
  1465. evt.stopPropagation();
  1466. evt.preventDefault();
  1467. }));
  1468. mxEvent.addListener(dlg, 'drop', mxUtils.bind(this, function(evt)
  1469. {
  1470. if (dropElt != null)
  1471. {
  1472. dropElt.parentNode.removeChild(dropElt);
  1473. dropElt = null;
  1474. }
  1475. if (evt.dataTransfer.files.length > 0)
  1476. {
  1477. editorUi.importFiles(evt.dataTransfer.files, 0, 0, editorUi.maxBackgroundSize, function(data, mimeType, x, y, w, h)
  1478. {
  1479. urlInput.value = data;
  1480. urlChanged();
  1481. }, function()
  1482. {
  1483. // No post processing
  1484. }, function(file)
  1485. {
  1486. // Handles only images
  1487. return file.type.substring(0, 6) == 'image/';
  1488. }, function(queue)
  1489. {
  1490. // Invokes elements of queue in order
  1491. for (var i = 0; i < queue.length; i++)
  1492. {
  1493. queue[i]();
  1494. }
  1495. }, true, editorUi.maxBackgroundBytes, editorUi.maxBackgroundBytes);
  1496. }
  1497. else if (mxUtils.indexOf(evt.dataTransfer.types, 'text/uri-list') >= 0)
  1498. {
  1499. var uri = evt.dataTransfer.getData('text/uri-list');
  1500. if ((/\.(gif|jpg|jpeg|tiff|png|svg)$/i).test(uri))
  1501. {
  1502. urlInput.value = decodeURIComponent(uri);
  1503. urlChanged();
  1504. }
  1505. }
  1506. evt.stopPropagation();
  1507. evt.preventDefault();
  1508. }), false);
  1509. }
  1510. };
  1511. div.appendChild(urlInput);
  1512. mxUtils.br(div);
  1513. mxUtils.br(div);
  1514. mxUtils.write(div, mxResources.get('width') + ':');
  1515. var widthInput = document.createElement('input');
  1516. widthInput.setAttribute('type', 'text');
  1517. widthInput.style.width = '60px';
  1518. widthInput.style.marginLeft = '4px';
  1519. widthInput.style.marginRight = '16px';
  1520. widthInput.value = (img != null) ? img.width : '';
  1521. div.appendChild(widthInput);
  1522. mxUtils.write(div, mxResources.get('height') + ':');
  1523. var heightInput = document.createElement('input');
  1524. heightInput.setAttribute('type', 'text');
  1525. heightInput.style.width = '60px';
  1526. heightInput.style.marginLeft = '4px';
  1527. heightInput.style.marginRight = '16px';
  1528. heightInput.value = (img != null) ? img.height : '';
  1529. div.appendChild(heightInput);
  1530. var resetBtn = mxUtils.button(mxResources.get('reset'), function()
  1531. {
  1532. urlInput.value = '';
  1533. widthInput.value = '';
  1534. heightInput.value = '';
  1535. resetting = false;
  1536. });
  1537. mxEvent.addListener(resetBtn, 'mousedown', function()
  1538. {
  1539. // Blocks processing a image URL while clicking reset
  1540. resetting = true;
  1541. });
  1542. mxEvent.addListener(resetBtn, 'touchstart', function()
  1543. {
  1544. // Blocks processing a image URL while clicking reset
  1545. resetting = true;
  1546. });
  1547. resetBtn.className = 'geBtn';
  1548. resetBtn.width = '100';
  1549. div.appendChild(resetBtn);
  1550. mxUtils.br(div);
  1551. mxEvent.addListener(urlInput, 'change', urlChanged);
  1552. ImageDialog.filePicked = function(data)
  1553. {
  1554. if (data.action == google.picker.Action.PICKED)
  1555. {
  1556. if (data.docs[0].thumbnails != null)
  1557. {
  1558. var thumb = data.docs[0].thumbnails[data.docs[0].thumbnails.length - 1];
  1559. if (thumb != null)
  1560. {
  1561. urlInput.value = thumb.url;
  1562. urlChanged();
  1563. }
  1564. }
  1565. }
  1566. urlInput.focus();
  1567. };
  1568. var btns = document.createElement('div');
  1569. btns.style.marginTop = '40px';
  1570. btns.style.textAlign = 'right';
  1571. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  1572. {
  1573. editorUi.hideDialog();
  1574. });
  1575. cancelBtn.className = 'geBtn';
  1576. if (editorUi.editor.cancelFirst)
  1577. {
  1578. btns.appendChild(cancelBtn);
  1579. }
  1580. if (!editorUi.isOffline())
  1581. {
  1582. // Dialogs not allowed inside iframes
  1583. if (typeof(google) != 'undefined' && typeof(google.picker) != 'undefined' && window.self === window.top)
  1584. {
  1585. var searchBtn = mxUtils.button(mxResources.get('search'), function()
  1586. {
  1587. // Creates one picker and reuses it to avoid polluting the DOM
  1588. if (editorUi.imageSearchPicker == null)
  1589. {
  1590. var picker = new google.picker.PickerBuilder()
  1591. .setLocale(mxLanguage)
  1592. .addView(google.picker.ViewId.IMAGE_SEARCH)
  1593. .enableFeature(google.picker.Feature.NAV_HIDDEN);
  1594. editorUi.imageSearchPicker = picker.setCallback(function(data)
  1595. {
  1596. ImageDialog.filePicked(data);
  1597. }).build();
  1598. }
  1599. editorUi.imageSearchPicker.setVisible(true);
  1600. });
  1601. searchBtn.className = 'geBtn';
  1602. btns.appendChild(searchBtn);
  1603. if (editorUi.drive != null && urlParams['photos'] == '1')
  1604. {
  1605. var gpBtn = mxUtils.button(mxResources.get('googlePlus'), function()
  1606. {
  1607. if (editorUi.spinner.spin(document.body, mxResources.get('authorizing')))
  1608. {
  1609. editorUi.drive.checkToken(mxUtils.bind(this, function()
  1610. {
  1611. editorUi.spinner.stop();
  1612. // Creates one picker and reuses it to avoid polluting the DOM
  1613. if (editorUi.photoPicker == null)
  1614. {
  1615. var token = gapi.auth.getToken().access_token;
  1616. var picker = new google.picker.PickerBuilder()
  1617. .setAppId(editorUi.drive.appId)
  1618. .setLocale(mxLanguage)
  1619. .setOAuthToken(token)
  1620. .addView(google.picker.ViewId.PHOTOS)
  1621. .addView(google.picker.ViewId.PHOTO_ALBUMS)
  1622. .addView(google.picker.ViewId.PHOTO_UPLOAD);
  1623. editorUi.photoPicker = picker.setCallback(function(data)
  1624. {
  1625. ImageDialog.filePicked(data);
  1626. }).build();
  1627. }
  1628. editorUi.photoPicker.setVisible(true);
  1629. }));
  1630. }
  1631. });
  1632. gpBtn.className = 'geBtn';
  1633. btns.appendChild(gpBtn);
  1634. }
  1635. }
  1636. }
  1637. var applyBtn = mxUtils.button(mxResources.get('apply'), function()
  1638. {
  1639. editorUi.hideDialog();
  1640. applyFn((urlInput.value != '') ? new mxImage(mxUtils.trim(urlInput.value), widthInput.value, heightInput.value) : null);
  1641. });
  1642. applyBtn.className = 'geBtn gePrimaryBtn';
  1643. btns.appendChild(applyBtn);
  1644. if (!editorUi.editor.cancelFirst)
  1645. {
  1646. btns.appendChild(cancelBtn);
  1647. }
  1648. div.appendChild(btns);
  1649. this.container = div;
  1650. };
  1651. /**
  1652. * Constructs a new parse dialog.
  1653. */
  1654. var ParseDialog = function(editorUi, title, defaultType)
  1655. {
  1656. var insertPoint = editorUi.editor.graph.getFreeInsertPoint();
  1657. function parse(text, type)
  1658. {
  1659. var lines = text.split('\n');
  1660. if (type == 'plantUmlPng' || type == 'plantUmlSvg' || type == 'plantUmlTxt')
  1661. {
  1662. var plantUmlServerUrl = (type == 'plantUmlTxt') ? PLANT_URL + '/txt/' :
  1663. ((type == 'plantUmlPng') ? PLANT_URL + '/png/' : PLANT_URL + '/svg/');
  1664. var graph = editorUi.editor.graph;
  1665. // TODO: Change server to return base64 and accept POST request
  1666. if (editorUi.spinner.spin(document.body, mxResources.get('inserting')))
  1667. {
  1668. function encode64(data)
  1669. {
  1670. r = "";
  1671. for (i = 0; i < data.length; i += 3)
  1672. {
  1673. if (i + 2 == data.length)
  1674. {
  1675. r += append3bytes(data.charCodeAt(i), data.charCodeAt(i + 1), 0);
  1676. }
  1677. else if (i + 1 == data.length)
  1678. {
  1679. r += append3bytes(data.charCodeAt(i), 0, 0);
  1680. }
  1681. else
  1682. {
  1683. r += append3bytes(data.charCodeAt(i), data.charCodeAt(i + 1),
  1684. data.charCodeAt(i + 2));
  1685. }
  1686. }
  1687. return r;
  1688. }
  1689. function append3bytes(b1, b2, b3)
  1690. {
  1691. c1 = b1 >> 2;
  1692. c2 = ((b1 & 0x3) << 4) | (b2 >> 4);
  1693. c3 = ((b2 & 0xF) << 2) | (b3 >> 6);
  1694. c4 = b3 & 0x3F;
  1695. r = "";
  1696. r += encode6bit(c1 & 0x3F);
  1697. r += encode6bit(c2 & 0x3F);
  1698. r += encode6bit(c3 & 0x3F);
  1699. r += encode6bit(c4 & 0x3F);
  1700. return r;
  1701. }
  1702. function encode6bit(b)
  1703. {
  1704. if (b < 10)
  1705. {
  1706. return String.fromCharCode(48 + b);
  1707. }
  1708. b -= 10;
  1709. if (b < 26)
  1710. {
  1711. return String.fromCharCode(65 + b);
  1712. }
  1713. b -= 26;
  1714. if (b < 26)
  1715. {
  1716. return String.fromCharCode(97 + b);
  1717. }
  1718. b -= 26;
  1719. if (b == 0)
  1720. {
  1721. return '-';
  1722. }
  1723. if (b == 1)
  1724. {
  1725. return '_';
  1726. }
  1727. return '?';
  1728. }
  1729. // TODO: Remove unescape, use btoa for compatibility with graph.compress
  1730. function compress(s)
  1731. {
  1732. return encode64(Graph.bytesToString(
  1733. pako.deflateRaw(unescape(
  1734. encodeURIComponent(s)))));
  1735. };
  1736. var xhr = new XMLHttpRequest();
  1737. xhr.open('GET', plantUmlServerUrl + compress(text), true);
  1738. if (type != 'plantUmlTxt')
  1739. {
  1740. xhr.responseType = 'blob';
  1741. }
  1742. xhr.onload = function(e)
  1743. {
  1744. if (this.status >= 200 && this.status < 300)
  1745. {
  1746. if (type == 'plantUmlTxt')
  1747. {
  1748. editorUi.spinner.stop();
  1749. graph.setSelectionCell(editorUi.insertAsPreText(
  1750. this.response, insertPoint.x, insertPoint.y));
  1751. graph.scrollCellToVisible(graph.getSelectionCell());
  1752. }
  1753. else
  1754. {
  1755. var reader = new FileReader();
  1756. reader.readAsDataURL(this.response);
  1757. reader.onloadend = function(e)
  1758. {
  1759. var img = new Image();
  1760. img.onload = function()
  1761. {
  1762. editorUi.spinner.stop();
  1763. var w = img.width;
  1764. var h = img.height;
  1765. // Workaround for 0 image size in IE11
  1766. if (w == 0 && h == 0)
  1767. {
  1768. var data = reader.result;
  1769. var comma = data.indexOf(',');
  1770. var svgText = decodeURIComponent(escape(atob(data.substring(comma + 1))));
  1771. var root = mxUtils.parseXml(svgText);
  1772. var svgs = root.getElementsByTagName('svg');
  1773. if (svgs.length > 0)
  1774. {
  1775. w = parseFloat(svgs[0].getAttribute('width'));
  1776. h = parseFloat(svgs[0].getAttribute('height'));
  1777. }
  1778. }
  1779. graph.getModel().beginUpdate();
  1780. try
  1781. {
  1782. cell = graph.insertVertex(null, null, text, insertPoint.x, insertPoint.y,
  1783. w, h, 'shape=image;noLabel=1;verticalAlign=top;aspect=fixed;imageAspect=0;' +
  1784. 'image=' + editorUi.convertDataUri(reader.result) + ';');
  1785. }
  1786. finally
  1787. {
  1788. graph.getModel().endUpdate();
  1789. }
  1790. graph.setSelectionCell(cell);
  1791. graph.scrollCellToVisible(graph.getSelectionCell());
  1792. };
  1793. img.src = reader.result;
  1794. };
  1795. reader.onerror = function(e)
  1796. {
  1797. editorUi.handleError(e);
  1798. };
  1799. }
  1800. }
  1801. else
  1802. {
  1803. editorUi.spinner.stop();
  1804. editorUi.handleError(e);
  1805. }
  1806. };
  1807. xhr.onerror = function(e)
  1808. {
  1809. editorUi.handleError(e);
  1810. };
  1811. xhr.send();
  1812. }
  1813. }
  1814. else if (type == 'table')
  1815. {
  1816. var tableCell = null;
  1817. var rows = null;
  1818. var cells = [];
  1819. var dx = 0;
  1820. for (var i = 0; i < lines.length; i++)
  1821. {
  1822. var tmp = mxUtils.trim(lines[i]);
  1823. if (tmp.substring(0, 12).toLowerCase() == 'create table')
  1824. {
  1825. var name = mxUtils.trim(tmp.substring(12));
  1826. if (name.charAt(name.length - 1) == '(')
  1827. {
  1828. name = name.substring(0, name.lastIndexOf(' '));
  1829. }
  1830. tableCell = new mxCell(name, new mxGeometry(dx, 0, 160, 26),
  1831. 'swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=26;fillColor=#e0e0e0;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;align=center;');
  1832. tableCell.vertex = true;
  1833. cells.push(tableCell);
  1834. var size = editorUi.editor.graph.getPreferredSizeForCell(rowCell);
  1835. if (size != null)
  1836. {
  1837. tableCell.geometry.width = size.width + 10;
  1838. }
  1839. // For primary key lookups
  1840. rows = {};
  1841. }
  1842. else if (tableCell != null && tmp.charAt(0) == ')')
  1843. {
  1844. dx += tableCell.geometry.width + 40;
  1845. tableCell = null;
  1846. }
  1847. else if (tmp != '(' && tableCell != null)
  1848. {
  1849. var name = tmp.substring(0, (tmp.charAt(tmp.length - 1) == ',') ? tmp.length - 1 : tmp.length);
  1850. if (name.substring(0, 11).toLowerCase() != 'primary key')
  1851. {
  1852. var pk = name.toLowerCase().indexOf('primary key');
  1853. name = name.replace(/primary key/i, '');
  1854. var rowCell = new mxCell(name, new mxGeometry(0, 0, 90, 26),
  1855. 'shape=partialRectangle;top=0;left=0;right=0;bottom=0;align=left;verticalAlign=top;spacingTop=-2;fillColor=none;spacingLeft=34;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;dropTarget=0;');
  1856. rowCell.vertex = true;
  1857. var left = sb.cloneCell(rowCell, (pk > 0) ? 'PK' : '');
  1858. left.connectable = false;
  1859. left.style = 'shape=partialRectangle;top=0;left=0;bottom=0;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[];portConstraint=eastwest;part=1;'
  1860. left.geometry.width = 30;
  1861. left.geometry.height = 26;
  1862. rowCell.insert(left);
  1863. var size = editorUi.editor.graph.getPreferredSizeForCell(rowCell);
  1864. if (size != null && tableCell.geometry.width < size.width + 10)
  1865. {
  1866. tableCell.geometry.width = Math.min(220, size.width + 10);
  1867. }
  1868. tableCell.insert(rowCell);
  1869. tableCell.geometry.height += 26;
  1870. rows[rowCell.value] = rowCell;
  1871. }
  1872. }
  1873. }
  1874. if (cells.length > 0)
  1875. {
  1876. var graph = editorUi.editor.graph;
  1877. var view = graph.view;
  1878. var bds = graph.getGraphBounds();
  1879. // Computes unscaled, untranslated graph bounds
  1880. var x = Math.ceil(Math.max(0, bds.x / view.scale - view.translate.x) + 4 * graph.gridSize);
  1881. var y = Math.ceil(Math.max(0, (bds.y + bds.height) / view.scale - view.translate.y) + 4 * graph.gridSize);
  1882. graph.setSelectionCells(graph.importCells(cells, x, y));
  1883. graph.scrollCellToVisible(graph.getSelectionCell());
  1884. }
  1885. }
  1886. else if (type == 'list')
  1887. {
  1888. if (lines.length > 0)
  1889. {
  1890. var graph = editorUi.editor.graph;
  1891. var listCell = new mxCell(lines[0], new mxGeometry(0, 0, 160, 26 + 4),
  1892. 'swimlane;fontStyle=1;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;');
  1893. listCell.vertex = true;
  1894. var size = graph.getPreferredSizeForCell(listCell);
  1895. if (size != null && listCell.geometry.width < size.width + 10)
  1896. {
  1897. listCell.geometry.width = size.width + 10;
  1898. }
  1899. var inserted = [listCell];
  1900. if (lines.length > 1)
  1901. {
  1902. for (var i = 1; i < lines.length; i++)
  1903. {
  1904. if (lines[i] == '--')
  1905. {
  1906. var divider = new mxCell('', new mxGeometry(0, 0, 40, 8), 'line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;');
  1907. divider.vertex = true;
  1908. listCell.geometry.height += divider.geometry.height;
  1909. listCell.insert(divider);
  1910. inserted.push(divider);
  1911. }
  1912. else if (lines[i].length > 0 && lines[i].charAt(0) != ';')
  1913. {
  1914. var field = new mxCell(lines[i], new mxGeometry(0, 0, 60, 26), 'text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;');
  1915. field.vertex = true;
  1916. var size = graph.getPreferredSizeForCell(field);
  1917. if (size != null && field.geometry.width < size.width)
  1918. {
  1919. field.geometry.width = size.width;
  1920. }
  1921. listCell.geometry.width = Math.max(listCell.geometry.width, field.geometry.width);
  1922. listCell.geometry.height += field.geometry.height;
  1923. listCell.insert(field);
  1924. inserted.push(field);
  1925. }
  1926. }
  1927. }
  1928. graph.getModel().beginUpdate();
  1929. try
  1930. {
  1931. listCell = graph.importCells([listCell], insertPoint.x, insertPoint.y)[0];
  1932. graph.fireEvent(new mxEventObject('cellsInserted', 'cells', [listCell].concat(listCell.children)));
  1933. }
  1934. finally
  1935. {
  1936. graph.getModel().endUpdate();
  1937. }
  1938. graph.setSelectionCell(listCell);
  1939. graph.scrollCellToVisible(graph.getSelectionCell());
  1940. }
  1941. }
  1942. else
  1943. {
  1944. var vertices = new Object();
  1945. var cells = [];
  1946. function getOrCreateVertex(id)
  1947. {
  1948. var vertex = vertices[id];
  1949. if (vertex == null)
  1950. {
  1951. vertex = new mxCell(id, new mxGeometry(0, 0, 80, 30), 'whiteSpace=wrap;html=1;');
  1952. vertex.vertex = true;
  1953. vertices[id] = vertex;
  1954. cells.push(vertex);
  1955. }
  1956. return vertex;
  1957. };
  1958. for (var i = 0; i < lines.length; i++)
  1959. {
  1960. if (lines[i].charAt(0) != ';')
  1961. {
  1962. var values = lines[i].split('->');
  1963. if (values.length >= 2)
  1964. {
  1965. var source = getOrCreateVertex(values[0]);
  1966. var target = getOrCreateVertex(values[values.length - 1]);
  1967. var edge = new mxCell((values.length > 2) ? values[1] : '', new mxGeometry());
  1968. edge.edge = true;
  1969. source.insertEdge(edge, true);
  1970. target.insertEdge(edge, false);
  1971. cells.push(edge);
  1972. }
  1973. }
  1974. }
  1975. if (cells.length > 0)
  1976. {
  1977. var container = document.createElement('div');
  1978. container.style.visibility = 'hidden';
  1979. document.body.appendChild(container);
  1980. // Temporary graph for running the layout
  1981. var graph = new Graph(container);
  1982. graph.getModel().beginUpdate();
  1983. try
  1984. {
  1985. cells = graph.importCells(cells);
  1986. for (var i = 0; i < cells.length; i++)
  1987. {
  1988. if (graph.getModel().isVertex(cells[i]))
  1989. {
  1990. var size = graph.getPreferredSizeForCell(cells[i]);
  1991. cells[i].geometry.width = Math.max(cells[i].geometry.width, size.width);
  1992. cells[i].geometry.height = Math.max(cells[i].geometry.height, size.height);
  1993. }
  1994. }
  1995. var layout = new mxFastOrganicLayout(graph);
  1996. layout.disableEdgeStyle = false;
  1997. layout.forceConstant = 120;
  1998. layout.execute(graph.getDefaultParent());
  1999. var edgeLayout = new mxParallelEdgeLayout(graph);
  2000. edgeLayout.spacing = 20;
  2001. edgeLayout.execute(graph.getDefaultParent());
  2002. }
  2003. finally
  2004. {
  2005. graph.getModel().endUpdate();
  2006. }
  2007. graph.clearCellOverlays();
  2008. // Copy to actual graph
  2009. var inserted = [];
  2010. editorUi.editor.graph.getModel().beginUpdate();
  2011. try
  2012. {
  2013. inserted = editorUi.editor.graph.importCells(graph.getModel().getChildren(
  2014. graph.getDefaultParent()), insertPoint.x, insertPoint.y)
  2015. editorUi.editor.graph.fireEvent(new mxEventObject('cellsInserted', 'cells', inserted));
  2016. }
  2017. finally
  2018. {
  2019. editorUi.editor.graph.getModel().endUpdate();
  2020. }
  2021. editorUi.editor.graph.setSelectionCells(inserted);
  2022. editorUi.editor.graph.scrollCellToVisible(editorUi.editor.graph.getSelectionCell());
  2023. graph.destroy();
  2024. container.parentNode.removeChild(container);
  2025. }
  2026. }
  2027. };
  2028. var div = document.createElement('div');
  2029. div.style.textAlign = 'right';
  2030. var textarea = document.createElement('textarea');
  2031. textarea.style.resize = 'none';
  2032. textarea.style.width = '100%';
  2033. textarea.style.height = '354px';
  2034. textarea.style.marginBottom = '16px';
  2035. var typeSelect = document.createElement('select');
  2036. if (defaultType == 'formatSql')
  2037. {
  2038. typeSelect.style.display = 'none';
  2039. }
  2040. var listOption = document.createElement('option');
  2041. listOption.setAttribute('value', 'list');
  2042. mxUtils.write(listOption, mxResources.get('list'));
  2043. if (defaultType != 'plantUml')
  2044. {
  2045. typeSelect.appendChild(listOption);
  2046. }
  2047. if (defaultType == null || defaultType == 'fromText')
  2048. {
  2049. listOption.setAttribute('selected', 'selected');
  2050. }
  2051. var tableOption = document.createElement('option');
  2052. tableOption.setAttribute('value', 'table');
  2053. mxUtils.write(tableOption, mxResources.get('formatSql'));
  2054. if (defaultType == 'formatSql')
  2055. {
  2056. typeSelect.appendChild(tableOption);
  2057. tableOption.setAttribute('selected', 'selected');
  2058. }
  2059. var diagramOption = document.createElement('option');
  2060. diagramOption.setAttribute('value', 'diagram');
  2061. mxUtils.write(diagramOption, mxResources.get('diagram'));
  2062. if (defaultType != 'plantUml')
  2063. {
  2064. typeSelect.appendChild(diagramOption);
  2065. }
  2066. var plantUmlSvgOption = document.createElement('option');
  2067. plantUmlSvgOption.setAttribute('value', 'plantUmlSvg');
  2068. mxUtils.write(plantUmlSvgOption, mxResources.get('plantUml') + ' (' + mxResources.get('formatSvg') + ')');
  2069. if (defaultType == 'plantUml')
  2070. {
  2071. plantUmlSvgOption.setAttribute('selected', 'selected');
  2072. }
  2073. var plantUmlPngOption = document.createElement('option');
  2074. plantUmlPngOption.setAttribute('value', 'plantUmlPng');
  2075. mxUtils.write(plantUmlPngOption, mxResources.get('plantUml') + ' (' + mxResources.get('formatPng') + ')');
  2076. var plantUmlTxtOption = document.createElement('option');
  2077. plantUmlTxtOption.setAttribute('value', 'plantUmlTxt');
  2078. mxUtils.write(plantUmlTxtOption, mxResources.get('plantUml') + ' (' + mxResources.get('text') + ')');
  2079. // Disabled for invalid hosts via CORS headers
  2080. if (EditorUi.enablePlantUml && Graph.fileSupport &&
  2081. !editorUi.isOffline() && defaultType == 'plantUml')
  2082. {
  2083. typeSelect.appendChild(plantUmlSvgOption);
  2084. typeSelect.appendChild(plantUmlPngOption);
  2085. typeSelect.appendChild(plantUmlTxtOption);
  2086. }
  2087. function getDefaultValue()
  2088. {
  2089. if (typeSelect.value == 'list')
  2090. {
  2091. return 'Person\n-name: String\n-birthDate: Date\n--\n+getName(): String\n+setName(String): void\n+isBirthday(): boolean';
  2092. }
  2093. else if (typeSelect.value == 'table')
  2094. {
  2095. return 'CREATE TABLE Suppliers\n(\nsupplier_id int NOT NULL PRIMARY KEY,\n' +
  2096. 'supplier_name char(50) NOT NULL,\ncontact_name char(50),\n);\n' +
  2097. 'CREATE TABLE Customers\n(\ncustomer_id int NOT NULL PRIMARY KEY,\n' +
  2098. 'customer_name char(50) NOT NULL,\naddress char(50),\n' +
  2099. 'city char(50),\nstate char(25),\nzip_code char(10)\n);\n';
  2100. }
  2101. else if (typeSelect.value == 'plantUmlPng')
  2102. {
  2103. return '@startuml\nskinparam backgroundcolor transparent\nskinparam shadowing false\nAlice -> Bob: Authentication Request\nBob --> Alice: Authentication Response\n\nAlice -> Bob: Another authentication Request\nAlice <-- Bob: another authentication Response\n@enduml';
  2104. }
  2105. else if (typeSelect.value == 'plantUmlSvg' || typeSelect.value == 'plantUmlTxt')
  2106. {
  2107. return '@startuml\nskinparam shadowing false\nAlice -> Bob: Authentication Request\nBob --> Alice: Authentication Response\n\nAlice -> Bob: Another authentication Request\nAlice <-- Bob: another authentication Response\n@enduml';
  2108. }
  2109. else
  2110. {
  2111. return ';Example:\na->b\nb->edge label->c\nc->a\n';
  2112. }
  2113. };
  2114. var defaultValue = getDefaultValue();
  2115. textarea.value = defaultValue;
  2116. div.appendChild(textarea);
  2117. this.init = function()
  2118. {
  2119. textarea.focus();
  2120. };
  2121. // Enables dropping files
  2122. if (Graph.fileSupport)
  2123. {
  2124. function handleDrop(evt)
  2125. {
  2126. evt.stopPropagation();
  2127. evt.preventDefault();
  2128. if (evt.dataTransfer.files.length > 0)
  2129. {
  2130. var file = evt.dataTransfer.files[0];
  2131. var reader = new FileReader();
  2132. reader.onload = function(e) { textarea.value = e.target.result; };
  2133. reader.readAsText(file);
  2134. }
  2135. };
  2136. function handleDragOver(evt)
  2137. {
  2138. evt.stopPropagation();
  2139. evt.preventDefault();
  2140. };
  2141. // Setup the dnd listeners.
  2142. textarea.addEventListener('dragover', handleDragOver, false);
  2143. textarea.addEventListener('drop', handleDrop, false);
  2144. }
  2145. div.appendChild(typeSelect);
  2146. mxEvent.addListener(typeSelect, 'change', function()
  2147. {
  2148. var newDefaultValue = getDefaultValue();
  2149. if (textarea.value.length == 0 || textarea.value == defaultValue)
  2150. {
  2151. defaultValue = newDefaultValue;
  2152. textarea.value = defaultValue;
  2153. }
  2154. });
  2155. var cancelBtn = mxUtils.button(mxResources.get('close'), function()
  2156. {
  2157. if (textarea.value == defaultValue)
  2158. {
  2159. editorUi.hideDialog();
  2160. }
  2161. else
  2162. {
  2163. editorUi.confirm(mxResources.get('areYouSure'), function()
  2164. {
  2165. editorUi.hideDialog();
  2166. });
  2167. }
  2168. });
  2169. cancelBtn.className = 'geBtn';
  2170. if (editorUi.editor.cancelFirst)
  2171. {
  2172. div.appendChild(cancelBtn);
  2173. }
  2174. var okBtn = mxUtils.button(mxResources.get('insert'), function()
  2175. {
  2176. editorUi.hideDialog();
  2177. parse(textarea.value, typeSelect.value);
  2178. });
  2179. div.appendChild(okBtn);
  2180. okBtn.className = 'geBtn gePrimaryBtn';
  2181. if (!editorUi.editor.cancelFirst)
  2182. {
  2183. div.appendChild(cancelBtn);
  2184. }
  2185. this.container = div;
  2186. };
  2187. /**
  2188. * Constructs a new dialog for creating files from templates.
  2189. */
  2190. var NewDialog = function(editorUi, compact, showName, callback, createOnly, cancelCallback,
  2191. leftHighlight, rightHighlight, rightHighlightBorder, itemPadding, templateFile,
  2192. recentDocsCallback, searchDocsCallback, openExtDocCallback, showImport, createButtonLabel)
  2193. {
  2194. showName = (showName != null) ? showName : true;
  2195. createOnly = (createOnly != null) ? createOnly : false;
  2196. leftHighlight = (leftHighlight != null) ? leftHighlight : '#ebf2f9';
  2197. rightHighlight = (rightHighlight != null) ? rightHighlight : '#e6eff8';
  2198. rightHighlightBorder = (rightHighlightBorder != null) ? rightHighlightBorder : '1px solid #ccd9ea';
  2199. templateFile = (templateFile != null) ? templateFile : EditorUi.templateFile;
  2200. var outer = document.createElement('div');
  2201. outer.style.height = '100%';
  2202. var header = document.createElement('div');
  2203. header.style.whiteSpace = 'nowrap';
  2204. header.style.height = '46px';
  2205. if (showName)
  2206. {
  2207. outer.appendChild(header);
  2208. }
  2209. var logo = document.createElement('img');
  2210. logo.setAttribute('border', '0');
  2211. logo.setAttribute('align', 'absmiddle');
  2212. logo.style.width = '40px';
  2213. logo.style.height = '40px';
  2214. logo.style.marginRight = '10px';
  2215. logo.style.paddingBottom = '4px';
  2216. if (editorUi.mode == App.MODE_GOOGLE)
  2217. {
  2218. logo.src = IMAGE_PATH + '/google-drive-logo.svg';
  2219. }
  2220. else if (editorUi.mode == App.MODE_DROPBOX)
  2221. {
  2222. logo.src = IMAGE_PATH + '/dropbox-logo.svg';
  2223. }
  2224. else if (editorUi.mode == App.MODE_ONEDRIVE)
  2225. {
  2226. logo.src = IMAGE_PATH + '/onedrive-logo.svg';
  2227. }
  2228. else if (editorUi.mode == App.MODE_GITHUB)
  2229. {
  2230. logo.src = IMAGE_PATH + '/github-logo.svg';
  2231. }
  2232. else if (editorUi.mode == App.MODE_TRELLO)
  2233. {
  2234. logo.src = IMAGE_PATH + '/trello-logo.svg';
  2235. }
  2236. else if (editorUi.mode == App.MODE_BROWSER)
  2237. {
  2238. logo.src = IMAGE_PATH + '/osa_database.png';
  2239. }
  2240. else
  2241. {
  2242. logo.src = IMAGE_PATH + '/osa_drive-harddisk.png';
  2243. }
  2244. if (!compact && showName)
  2245. {
  2246. header.appendChild(logo);
  2247. }
  2248. if (showName)
  2249. {
  2250. mxUtils.write(header, ((editorUi.mode == null || editorUi.mode == App.MODE_GOOGLE ||
  2251. editorUi.mode == App.MODE_BROWSER) ? mxResources.get('diagramName') : mxResources.get('filename')) + ':');
  2252. }
  2253. var ext = '.drawio';
  2254. if (editorUi.mode == App.MODE_GOOGLE && editorUi.drive != null)
  2255. {
  2256. ext = editorUi.drive.extension;
  2257. }
  2258. else if (editorUi.mode == App.MODE_DROPBOX && editorUi.dropbox != null)
  2259. {
  2260. ext = editorUi.dropbox.extension;
  2261. }
  2262. else if (editorUi.mode == App.MODE_ONEDRIVE && editorUi.oneDrive != null)
  2263. {
  2264. ext = editorUi.oneDrive.extension;
  2265. }
  2266. else if (editorUi.mode == App.MODE_GITHUB && editorUi.gitHub != null)
  2267. {
  2268. ext = editorUi.gitHub.extension;
  2269. }
  2270. else if (editorUi.mode == App.MODE_TRELLO && editorUi.trello != null)
  2271. {
  2272. ext = editorUi.trello.extension;
  2273. }
  2274. var nameInput = document.createElement('input');
  2275. nameInput.setAttribute('value', editorUi.defaultFilename + ext);
  2276. nameInput.style.marginLeft = '10px';
  2277. nameInput.style.width = (compact) ? '220px' : '430px';
  2278. this.init = function()
  2279. {
  2280. if (showName)
  2281. {
  2282. nameInput.focus();
  2283. if (mxClient.IS_GC || mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS)
  2284. {
  2285. nameInput.select();
  2286. }
  2287. else
  2288. {
  2289. document.execCommand('selectAll', false, null);
  2290. }
  2291. }
  2292. };
  2293. if (showName)
  2294. {
  2295. header.appendChild(nameInput);
  2296. if (editorUi.editor.fileExtensions != null)
  2297. {
  2298. var hint = FilenameDialog.createTypeHint(
  2299. editorUi, nameInput, editorUi.editor.fileExtensions);
  2300. hint.style.marginTop = '12px';
  2301. header.appendChild(hint);
  2302. }
  2303. }
  2304. var hasTabs = false;
  2305. var i0 = 0;
  2306. // Dynamic loading
  2307. function addTemplates()
  2308. {
  2309. var first = true;
  2310. //TODO support paging of external templates
  2311. if (templates != null)
  2312. {
  2313. while (i0 < templates.length && (first || mxUtils.mod(i0, 30) != 0))
  2314. {
  2315. var tmp = templates[i0++];
  2316. addButton(tmp.url, tmp.libs, tmp.title, tmp.tooltip? tmp.tooltip : tmp.title,
  2317. tmp.select, tmp.imgUrl, tmp.info, tmp.onClick, tmp.preview);
  2318. first = false;
  2319. }
  2320. }
  2321. };
  2322. var spinner = new Spinner({
  2323. lines: 12, // The number of lines to draw
  2324. length: 10, // The length of each line
  2325. width: 5, // The line thickness
  2326. radius: 10, // The radius of the inner circle
  2327. rotate: 0, // The rotation offset
  2328. color: '#000', // #rgb or #rrggbb
  2329. speed: 1.5, // Rounds per second
  2330. trail: 60, // Afterglow percentage
  2331. shadow: false, // Whether to render a shadow
  2332. hwaccel: false, // Whether to use hardware acceleration
  2333. top: '40%',
  2334. zIndex: 2e9 // The z-index (defaults to 2000000000)
  2335. });
  2336. var createButton = mxUtils.button(createButtonLabel || mxResources.get('create'), function()
  2337. {
  2338. createButton.setAttribute('disabled', 'disabled');
  2339. create();
  2340. createButton.removeAttribute('disabled');
  2341. });
  2342. createButton.className = 'geBtn gePrimaryBtn';
  2343. if (recentDocsCallback || searchDocsCallback)
  2344. {
  2345. var tabsEl = [];
  2346. var oldTemplates = null;
  2347. var setActiveTab = function(index)
  2348. {
  2349. createButton.setAttribute('disabled', 'disabled');
  2350. for (var i = 0; i < tabsEl.length; i++)
  2351. {
  2352. if (i == index)
  2353. tabsEl[i].className = 'geBtn gePrimaryBtn';
  2354. else
  2355. tabsEl[i].className = 'geBtn';
  2356. }
  2357. }
  2358. hasTabs = true;
  2359. var tabs = document.createElement('div');
  2360. tabs.style.whiteSpace = 'nowrap';
  2361. tabs.style.height = '30px';
  2362. outer.appendChild(tabs);
  2363. var templatesTab = mxUtils.button(mxResources.get('Templates', null, 'Templates'), function()
  2364. {
  2365. list.style.display = '';
  2366. div.style.left = '160px';
  2367. setActiveTab(0);
  2368. div.scrollTop = 0;
  2369. div.innerHTML = '';
  2370. i0 = 0;
  2371. if (oldTemplates != templates)
  2372. {
  2373. templates = oldTemplates;
  2374. addTemplates();
  2375. oldTemplates = null;
  2376. }
  2377. });
  2378. tabsEl.push(templatesTab);
  2379. tabs.appendChild(templatesTab);
  2380. var getExtTemplates = function(isSearch)
  2381. {
  2382. list.style.display = 'none';
  2383. div.style.left = '30px';
  2384. setActiveTab(isSearch? -1 : 1); //deselect all of them if isSearch
  2385. if (oldTemplates == null)
  2386. {
  2387. oldTemplates = templates;
  2388. }
  2389. div.scrollTop = 0;
  2390. div.innerHTML = '';
  2391. spinner.spin(div);
  2392. i0 = 0;
  2393. var callback2 = function(list, errorMsg)
  2394. {
  2395. spinner.stop();
  2396. templates = list;
  2397. if (errorMsg)
  2398. {
  2399. div.innerHTML = errorMsg;
  2400. }
  2401. else if (list.length == 0)
  2402. {
  2403. div.innerHTML = mxUtils.htmlEntities(mxResources.get('noDiagrams', null, 'No Diagrams Found'));
  2404. }
  2405. else
  2406. {
  2407. div.innerHTML = '';
  2408. addTemplates();
  2409. }
  2410. }
  2411. if (isSearch)
  2412. {
  2413. searchDocsCallback(searchInput.value, callback2);
  2414. }
  2415. else
  2416. {
  2417. recentDocsCallback(callback2);
  2418. }
  2419. }
  2420. if (recentDocsCallback)
  2421. {
  2422. var recentTab = mxUtils.button(mxResources.get('Recent', null, 'Recent'), function()
  2423. {
  2424. getExtTemplates();
  2425. });
  2426. tabs.appendChild(recentTab);
  2427. tabsEl.push(recentTab);
  2428. }
  2429. if (searchDocsCallback)
  2430. {
  2431. var searchTab = document.createElement('span');
  2432. searchTab.style.marginLeft = '10px';
  2433. searchTab.innerHTML = mxUtils.htmlEntities(mxResources.get('search') + ':');
  2434. tabs.appendChild(searchTab);
  2435. var searchInput = document.createElement('input');
  2436. searchInput.style.marginRight = '10px';
  2437. searchInput.style.marginLeft = '10px';
  2438. searchInput.style.width = '220px';
  2439. mxEvent.addListener(searchInput, 'keypress', function(e)
  2440. {
  2441. if (e.keyCode == 13)
  2442. {
  2443. getExtTemplates(true);
  2444. }
  2445. });
  2446. tabs.appendChild(searchInput);
  2447. var searchBtn = mxUtils.button(mxResources.get('search'), function()
  2448. {
  2449. getExtTemplates(true);
  2450. });
  2451. searchBtn.className = 'geBtn';
  2452. tabs.appendChild(searchBtn);
  2453. }
  2454. setActiveTab(0);
  2455. }
  2456. var templateLibs = null;
  2457. var templateXml = null;
  2458. var selectedElt = null;
  2459. var templateExtUrl = null;
  2460. var templateInfoObj = null;
  2461. function create()
  2462. {
  2463. if (templateExtUrl)
  2464. {
  2465. if (!showName)
  2466. {
  2467. editorUi.hideDialog();
  2468. }
  2469. openExtDocCallback(templateExtUrl, templateInfoObj, nameInput.value);
  2470. }
  2471. else if (callback)
  2472. {
  2473. if (!showName)
  2474. {
  2475. editorUi.hideDialog();
  2476. }
  2477. callback(templateXml, nameInput.value);
  2478. }
  2479. else
  2480. {
  2481. var title = nameInput.value;
  2482. if (title != null && title.length > 0)
  2483. {
  2484. editorUi.pickFolder(editorUi.mode, function(folderId)
  2485. {
  2486. editorUi.createFile(title, templateXml, (templateLibs != null &&
  2487. templateLibs.length > 0) ? templateLibs : null, null, function()
  2488. {
  2489. editorUi.hideDialog();
  2490. }, null, folderId);
  2491. }, editorUi.mode != App.MODE_GOOGLE ||
  2492. editorUi.stateArg == null ||
  2493. editorUi.stateArg.folderId == null);
  2494. }
  2495. }
  2496. };
  2497. var div = document.createElement('div');
  2498. div.style.border = '1px solid #d3d3d3';
  2499. div.style.position = 'absolute';
  2500. div.style.left = '160px';
  2501. div.style.right = '34px';
  2502. var divTop = (showName) ? 72 : 40;
  2503. divTop += hasTabs? 30 : 0;
  2504. div.style.top = divTop + 'px';
  2505. div.style.bottom = '68px';
  2506. div.style.margin = '6px 0 0 -1px';
  2507. div.style.padding = '6px';
  2508. div.style.overflow = 'auto';
  2509. var list = document.createElement('div');
  2510. list.style.cssText = 'position:absolute;left:30px;width:128px;top:' + divTop + 'px;bottom:68px;margin-top:6px;overflow:auto;border:1px solid #d3d3d3;';
  2511. var w = 140;
  2512. var h = 140;
  2513. function selectElement(elt, xml, libs, extUrl, infoObj)
  2514. {
  2515. if (selectedElt != null)
  2516. {
  2517. selectedElt.style.backgroundColor = 'transparent';
  2518. selectedElt.style.border = '1px solid transparent';
  2519. }
  2520. createButton.removeAttribute('disabled');
  2521. templateXml = xml;
  2522. templateLibs = libs;
  2523. selectedElt = elt;
  2524. templateExtUrl = extUrl;
  2525. templateInfoObj = infoObj;
  2526. selectedElt.style.backgroundColor = rightHighlight;
  2527. selectedElt.style.border = rightHighlightBorder;
  2528. };
  2529. function addButton(url, libs, title, tooltip, select, imgUrl, infoObj, onClick, preview)
  2530. {
  2531. var elt = document.createElement('div');
  2532. elt.className = 'geTemplate';
  2533. elt.style.height = w + 'px';
  2534. elt.style.width = h + 'px';
  2535. if (tooltip != null && tooltip.length > 0)
  2536. {
  2537. elt.setAttribute('title', tooltip);
  2538. }
  2539. if (imgUrl != null)
  2540. {
  2541. elt.style.backgroundImage = 'url(' + imgUrl + ')';
  2542. elt.style.backgroundSize = 'contain';
  2543. elt.style.backgroundPosition = 'center center';
  2544. elt.style.backgroundRepeat = 'no-repeat';
  2545. mxEvent.addListener(elt, 'click', function(evt)
  2546. {
  2547. selectElement(elt, null, null, url, infoObj);
  2548. });
  2549. mxEvent.addListener(elt, 'dblclick', function(evt)
  2550. {
  2551. create();
  2552. });
  2553. }
  2554. else if (url != null && url.length > 0)
  2555. {
  2556. var png = preview || (TEMPLATE_PATH + '/' + url.substring(0, url.length - 4) + '.png');
  2557. elt.style.backgroundImage = 'url(' + png + ')';
  2558. elt.style.backgroundPosition = 'center center';
  2559. elt.style.backgroundRepeat = 'no-repeat';
  2560. var createIt = false;
  2561. mxEvent.addListener(elt, 'click', function(evt)
  2562. {
  2563. createButton.setAttribute('disabled', 'disabled');
  2564. elt.style.backgroundColor = 'transparent';
  2565. elt.style.border = '1px solid transparent';
  2566. var realUrl = url;
  2567. if (/^https?:\/\//.test(realUrl) && !editorUi.editor.isCorsEnabledForUrl(realUrl))
  2568. {
  2569. realUrl = PROXY_URL + '?url=' + encodeURIComponent(realUrl);
  2570. }
  2571. else
  2572. {
  2573. realUrl = TEMPLATE_PATH + '/' + realUrl;
  2574. }
  2575. spinner.spin(div);
  2576. mxUtils.get(realUrl, mxUtils.bind(this, function(req)
  2577. {
  2578. spinner.stop();
  2579. if (req.getStatus() >= 200 && req.getStatus() <= 299)
  2580. {
  2581. selectElement(elt, req.getText(), libs);
  2582. if (createIt)
  2583. {
  2584. create();
  2585. }
  2586. }
  2587. }));
  2588. });
  2589. mxEvent.addListener(elt, 'dblclick', function(evt)
  2590. {
  2591. // Asynchronous double click handling after loading template
  2592. createIt = true;
  2593. });
  2594. }
  2595. else
  2596. {
  2597. elt.innerHTML = '<table width="100%" height="100%" style="line-height:1em;"><tr>' +
  2598. '<td align="center" valign="middle">' + mxResources.get(title) + '</td></tr></table>';
  2599. if (select)
  2600. {
  2601. selectElement(elt);
  2602. }
  2603. if (onClick != null)
  2604. {
  2605. mxEvent.addListener(elt, 'click', onClick);
  2606. }
  2607. else
  2608. {
  2609. mxEvent.addListener(elt, 'click', function(evt)
  2610. {
  2611. selectElement(elt);
  2612. });
  2613. mxEvent.addListener(elt, 'dblclick', function(evt)
  2614. {
  2615. create();
  2616. });
  2617. }
  2618. }
  2619. div.appendChild(elt);
  2620. };
  2621. var categories = {};
  2622. var categoryCount = 1;
  2623. // Adds local basic templates
  2624. categories['basic'] = [{title: 'blankDiagram', select: true}];
  2625. var templates = categories['basic'];
  2626. function initUi()
  2627. {
  2628. mxEvent.addListener(div, 'scroll', function(evt)
  2629. {
  2630. if (div.scrollTop + div.clientHeight >= div.scrollHeight)
  2631. {
  2632. addTemplates();
  2633. mxEvent.consume(evt);
  2634. }
  2635. });
  2636. var currentEntry = null;
  2637. for (var cat in categories)
  2638. {
  2639. var entry = document.createElement('div');
  2640. var label = mxResources.get(cat);
  2641. var templateList = categories[cat];
  2642. if (label == null)
  2643. {
  2644. label = cat.substring(0, 1).toUpperCase() + cat.substring(1);
  2645. }
  2646. if (label.length > 18)
  2647. {
  2648. label = label.substring(0, 18) + '&hellip;';
  2649. }
  2650. entry.style.cssText = 'display:block;cursor:pointer;padding:6px;white-space:nowrap;margin-bottom:-1px;overflow:hidden;text-overflow:ellipsis;';
  2651. entry.setAttribute('title', label + ' (' + templateList.length + ')');
  2652. mxUtils.write(entry, entry.getAttribute('title'));
  2653. if (itemPadding != null)
  2654. {
  2655. entry.style.padding = itemPadding;
  2656. }
  2657. list.appendChild(entry);
  2658. if (currentEntry == null)
  2659. {
  2660. currentEntry = entry;
  2661. currentEntry.style.backgroundColor = leftHighlight;
  2662. }
  2663. (function(cat2, entry2)
  2664. {
  2665. mxEvent.addListener(entry, 'click', function()
  2666. {
  2667. if (currentEntry != entry2)
  2668. {
  2669. currentEntry.style.backgroundColor = '';
  2670. currentEntry = entry2;
  2671. currentEntry.style.backgroundColor = leftHighlight;
  2672. div.scrollTop = 0;
  2673. div.innerHTML = '';
  2674. i0 = 0;
  2675. templates = categories[cat2];
  2676. oldTemplates = null;
  2677. addTemplates();
  2678. }
  2679. });
  2680. })(cat, entry);
  2681. }
  2682. addTemplates();
  2683. }
  2684. if (!compact)
  2685. {
  2686. outer.appendChild(list);
  2687. outer.appendChild(div);
  2688. var indexLoaded = false;
  2689. var realUrl = templateFile;
  2690. if (/^https?:\/\//.test(realUrl) && !editorUi.editor.isCorsEnabledForUrl(realUrl))
  2691. {
  2692. realUrl = PROXY_URL + '?url=' + encodeURIComponent(realUrl);
  2693. }
  2694. mxUtils.get(realUrl, function(req)
  2695. {
  2696. // Workaround for index loaded 3 times in iOS offline mode
  2697. if (!indexLoaded)
  2698. {
  2699. indexLoaded = true;
  2700. var tmpDoc = req.getXml();
  2701. var node = tmpDoc.documentElement.firstChild;
  2702. while (node != null)
  2703. {
  2704. if (typeof(node.getAttribute) !== 'undefined')
  2705. {
  2706. var url = node.getAttribute('url');
  2707. if (url != null)
  2708. {
  2709. var category = node.getAttribute('section');
  2710. if (category == null)
  2711. {
  2712. var slash = url.indexOf('/');
  2713. category = url.substring(0, slash);
  2714. }
  2715. var list = categories[category];
  2716. if (list == null)
  2717. {
  2718. categoryCount++;
  2719. list = [];
  2720. categories[category] = list;
  2721. }
  2722. list.push({url: node.getAttribute('url'), libs: node.getAttribute('libs'),
  2723. title: node.getAttribute('title'), tooltip: node.getAttribute('url'),
  2724. preview: node.getAttribute('preview')});
  2725. }
  2726. }
  2727. node = node.nextSibling;
  2728. }
  2729. initUi();
  2730. }
  2731. });
  2732. }
  2733. mxEvent.addListener(nameInput, 'keypress', function(e)
  2734. {
  2735. if (editorUi.dialog.container.firstChild == outer &&
  2736. e.keyCode == 13)
  2737. {
  2738. create();
  2739. }
  2740. });
  2741. var btns = document.createElement('div');
  2742. btns.style.marginTop = (compact) ? '4px' : '16px';
  2743. btns.style.textAlign = 'right';
  2744. btns.style.position = 'absolute';
  2745. btns.style.left = '40px';
  2746. btns.style.bottom = '24px';
  2747. btns.style.right = '40px';
  2748. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  2749. {
  2750. if (cancelCallback != null)
  2751. {
  2752. cancelCallback();
  2753. }
  2754. editorUi.hideDialog(true);
  2755. });
  2756. cancelBtn.className = 'geBtn';
  2757. if (editorUi.editor.cancelFirst && (!createOnly || cancelCallback != null))
  2758. {
  2759. btns.appendChild(cancelBtn);
  2760. }
  2761. if (!compact && !editorUi.isOffline() && showName && callback == null && !createOnly)
  2762. {
  2763. var helpBtn = mxUtils.button(mxResources.get('help'), function()
  2764. {
  2765. editorUi.openLink('https://support.draw.io/display/DO/Creating+and+Opening+Files');
  2766. });
  2767. helpBtn.className = 'geBtn';
  2768. btns.appendChild(helpBtn);
  2769. }
  2770. if (!compact && urlParams['embed'] != '1' && !createOnly)
  2771. {
  2772. var fromTmpBtn = mxUtils.button(mxResources.get('fromTemplateUrl'), function()
  2773. {
  2774. var dlg = new FilenameDialog(editorUi, '', mxResources.get('create'), function(fileUrl)
  2775. {
  2776. if (fileUrl != null && fileUrl.length > 0)
  2777. {
  2778. var url = editorUi.getUrl(window.location.pathname + '?mode=' + editorUi.mode +
  2779. '&title=' + encodeURIComponent(nameInput.value) +
  2780. '&create=' + encodeURIComponent(fileUrl));
  2781. if (editorUi.getCurrentFile() == null)
  2782. {
  2783. window.location.href = url;
  2784. }
  2785. else
  2786. {
  2787. window.openWindow(url);
  2788. }
  2789. }
  2790. }, mxResources.get('url'));
  2791. editorUi.showDialog(dlg.container, 300, 80, true, true);
  2792. dlg.init();
  2793. });
  2794. fromTmpBtn.className = 'geBtn';
  2795. btns.appendChild(fromTmpBtn);
  2796. }
  2797. if (Graph.fileSupport && showImport)
  2798. {
  2799. var importBtn = mxUtils.button(mxResources.get('import'), function()
  2800. {
  2801. var fileInput = document.createElement('input');
  2802. fileInput.setAttribute('multiple', 'multiple');
  2803. fileInput.setAttribute('type', 'file');
  2804. mxEvent.addListener(fileInput, 'change', function(evt)
  2805. {
  2806. editorUi.openFiles(fileInput.files, true);
  2807. });
  2808. fileInput.click();
  2809. });
  2810. importBtn.className = 'geBtn';
  2811. btns.appendChild(importBtn);
  2812. }
  2813. btns.appendChild(createButton);
  2814. if (!editorUi.editor.cancelFirst && callback == null && (!createOnly || cancelCallback != null))
  2815. {
  2816. btns.appendChild(cancelBtn);
  2817. }
  2818. outer.appendChild(btns);
  2819. this.container = outer;
  2820. };
  2821. /**
  2822. * Constructs a dialog for creating new files from a template URL.
  2823. */
  2824. var CreateDialog = function(editorUi, title, createFn, cancelFn, dlgTitle, btnLabel, overrideExtension,
  2825. allowBrowser, allowTab, helpLink, showDeviceButton, rowLimit, data, mimeType, base64Encoded, hints)
  2826. {
  2827. overrideExtension = (overrideExtension != null) ? overrideExtension : true;
  2828. allowBrowser = (allowBrowser != null) ? allowBrowser : true;
  2829. rowLimit = (rowLimit != null) ? rowLimit : 4;
  2830. var div = document.createElement('div');
  2831. var showButtons = true;
  2832. if (cancelFn == null)
  2833. {
  2834. editorUi.addLanguageMenu(div);
  2835. }
  2836. var h3 = document.createElement('h2');
  2837. mxUtils.write(h3, dlgTitle || mxResources.get('create'));
  2838. h3.style.marginTop = '0px';
  2839. h3.style.marginBottom = '24px';
  2840. div.appendChild(h3);
  2841. mxUtils.write(div, mxResources.get('filename') + ':');
  2842. var nameInput = document.createElement('input');
  2843. nameInput.setAttribute('value', title);
  2844. nameInput.style.width = '280px';
  2845. nameInput.style.marginLeft = '10px';
  2846. nameInput.style.marginBottom = '20px';
  2847. this.init = function()
  2848. {
  2849. nameInput.focus();
  2850. if (mxClient.IS_GC || mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS)
  2851. {
  2852. nameInput.select();
  2853. }
  2854. else
  2855. {
  2856. document.execCommand('selectAll', false, null);
  2857. }
  2858. };
  2859. div.appendChild(nameInput);
  2860. if (hints != null)
  2861. {
  2862. div.appendChild(FilenameDialog.createTypeHint(editorUi, nameInput, hints));
  2863. }
  2864. if (data != null && mimeType != null && mimeType.substring(0, 6) == 'image/')
  2865. {
  2866. nameInput.style.width = '160px';
  2867. var preview = null;
  2868. // Workaround for broken images in SVG preview in Chrome
  2869. if (mimeType == 'image/svg+xml' && mxClient.IS_SVG)
  2870. {
  2871. preview = document.createElement('div');
  2872. preview.innerHTML = mxUtils.trim(data);
  2873. var svg = preview.getElementsByTagName('svg')[0];
  2874. var w = parseInt(svg.getAttribute('width'));
  2875. var h = parseInt(svg.getAttribute('height'));
  2876. svg.setAttribute('viewBox', '0 0 ' + w + ' ' + h);
  2877. svg.setAttribute('width', '120px');
  2878. svg.setAttribute('height', '80px');
  2879. }
  2880. else
  2881. {
  2882. preview = document.createElement('img');
  2883. preview.setAttribute('src', 'data:' + mimeType + ((base64Encoded) ? ';base64,': ';utf8,') + data);
  2884. }
  2885. preview.style.position = 'absolute';
  2886. preview.style.top = '70px';
  2887. preview.style.right = '100px';
  2888. preview.style.maxWidth = '120px';
  2889. preview.style.maxHeight = '80px';
  2890. mxUtils.setPrefixedStyle(preview.style, 'transform', 'translate(50%,-50%)');
  2891. div.appendChild(preview);
  2892. if (allowTab && Editor.popupsAllowed)
  2893. {
  2894. preview.style.cursor = 'pointer';
  2895. mxEvent.addListener(preview, 'click', function()
  2896. {
  2897. create('_blank');
  2898. });
  2899. }
  2900. }
  2901. mxUtils.br(div);
  2902. var buttons = document.createElement('div');
  2903. buttons.style.textAlign = 'center';
  2904. var count = 0;
  2905. function addLogo(img, title, mode, clientName)
  2906. {
  2907. var button = document.createElement('a');
  2908. button.style.overflow = 'hidden';
  2909. var logo = document.createElement('img');
  2910. logo.src = img;
  2911. logo.setAttribute('border', '0');
  2912. logo.setAttribute('align', 'absmiddle');
  2913. logo.style.width = '60px';
  2914. logo.style.height = '60px';
  2915. logo.style.paddingBottom = '6px';
  2916. button.style.display = (mxClient.IS_QUIRKS) ? 'inline' : 'inline-block';
  2917. button.className = 'geBaseButton';
  2918. button.style.position = 'relative';
  2919. button.style.margin = '4px';
  2920. button.style.padding = '8px 8px 10px 8px';
  2921. button.style.whiteSpace = 'nowrap';
  2922. button.appendChild(logo);
  2923. // Workaround for quirks is a vertical list (limited to max 2 items)
  2924. if (mxClient.IS_QUIRKS)
  2925. {
  2926. button.style.cssFloat = 'left';
  2927. button.style.zoom = '1';
  2928. }
  2929. button.style.color = 'gray';
  2930. button.style.fontSize = '11px';
  2931. var label = document.createElement('div');
  2932. button.appendChild(label);
  2933. mxUtils.write(label, title);
  2934. function initButton()
  2935. {
  2936. mxEvent.addListener(button, 'click', function()
  2937. {
  2938. // Updates extension
  2939. change(mode);
  2940. create(mode);
  2941. });
  2942. };
  2943. // Supports lazy loading
  2944. if (clientName != null && editorUi[clientName] == null)
  2945. {
  2946. logo.style.visibility = 'hidden';
  2947. mxUtils.setOpacity(label, 10);
  2948. var size = 12;
  2949. var spinner = new Spinner({
  2950. lines: 12, // The number of lines to draw
  2951. length: size, // The length of each line
  2952. width: 5, // The line thickness
  2953. radius: 10, // The radius of the inner circle
  2954. rotate: 0, // The rotation offset
  2955. color: '#000', // #rgb or #rrggbb
  2956. speed: 1.5, // Rounds per second
  2957. trail: 60, // Afterglow percentage
  2958. shadow: false, // Whether to render a shadow
  2959. hwaccel: false, // Whether to use hardware acceleration
  2960. top: '40%',
  2961. zIndex: 2e9 // The z-index (defaults to 2000000000)
  2962. });
  2963. spinner.spin(button);
  2964. // Timeout after 30 secs
  2965. var timeout = window.setTimeout(function()
  2966. {
  2967. if (editorUi[clientName] == null)
  2968. {
  2969. spinner.stop();
  2970. button.style.display = 'none';
  2971. }
  2972. }, 30000);
  2973. editorUi.addListener('clientLoaded', mxUtils.bind(this, function()
  2974. {
  2975. if (editorUi[clientName] != null)
  2976. {
  2977. window.clearTimeout(timeout);
  2978. mxUtils.setOpacity(label, 100);
  2979. logo.style.visibility = '';
  2980. spinner.stop();
  2981. initButton();
  2982. }
  2983. }));
  2984. }
  2985. else
  2986. {
  2987. initButton();
  2988. }
  2989. buttons.appendChild(button);
  2990. if (++count == rowLimit)
  2991. {
  2992. mxUtils.br(buttons);
  2993. count = 0;
  2994. }
  2995. };
  2996. if (!showButtons)
  2997. {
  2998. mxUtils.write(div, mxResources.get('chooseAnOption') + ':');
  2999. }
  3000. else
  3001. {
  3002. buttons.style.marginTop = '6px';
  3003. div.appendChild(buttons);
  3004. }
  3005. // Adds all papersize options
  3006. var serviceSelect = document.createElement('select');
  3007. serviceSelect.style.marginLeft = '10px';
  3008. if (!editorUi.isOfflineApp() && !editorUi.isOffline())
  3009. {
  3010. if (typeof window.DriveClient === 'function')
  3011. {
  3012. var googleOption = document.createElement('option');
  3013. googleOption.setAttribute('value', App.MODE_GOOGLE);
  3014. mxUtils.write(googleOption, mxResources.get('googleDrive'));
  3015. serviceSelect.appendChild(googleOption);
  3016. addLogo(IMAGE_PATH + '/google-drive-logo.svg', mxResources.get('googleDrive'), App.MODE_GOOGLE, 'drive');
  3017. }
  3018. if (typeof window.OneDriveClient === 'function')
  3019. {
  3020. var oneDriveOption = document.createElement('option');
  3021. oneDriveOption.setAttribute('value', App.MODE_ONEDRIVE);
  3022. mxUtils.write(oneDriveOption, mxResources.get('oneDrive'));
  3023. serviceSelect.appendChild(oneDriveOption);
  3024. if (editorUi.mode == App.MODE_ONEDRIVE)
  3025. {
  3026. oneDriveOption.setAttribute('selected', 'selected');
  3027. }
  3028. addLogo(IMAGE_PATH + '/onedrive-logo.svg', mxResources.get('oneDrive'), App.MODE_ONEDRIVE, 'oneDrive');
  3029. }
  3030. if (typeof window.DropboxClient === 'function')
  3031. {
  3032. var dropboxOption = document.createElement('option');
  3033. dropboxOption.setAttribute('value', App.MODE_DROPBOX);
  3034. mxUtils.write(dropboxOption, mxResources.get('dropbox'));
  3035. serviceSelect.appendChild(dropboxOption);
  3036. if (editorUi.mode == App.MODE_DROPBOX)
  3037. {
  3038. dropboxOption.setAttribute('selected', 'selected');
  3039. }
  3040. addLogo(IMAGE_PATH + '/dropbox-logo.svg', mxResources.get('dropbox'), App.MODE_DROPBOX, 'dropbox');
  3041. }
  3042. if (editorUi.gitHub != null)
  3043. {
  3044. var gitHubOption = document.createElement('option');
  3045. gitHubOption.setAttribute('value', App.MODE_GITHUB);
  3046. mxUtils.write(gitHubOption, mxResources.get('github'));
  3047. serviceSelect.appendChild(gitHubOption);
  3048. addLogo(IMAGE_PATH + '/github-logo.svg', mxResources.get('github'), App.MODE_GITHUB, 'gitHub');
  3049. }
  3050. if (typeof window.TrelloClient === 'function')
  3051. {
  3052. var trelloOption = document.createElement('option');
  3053. trelloOption.setAttribute('value', App.MODE_TRELLO);
  3054. mxUtils.write(trelloOption, mxResources.get('trello'));
  3055. serviceSelect.appendChild(trelloOption);
  3056. addLogo(IMAGE_PATH + '/trello-logo.svg', mxResources.get('trello'), App.MODE_TRELLO, 'trello');
  3057. }
  3058. }
  3059. if (!Editor.useLocalStorage || urlParams['storage'] == 'device' ||
  3060. (editorUi.getCurrentFile() != null/* && !mxClient.IS_IOS*/))
  3061. {
  3062. var deviceOption = document.createElement('option');
  3063. deviceOption.setAttribute('value', App.MODE_DEVICE);
  3064. mxUtils.write(deviceOption, mxResources.get('device'));
  3065. serviceSelect.appendChild(deviceOption);
  3066. if (editorUi.mode == App.MODE_DEVICE || !allowBrowser)
  3067. {
  3068. deviceOption.setAttribute('selected', 'selected');
  3069. }
  3070. if (showDeviceButton)
  3071. {
  3072. addLogo(IMAGE_PATH + '/osa_drive-harddisk.png', mxResources.get('device'), App.MODE_DEVICE);
  3073. }
  3074. }
  3075. if (allowBrowser && isLocalStorage && urlParams['browser'] != '0')
  3076. {
  3077. var browserOption = document.createElement('option');
  3078. browserOption.setAttribute('value', App.MODE_BROWSER);
  3079. mxUtils.write(browserOption, mxResources.get('browser'));
  3080. serviceSelect.appendChild(browserOption);
  3081. if (editorUi.mode == App.MODE_BROWSER)
  3082. {
  3083. browserOption.setAttribute('selected', 'selected');
  3084. }
  3085. addLogo(IMAGE_PATH + '/osa_database.png', mxResources.get('browser'), App.MODE_BROWSER);
  3086. }
  3087. function change(newMode)
  3088. {
  3089. if (overrideExtension)
  3090. {
  3091. var fn = nameInput.value;
  3092. var idx = fn.lastIndexOf('.');
  3093. if (title.lastIndexOf('.') < 0 && (!showButtons || idx < 0))
  3094. {
  3095. newMode = (newMode != null) ? newMode : serviceSelect.value;
  3096. var ext = '';
  3097. if (newMode == App.MODE_GOOGLE)
  3098. {
  3099. ext = editorUi.drive.extension;
  3100. }
  3101. else if (newMode == App.MODE_GITHUB)
  3102. {
  3103. ext = editorUi.gitHub.extension;
  3104. }
  3105. else if (newMode == App.MODE_TRELLO)
  3106. {
  3107. ext = editorUi.trello.extension;
  3108. }
  3109. else if (newMode == App.MODE_DROPBOX)
  3110. {
  3111. ext = editorUi.dropbox.extension;
  3112. }
  3113. else if (newMode == App.MODE_ONEDRIVE)
  3114. {
  3115. ext = editorUi.oneDrive.extension;
  3116. }
  3117. else if (newMode == App.MODE_DEVICE)
  3118. {
  3119. ext = '.drawio';
  3120. }
  3121. if (idx >= 0)
  3122. {
  3123. fn = fn.substring(0, idx);
  3124. }
  3125. nameInput.value = fn + ext;
  3126. }
  3127. }
  3128. };
  3129. var btns = document.createElement('div');
  3130. btns.style.marginTop = (showButtons) ? '26px' : '38px';
  3131. btns.style.textAlign = 'center';
  3132. if (!showButtons)
  3133. {
  3134. div.appendChild(serviceSelect);
  3135. mxEvent.addListener(serviceSelect, 'change', change);
  3136. change();
  3137. }
  3138. if (helpLink != null)
  3139. {
  3140. var helpBtn = mxUtils.button(mxResources.get('help'), function()
  3141. {
  3142. editorUi.openLink(helpLink);
  3143. });
  3144. helpBtn.className = 'geBtn';
  3145. btns.appendChild(helpBtn);
  3146. }
  3147. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  3148. {
  3149. if (cancelFn != null)
  3150. {
  3151. cancelFn();
  3152. }
  3153. else
  3154. {
  3155. editorUi.fileLoaded(null);
  3156. editorUi.hideDialog();
  3157. window.close();
  3158. window.location.href = editorUi.getUrl();
  3159. }
  3160. });
  3161. cancelBtn.className = 'geBtn';
  3162. if (editorUi.editor.cancelFirst)
  3163. {
  3164. btns.appendChild(cancelBtn);
  3165. }
  3166. function create(mode)
  3167. {
  3168. var title = nameInput.value;
  3169. if (mode == null || (title != null && title.length > 0))
  3170. {
  3171. editorUi.hideDialog();
  3172. createFn(title, mode);
  3173. };
  3174. }
  3175. if (cancelFn == null)
  3176. {
  3177. var laterBtn = mxUtils.button(mxResources.get('decideLater'), function()
  3178. {
  3179. create(null);
  3180. });
  3181. laterBtn.className = 'geBtn';
  3182. btns.appendChild(laterBtn);
  3183. }
  3184. if (allowTab && Editor.popupsAllowed)
  3185. {
  3186. var openBtn = mxUtils.button(mxResources.get('openInNewWindow'), function()
  3187. {
  3188. create('_blank');
  3189. });
  3190. openBtn.className = 'geBtn';
  3191. btns.appendChild(openBtn);
  3192. }
  3193. if (CreateDialog.showDownloadButton)
  3194. {
  3195. var downloadButton = mxUtils.button(mxResources.get('download'), function()
  3196. {
  3197. create('download');
  3198. });
  3199. downloadButton.className = 'geBtn';
  3200. btns.appendChild(downloadButton);
  3201. }
  3202. if (/*!mxClient.IS_IOS || */!showButtons)
  3203. {
  3204. var createBtn = mxUtils.button(btnLabel || mxResources.get('create'), function()
  3205. {
  3206. create((showDeviceButton) ? 'download' : ((showButtons) ? App.MODE_DEVICE : serviceSelect.value));
  3207. });
  3208. createBtn.className = 'geBtn gePrimaryBtn';
  3209. btns.appendChild(createBtn);
  3210. }
  3211. if (!editorUi.editor.cancelFirst)
  3212. {
  3213. btns.appendChild(cancelBtn);
  3214. }
  3215. mxEvent.addListener(nameInput, 'keypress', function(e)
  3216. {
  3217. if (e.keyCode == 13)
  3218. {
  3219. create((showButtons) ? App.MODE_DEVICE : serviceSelect.value);
  3220. }
  3221. else if (e.keyCode == 27)
  3222. {
  3223. editorUi.fileLoaded(null);
  3224. editorUi.hideDialog();
  3225. window.close();
  3226. }
  3227. });
  3228. div.appendChild(btns);
  3229. this.container = div;
  3230. };
  3231. /**
  3232. *
  3233. */
  3234. CreateDialog.showDownloadButton = true;
  3235. /**
  3236. * Constructs a new popup dialog.
  3237. */
  3238. var PopupDialog = function(editorUi, url, pre, fallback, hideDialog)
  3239. {
  3240. hideDialog = (hideDialog != null) ? hideDialog : true;
  3241. var div = document.createElement('div');
  3242. div.style.textAlign = 'left';
  3243. mxUtils.write(div, mxResources.get('fileOpenLocation'));
  3244. mxUtils.br(div);
  3245. mxUtils.br(div);
  3246. var replaceBtn = mxUtils.button(mxResources.get('openInThisWindow'), function()
  3247. {
  3248. if (hideDialog)
  3249. {
  3250. editorUi.hideDialog();
  3251. }
  3252. if (fallback != null)
  3253. {
  3254. fallback();
  3255. }
  3256. });
  3257. replaceBtn.className = 'geBtn';
  3258. replaceBtn.style.marginBottom = '8px';
  3259. replaceBtn.style.width = '280px';
  3260. div.appendChild(replaceBtn);
  3261. mxUtils.br(div);
  3262. var wndBtn = mxUtils.button(mxResources.get('openInNewWindow'), function()
  3263. {
  3264. if (hideDialog)
  3265. {
  3266. editorUi.hideDialog();
  3267. }
  3268. if (pre != null)
  3269. {
  3270. pre();
  3271. }
  3272. editorUi.openLink(url, null, true);
  3273. });
  3274. wndBtn.className = 'geBtn gePrimaryBtn';
  3275. wndBtn.style.width = replaceBtn.style.width;
  3276. div.appendChild(wndBtn);
  3277. mxUtils.br(div);
  3278. mxUtils.br(div);
  3279. mxUtils.write(div, mxResources.get('allowPopups'));
  3280. this.container = div;
  3281. };
  3282. /**
  3283. * Constructs a new image dialog.
  3284. */
  3285. var ImageDialog = function(editorUi, title, initialValue, fn, ignoreExisting, convertDataUri)
  3286. {
  3287. convertDataUri = (convertDataUri != null) ? convertDataUri : true;
  3288. var graph = editorUi.editor.graph;
  3289. var div = document.createElement('div');
  3290. mxUtils.write(div, title);
  3291. var inner = document.createElement('div');
  3292. inner.className = 'geTitle';
  3293. inner.style.backgroundColor = 'transparent';
  3294. inner.style.borderColor = 'transparent';
  3295. inner.style.whiteSpace = 'nowrap';
  3296. inner.style.textOverflow = 'clip';
  3297. inner.style.cursor = 'default';
  3298. if (!mxClient.IS_VML)
  3299. {
  3300. inner.style.paddingRight = '20px';
  3301. }
  3302. var linkInput = document.createElement('input');
  3303. linkInput.setAttribute('value', initialValue);
  3304. linkInput.setAttribute('type', 'text');
  3305. linkInput.setAttribute('spellcheck', 'false');
  3306. linkInput.setAttribute('autocorrect', 'off');
  3307. linkInput.setAttribute('autocomplete', 'off');
  3308. linkInput.setAttribute('autocapitalize', 'off');
  3309. linkInput.style.marginTop = '6px';
  3310. var realWidth = (Graph.fileSupport) ? 420 : 340;
  3311. linkInput.style.width = realWidth + ((mxClient.IS_QUIRKS) ? 20 : -20) + 'px';
  3312. linkInput.style.backgroundImage = 'url(\'' + Dialog.prototype.clearImage + '\')';
  3313. linkInput.style.backgroundRepeat = 'no-repeat';
  3314. linkInput.style.backgroundPosition = '100% 50%';
  3315. linkInput.style.paddingRight = '14px';
  3316. var cross = document.createElement('div');
  3317. cross.setAttribute('title', mxResources.get('reset'));
  3318. cross.style.position = 'relative';
  3319. cross.style.left = '-16px';
  3320. cross.style.width = '12px';
  3321. cross.style.height = '14px';
  3322. cross.style.cursor = 'pointer';
  3323. // Workaround for inline-block not supported in IE
  3324. cross.style.display = (mxClient.IS_VML) ? 'inline' : 'inline-block';
  3325. cross.style.top = ((mxClient.IS_VML) ? 0 : 3) + 'px';
  3326. // Needed to block event transparency in IE
  3327. cross.style.background = 'url(\'' + editorUi.editor.transparentImage + '\')';
  3328. mxEvent.addListener(cross, 'click', function()
  3329. {
  3330. linkInput.value = '';
  3331. linkInput.focus();
  3332. });
  3333. inner.appendChild(linkInput);
  3334. inner.appendChild(cross);
  3335. div.appendChild(inner);
  3336. var insertImage = function(newValue, w, h, resize)
  3337. {
  3338. var dataUri = newValue.substring(0, 5) == 'data:';
  3339. if (!editorUi.isOffline() || (dataUri && typeof chrome === 'undefined'))
  3340. {
  3341. if (newValue.length > 0 && editorUi.spinner.spin(document.body, mxResources.get('inserting')))
  3342. {
  3343. var maxSize = 520;
  3344. editorUi.loadImage(newValue, function(img)
  3345. {
  3346. editorUi.spinner.stop();
  3347. editorUi.hideDialog();
  3348. var s = (resize === false) ? 1 :
  3349. (w != null && h != null) ? Math.max(w / img.width, h / img.height) :
  3350. Math.min(1, Math.min(maxSize / img.width, maxSize / img.height));
  3351. // Handles special case of data URI which needs to be rewritten
  3352. // to be used in a cell style to remove the semicolon
  3353. if (convertDataUri)
  3354. {
  3355. newValue = editorUi.convertDataUri(newValue);
  3356. }
  3357. fn(newValue, Math.round(Number(img.width) * s), Math.round(Number(img.height) * s));
  3358. }, function()
  3359. {
  3360. editorUi.spinner.stop();
  3361. fn(null);
  3362. editorUi.showError(mxResources.get('error'), mxResources.get('fileNotFound'), mxResources.get('ok'));
  3363. });
  3364. }
  3365. else
  3366. {
  3367. editorUi.hideDialog();
  3368. fn(newValue);
  3369. }
  3370. }
  3371. else
  3372. {
  3373. newValue = editorUi.convertDataUri(newValue);
  3374. w = (w == null) ? 120 : w;
  3375. h = (h == null) ? 100 : h;
  3376. editorUi.hideDialog();
  3377. fn(newValue, w, h);
  3378. }
  3379. };
  3380. var apply = function(newValue, resize)
  3381. {
  3382. if (newValue != null)
  3383. {
  3384. var geo = (ignoreExisting) ? null : graph.getModel().getGeometry(graph.getSelectionCell());
  3385. // Reuses width and height of existing cell
  3386. if (geo != null)
  3387. {
  3388. insertImage(newValue, geo.width, geo.height, resize);
  3389. }
  3390. else
  3391. {
  3392. insertImage(newValue, null, null, resize);
  3393. }
  3394. }
  3395. else
  3396. {
  3397. editorUi.hideDialog();
  3398. fn(null);
  3399. }
  3400. };
  3401. this.init = function()
  3402. {
  3403. linkInput.focus();
  3404. // Installs drag and drop handler for local images and links
  3405. if (Graph.fileSupport)
  3406. {
  3407. linkInput.setAttribute('placeholder', mxResources.get('dragImagesHere'));
  3408. // Setup the dnd listeners
  3409. var dlg = div.parentNode;
  3410. var graph = editorUi.editor.graph;
  3411. var dropElt = null;
  3412. mxEvent.addListener(dlg, 'dragleave', function(evt)
  3413. {
  3414. if (dropElt != null)
  3415. {
  3416. dropElt.parentNode.removeChild(dropElt);
  3417. dropElt = null;
  3418. }
  3419. evt.stopPropagation();
  3420. evt.preventDefault();
  3421. });
  3422. mxEvent.addListener(dlg, 'dragover', mxUtils.bind(this, function(evt)
  3423. {
  3424. // IE 10 does not implement pointer-events so it can't have a drop highlight
  3425. if (dropElt == null && (!mxClient.IS_IE || document.documentMode > 10))
  3426. {
  3427. dropElt = editorUi.highlightElement(dlg);
  3428. }
  3429. evt.stopPropagation();
  3430. evt.preventDefault();
  3431. }));
  3432. mxEvent.addListener(dlg, 'drop', mxUtils.bind(this, function(evt)
  3433. {
  3434. if (dropElt != null)
  3435. {
  3436. dropElt.parentNode.removeChild(dropElt);
  3437. dropElt = null;
  3438. }
  3439. if (evt.dataTransfer.files.length > 0)
  3440. {
  3441. editorUi.importFiles(evt.dataTransfer.files, 0, 0, editorUi.maxImageSize, function(data, mimeType, x, y, w, h, fileName, resize)
  3442. {
  3443. apply(data, resize);
  3444. }, function()
  3445. {
  3446. // No post processing
  3447. }, function(file)
  3448. {
  3449. // Handles only images
  3450. return file.type.substring(0, 6) == 'image/';
  3451. }, function(queue)
  3452. {
  3453. // Invokes elements of queue in order
  3454. for (var i = 0; i < queue.length; i++)
  3455. {
  3456. queue[i]();
  3457. }
  3458. }, !mxEvent.isControlDown(evt));
  3459. }
  3460. else if (mxUtils.indexOf(evt.dataTransfer.types, 'text/uri-list') >= 0)
  3461. {
  3462. var uri = evt.dataTransfer.getData('text/uri-list');
  3463. if ((/\.(gif|jpg|jpeg|tiff|png|svg)($|\?)/i).test(uri))
  3464. {
  3465. apply(decodeURIComponent(uri));
  3466. }
  3467. }
  3468. evt.stopPropagation();
  3469. evt.preventDefault();
  3470. }), false);
  3471. }
  3472. };
  3473. var btns = document.createElement('div');
  3474. btns.style.marginTop = (mxClient.IS_QUIRKS) ? '22px' : '14px';
  3475. btns.style.textAlign = 'right';
  3476. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  3477. {
  3478. // Just in case a spinner is spinning, has no effect otherwise
  3479. editorUi.spinner.stop();
  3480. editorUi.hideDialog();
  3481. });
  3482. cancelBtn.className = 'geBtn';
  3483. if (editorUi.editor.cancelFirst)
  3484. {
  3485. btns.appendChild(cancelBtn);
  3486. }
  3487. ImageDialog.filePicked = function(data)
  3488. {
  3489. if (data.action == google.picker.Action.PICKED)
  3490. {
  3491. if (data.docs[0].thumbnails != null)
  3492. {
  3493. var thumb = data.docs[0].thumbnails[data.docs[0].thumbnails.length - 1];
  3494. if (thumb != null)
  3495. {
  3496. linkInput.value = thumb.url;
  3497. }
  3498. }
  3499. }
  3500. linkInput.focus();
  3501. };
  3502. if (Graph.fileSupport)
  3503. {
  3504. var fileInput = document.createElement('input');
  3505. fileInput.setAttribute('multiple', 'multiple');
  3506. fileInput.setAttribute('type', 'file');
  3507. if (document.documentMode == null)
  3508. {
  3509. mxEvent.addListener(fileInput, 'change', function(evt)
  3510. {
  3511. editorUi.importFiles(fileInput.files, 0, 0, editorUi.maxImageSize, function(data, mimeType, x, y, w, h)
  3512. {
  3513. apply(data);
  3514. }, function()
  3515. {
  3516. // No post processing
  3517. }, function(file)
  3518. {
  3519. // Handles only images
  3520. return file.type.substring(0, 6) == 'image/';
  3521. }, function(queue)
  3522. {
  3523. // Invokes elements of queue in order
  3524. for (var i = 0; i < queue.length; i++)
  3525. {
  3526. queue[i]();
  3527. }
  3528. }, true);
  3529. });
  3530. var btn = mxUtils.button(mxResources.get('open'), function()
  3531. {
  3532. fileInput.click();
  3533. });
  3534. btn.className = 'geBtn';
  3535. btns.appendChild(btn);
  3536. }
  3537. }
  3538. // Image cropping (experimental)
  3539. if (!!document.createElement('canvas').getContext && linkInput.value.substring(0, 11) == 'data:image/' &&
  3540. linkInput.value.substring(0, 14) != 'data:image/svg')
  3541. {
  3542. var cropBtn = mxUtils.button(mxResources.get('crop'), function()
  3543. {
  3544. var dlg = new CropImageDialog(editorUi, linkInput.value, function(image)
  3545. {
  3546. linkInput.value = image;
  3547. });
  3548. editorUi.showDialog(dlg.container, 200, 185, true, true);
  3549. dlg.init();
  3550. });
  3551. cropBtn.className = 'geBtn';
  3552. btns.appendChild(cropBtn);
  3553. }
  3554. if (typeof(google) != 'undefined' && typeof(google.picker) != 'undefined' && window.self === window.top)
  3555. {
  3556. var searchBtn = mxUtils.button(mxResources.get('search'), function()
  3557. {
  3558. // Creates one picker and reuses it to avoid polluting the DOM
  3559. if (editorUi.imageSearchPicker == null)
  3560. {
  3561. var picker = new google.picker.PickerBuilder()
  3562. .setLocale(mxLanguage)
  3563. .addView(google.picker.ViewId.IMAGE_SEARCH)
  3564. .enableFeature(google.picker.Feature.NAV_HIDDEN);
  3565. editorUi.imageSearchPicker = picker.setCallback(function(data)
  3566. {
  3567. ImageDialog.filePicked(data);
  3568. }).build();
  3569. }
  3570. editorUi.imageSearchPicker.setVisible(true);
  3571. });
  3572. searchBtn.className = 'geBtn';
  3573. btns.appendChild(searchBtn);
  3574. if (editorUi.drive != null && urlParams['photos'] == '1')
  3575. {
  3576. var gpBtn = mxUtils.button(mxResources.get('googlePlus'), function()
  3577. {
  3578. if (editorUi.spinner.spin(document.body, mxResources.get('authorizing')))
  3579. {
  3580. editorUi.drive.checkToken(mxUtils.bind(this, function()
  3581. {
  3582. editorUi.spinner.stop();
  3583. // Creates one picker and reuses it to avoid polluting the DOM
  3584. if (editorUi.photoPicker == null)
  3585. {
  3586. var token = gapi.auth.getToken().access_token;
  3587. var picker = new google.picker.PickerBuilder()
  3588. .setAppId(editorUi.drive.appId)
  3589. .setLocale(mxLanguage)
  3590. .setOAuthToken(token)
  3591. .addView(google.picker.ViewId.PHOTOS)
  3592. .addView(google.picker.ViewId.PHOTO_ALBUMS)
  3593. .addView(google.picker.ViewId.PHOTO_UPLOAD);
  3594. editorUi.photoPicker = picker.setCallback(function(data)
  3595. {
  3596. ImageDialog.filePicked(data);
  3597. }).build();
  3598. }
  3599. editorUi.photoPicker.setVisible(true);
  3600. }));
  3601. }
  3602. });
  3603. gpBtn.className = 'geBtn';
  3604. btns.appendChild(gpBtn);
  3605. }
  3606. }
  3607. mxEvent.addListener(linkInput, 'keypress', function(e)
  3608. {
  3609. if (e.keyCode == 13)
  3610. {
  3611. apply(linkInput.value);
  3612. }
  3613. });
  3614. var applyBtn = mxUtils.button(mxResources.get('apply'), function()
  3615. {
  3616. apply(linkInput.value);
  3617. });
  3618. applyBtn.className = 'geBtn gePrimaryBtn';
  3619. btns.appendChild(applyBtn);
  3620. if (!editorUi.editor.cancelFirst)
  3621. {
  3622. btns.appendChild(cancelBtn);
  3623. }
  3624. // Shows drop icon in dialog background
  3625. if (Graph.fileSupport)
  3626. {
  3627. btns.style.marginTop = '120px';
  3628. div.style.backgroundImage = 'url(\'' + IMAGE_PATH + '/droptarget.png\')';
  3629. div.style.backgroundPosition = 'center 65%';
  3630. div.style.backgroundRepeat = 'no-repeat';
  3631. var bg = document.createElement('div');
  3632. bg.style.position = 'absolute';
  3633. bg.style.width = '420px';
  3634. bg.style.top = '58%';
  3635. bg.style.textAlign = 'center';
  3636. bg.style.fontSize = '18px';
  3637. bg.style.color = '#a0c3ff';
  3638. mxUtils.write(bg, mxResources.get('dragImagesHere'));
  3639. div.appendChild(bg);
  3640. }
  3641. div.appendChild(btns);
  3642. this.container = div;
  3643. };
  3644. /**
  3645. * Overrides link dialog to add Google Picker.
  3646. */
  3647. var LinkDialog = function(editorUi, initialValue, btnLabel, fn, showPages)
  3648. {
  3649. var div = document.createElement('div');
  3650. mxUtils.write(div, mxResources.get('editLink') + ':');
  3651. var inner = document.createElement('div');
  3652. inner.className = 'geTitle';
  3653. inner.style.backgroundColor = 'transparent';
  3654. inner.style.borderColor = 'transparent';
  3655. inner.style.whiteSpace = 'nowrap';
  3656. inner.style.textOverflow = 'clip';
  3657. inner.style.cursor = 'default';
  3658. if (!mxClient.IS_VML)
  3659. {
  3660. inner.style.paddingRight = '20px';
  3661. }
  3662. var linkInput = document.createElement('input');
  3663. linkInput.setAttribute('placeholder', mxResources.get('dragUrlsHere'));
  3664. linkInput.setAttribute('type', 'text');
  3665. linkInput.style.marginTop = '6px';
  3666. linkInput.style.width = '440px';
  3667. linkInput.style.backgroundImage = 'url(\'' + Dialog.prototype.clearImage + '\')';
  3668. linkInput.style.backgroundRepeat = 'no-repeat';
  3669. linkInput.style.backgroundPosition = '100% 50%';
  3670. linkInput.style.paddingRight = '14px';
  3671. var cross = document.createElement('div');
  3672. cross.setAttribute('title', mxResources.get('reset'));
  3673. cross.style.position = 'relative';
  3674. cross.style.left = '-16px';
  3675. cross.style.width = '12px';
  3676. cross.style.height = '14px';
  3677. cross.style.cursor = 'pointer';
  3678. // Workaround for inline-block not supported in IE
  3679. cross.style.display = (mxClient.IS_VML) ? 'inline' : 'inline-block';
  3680. cross.style.top = ((mxClient.IS_VML) ? 0 : 3) + 'px';
  3681. // Needed to block event transparency in IE
  3682. cross.style.background = 'url(\'' + editorUi.editor.transparentImage + '\')';
  3683. mxEvent.addListener(cross, 'click', function()
  3684. {
  3685. linkInput.value = '';
  3686. linkInput.focus();
  3687. });
  3688. var urlRadio = document.createElement('input');
  3689. urlRadio.style.cssText = 'margin-right:8px;margin-bottom:8px;';
  3690. urlRadio.setAttribute('value', 'url');
  3691. urlRadio.setAttribute('type', 'radio');
  3692. urlRadio.setAttribute('name', 'current-linkdialog');
  3693. var pageRadio = document.createElement('input');
  3694. pageRadio.style.cssText = 'margin-right:8px;margin-bottom:8px;';
  3695. pageRadio.setAttribute('value', 'url');
  3696. pageRadio.setAttribute('type', 'radio');
  3697. pageRadio.setAttribute('name', 'current-linkdialog');
  3698. var pageSelect = document.createElement('select');
  3699. pageSelect.style.width = '420px';
  3700. if (showPages && editorUi.pages != null)
  3701. {
  3702. if (initialValue != null && initialValue.substring(0, 13) == 'data:page/id,')
  3703. {
  3704. pageRadio.setAttribute('checked', 'checked');
  3705. pageRadio.defaultChecked = true;
  3706. }
  3707. else
  3708. {
  3709. linkInput.setAttribute('value', initialValue);
  3710. urlRadio.setAttribute('checked', 'checked');
  3711. urlRadio.defaultChecked = true;
  3712. }
  3713. linkInput.style.width = '420px';
  3714. inner.appendChild(urlRadio);
  3715. inner.appendChild(linkInput);
  3716. inner.appendChild(cross);
  3717. mxUtils.br(inner);
  3718. inner.appendChild(pageRadio);
  3719. var pageFound = false;
  3720. for (var i = 0; i < editorUi.pages.length; i++)
  3721. {
  3722. var pageOption = document.createElement('option');
  3723. mxUtils.write(pageOption, editorUi.pages[i].getName() ||
  3724. mxResources.get('pageWithNumber', [i + 1]));
  3725. pageOption.setAttribute('value', 'data:page/id,' +
  3726. editorUi.pages[i].getId());
  3727. if (initialValue == pageOption.getAttribute('value'))
  3728. {
  3729. pageOption.setAttribute('selected', 'selected');
  3730. pageFound = true;
  3731. }
  3732. pageSelect.appendChild(pageOption);
  3733. }
  3734. if (!pageFound && pageRadio.checked)
  3735. {
  3736. var notFoundOption = document.createElement('option');
  3737. mxUtils.write(notFoundOption, mxResources.get('pageNotFound'));
  3738. notFoundOption.setAttribute('disabled', 'disabled');
  3739. notFoundOption.setAttribute('selected', 'selected');
  3740. notFoundOption.setAttribute('value', 'pageNotFound');
  3741. pageSelect.appendChild(notFoundOption);
  3742. mxEvent.addListener(pageSelect, 'change', function()
  3743. {
  3744. if (notFoundOption.parentNode != null && !notFoundOption.selected)
  3745. {
  3746. notFoundOption.parentNode.removeChild(notFoundOption);
  3747. }
  3748. });
  3749. }
  3750. inner.appendChild(pageSelect);
  3751. }
  3752. else
  3753. {
  3754. linkInput.setAttribute('value', initialValue);
  3755. inner.appendChild(linkInput);
  3756. inner.appendChild(cross);
  3757. }
  3758. div.appendChild(inner);
  3759. var mainBtn = mxUtils.button(btnLabel, function()
  3760. {
  3761. editorUi.hideDialog();
  3762. var value = (pageRadio.checked) ? ((pageSelect.value !== 'pageNotFound') ?
  3763. pageSelect.value : initialValue) : linkInput.value;
  3764. fn(value, LinkDialog.selectedDocs);
  3765. });
  3766. mainBtn.style.verticalAlign = 'middle';
  3767. mainBtn.className = 'geBtn gePrimaryBtn';
  3768. this.init = function()
  3769. {
  3770. if (pageRadio.checked)
  3771. {
  3772. pageSelect.focus();
  3773. }
  3774. else
  3775. {
  3776. linkInput.focus();
  3777. if (mxClient.IS_GC || mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS)
  3778. {
  3779. linkInput.select();
  3780. }
  3781. else
  3782. {
  3783. document.execCommand('selectAll', false, null);
  3784. }
  3785. }
  3786. mxEvent.addListener(pageSelect, 'focus', function()
  3787. {
  3788. urlRadio.removeAttribute('checked');
  3789. pageRadio.setAttribute('checked', 'checked');
  3790. pageRadio.checked = true;
  3791. });
  3792. mxEvent.addListener(linkInput, 'focus', function()
  3793. {
  3794. pageRadio.removeAttribute('checked');
  3795. urlRadio.setAttribute('checked', 'checked');
  3796. urlRadio.checked = true;
  3797. });
  3798. // Installs drag and drop handler for links
  3799. if (Graph.fileSupport)
  3800. {
  3801. // Setup the dnd listeners
  3802. var dlg = div.parentNode;
  3803. var graph = editorUi.editor.graph;
  3804. var dropElt = null;
  3805. mxEvent.addListener(dlg, 'dragleave', function(evt)
  3806. {
  3807. if (dropElt != null)
  3808. {
  3809. dropElt.parentNode.removeChild(dropElt);
  3810. dropElt = null;
  3811. }
  3812. evt.stopPropagation();
  3813. evt.preventDefault();
  3814. });
  3815. mxEvent.addListener(dlg, 'dragover', mxUtils.bind(this, function(evt)
  3816. {
  3817. // IE 10 does not implement pointer-events so it can't have a drop highlight
  3818. if (dropElt == null && (!mxClient.IS_IE || document.documentMode > 10))
  3819. {
  3820. dropElt = editorUi.highlightElement(dlg);
  3821. }
  3822. evt.stopPropagation();
  3823. evt.preventDefault();
  3824. }));
  3825. mxEvent.addListener(dlg, 'drop', mxUtils.bind(this, function(evt)
  3826. {
  3827. if (dropElt != null)
  3828. {
  3829. dropElt.parentNode.removeChild(dropElt);
  3830. dropElt = null;
  3831. }
  3832. if (mxUtils.indexOf(evt.dataTransfer.types, 'text/uri-list') >= 0)
  3833. {
  3834. linkInput.value = decodeURIComponent(evt.dataTransfer.getData('text/uri-list'));
  3835. urlRadio.setAttribute('checked', 'checked');
  3836. urlRadio.checked = true;
  3837. mainBtn.click();
  3838. }
  3839. evt.stopPropagation();
  3840. evt.preventDefault();
  3841. }), false);
  3842. }
  3843. };
  3844. var btns = document.createElement('div');
  3845. btns.style.marginTop = '20px';
  3846. btns.style.textAlign = 'right';
  3847. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  3848. {
  3849. editorUi.hideDialog();
  3850. });
  3851. cancelBtn.style.verticalAlign = 'middle';
  3852. cancelBtn.className = 'geBtn';
  3853. if (editorUi.editor.cancelFirst)
  3854. {
  3855. btns.appendChild(cancelBtn);
  3856. }
  3857. var helpBtn = mxUtils.button(mxResources.get('help'), function()
  3858. {
  3859. editorUi.openLink('https://desk.draw.io/solution/articles/16000080137');
  3860. });
  3861. helpBtn.style.verticalAlign = 'middle';
  3862. helpBtn.className = 'geBtn';
  3863. btns.appendChild(helpBtn);
  3864. if (editorUi.isOffline() && !mxClient.IS_CHROMEAPP)
  3865. {
  3866. helpBtn.style.display = 'none';
  3867. }
  3868. LinkDialog.selectedDocs = null;
  3869. LinkDialog.filePicked = function(data)
  3870. {
  3871. if (data.action == google.picker.Action.PICKED)
  3872. {
  3873. LinkDialog.selectedDocs = data.docs;
  3874. var href = data.docs[0].url;
  3875. if (data.docs[0].mimeType == 'application/mxe' || (data.docs[0].mimeType != null &&
  3876. data.docs[0].mimeType.substring(0, 23) == 'application/vnd.jgraph.'))
  3877. {
  3878. href = 'https://www.draw.io/#G' + data.docs[0].id;
  3879. }
  3880. else if (data.docs[0].mimeType == 'application/vnd.google-apps.folder')
  3881. {
  3882. // Do not use folderview in data.docs[0].url link to Google Drive instead
  3883. href = 'https://drive.google.com/#folders/' + data.docs[0].id;
  3884. }
  3885. linkInput.value = href;
  3886. linkInput.focus();
  3887. }
  3888. else
  3889. {
  3890. LinkDialog.selectedDocs = null;
  3891. }
  3892. linkInput.focus();
  3893. };
  3894. function addButton(src, tooltip, fn)
  3895. {
  3896. var btn = mxUtils.button('', fn);
  3897. btn.className = 'geBtn';
  3898. btn.setAttribute('title', tooltip);
  3899. var img = document.createElement('img');
  3900. img.style.height = '26px';
  3901. img.style.width = '26px';
  3902. img.setAttribute('src', src);
  3903. btn.style.minWidth = '42px';
  3904. btn.style.verticalAlign = 'middle';
  3905. btn.appendChild(img);
  3906. btns.appendChild(btn);
  3907. };
  3908. if (typeof(google) != 'undefined' && typeof(google.picker) != 'undefined' && editorUi.drive != null)
  3909. {
  3910. addButton(IMAGE_PATH + '/google-drive-logo.svg', mxResources.get('googlePlus'), function()
  3911. {
  3912. if (editorUi.spinner.spin(document.body, mxResources.get('authorizing')))
  3913. {
  3914. editorUi.drive.checkToken(mxUtils.bind(this, function()
  3915. {
  3916. editorUi.spinner.stop();
  3917. // Creates one picker and reuses it to avoid polluting the DOM
  3918. if (editorUi.linkPicker == null)
  3919. {
  3920. var token = gapi.auth.getToken().access_token;
  3921. var view = new google.picker.DocsView(google.picker.ViewId.FOLDERS)
  3922. .setParent('root')
  3923. .setIncludeFolders(true)
  3924. .setSelectFolderEnabled(true);
  3925. var view2 = new google.picker.DocsView()
  3926. .setIncludeFolders(true)
  3927. .setSelectFolderEnabled(true);
  3928. var view21 = new google.picker.DocsView()
  3929. .setIncludeFolders(true)
  3930. .setEnableTeamDrives(true)
  3931. .setSelectFolderEnabled(true);
  3932. var picker = new google.picker.PickerBuilder()
  3933. .setAppId(editorUi.drive.appId)
  3934. .setLocale(mxLanguage)
  3935. .setOAuthToken(token)
  3936. .enableFeature(google.picker.Feature.SUPPORT_TEAM_DRIVES)
  3937. .addView(view)
  3938. .addView(view2)
  3939. .addView(view21)
  3940. .addView(google.picker.ViewId.RECENTLY_PICKED)
  3941. .addView(google.picker.ViewId.IMAGE_SEARCH)
  3942. .addView(google.picker.ViewId.VIDEO_SEARCH)
  3943. .addView(google.picker.ViewId.MAPS);
  3944. if (urlParams['photos'] == '1')
  3945. {
  3946. picker.addView(google.picker.ViewId.PHOTOS)
  3947. .addView(google.picker.ViewId.PHOTO_ALBUMS)
  3948. .addView(google.picker.ViewId.PHOTO_UPLOAD)
  3949. }
  3950. editorUi.linkPicker = picker.setCallback(function(data)
  3951. {
  3952. LinkDialog.filePicked(data);
  3953. }).build();
  3954. }
  3955. editorUi.linkPicker.setVisible(true);
  3956. }));
  3957. }
  3958. });
  3959. }
  3960. if (typeof(Dropbox) != 'undefined' && typeof(Dropbox.choose) != 'undefined')
  3961. {
  3962. addButton(IMAGE_PATH + '/dropbox-logo.svg', mxResources.get('dropbox'), function()
  3963. {
  3964. // Authentication will be carried out on open to make sure the
  3965. // autosave does not show an auth dialog. Showing it here will
  3966. // block the second dialog (the file picker) so it's too early.
  3967. Dropbox.choose(
  3968. {
  3969. linkType : 'direct',
  3970. cancel: function()
  3971. {
  3972. // do nothing
  3973. },
  3974. success : function(files)
  3975. {
  3976. linkInput.value = files[0].link;
  3977. linkInput.focus();
  3978. }
  3979. });
  3980. });
  3981. }
  3982. if (editorUi.oneDrive != null)
  3983. {
  3984. addButton(IMAGE_PATH + '/onedrive-logo.svg', mxResources.get('oneDrive'), function()
  3985. {
  3986. editorUi.oneDrive.pickFile(function(id, files)
  3987. {
  3988. linkInput.value = files.value[0].webUrl;
  3989. linkInput.focus();
  3990. });
  3991. });
  3992. }
  3993. if (editorUi.gitHub != null)
  3994. {
  3995. addButton(IMAGE_PATH + '/github-logo.svg', mxResources.get('github'), function()
  3996. {
  3997. editorUi.gitHub.pickFile(function(path)
  3998. {
  3999. if (path != null)
  4000. {
  4001. var tokens = path.split('/');
  4002. var org = tokens[0];
  4003. var repo = tokens[1];
  4004. var ref = tokens[2];
  4005. var path = tokens.slice(3, tokens.length).join('/');
  4006. linkInput.value = 'https://github.com/' + org + '/' +
  4007. repo + '/blob/' + ref + '/' + path;
  4008. linkInput.focus();
  4009. }
  4010. });
  4011. });
  4012. }
  4013. //TODO should Trello support this?
  4014. mxEvent.addListener(linkInput, 'keypress', function(e)
  4015. {
  4016. if (e.keyCode == 13)
  4017. {
  4018. editorUi.hideDialog();
  4019. var value = (pageRadio.checked) ? pageSelect.value : linkInput.value;
  4020. fn(value, LinkDialog.selectedDocs);
  4021. }
  4022. });
  4023. btns.appendChild(mainBtn);
  4024. if (!editorUi.editor.cancelFirst)
  4025. {
  4026. btns.appendChild(cancelBtn);
  4027. }
  4028. div.appendChild(btns);
  4029. this.container = div;
  4030. };
  4031. /**
  4032. * Constructs a new about dialog
  4033. */
  4034. var AboutDialog = function(editorUi)
  4035. {
  4036. var div = document.createElement('div');
  4037. div.style.marginTop = '6px';
  4038. div.setAttribute('align', 'center');
  4039. var img = document.createElement('img');
  4040. img.style.border = '0px';
  4041. if (mxClient.IS_SVG)
  4042. {
  4043. img.setAttribute('width', '164');
  4044. img.setAttribute('height', '221');
  4045. img.style.width = '164px';
  4046. img.style.height = '221px';
  4047. img.setAttribute('src', IMAGE_PATH + '/drawlogo-text-bottom.svg');
  4048. }
  4049. else
  4050. {
  4051. img.setAttribute('width', '176');
  4052. img.setAttribute('height', '219');
  4053. img.style.width = '170px';
  4054. img.style.height = '219px';
  4055. img.setAttribute('src', IMAGE_PATH + '/logo-flat.png');
  4056. }
  4057. if (uiTheme == 'dark')
  4058. {
  4059. img.style.filter = 'grayscale(100%) invert(100%)';
  4060. }
  4061. div.appendChild(img);
  4062. mxUtils.br(div);
  4063. var clr = (uiTheme == 'dark') ? '#cccccc' : '#505050';
  4064. var v = document.createElement('small');
  4065. v.innerHTML = 'v ' + EditorUi.VERSION;
  4066. v.style.color = clr;
  4067. div.appendChild(v);
  4068. mxUtils.br(div);
  4069. mxUtils.br(div);
  4070. var small = document.createElement('small');
  4071. small.style.color = clr;
  4072. small.innerHTML = '&copy; 2005-2019 <a href="https://about.draw.io/" style="color:inherit;" target="_blank">JGraph Ltd</a>.<br>All Rights Reserved.';
  4073. div.appendChild(small);
  4074. mxEvent.addListener(div, 'click', function(e)
  4075. {
  4076. if (mxEvent.getSource(e).nodeName != 'A')
  4077. {
  4078. editorUi.hideDialog();
  4079. }
  4080. });
  4081. this.container = div;
  4082. };
  4083. /**
  4084. * Constructs a new about dialog
  4085. */
  4086. var FeedbackDialog = function(editorUi)
  4087. {
  4088. var div = document.createElement('div');
  4089. var label = document.createElement('div');
  4090. mxUtils.write(label, mxResources.get('sendYourFeedbackToDrawIo'));
  4091. label.style.fontSize = '18px';
  4092. label.style.marginBottom = '18px';
  4093. div.appendChild(label);
  4094. label = document.createElement('div');
  4095. mxUtils.write(label, mxResources.get('yourEmailAddress') + ' (' + mxResources.get('required') + ')');
  4096. div.appendChild(label);
  4097. var email = document.createElement('input');
  4098. email.setAttribute('type', 'text');
  4099. email.style.marginTop = '6px';
  4100. email.style.width = '600px';
  4101. var sendButton = mxUtils.button(mxResources.get('sendMessage'), function()
  4102. {
  4103. var diagram = textarea.value +
  4104. ((cb.checked) ? '\nDiagram:\n' + mxUtils.getXml(editorUi.getXmlFileData()) : '') +
  4105. '\nBrowser:\n' + navigator.userAgent;
  4106. if (diagram.length > FeedbackDialog.maxAttachmentSize)
  4107. {
  4108. editorUi.alert(mxResources.get('drawingTooLarge'));
  4109. }
  4110. else
  4111. {
  4112. editorUi.hideDialog();
  4113. if (editorUi.spinner.spin(document.body))
  4114. {
  4115. var postUrl = (FeedbackDialog.feedbackUrl != null) ? FeedbackDialog.feedbackUrl : '/email';
  4116. mxUtils.post(postUrl, 'email=' + encodeURIComponent(email.value) +
  4117. '&version=' + encodeURIComponent(EditorUi.VERSION) +
  4118. '&url=' + encodeURIComponent(window.location.href) +
  4119. '&body=' + encodeURIComponent('Feedback:\n' + diagram),
  4120. function(req)
  4121. {
  4122. editorUi.spinner.stop();
  4123. if (req.getStatus() >= 200 && req.getStatus() <= 299)
  4124. {
  4125. editorUi.alert(mxResources.get('feedbackSent'));
  4126. }
  4127. else
  4128. {
  4129. editorUi.alert(mxResources.get('errorSendingFeedback'));
  4130. }
  4131. },
  4132. function()
  4133. {
  4134. editorUi.spinner.stop();
  4135. editorUi.alert(mxResources.get('errorSendingFeedback'));
  4136. });
  4137. }
  4138. }
  4139. });
  4140. sendButton.className = 'geBtn gePrimaryBtn';
  4141. sendButton.setAttribute('disabled', 'disabled');
  4142. var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  4143. mxEvent.addListener(email, 'change', function()
  4144. {
  4145. if (email.value.length > 0 && re.test(email.value) > 0)
  4146. {
  4147. sendButton.removeAttribute('disabled');
  4148. }
  4149. else
  4150. {
  4151. sendButton.setAttribute('disabled', 'disabled');
  4152. }
  4153. });
  4154. mxEvent.addListener(email, 'keyup', function()
  4155. {
  4156. if (email.value.length > 0 && re.test(email.value))
  4157. {
  4158. sendButton.removeAttribute('disabled');
  4159. }
  4160. else
  4161. {
  4162. sendButton.setAttribute('disabled', 'disabled');
  4163. }
  4164. });
  4165. div.appendChild(email);
  4166. this.init = function()
  4167. {
  4168. email.focus();
  4169. };
  4170. var cb = document.createElement('input');
  4171. cb.setAttribute('type', 'checkbox');
  4172. cb.setAttribute('checked', 'checked');
  4173. cb.defaultChecked = true;
  4174. var p2 = document.createElement('p');
  4175. p2.style.marginTop = '14px';
  4176. p2.appendChild(cb);
  4177. var span = document.createElement('span');
  4178. mxUtils.write(span, ' ' + mxResources.get('includeCopyOfMyDiagram'));
  4179. p2.appendChild(span);
  4180. mxEvent.addListener(span, 'click', function(evt)
  4181. {
  4182. cb.checked = !cb.checked;
  4183. mxEvent.consume(evt);
  4184. });
  4185. div.appendChild(p2);
  4186. label = document.createElement('div');
  4187. mxUtils.write(label, mxResources.get('feedback'));
  4188. div.appendChild(label);
  4189. var textarea = document.createElement('textarea');
  4190. textarea.style.resize = 'none';
  4191. textarea.style.width = '600px';
  4192. textarea.style.height = '140px';
  4193. textarea.style.marginTop = '6px';
  4194. textarea.setAttribute('placeholder', mxResources.get('comments'));
  4195. div.appendChild(textarea);
  4196. var buttons = document.createElement('div');
  4197. buttons.style.marginTop = '26px';
  4198. buttons.style.textAlign = 'right';
  4199. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  4200. {
  4201. editorUi.hideDialog();
  4202. });
  4203. cancelBtn.className = 'geBtn';
  4204. if (editorUi.editor.cancelFirst)
  4205. {
  4206. buttons.appendChild(cancelBtn);
  4207. buttons.appendChild(sendButton);
  4208. }
  4209. else
  4210. {
  4211. buttons.appendChild(sendButton);
  4212. buttons.appendChild(cancelBtn);
  4213. }
  4214. div.appendChild(buttons);
  4215. this.container = div;
  4216. };
  4217. /**
  4218. * Maximum size of attachments in bytes. Default is 1000000.
  4219. */
  4220. FeedbackDialog.maxAttachmentSize = 1000000;
  4221. /**
  4222. * Constructs a new revision dialog
  4223. */
  4224. var RevisionDialog = function(editorUi, revs, restoreFn)
  4225. {
  4226. var div = document.createElement('div');
  4227. var title = document.createElement('h3');
  4228. title.style.marginTop = '0px';
  4229. mxUtils.write(title, mxResources.get('revisionHistory'));
  4230. div.appendChild(title);
  4231. var list = document.createElement('div');
  4232. list.style.position = 'absolute';
  4233. list.style.overflow = 'auto';
  4234. list.style.width = '170px';
  4235. list.style.height = '378px';
  4236. div.appendChild(list);
  4237. var container = document.createElement('div');
  4238. container.style.position = 'absolute';
  4239. container.style.border = '1px solid lightGray';
  4240. container.style.left = '199px';
  4241. container.style.width = '470px';
  4242. container.style.height = '376px';
  4243. container.style.overflow = 'hidden';
  4244. mxEvent.disableContextMenu(container);
  4245. div.appendChild(container);
  4246. var graph = new Graph(container);
  4247. graph.setTooltips(false);
  4248. graph.setEnabled(false);
  4249. graph.setPanning(true);
  4250. graph.panningHandler.ignoreCell = true;
  4251. graph.panningHandler.useLeftButtonForPanning = true;
  4252. graph.minFitScale = null;
  4253. graph.maxFitScale = null;
  4254. graph.centerZoom = true;
  4255. // Handles placeholders for pages
  4256. var currentPage = 0;
  4257. var diagrams = null;
  4258. var realPage = 0;
  4259. var graphGetGlobalVariable = graph.getGlobalVariable;
  4260. graph.getGlobalVariable = function(name)
  4261. {
  4262. if (name == 'page' && diagrams != null && diagrams[realPage] != null)
  4263. {
  4264. return diagrams[realPage].getAttribute('name');
  4265. }
  4266. else if (name == 'pagenumber')
  4267. {
  4268. return realPage + 1;
  4269. }
  4270. return graphGetGlobalVariable.apply(this, arguments);
  4271. };
  4272. // Disables hyperlinks
  4273. graph.getLinkForCell = function()
  4274. {
  4275. return null;
  4276. };
  4277. if (Editor.MathJaxRender)
  4278. {
  4279. graph.addListener(mxEvent.SIZE, mxUtils.bind(this, function(sender, evt)
  4280. {
  4281. // LATER: Math support is used if current graph has math enabled
  4282. // should use switch from history instead but requires setting the
  4283. // global mxClient.NO_FO switch
  4284. if (editorUi.editor.graph.mathEnabled)
  4285. {
  4286. Editor.MathJaxRender(graph.container);
  4287. }
  4288. }));
  4289. }
  4290. var opts = {
  4291. lines: 11, // The number of lines to draw
  4292. length: 15, // The length of each line
  4293. width: 6, // The line thickness
  4294. radius: 10, // The radius of the inner circle
  4295. corners: 1, // Corner roundness (0..1)
  4296. rotate: 0, // The rotation offset
  4297. direction: 1, // 1: clockwise, -1: counterclockwise
  4298. color: '#000', // #rgb or #rrggbb or array of colors
  4299. speed: 1.4, // Rounds per second
  4300. trail: 60, // Afterglow percentage
  4301. shadow: false, // Whether to render a shadow
  4302. hwaccel: false, // Whether to use hardware acceleration
  4303. className: 'spinner', // The CSS class to assign to the spinner
  4304. zIndex: 2e9, // The z-index (defaults to 2000000000)
  4305. top: '50%', // Top position relative to parent
  4306. left: '50%' // Left position relative to parent
  4307. };
  4308. var spinner = new Spinner(opts);
  4309. var file = editorUi.getCurrentFile();
  4310. var currentRow = null;
  4311. var currentRev = null;
  4312. var currentDoc = null;
  4313. var currentXml = null;
  4314. var zoomInBtn = mxUtils.button('', function()
  4315. {
  4316. if (currentDoc != null)
  4317. {
  4318. graph.zoomIn();
  4319. }
  4320. });
  4321. zoomInBtn.className = 'geSprite geSprite-zoomin';
  4322. zoomInBtn.setAttribute('title', mxResources.get('zoomIn'));
  4323. zoomInBtn.style.outline = 'none';
  4324. zoomInBtn.style.border = 'none';
  4325. zoomInBtn.style.margin = '2px';
  4326. zoomInBtn.setAttribute('disabled', 'disabled');
  4327. mxUtils.setOpacity(zoomInBtn, 20);
  4328. var zoomOutBtn = mxUtils.button('', function()
  4329. {
  4330. if (currentDoc != null)
  4331. {
  4332. graph.zoomOut();
  4333. }
  4334. });
  4335. zoomOutBtn.className = 'geSprite geSprite-zoomout';
  4336. zoomOutBtn.setAttribute('title', mxResources.get('zoomOut'));
  4337. zoomOutBtn.style.outline = 'none';
  4338. zoomOutBtn.style.border = 'none';
  4339. zoomOutBtn.style.margin = '2px';
  4340. zoomOutBtn.setAttribute('disabled', 'disabled');
  4341. mxUtils.setOpacity(zoomOutBtn, 20);
  4342. var zoomFitBtn = mxUtils.button('', function()
  4343. {
  4344. if (currentDoc != null)
  4345. {
  4346. graph.maxFitScale = 8;
  4347. graph.fit(8);
  4348. graph.center();
  4349. }
  4350. });
  4351. zoomFitBtn.className = 'geSprite geSprite-fit';
  4352. zoomFitBtn.setAttribute('title', mxResources.get('fit'));
  4353. zoomFitBtn.style.outline = 'none';
  4354. zoomFitBtn.style.border = 'none';
  4355. zoomFitBtn.style.margin = '2px';
  4356. zoomFitBtn.setAttribute('disabled', 'disabled');
  4357. mxUtils.setOpacity(zoomFitBtn, 20);
  4358. var zoomActualBtn = mxUtils.button('', function()
  4359. {
  4360. if (currentDoc != null)
  4361. {
  4362. graph.zoomActual();
  4363. graph.center();
  4364. }
  4365. });
  4366. zoomActualBtn.className = 'geSprite geSprite-actualsize';
  4367. zoomActualBtn.setAttribute('title', mxResources.get('actualSize'));
  4368. zoomActualBtn.style.outline = 'none';
  4369. zoomActualBtn.style.border = 'none';
  4370. zoomActualBtn.style.margin = '2px';
  4371. zoomActualBtn.setAttribute('disabled', 'disabled');
  4372. mxUtils.setOpacity(zoomActualBtn, 20);
  4373. var fileInfo = document.createElement('div');
  4374. fileInfo.style.position = 'absolute';
  4375. fileInfo.style.textAlign = 'right';
  4376. fileInfo.style.color = 'gray';
  4377. fileInfo.style.marginTop = '10px';
  4378. fileInfo.style.backgroundColor = 'transparent';
  4379. fileInfo.style.top = '440px';
  4380. fileInfo.style.right = '32px';
  4381. fileInfo.style.maxWidth = '380px';
  4382. fileInfo.style.cursor = 'default';
  4383. var downloadBtn = mxUtils.button(mxResources.get('download'), function()
  4384. {
  4385. if (currentDoc != null)
  4386. {
  4387. var data = mxUtils.getXml(currentDoc.documentElement);
  4388. var filename = editorUi.getBaseFilename() + '.drawio';
  4389. if (editorUi.isLocalFileSave())
  4390. {
  4391. editorUi.saveLocalFile(data, filename, 'text/xml');
  4392. }
  4393. else
  4394. {
  4395. var param = (typeof(pako) === 'undefined') ? '&xml=' + encodeURIComponent(data) :
  4396. '&data=' + encodeURIComponent(Graph.compress(data));
  4397. new mxXmlRequest(SAVE_URL, 'filename=' + encodeURIComponent(filename) +
  4398. '&format=xml' + param).simulate(document, '_blank');
  4399. }
  4400. }
  4401. });
  4402. downloadBtn.className = 'geBtn';
  4403. downloadBtn.setAttribute('disabled', 'disabled');
  4404. var restoreBtn = mxUtils.button(mxResources.get('restore'), function()
  4405. {
  4406. if (currentDoc != null && currentXml != null)
  4407. {
  4408. editorUi.confirm(mxResources.get('areYouSure'), function()
  4409. {
  4410. if (restoreFn != null)
  4411. {
  4412. restoreFn(currentXml);
  4413. }
  4414. else
  4415. {
  4416. if (editorUi.spinner.spin(document.body, mxResources.get('restoring')))
  4417. {
  4418. file.save(true, function(resp)
  4419. {
  4420. editorUi.spinner.stop();
  4421. editorUi.replaceFileData(currentXml);
  4422. editorUi.hideDialog();
  4423. }, function(resp)
  4424. {
  4425. editorUi.spinner.stop();
  4426. editorUi.editor.setStatus('');
  4427. editorUi.handleError(resp, (resp != null) ? mxResources.get('errorSavingFile') : null);
  4428. });
  4429. }
  4430. }
  4431. });
  4432. }
  4433. });
  4434. restoreBtn.className = 'geBtn';
  4435. restoreBtn.setAttribute('disabled', 'disabled');
  4436. var pageSelect = document.createElement('select');
  4437. pageSelect.setAttribute('disabled', 'disabled');
  4438. pageSelect.style.maxWidth = '80px';
  4439. pageSelect.style.position = 'relative';
  4440. pageSelect.style.top = '-2px';
  4441. pageSelect.style.verticalAlign = 'bottom';
  4442. pageSelect.style.marginRight = '6px';
  4443. pageSelect.style.display = 'none';
  4444. var pageSelectFunction = null;
  4445. mxEvent.addListener(pageSelect, 'change', function(evt)
  4446. {
  4447. if (pageSelectFunction != null)
  4448. {
  4449. pageSelectFunction(evt);
  4450. mxEvent.consume(evt);
  4451. }
  4452. });
  4453. var newBtn = mxUtils.button(mxResources.get('edit'), function()
  4454. {
  4455. if (currentDoc != null)
  4456. {
  4457. window.openFile = new OpenFile(function()
  4458. {
  4459. window.openFile = null;
  4460. });
  4461. window.openFile.setData(mxUtils.getXml(currentDoc.documentElement));
  4462. editorUi.openLink(editorUi.getUrl(), null, true);
  4463. }
  4464. });
  4465. newBtn.className = 'geBtn';
  4466. newBtn.setAttribute('disabled', 'disabled');
  4467. if (restoreFn != null)
  4468. {
  4469. newBtn.style.display = 'none';
  4470. }
  4471. var showBtn = mxUtils.button(mxResources.get('show'), function()
  4472. {
  4473. if (currentRev != null)
  4474. {
  4475. editorUi.openLink(currentRev.getUrl(pageSelect.selectedIndex));
  4476. }
  4477. });
  4478. showBtn.className = 'geBtn gePrimaryBtn';
  4479. showBtn.setAttribute('disabled', 'disabled');
  4480. if (restoreFn != null)
  4481. {
  4482. showBtn.style.display = 'none';
  4483. restoreBtn.className = 'geBtn gePrimaryBtn';
  4484. }
  4485. var buttons = document.createElement('div');
  4486. buttons.style.position = 'absolute';
  4487. buttons.style.top = '482px';
  4488. buttons.style.width = '640px';
  4489. buttons.style.textAlign = 'right';
  4490. var tb = document.createElement('div');
  4491. tb.className = 'geToolbarContainer';
  4492. tb.style.backgroundColor = 'transparent';
  4493. tb.style.padding = '2px';
  4494. tb.style.border = 'none';
  4495. tb.style.left = '199px';
  4496. tb.style.top = '442px';
  4497. var currentElt = null;
  4498. if (revs != null && revs.length > 0)
  4499. {
  4500. container.style.cursor = 'move';
  4501. var table = document.createElement('table');
  4502. table.style.border = '1px solid lightGray';
  4503. table.style.borderCollapse = 'collapse';
  4504. table.style.borderSpacing = '0px';
  4505. table.style.width = '100%';
  4506. var tbody = document.createElement('tbody');
  4507. var today = new Date().toDateString();
  4508. if (editorUi.currentPage != null && editorUi.pages != null)
  4509. {
  4510. currentPage = mxUtils.indexOf(editorUi.pages, editorUi.currentPage);
  4511. }
  4512. for (var i = revs.length - 1; i >= 0; i--)
  4513. {
  4514. var elt = (function(item)
  4515. {
  4516. var ts = new Date(item.modifiedDate);
  4517. var row = null;
  4518. var pd = '6px';
  4519. // Workaround for negative timestamps in Dropbox
  4520. if (ts.getTime() >= 0)
  4521. {
  4522. row = document.createElement('tr');
  4523. row.style.borderBottom = '1px solid lightGray';
  4524. row.style.fontSize = '12px';
  4525. row.style.cursor = 'pointer';
  4526. var date = document.createElement('td');
  4527. date.style.padding = pd;
  4528. date.style.whiteSpace = 'nowrap';
  4529. if (item == revs[revs.length - 1])
  4530. {
  4531. mxUtils.write(date, mxResources.get('current'));
  4532. }
  4533. else
  4534. {
  4535. if (ts.toDateString() === today)
  4536. {
  4537. mxUtils.write(date, ts.toLocaleTimeString());
  4538. }
  4539. else
  4540. {
  4541. mxUtils.write(date, ts.toLocaleDateString() + ' ' +
  4542. ts.toLocaleTimeString());
  4543. }
  4544. }
  4545. row.appendChild(date);
  4546. row.setAttribute('title', ts.toLocaleDateString() + ' ' +
  4547. ts.toLocaleTimeString() + ' ' +
  4548. editorUi.formatFileSize(parseInt(item.fileSize)) +
  4549. ((item.lastModifyingUserName != null) ? ' ' +
  4550. item.lastModifyingUserName : ''));
  4551. function updateGraph(xml)
  4552. {
  4553. spinner.stop();
  4554. var doc = mxUtils.parseXml(xml);
  4555. var node = editorUi.editor.extractGraphModel(doc.documentElement, true);
  4556. if (node != null)
  4557. {
  4558. pageSelect.style.display = 'none';
  4559. pageSelect.innerHTML = '';
  4560. currentDoc = doc;
  4561. currentXml = xml;
  4562. parseSelectFunction = null;
  4563. diagrams = null;
  4564. realPage = 0;
  4565. function parseGraphModel(dataNode)
  4566. {
  4567. var bg = dataNode.getAttribute('background');
  4568. if (bg == null || bg == '' || bg == mxConstants.NONE)
  4569. {
  4570. bg = '#ffffff';
  4571. }
  4572. container.style.backgroundColor = bg;
  4573. var codec = new mxCodec(dataNode.ownerDocument);
  4574. codec.decode(dataNode, graph.getModel());
  4575. graph.maxFitScale = 1;
  4576. graph.fit(8);
  4577. graph.center();
  4578. return dataNode;
  4579. }
  4580. function parseDiagram(diagramNode)
  4581. {
  4582. if (diagramNode != null)
  4583. {
  4584. diagramNode = parseGraphModel(mxUtils.parseXml(Graph.decompress(
  4585. mxUtils.getTextContent(diagramNode))).documentElement);
  4586. }
  4587. return diagramNode;
  4588. }
  4589. if (node.nodeName == 'mxfile')
  4590. {
  4591. // Workaround for "invalid calling object" error in IE
  4592. var tmp = node.getElementsByTagName('diagram');
  4593. diagrams = [];
  4594. for (var i = 0; i < tmp.length; i++)
  4595. {
  4596. diagrams.push(tmp[i]);
  4597. }
  4598. realPage = Math.min(currentPage, diagrams.length - 1);
  4599. if (diagrams.length > 0)
  4600. {
  4601. parseDiagram(diagrams[realPage]);
  4602. }
  4603. if (diagrams.length > 1)
  4604. {
  4605. pageSelect.removeAttribute('disabled');
  4606. pageSelect.style.display = '';
  4607. for (var i = 0; i < diagrams.length; i++)
  4608. {
  4609. var pageOption = document.createElement('option');
  4610. mxUtils.write(pageOption, diagrams[i].getAttribute('name') ||
  4611. mxResources.get('pageWithNumber', [i + 1]));
  4612. pageOption.setAttribute('value', i);
  4613. if (i == realPage)
  4614. {
  4615. pageOption.setAttribute('selected', 'selected');
  4616. }
  4617. pageSelect.appendChild(pageOption);
  4618. }
  4619. }
  4620. pageSelectFunction = function()
  4621. {
  4622. try
  4623. {
  4624. var temp = parseInt(pageSelect.value);
  4625. parseDiagram(diagrams[temp]);
  4626. currentPage = temp;
  4627. realPage = currentPage;
  4628. }
  4629. catch (e)
  4630. {
  4631. pageSelect.value = currentPage;
  4632. editorUi.handleError(e);
  4633. }
  4634. };
  4635. }
  4636. else
  4637. {
  4638. parseGraphModel(node);
  4639. }
  4640. var shortUser = item.lastModifyingUserName;
  4641. if (shortUser != null && shortUser.length > 20)
  4642. {
  4643. shortUser = shortUser.substring(0, 20) + '...';
  4644. }
  4645. fileInfo.innerHTML = '';
  4646. mxUtils.write(fileInfo, ((shortUser != null) ?
  4647. (shortUser + ' ') : '') + ts.toLocaleDateString() +
  4648. ' ' + ts.toLocaleTimeString());
  4649. fileInfo.setAttribute('title', row.getAttribute('title'));
  4650. zoomInBtn.removeAttribute('disabled');
  4651. zoomOutBtn.removeAttribute('disabled');
  4652. zoomFitBtn.removeAttribute('disabled');
  4653. zoomActualBtn.removeAttribute('disabled');
  4654. if (file == null || !file.isRestricted())
  4655. {
  4656. if (editorUi.editor.graph.isEnabled())
  4657. {
  4658. restoreBtn.removeAttribute('disabled');
  4659. }
  4660. downloadBtn.removeAttribute('disabled');
  4661. showBtn.removeAttribute('disabled');
  4662. newBtn.removeAttribute('disabled');
  4663. }
  4664. mxUtils.setOpacity(zoomInBtn, 60);
  4665. mxUtils.setOpacity(zoomOutBtn, 60);
  4666. mxUtils.setOpacity(zoomFitBtn, 60);
  4667. mxUtils.setOpacity(zoomActualBtn, 60);
  4668. }
  4669. else
  4670. {
  4671. pageSelect.style.display = 'none';
  4672. pageSelect.innerHTML = '';
  4673. fileInfo.innerHTML = '';
  4674. mxUtils.write(fileInfo, mxResources.get('errorLoadingFile'));
  4675. }
  4676. };
  4677. mxEvent.addListener(row, 'click', function(evt)
  4678. {
  4679. if (currentRev != item)
  4680. {
  4681. spinner.stop();
  4682. if (currentRow != null)
  4683. {
  4684. currentRow.style.backgroundColor = '';
  4685. }
  4686. currentRev = item;
  4687. currentRow = row;
  4688. currentRow.style.backgroundColor = '#ebf2f9';
  4689. currentDoc = null;
  4690. currentXml = null;
  4691. fileInfo.removeAttribute('title');
  4692. fileInfo.innerHTML = mxUtils.htmlEntities(mxResources.get('loading') + '...');
  4693. container.style.backgroundColor = '#ffffff';
  4694. graph.getModel().clear();
  4695. restoreBtn.setAttribute('disabled', 'disabled');
  4696. downloadBtn.setAttribute('disabled', 'disabled');
  4697. zoomInBtn.setAttribute('disabled', 'disabled');
  4698. zoomOutBtn.setAttribute('disabled', 'disabled');
  4699. zoomActualBtn.setAttribute('disabled', 'disabled');
  4700. zoomFitBtn.setAttribute('disabled', 'disabled');
  4701. newBtn.setAttribute('disabled', 'disabled');
  4702. showBtn.setAttribute('disabled', 'disabled');
  4703. pageSelect.setAttribute('disabled', 'disabled');
  4704. mxUtils.setOpacity(zoomInBtn, 20);
  4705. mxUtils.setOpacity(zoomOutBtn, 20);
  4706. mxUtils.setOpacity(zoomFitBtn, 20);
  4707. mxUtils.setOpacity(zoomActualBtn, 20);
  4708. spinner.spin(container);
  4709. item.getXml(function(xml)
  4710. {
  4711. if (currentRev == item)
  4712. {
  4713. try
  4714. {
  4715. updateGraph(xml);
  4716. }
  4717. catch (e)
  4718. {
  4719. fileInfo.innerHTML = mxUtils.htmlEntities(
  4720. mxResources.get('error') + ': ' + e.message);
  4721. }
  4722. }
  4723. }, function(err)
  4724. {
  4725. spinner.stop();
  4726. pageSelect.style.display = 'none';
  4727. pageSelect.innerHTML = '';
  4728. fileInfo.innerHTML = '';
  4729. mxUtils.write(fileInfo, mxResources.get('errorLoadingFile'));
  4730. });
  4731. mxEvent.consume(evt);
  4732. }
  4733. });
  4734. mxEvent.addListener(row, 'dblclick', function(evt)
  4735. {
  4736. showBtn.click();
  4737. if (window.getSelection)
  4738. {
  4739. window.getSelection().removeAllRanges();
  4740. }
  4741. else if (document.selection)
  4742. {
  4743. document.selection.empty();
  4744. }
  4745. mxEvent.consume(evt);
  4746. }, false);
  4747. tbody.appendChild(row);
  4748. }
  4749. return row;
  4750. })(revs[i]);
  4751. // Selects and loads first element in list (ie current version) after
  4752. // graph container was initialized since there is no loading delay
  4753. if (elt != null && i == revs.length - 1)
  4754. {
  4755. currentElt = elt;
  4756. }
  4757. }
  4758. table.appendChild(tbody);
  4759. list.appendChild(table);
  4760. }
  4761. else if (file == null || (editorUi.drive == null && file.constructor == window.DriveFile) ||
  4762. (editorUi.dropbox == null && file.constructor == window.DropboxFile))
  4763. {
  4764. container.style.display = 'none';
  4765. tb.style.display = 'none';
  4766. mxUtils.write(list, mxResources.get('notAvailable'));
  4767. }
  4768. else
  4769. {
  4770. container.style.display = 'none';
  4771. tb.style.display = 'none';
  4772. mxUtils.write(list, mxResources.get('noRevisions'));
  4773. }
  4774. this.init = function()
  4775. {
  4776. if (currentElt != null)
  4777. {
  4778. currentElt.click();
  4779. }
  4780. };
  4781. var closeBtn = mxUtils.button(mxResources.get('close'), function()
  4782. {
  4783. editorUi.hideDialog();
  4784. });
  4785. closeBtn.className = 'geBtn';
  4786. tb.appendChild(pageSelect);
  4787. tb.appendChild(zoomInBtn);
  4788. tb.appendChild(zoomOutBtn);
  4789. tb.appendChild(zoomActualBtn);
  4790. tb.appendChild(zoomFitBtn);
  4791. if (editorUi.editor.cancelFirst)
  4792. {
  4793. buttons.appendChild(closeBtn);
  4794. buttons.appendChild(downloadBtn);
  4795. buttons.appendChild(newBtn);
  4796. buttons.appendChild(restoreBtn);
  4797. buttons.appendChild(showBtn);
  4798. }
  4799. else
  4800. {
  4801. buttons.appendChild(downloadBtn);
  4802. buttons.appendChild(newBtn);
  4803. buttons.appendChild(restoreBtn);
  4804. buttons.appendChild(showBtn);
  4805. buttons.appendChild(closeBtn);
  4806. }
  4807. div.appendChild(buttons);
  4808. div.appendChild(tb);
  4809. div.appendChild(fileInfo);
  4810. this.container = div;
  4811. };
  4812. /**
  4813. * Constructs a new revision dialog
  4814. */
  4815. var DraftDialog = function(editorUi, title, xml, editFn, discardFn, editLabel, discardLabel, ignoreFn)
  4816. {
  4817. var div = document.createElement('div');
  4818. var titleDiv = document.createElement('div');
  4819. titleDiv.style.marginTop = '0px';
  4820. titleDiv.style.whiteSpace = 'nowrap';
  4821. titleDiv.style.overflow = 'auto';
  4822. mxUtils.write(titleDiv, title);
  4823. div.appendChild(titleDiv);
  4824. var container = document.createElement('div');
  4825. container.style.position = 'absolute';
  4826. container.style.border = '1px solid lightGray';
  4827. container.style.marginTop = '10px';
  4828. container.style.width = '640px';
  4829. container.style.top = '46px';
  4830. container.style.bottom = '74px';
  4831. container.style.overflow = 'hidden';
  4832. mxEvent.disableContextMenu(container);
  4833. div.appendChild(container);
  4834. var graph = new Graph(container);
  4835. graph.setEnabled(false);
  4836. graph.setPanning(true);
  4837. graph.panningHandler.ignoreCell = true;
  4838. graph.panningHandler.useLeftButtonForPanning = true;
  4839. graph.minFitScale = null;
  4840. graph.maxFitScale = null;
  4841. graph.centerZoom = true;
  4842. // Handles placeholders for pages
  4843. var doc = mxUtils.parseXml(xml);
  4844. var node = editorUi.editor.extractGraphModel(doc.documentElement, true);
  4845. var currentPage = 0;
  4846. var diagrams = null;
  4847. var graphGetGlobalVariable = graph.getGlobalVariable;
  4848. graph.getGlobalVariable = function(name)
  4849. {
  4850. if (name == 'page' && diagrams != null && diagrams[currentPage] != null)
  4851. {
  4852. return diagrams[currentPage].getAttribute('name');
  4853. }
  4854. else if (name == 'pagenumber')
  4855. {
  4856. return currentPage + 1;
  4857. }
  4858. return graphGetGlobalVariable.apply(this, arguments);
  4859. };
  4860. // Disables hyperlinks
  4861. graph.getLinkForCell = function()
  4862. {
  4863. return null;
  4864. };
  4865. // TODO: Enable per-page math
  4866. // if (Editor.MathJaxRender)
  4867. // {
  4868. // graph.addListener(mxEvent.SIZE, mxUtils.bind(this, function(sender, evt)
  4869. // {
  4870. // // LATER: Math support is used if current graph has math enabled
  4871. // // should use switch from history instead but requires setting the
  4872. // // global mxClient.NO_FO switch
  4873. // if (editorUi.editor.graph.mathEnabled)
  4874. // {
  4875. // Editor.MathJaxRender(graph.container);
  4876. // }
  4877. // }));
  4878. // }
  4879. var zoomInBtn = mxUtils.button('', function()
  4880. {
  4881. graph.zoomIn();
  4882. });
  4883. zoomInBtn.className = 'geSprite geSprite-zoomin';
  4884. zoomInBtn.setAttribute('title', mxResources.get('zoomIn'));
  4885. zoomInBtn.style.outline = 'none';
  4886. zoomInBtn.style.border = 'none';
  4887. zoomInBtn.style.margin = '2px';
  4888. mxUtils.setOpacity(zoomInBtn, 60);
  4889. var zoomOutBtn = mxUtils.button('', function()
  4890. {
  4891. graph.zoomOut();
  4892. });
  4893. zoomOutBtn.className = 'geSprite geSprite-zoomout';
  4894. zoomOutBtn.setAttribute('title', mxResources.get('zoomOut'));
  4895. zoomOutBtn.style.outline = 'none';
  4896. zoomOutBtn.style.border = 'none';
  4897. zoomOutBtn.style.margin = '2px';
  4898. mxUtils.setOpacity(zoomOutBtn, 60);
  4899. var zoomFitBtn = mxUtils.button('', function()
  4900. {
  4901. graph.maxFitScale = 8;
  4902. graph.fit(8);
  4903. graph.center();
  4904. });
  4905. zoomFitBtn.className = 'geSprite geSprite-fit';
  4906. zoomFitBtn.setAttribute('title', mxResources.get('fit'));
  4907. zoomFitBtn.style.outline = 'none';
  4908. zoomFitBtn.style.border = 'none';
  4909. zoomFitBtn.style.margin = '2px';
  4910. mxUtils.setOpacity(zoomFitBtn, 60);
  4911. var zoomActualBtn = mxUtils.button('', function()
  4912. {
  4913. graph.zoomActual();
  4914. graph.center();
  4915. });
  4916. zoomActualBtn.className = 'geSprite geSprite-actualsize';
  4917. zoomActualBtn.setAttribute('title', mxResources.get('actualSize'));
  4918. zoomActualBtn.style.outline = 'none';
  4919. zoomActualBtn.style.border = 'none';
  4920. zoomActualBtn.style.margin = '2px';
  4921. mxUtils.setOpacity(zoomActualBtn, 60);
  4922. var restoreBtn = mxUtils.button(discardLabel || mxResources.get('discard'), discardFn);
  4923. restoreBtn.className = 'geBtn';
  4924. var pageSelect = document.createElement('select');
  4925. pageSelect.style.maxWidth = '80px';
  4926. pageSelect.style.position = 'relative';
  4927. pageSelect.style.top = '-2px';
  4928. pageSelect.style.verticalAlign = 'bottom';
  4929. pageSelect.style.marginRight = '6px';
  4930. pageSelect.style.display = 'none';
  4931. var showBtn = mxUtils.button(editLabel || mxResources.get('edit'), editFn);
  4932. showBtn.className = 'geBtn gePrimaryBtn';
  4933. var buttons = document.createElement('div');
  4934. buttons.style.position = 'absolute';
  4935. buttons.style.bottom = '30px';
  4936. buttons.style.width = '640px';
  4937. buttons.style.textAlign = 'right';
  4938. var tb = document.createElement('div');
  4939. tb.className = 'geToolbarContainer';
  4940. tb.style.cssText = 'box-shadow:none !important;background-color:transparent;' +
  4941. 'padding:2px;border-style:none !important;bottom:30px;';
  4942. this.init = function()
  4943. {
  4944. function parseGraphModel(dataNode)
  4945. {
  4946. if (dataNode != null)
  4947. {
  4948. var bg = dataNode.getAttribute('background');
  4949. if (bg == null || bg == '' || bg == mxConstants.NONE)
  4950. {
  4951. bg = '#ffffff';
  4952. }
  4953. container.style.backgroundColor = bg;
  4954. var codec = new mxCodec(dataNode.ownerDocument);
  4955. codec.decode(dataNode, graph.getModel());
  4956. graph.maxFitScale = 1;
  4957. graph.fit(8);
  4958. graph.center();
  4959. }
  4960. };
  4961. function parseDiagram(diagramNode)
  4962. {
  4963. if (diagramNode != null)
  4964. {
  4965. diagramNode = parseGraphModel(mxUtils.parseXml(Graph.decompress(
  4966. mxUtils.getTextContent(diagramNode))).documentElement);
  4967. }
  4968. return diagramNode;
  4969. };
  4970. mxEvent.addListener(pageSelect, 'change', function(evt)
  4971. {
  4972. currentPage = parseInt(pageSelect.value);
  4973. parseDiagram(diagrams[currentPage]);
  4974. mxEvent.consume(evt);
  4975. });
  4976. if (node.nodeName == 'mxfile')
  4977. {
  4978. // Workaround for "invalid calling object" error in IE
  4979. var tmp = node.getElementsByTagName('diagram');
  4980. diagrams = [];
  4981. for (var i = 0; i < tmp.length; i++)
  4982. {
  4983. diagrams.push(tmp[i]);
  4984. }
  4985. if (diagrams.length > 0)
  4986. {
  4987. parseDiagram(diagrams[currentPage]);
  4988. }
  4989. if (diagrams.length > 1)
  4990. {
  4991. pageSelect.style.display = '';
  4992. for (var i = 0; i < diagrams.length; i++)
  4993. {
  4994. var pageOption = document.createElement('option');
  4995. mxUtils.write(pageOption, diagrams[i].getAttribute('name') ||
  4996. mxResources.get('pageWithNumber', [i + 1]));
  4997. pageOption.setAttribute('value', i);
  4998. if (i == currentPage)
  4999. {
  5000. pageOption.setAttribute('selected', 'selected');
  5001. }
  5002. pageSelect.appendChild(pageOption);
  5003. }
  5004. }
  5005. }
  5006. else
  5007. {
  5008. parseGraphModel(node);
  5009. }
  5010. };
  5011. tb.appendChild(pageSelect);
  5012. tb.appendChild(zoomInBtn);
  5013. tb.appendChild(zoomOutBtn);
  5014. tb.appendChild(zoomActualBtn);
  5015. tb.appendChild(zoomFitBtn);
  5016. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  5017. {
  5018. editorUi.hideDialog(true);
  5019. });
  5020. cancelBtn.className = 'geBtn';
  5021. var ignoreBtn = (ignoreFn != null) ? mxUtils.button(mxResources.get('ignore'), ignoreFn) : null;
  5022. if (ignoreBtn != null)
  5023. {
  5024. ignoreBtn.className = 'geBtn';
  5025. }
  5026. if (editorUi.editor.cancelFirst)
  5027. {
  5028. buttons.appendChild(cancelBtn);
  5029. if (ignoreBtn != null)
  5030. {
  5031. buttons.appendChild(ignoreBtn);
  5032. }
  5033. buttons.appendChild(restoreBtn);
  5034. buttons.appendChild(showBtn);
  5035. }
  5036. else
  5037. {
  5038. buttons.appendChild(showBtn);
  5039. buttons.appendChild(restoreBtn);
  5040. if (ignoreBtn != null)
  5041. {
  5042. buttons.appendChild(ignoreBtn);
  5043. }
  5044. buttons.appendChild(cancelBtn);
  5045. }
  5046. div.appendChild(buttons);
  5047. div.appendChild(tb);
  5048. this.container = div;
  5049. };
  5050. /**
  5051. *
  5052. */
  5053. var FindWindow = function(ui, x, y, w, h)
  5054. {
  5055. var action = ui.actions.get('find');
  5056. var graph = ui.editor.graph;
  5057. var lastSearch = null;
  5058. var lastFound = null;
  5059. var div = document.createElement('div');
  5060. div.style.userSelect = 'none';
  5061. div.style.overflow = 'hidden';
  5062. div.style.padding = '10px';
  5063. div.style.height = '100%';
  5064. var searchInput = document.createElement('input');
  5065. searchInput.setAttribute('placeholder', mxResources.get('find'));
  5066. searchInput.setAttribute('type', 'text');
  5067. searchInput.style.marginTop = '4px';
  5068. searchInput.style.marginBottom = '6px';
  5069. searchInput.style.width = '200px';
  5070. searchInput.style.fontSize = '12px';
  5071. searchInput.style.borderRadius = '4px';
  5072. searchInput.style.padding = '6px';
  5073. div.appendChild(searchInput);
  5074. mxUtils.br(div);
  5075. var regexInput = document.createElement('input');
  5076. regexInput.setAttribute('type', 'checkbox');
  5077. regexInput.style.marginRight = '4px';
  5078. div.appendChild(regexInput);
  5079. mxUtils.write(div, mxResources.get('regularExpression'));
  5080. var help = ui.menus.createHelpLink('https://desk.draw.io/support/solutions/articles/16000088250');
  5081. help.style.position = 'relative';
  5082. help.style.marginLeft = '6px';
  5083. help.style.top = '-1px';
  5084. div.appendChild(help);
  5085. var tmp = document.createElement('div');
  5086. function testMeta(re, cell, search)
  5087. {
  5088. if (typeof cell.value === 'object' && cell.value.attributes != null)
  5089. {
  5090. var attrs = cell.value.attributes;
  5091. for (var i = 0; i < attrs.length; i++)
  5092. {
  5093. if (attrs[i].nodeName != 'label')
  5094. {
  5095. var value = mxUtils.trim(attrs[i].nodeValue.replace(/[\x00-\x1F\x7F-\x9F]|\s+/g, ' ')).toLowerCase();
  5096. if ((re == null && value.substring(0, search.length) === search) ||
  5097. (re != null && re.test(value)))
  5098. {
  5099. return true;
  5100. }
  5101. }
  5102. }
  5103. }
  5104. return false;
  5105. };
  5106. function search()
  5107. {
  5108. var cells = graph.model.getDescendants(graph.model.getRoot());
  5109. var search = searchInput.value.toLowerCase();
  5110. var re = (regexInput.checked) ? new RegExp(search) : null;
  5111. var firstMatch = null;
  5112. if (lastSearch != search)
  5113. {
  5114. lastSearch = search;
  5115. lastFound = null;
  5116. }
  5117. var active = lastFound == null;
  5118. if (search.length > 0)
  5119. {
  5120. for (var i = 0; i < cells.length; i++)
  5121. {
  5122. var state = graph.view.getState(cells[i]);
  5123. if (state != null && state.cell.value != null && (active || firstMatch == null) &&
  5124. (graph.model.isVertex(state.cell) || graph.model.isEdge(state.cell)))
  5125. {
  5126. if (graph.isHtmlLabel(state.cell))
  5127. {
  5128. tmp.innerHTML = graph.getLabel(state.cell);
  5129. label = mxUtils.extractTextWithWhitespace([tmp]);
  5130. }
  5131. else
  5132. {
  5133. label = graph.getLabel(state.cell);
  5134. }
  5135. label = mxUtils.trim(label.replace(/[\x00-\x1F\x7F-\x9F]|\s+/g, ' ')).toLowerCase();
  5136. if ((re == null && (label.substring(0, search.length) === search || testMeta(re, state.cell, search))) ||
  5137. (re != null && (re.test(label) || testMeta(re, state.cell, search))))
  5138. {
  5139. if (active)
  5140. {
  5141. firstMatch = state;
  5142. break;
  5143. }
  5144. else if (firstMatch == null)
  5145. {
  5146. firstMatch = state;
  5147. }
  5148. }
  5149. }
  5150. active = active || state == lastFound;
  5151. }
  5152. }
  5153. if (firstMatch != null)
  5154. {
  5155. lastFound = firstMatch;
  5156. graph.scrollCellToVisible(lastFound.cell);
  5157. if (graph.isEnabled())
  5158. {
  5159. graph.setSelectionCell(lastFound.cell);
  5160. }
  5161. else
  5162. {
  5163. graph.highlightCell(lastFound.cell);
  5164. }
  5165. }
  5166. else if (graph.isEnabled())
  5167. {
  5168. graph.clearSelection();
  5169. }
  5170. return search.length == 0 || firstMatch != null;
  5171. };
  5172. mxUtils.br(div);
  5173. var resetBtn = mxUtils.button(mxResources.get('reset'), function()
  5174. {
  5175. searchInput.value = '';
  5176. searchInput.style.backgroundColor = '';
  5177. lastFound = null;
  5178. lastSearch = null;
  5179. searchInput.focus();
  5180. });
  5181. resetBtn.setAttribute('title', mxResources.get('reset'));
  5182. resetBtn.style.marginTop = '6px';
  5183. resetBtn.style.marginRight = '4px';
  5184. resetBtn.className = 'geBtn';
  5185. div.appendChild(resetBtn);
  5186. var btn = mxUtils.button(mxResources.get('find'), function()
  5187. {
  5188. try
  5189. {
  5190. searchInput.style.backgroundColor = search() ? '' : '#ffcfcf';
  5191. }
  5192. catch (e)
  5193. {
  5194. ui.handleError(e);
  5195. }
  5196. });
  5197. btn.setAttribute('title', mxResources.get('find') + ' (Enter)');
  5198. btn.style.marginTop = '6px';
  5199. btn.className = 'geBtn gePrimaryBtn';
  5200. div.appendChild(btn);
  5201. mxEvent.addListener(searchInput, 'keyup', function(evt)
  5202. {
  5203. // Ctrl or Cmd keys
  5204. if (evt.keyCode == 91 || evt.keyCode == 17)
  5205. {
  5206. // Workaround for lost focus on show
  5207. mxEvent.consume(evt);
  5208. }
  5209. else if (evt.keyCode == 27)
  5210. {
  5211. action.funct();
  5212. }
  5213. else if (lastSearch != searchInput.value.toLowerCase() || evt.keyCode == 13)
  5214. {
  5215. try
  5216. {
  5217. searchInput.style.backgroundColor = search() ? '' : '#ffcfcf';
  5218. }
  5219. catch (e)
  5220. {
  5221. searchInput.style.backgroundColor = '#ffcfcf';
  5222. }
  5223. }
  5224. });
  5225. mxEvent.addListener(div, 'keydown', function(evt)
  5226. {
  5227. if (evt.keyCode == 70 && ui.keyHandler.isControlDown(evt) && !mxEvent.isShiftDown(evt))
  5228. {
  5229. action.funct();
  5230. mxEvent.consume(evt);
  5231. }
  5232. });
  5233. this.window = new mxWindow(mxResources.get('find'), div, x, y, w, h, true, true);
  5234. this.window.destroyOnClose = false;
  5235. this.window.setMaximizable(false);
  5236. this.window.setResizable(false);
  5237. this.window.setClosable(true);
  5238. this.window.addListener('show', mxUtils.bind(this, function()
  5239. {
  5240. this.window.fit();
  5241. if (this.window.isVisible())
  5242. {
  5243. searchInput.focus();
  5244. if (mxClient.IS_GC || mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS)
  5245. {
  5246. searchInput.select();
  5247. }
  5248. else
  5249. {
  5250. document.execCommand('selectAll', false, null);
  5251. }
  5252. }
  5253. else
  5254. {
  5255. graph.container.focus();
  5256. }
  5257. }));
  5258. this.window.setLocation = function(x, y)
  5259. {
  5260. var iw = window.innerWidth || document.body.clientWidth || document.documentElement.clientWidth;
  5261. var ih = window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight;
  5262. x = Math.max(0, Math.min(x, iw - this.table.clientWidth));
  5263. y = Math.max(0, Math.min(y, ih - this.table.clientHeight - 48));
  5264. if (this.getX() != x || this.getY() != y)
  5265. {
  5266. mxWindow.prototype.setLocation.apply(this, arguments);
  5267. }
  5268. };
  5269. var resizeListener = mxUtils.bind(this, function()
  5270. {
  5271. var x = this.window.getX();
  5272. var y = this.window.getY();
  5273. this.window.setLocation(x, y);
  5274. });
  5275. mxEvent.addListener(window, 'resize', resizeListener);
  5276. this.destroy = function()
  5277. {
  5278. mxEvent.removeListener(window, 'resize', resizeListener);
  5279. this.window.destroy();
  5280. }
  5281. };
  5282. /**
  5283. *
  5284. */
  5285. var TagsWindow = function(editorUi, x, y, w, h)
  5286. {
  5287. var graph = editorUi.editor.graph;
  5288. var propertyName = 'tags';
  5289. var div = document.createElement('div');
  5290. div.style.userSelect = 'none';
  5291. div.style.overflow = 'hidden';
  5292. div.style.padding = '10px';
  5293. div.style.height = '100%';
  5294. var searchInput = document.createElement('input');
  5295. searchInput.setAttribute('placeholder', mxResources.get('allTags'));
  5296. searchInput.setAttribute('type', 'text');
  5297. searchInput.style.marginTop = '4px';
  5298. searchInput.style.width = '260px';
  5299. searchInput.style.fontSize = '12px';
  5300. searchInput.style.borderRadius = '4px';
  5301. searchInput.style.padding = '6px';
  5302. div.appendChild(searchInput);
  5303. if (!editorUi.isOffline() || mxClient.IS_CHROMEAPP)
  5304. {
  5305. searchInput.style.width = '240px';
  5306. var elt = editorUi.menus.createHelpLink('https://desk.draw.io/support/solutions/articles/16000046966');
  5307. elt.firstChild.style.marginBottom = '6px';
  5308. elt.style.marginLeft = '6px';
  5309. div.appendChild(elt);
  5310. }
  5311. mxEvent.addListener(searchInput, 'dblclick', function()
  5312. {
  5313. var dlg = new FilenameDialog(editorUi, propertyName, mxResources.get('ok'), mxUtils.bind(this, function(name)
  5314. {
  5315. if (name != null && name.length > 0)
  5316. {
  5317. propertyName = name;
  5318. }
  5319. }), mxResources.get('enterPropertyName'));
  5320. editorUi.showDialog(dlg.container, 300, 80, true, true);
  5321. dlg.init();
  5322. });
  5323. searchInput.setAttribute('title', mxResources.get('doubleClickChangeProperty'));
  5324. function searchCells(cells)
  5325. {
  5326. return graph.getCellsForTags(searchInput.value.split(' '), cells, propertyName);
  5327. };
  5328. function setCellsVisible(cells, visible)
  5329. {
  5330. graph.setCellsVisible(cells, visible);
  5331. };
  5332. mxUtils.br(div);
  5333. var hideBtn = mxUtils.button(mxResources.get('hide'), function()
  5334. {
  5335. setCellsVisible(searchCells(), false);
  5336. });
  5337. hideBtn.setAttribute('title', mxResources.get('hide'));
  5338. hideBtn.style.marginTop = '8px';
  5339. hideBtn.style.marginRight = '4px';
  5340. hideBtn.className = 'geBtn';
  5341. div.appendChild(hideBtn);
  5342. var showBtn = mxUtils.button(mxResources.get('show'), function()
  5343. {
  5344. var cells = searchCells();
  5345. setCellsVisible(cells, true);
  5346. if (graph.isEnabled())
  5347. {
  5348. graph.setSelectionCells(cells);
  5349. }
  5350. else
  5351. {
  5352. for (var i = 0; i < cells.length; i++)
  5353. {
  5354. graph.highlightCell(cells[i]);
  5355. }
  5356. }
  5357. });
  5358. showBtn.setAttribute('title', mxResources.get('show'));
  5359. showBtn.style.marginTop = '8px';
  5360. showBtn.style.marginRight = '4px';
  5361. showBtn.className = 'geBtn';
  5362. div.appendChild(showBtn);
  5363. var action = editorUi.actions.get('tags');
  5364. var btn = mxUtils.button(mxResources.get('close'), function()
  5365. {
  5366. action.funct();
  5367. });
  5368. btn.setAttribute('title', mxResources.get('close') + ' (Enter/Esc)');
  5369. btn.style.marginTop = '8px';
  5370. btn.className = 'geBtn gePrimaryBtn';
  5371. div.appendChild(btn);
  5372. mxEvent.addListener(searchInput, 'keyup', function(evt)
  5373. {
  5374. // Ctrl or Cmd keys
  5375. if (evt.keyCode == 13 || evt.keyCode == 27)
  5376. {
  5377. action.funct();
  5378. }
  5379. });
  5380. this.window = new mxWindow(mxResources.get('tags'), div, x, y, w, h, true, true);
  5381. this.window.destroyOnClose = false;
  5382. this.window.setMaximizable(false);
  5383. this.window.setResizable(false);
  5384. this.window.setClosable(true);
  5385. this.window.addListener('show', mxUtils.bind(this, function()
  5386. {
  5387. this.window.fit();
  5388. if (this.window.isVisible())
  5389. {
  5390. searchInput.focus();
  5391. if (mxClient.IS_GC || mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS)
  5392. {
  5393. searchInput.select();
  5394. }
  5395. else
  5396. {
  5397. document.execCommand('selectAll', false, null);
  5398. }
  5399. }
  5400. else
  5401. {
  5402. graph.container.focus();
  5403. }
  5404. }));
  5405. this.window.setLocation = function(x, y)
  5406. {
  5407. var iw = window.innerWidth || document.body.clientWidth || document.documentElement.clientWidth;
  5408. var ih = window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight;
  5409. x = Math.max(0, Math.min(x, iw - this.table.clientWidth));
  5410. y = Math.max(0, Math.min(y, ih - this.table.clientHeight - 48));
  5411. if (this.getX() != x || this.getY() != y)
  5412. {
  5413. mxWindow.prototype.setLocation.apply(this, arguments);
  5414. }
  5415. };
  5416. var resizeListener = mxUtils.bind(this, function()
  5417. {
  5418. var x = this.window.getX();
  5419. var y = this.window.getY();
  5420. this.window.setLocation(x, y);
  5421. });
  5422. mxEvent.addListener(window, 'resize', resizeListener);
  5423. this.destroy = function()
  5424. {
  5425. mxEvent.removeListener(window, 'resize', resizeListener);
  5426. this.window.destroy();
  5427. }
  5428. };
  5429. /**
  5430. * Constructs a new auth dialog.
  5431. */
  5432. var AuthDialog = function(editorUi, peer, showRememberOption, fn)
  5433. {
  5434. var div = document.createElement('div');
  5435. div.style.textAlign = 'center';
  5436. var hd = document.createElement('p');
  5437. hd.style.fontSize = '16pt';
  5438. hd.style.padding = '0px';
  5439. hd.style.margin = '0px';
  5440. hd.style.color = 'gray';
  5441. mxUtils.write(hd, mxResources.get('authorizationRequired'));
  5442. var service = 'Unknown';
  5443. var img = document.createElement('img');
  5444. img.setAttribute('border', '0');
  5445. img.setAttribute('align', 'absmiddle');
  5446. img.style.marginRight = '10px';
  5447. if (peer == editorUi.drive)
  5448. {
  5449. service = mxResources.get('googleDrive');
  5450. img.src = IMAGE_PATH + '/google-drive-logo-white.svg';
  5451. }
  5452. else if (peer == editorUi.dropbox)
  5453. {
  5454. service = mxResources.get('dropbox');
  5455. img.src = IMAGE_PATH + '/dropbox-logo-white.svg';
  5456. }
  5457. else if (peer == editorUi.oneDrive)
  5458. {
  5459. service = mxResources.get('oneDrive');
  5460. img.src = IMAGE_PATH + '/onedrive-logo-white.svg';
  5461. }
  5462. else if (peer == editorUi.gitHub)
  5463. {
  5464. service = mxResources.get('github');
  5465. img.src = IMAGE_PATH + '/github-logo-white.svg';
  5466. }
  5467. else if (peer == editorUi.trello)
  5468. {
  5469. service = mxResources.get('trello');
  5470. img.src = IMAGE_PATH + '/trello-logo-white.svg';
  5471. }
  5472. var p = document.createElement('p');
  5473. mxUtils.write(p, mxResources.get('authorizeThisAppIn', [service]));
  5474. var cb = document.createElement('input');
  5475. cb.setAttribute('type', 'checkbox');
  5476. var button = mxUtils.button(mxResources.get('authorize'), function()
  5477. {
  5478. fn(cb.checked);
  5479. });
  5480. button.insertBefore(img, button.firstChild);
  5481. button.style.marginTop = '6px';
  5482. button.className = 'geBigButton';
  5483. div.appendChild(hd);
  5484. div.appendChild(p);
  5485. div.appendChild(button);
  5486. if (showRememberOption)
  5487. {
  5488. var p2 = document.createElement('p');
  5489. p2.style.marginTop = '20px';
  5490. p2.appendChild(cb);
  5491. var span = document.createElement('span');
  5492. mxUtils.write(span, ' ' + mxResources.get('rememberMe'));
  5493. p2.appendChild(span);
  5494. div.appendChild(p2);
  5495. cb.checked = true;
  5496. cb.defaultChecked = true;
  5497. mxEvent.addListener(span, 'click', function(evt)
  5498. {
  5499. cb.checked = !cb.checked;
  5500. mxEvent.consume(evt);
  5501. });
  5502. }
  5503. this.container = div;
  5504. };
  5505. var MoreShapesDialog = function(editorUi, expanded, entries)
  5506. {
  5507. entries = (entries != null) ? entries : editorUi.sidebar.entries;
  5508. var div = document.createElement('div');
  5509. var newEntries = [];
  5510. // Adds custom sections first
  5511. if (editorUi.sidebar.customEntries != null)
  5512. {
  5513. for (var i = 0; i < editorUi.sidebar.customEntries.length; i++)
  5514. {
  5515. var section = editorUi.sidebar.customEntries[i];
  5516. var tmp = {title: editorUi.getResource(section.title), entries: []};
  5517. for (var j = 0; j < section.entries.length; j++)
  5518. {
  5519. var entry = section.entries[j];
  5520. tmp.entries.push({id: entry.id, title:
  5521. editorUi.getResource(entry.title),
  5522. desc: editorUi.getResource(entry.desc),
  5523. image: entry.preview});
  5524. }
  5525. newEntries.push(tmp);
  5526. }
  5527. }
  5528. // Adds built-in sections and filter entries
  5529. for (var i = 0; i < entries.length; i++)
  5530. {
  5531. if (editorUi.sidebar.enabledLibraries == null)
  5532. {
  5533. newEntries.push(entries[i]);
  5534. }
  5535. else
  5536. {
  5537. var tmp = {title: entries[i].title, entries: []};
  5538. for (var j = 0; j < entries[i].entries.length; j++)
  5539. {
  5540. if (mxUtils.indexOf(editorUi.sidebar.enabledLibraries,
  5541. entries[i].entries[j].id) >= 0)
  5542. {
  5543. tmp.entries.push(entries[i].entries[j]);
  5544. }
  5545. }
  5546. if (tmp.entries.length > 0)
  5547. {
  5548. newEntries.push(tmp);
  5549. }
  5550. }
  5551. }
  5552. entries = newEntries;
  5553. if (expanded)
  5554. {
  5555. var hd = document.createElement('div');
  5556. hd.className = 'geDialogTitle';
  5557. mxUtils.write(hd, mxResources.get('shapes'));
  5558. hd.style.position = 'absolute';
  5559. hd.style.top = '0px';
  5560. hd.style.left = '0px';
  5561. hd.style.lineHeight = '40px';
  5562. hd.style.height = '40px';
  5563. hd.style.right = '0px';
  5564. if (mxClient.IS_QUIRKS)
  5565. {
  5566. hd.style.width = '718px';
  5567. }
  5568. var list = document.createElement('div');
  5569. var preview = document.createElement('div');
  5570. list.style.position = 'absolute';
  5571. list.style.top = '40px';
  5572. list.style.left = '0px';
  5573. list.style.width = '202px';
  5574. list.style.bottom = '60px';
  5575. list.style.overflow = 'auto';
  5576. if (mxClient.IS_QUIRKS)
  5577. {
  5578. list.style.height = '437px';
  5579. list.style.marginTop = '1px';
  5580. }
  5581. preview.style.position = 'absolute';
  5582. preview.style.left = '202px';
  5583. preview.style.right = '0px';
  5584. preview.style.top = '40px';
  5585. preview.style.bottom = '60px';
  5586. preview.style.overflow = 'auto';
  5587. preview.style.borderLeft = '1px solid rgb(211, 211, 211)';
  5588. preview.style.textAlign = 'center';
  5589. if (mxClient.IS_QUIRKS)
  5590. {
  5591. preview.style.width = parseInt(hd.style.width) - 202 + 'px';
  5592. preview.style.height = list.style.height;
  5593. preview.style.marginTop = list.style.marginTop;
  5594. }
  5595. var currentListItem = null;
  5596. var applyFunctions = [];
  5597. var listEntry = document.createElement('div');
  5598. listEntry.style.position = 'relative';
  5599. listEntry.style.left = '0px';
  5600. listEntry.style.right = '0px';
  5601. for (var i = 0; i < entries.length; i++)
  5602. {
  5603. (function(section)
  5604. {
  5605. var title = listEntry.cloneNode(false);
  5606. title.style.fontWeight = 'bold';
  5607. title.style.backgroundColor = (uiTheme == 'dark') ? '#505759' : '#e5e5e5';
  5608. title.style.padding = '6px 0px 6px 20px';
  5609. mxUtils.write(title, section.title);
  5610. list.appendChild(title);
  5611. for (var j = 0; j < section.entries.length; j++)
  5612. {
  5613. (function(entry)
  5614. {
  5615. var option = listEntry.cloneNode(false);
  5616. option.style.cursor = 'pointer';
  5617. option.style.padding = '4px 0px 4px 20px';
  5618. option.setAttribute('title', entry.title + ' (' + entry.id + ')');
  5619. var checkbox = document.createElement('input');
  5620. checkbox.setAttribute('type', 'checkbox');
  5621. checkbox.checked = editorUi.sidebar.isEntryVisible(entry.id);
  5622. checkbox.defaultChecked = checkbox.checked;
  5623. option.appendChild(checkbox);
  5624. mxUtils.write(option, ' ' + entry.title);
  5625. list.appendChild(option);
  5626. var itemClicked = function(evt)
  5627. {
  5628. if (evt == null || mxEvent.getSource(evt).nodeName != 'INPUT')
  5629. {
  5630. preview.style.textAlign = 'center';
  5631. preview.style.padding = '0px';
  5632. preview.style.color = '';
  5633. preview.innerHTML = '';
  5634. if (entry.desc != null)
  5635. {
  5636. var pre = document.createElement('pre');
  5637. pre.style.boxSizing = 'border-box';
  5638. pre.style.fontFamily = 'inherit';
  5639. pre.style.margin = '20px';
  5640. pre.style.right = '0px';
  5641. pre.style.textAlign = 'left';
  5642. mxUtils.write(pre, entry.desc);
  5643. preview.appendChild(pre);
  5644. }
  5645. if (entry.imageCallback != null)
  5646. {
  5647. entry.imageCallback(preview);
  5648. }
  5649. else if (entry.image != null)
  5650. {
  5651. preview.innerHTML += '<img border="0" src="' + entry.image + '"/>';
  5652. }
  5653. else if (entry.desc == null)
  5654. {
  5655. preview.style.padding = '20px';
  5656. preview.style.color = 'rgb(179, 179, 179)';
  5657. mxUtils.write(preview, mxResources.get('noPreview'));
  5658. }
  5659. if (currentListItem != null)
  5660. {
  5661. currentListItem.style.backgroundColor = '';
  5662. }
  5663. currentListItem = option;
  5664. currentListItem.style.backgroundColor = (uiTheme == 'dark') ? '#505759' : '#ebf2f9';
  5665. if (evt != null)
  5666. {
  5667. mxEvent.consume(evt);
  5668. }
  5669. }
  5670. };
  5671. mxEvent.addListener(option, 'click', itemClicked);
  5672. mxEvent.addListener(option, 'dblclick', function(evt)
  5673. {
  5674. checkbox.checked = !checkbox.checked;
  5675. mxEvent.consume(evt);
  5676. });
  5677. applyFunctions.push(function()
  5678. {
  5679. return (checkbox.checked) ? entry.id : null;
  5680. });
  5681. // Selects first entry
  5682. if (i == 0 && j == 0)
  5683. {
  5684. itemClicked();
  5685. }
  5686. })(section.entries[j]);
  5687. }
  5688. })(entries[i]);
  5689. }
  5690. div.style.padding = '30px';
  5691. div.appendChild(hd);
  5692. div.appendChild(list);
  5693. div.appendChild(preview);
  5694. var buttons = document.createElement('div');
  5695. buttons.className = 'geDialogFooter';
  5696. buttons.style.position = 'absolute';
  5697. buttons.style.paddingRight = '16px';
  5698. buttons.style.color = 'gray';
  5699. buttons.style.left = '0px';
  5700. buttons.style.right = '0px';
  5701. buttons.style.bottom = '0px';
  5702. buttons.style.height = '60px';
  5703. buttons.style.lineHeight = '52px';
  5704. if (mxClient.IS_QUIRKS)
  5705. {
  5706. buttons.style.width = hd.style.width;
  5707. buttons.style.paddingTop = '12px';
  5708. }
  5709. var cb = document.createElement('input');
  5710. cb.setAttribute('type', 'checkbox');
  5711. if (isLocalStorage || mxClient.IS_CHROMEAPP)
  5712. {
  5713. var span = document.createElement('span');
  5714. span.style.paddingRight = '20px';
  5715. span.appendChild(cb);
  5716. mxUtils.write(span, ' ' + mxResources.get('rememberThisSetting'));
  5717. cb.checked = true;
  5718. cb.defaultChecked = true;
  5719. mxEvent.addListener(span, 'click', function(evt)
  5720. {
  5721. if (mxEvent.getSource(evt) != cb)
  5722. {
  5723. cb.checked = !cb.checked;
  5724. mxEvent.consume(evt);
  5725. }
  5726. });
  5727. if (mxClient.IS_QUIRKS)
  5728. {
  5729. span.style.position = 'relative';
  5730. span.style.top = '-6px';
  5731. }
  5732. buttons.appendChild(span);
  5733. }
  5734. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  5735. {
  5736. editorUi.hideDialog();
  5737. });
  5738. cancelBtn.className = 'geBtn';
  5739. var applyBtn = mxUtils.button(mxResources.get('apply'), function()
  5740. {
  5741. editorUi.hideDialog();
  5742. var libs = [];
  5743. for (var i = 0; i < applyFunctions.length; i++)
  5744. {
  5745. var lib = applyFunctions[i].apply(this, arguments);
  5746. if (lib != null)
  5747. {
  5748. libs.push(lib);
  5749. }
  5750. }
  5751. editorUi.sidebar.showEntries(libs.join(';'), cb.checked, true);
  5752. });
  5753. applyBtn.className = 'geBtn gePrimaryBtn';
  5754. if (editorUi.editor.cancelFirst)
  5755. {
  5756. buttons.appendChild(cancelBtn);
  5757. buttons.appendChild(applyBtn);
  5758. }
  5759. else
  5760. {
  5761. buttons.appendChild(applyBtn);
  5762. buttons.appendChild(cancelBtn);
  5763. }
  5764. div.appendChild(buttons);
  5765. }
  5766. else
  5767. {
  5768. var libFS = document.createElement('table');
  5769. var tbody = document.createElement('tbody');
  5770. div.style.height = '100%';
  5771. div.style.overflow = 'auto';
  5772. var row = document.createElement('tr');
  5773. libFS.style.width = '100%';
  5774. var leftDiv = document.createElement('td');
  5775. var midDiv = document.createElement('td');
  5776. var rightDiv = document.createElement('td');
  5777. var addLibCB = mxUtils.bind(this, function(wrapperDiv, title, key)
  5778. {
  5779. var libCB = document.createElement('input');
  5780. libCB.type = 'checkbox';
  5781. libFS.appendChild(libCB);
  5782. libCB.checked = editorUi.sidebar.isEntryVisible(key);
  5783. var libSpan = document.createElement('span');
  5784. mxUtils.write(libSpan, title);
  5785. var label = document.createElement('div');
  5786. label.style.display = 'block';
  5787. label.appendChild(libCB);
  5788. label.appendChild(libSpan);
  5789. mxEvent.addListener(libSpan, 'click', function(evt)
  5790. {
  5791. libCB.checked = !libCB.checked;
  5792. mxEvent.consume(evt);
  5793. });
  5794. wrapperDiv.appendChild(label);
  5795. return function()
  5796. {
  5797. return (libCB.checked) ? key : null;
  5798. };
  5799. });
  5800. row.appendChild(leftDiv);
  5801. row.appendChild(midDiv);
  5802. row.appendChild(rightDiv);
  5803. tbody.appendChild(row);
  5804. libFS.appendChild(tbody);
  5805. var applyFunctions = [];
  5806. var count = 0;
  5807. // Counts total number of entries
  5808. for (var i = 0; i < entries.length; i++)
  5809. {
  5810. for (var j = 0; j < entries[i].entries.length; j++)
  5811. {
  5812. count++;
  5813. }
  5814. }
  5815. // Distributes entries on columns
  5816. var cols = [leftDiv, midDiv, rightDiv];
  5817. var counter = 0;
  5818. for (var i = 0; i < entries.length; i++)
  5819. {
  5820. (function(section)
  5821. {
  5822. for (var j = 0; j < section.entries.length; j++)
  5823. {
  5824. (function(entry)
  5825. {
  5826. var index = Math.floor(counter / (count / 3));
  5827. applyFunctions.push(addLibCB(cols[index], entry.title, entry.id));
  5828. counter++;
  5829. })(section.entries[j]);
  5830. }
  5831. })(entries[i]);
  5832. }
  5833. div.appendChild(libFS);
  5834. var remember = document.createElement('div');
  5835. remember.style.marginTop = '18px';
  5836. remember.style.textAlign = 'center';
  5837. var cb = document.createElement('input');
  5838. if (isLocalStorage)
  5839. {
  5840. cb.setAttribute('type', 'checkbox');
  5841. cb.checked = true;
  5842. cb.defaultChecked = true;
  5843. remember.appendChild(cb);
  5844. var span = document.createElement('span');
  5845. mxUtils.write(span, ' ' + mxResources.get('rememberThisSetting'));
  5846. remember.appendChild(span);
  5847. mxEvent.addListener(span, 'click', function(evt)
  5848. {
  5849. cb.checked = !cb.checked;
  5850. mxEvent.consume(evt);
  5851. });
  5852. }
  5853. div.appendChild(remember);
  5854. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  5855. {
  5856. editorUi.hideDialog();
  5857. });
  5858. cancelBtn.className = 'geBtn';
  5859. var applyBtn = mxUtils.button(mxResources.get('apply'), function()
  5860. {
  5861. var libs = ['search'];
  5862. for (var i = 0; i < applyFunctions.length; i++)
  5863. {
  5864. var lib = applyFunctions[i].apply(this, arguments);
  5865. if (lib != null)
  5866. {
  5867. libs.push(lib);
  5868. }
  5869. }
  5870. editorUi.sidebar.showEntries((libs.length > 0) ? libs.join(';') : '', cb.checked);
  5871. editorUi.hideDialog();
  5872. });
  5873. applyBtn.className = 'geBtn gePrimaryBtn';
  5874. var buttons = document.createElement('div');
  5875. buttons.style.marginTop = '26px';
  5876. buttons.style.textAlign = 'right';
  5877. if (editorUi.editor.cancelFirst)
  5878. {
  5879. buttons.appendChild(cancelBtn);
  5880. buttons.appendChild(applyBtn);
  5881. }
  5882. else
  5883. {
  5884. buttons.appendChild(applyBtn);
  5885. buttons.appendChild(cancelBtn);
  5886. }
  5887. div.appendChild(buttons);
  5888. }
  5889. this.container = div;
  5890. };
  5891. var PluginsDialog = function(editorUi)
  5892. {
  5893. var div = document.createElement('div');
  5894. var inner = document.createElement('div');
  5895. inner.style.height = '120px';
  5896. inner.style.overflow = 'auto';
  5897. var plugins = mxSettings.getPlugins().slice();
  5898. function refresh()
  5899. {
  5900. if (plugins.length == 0)
  5901. {
  5902. inner.innerHTML = mxUtils.htmlEntities(mxResources.get('noPlugins'));
  5903. }
  5904. else
  5905. {
  5906. inner.innerHTML = '';
  5907. for (var i = 0; i < plugins.length; i++)
  5908. {
  5909. var span = document.createElement('span');
  5910. span.style.whiteSpace = 'nowrap';
  5911. var img = document.createElement('span');
  5912. img.className = 'geSprite geSprite-delete';
  5913. img.style.position = 'relative';
  5914. img.style.cursor = 'pointer';
  5915. img.style.top = '5px';
  5916. img.style.marginRight = '4px';
  5917. img.style.display = 'inline-block';
  5918. span.appendChild(img);
  5919. mxUtils.write(span, plugins[i]);
  5920. inner.appendChild(span);
  5921. mxUtils.br(inner);
  5922. mxEvent.addListener(img, 'click', (function(index)
  5923. {
  5924. return function()
  5925. {
  5926. editorUi.confirm(mxResources.get('delete') + ' "' + plugins[index] + '"?', function()
  5927. {
  5928. plugins.splice(index, 1);
  5929. refresh();
  5930. });
  5931. };
  5932. })(i));
  5933. }
  5934. }
  5935. }
  5936. div.appendChild(inner);
  5937. refresh();
  5938. var addBtn = mxUtils.button(mxResources.get('add'), function()
  5939. {
  5940. var tmp = '';
  5941. var param = urlParams['p'];
  5942. if (param != null && param.length > 0)
  5943. {
  5944. var tokens = param.split(';');
  5945. for (var i = 0; i < tokens.length; i++)
  5946. {
  5947. var url = App.pluginRegistry[tokens[i]];
  5948. if (url != null)
  5949. {
  5950. tmp += url + ';';
  5951. }
  5952. }
  5953. if (tmp.charAt(tmp.length - 1) == ';')
  5954. {
  5955. tmp = tmp.substring(0, tmp.length - 1);
  5956. }
  5957. }
  5958. var dlg = new FilenameDialog(editorUi, tmp, mxResources.get('add'), function(newValue)
  5959. {
  5960. if (newValue != null && newValue.length > 0)
  5961. {
  5962. tokens = newValue.split(';');
  5963. for (var i = 0; i < tokens.length; i++)
  5964. {
  5965. var token = tokens[i];
  5966. var url = App.pluginRegistry[token];
  5967. if (url != null)
  5968. {
  5969. token = url;
  5970. }
  5971. if (token.length > 0 && mxUtils.indexOf(plugins, token) < 0)
  5972. {
  5973. plugins.push(token);
  5974. }
  5975. }
  5976. refresh();
  5977. }
  5978. }, mxResources.get('enterValue') + ' (' + mxResources.get('url') + ')');
  5979. editorUi.showDialog(dlg.container, 300, 80, true, true);
  5980. dlg.init();
  5981. });
  5982. addBtn.className = 'geBtn';
  5983. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  5984. {
  5985. editorUi.hideDialog();
  5986. });
  5987. cancelBtn.className = 'geBtn';
  5988. var applyBtn = mxUtils.button(mxResources.get('apply'), function()
  5989. {
  5990. mxSettings.setPlugins(plugins);
  5991. mxSettings.save();
  5992. editorUi.hideDialog();
  5993. editorUi.alert(mxResources.get('restartForChangeRequired'));
  5994. });
  5995. applyBtn.className = 'geBtn gePrimaryBtn';
  5996. var helpBtn = mxUtils.button(mxResources.get('help'), function()
  5997. {
  5998. editorUi.openLink('https://desk.draw.io/support/solutions/articles/16000056430');
  5999. });
  6000. helpBtn.className = 'geBtn';
  6001. if (editorUi.isOffline() && !mxClient.IS_CHROMEAPP)
  6002. {
  6003. helpBtn.style.display = 'none';
  6004. }
  6005. var buttons = document.createElement('div');
  6006. buttons.style.marginTop = '14px';
  6007. buttons.style.textAlign = 'right';
  6008. if (editorUi.editor.cancelFirst)
  6009. {
  6010. buttons.appendChild(cancelBtn);
  6011. buttons.appendChild(helpBtn);
  6012. buttons.appendChild(addBtn);
  6013. buttons.appendChild(applyBtn);
  6014. }
  6015. else
  6016. {
  6017. buttons.appendChild(helpBtn);
  6018. buttons.appendChild(addBtn);
  6019. buttons.appendChild(applyBtn);
  6020. buttons.appendChild(cancelBtn);
  6021. }
  6022. div.appendChild(buttons);
  6023. this.container = div;
  6024. };
  6025. var CropImageDialog = function(editorUi, image, fn)
  6026. {
  6027. var div = document.createElement('div');
  6028. var table = document.createElement('table');
  6029. var tbody = document.createElement('tbody');
  6030. var row = document.createElement('tr');
  6031. var size = document.createElement('td');
  6032. size.style.whiteSpace = 'nowrap';
  6033. size.setAttribute('colspan', '2');
  6034. mxUtils.write(size, mxResources.get('loading') + '...');
  6035. row.appendChild(size);
  6036. tbody.appendChild(row);
  6037. var row = document.createElement('tr');
  6038. var left = document.createElement('td');
  6039. var right = document.createElement('td');
  6040. table.style.paddingLeft = '6px';
  6041. mxUtils.write(left, mxResources.get('left') + ':');
  6042. var xInput = document.createElement('input');
  6043. xInput.setAttribute('type', 'text');
  6044. xInput.style.width = '100px';
  6045. xInput.value = '0';
  6046. this.init = function()
  6047. {
  6048. xInput.focus();
  6049. xInput.select();
  6050. };
  6051. right.appendChild(xInput);
  6052. row.appendChild(left);
  6053. row.appendChild(right);
  6054. tbody.appendChild(row);
  6055. row = document.createElement('tr');
  6056. left = document.createElement('td');
  6057. right = document.createElement('td');
  6058. mxUtils.write(left, mxResources.get('top') + ':');
  6059. var yInput = document.createElement('input');
  6060. yInput.setAttribute('type', 'text');
  6061. yInput.style.width = '100px';
  6062. yInput.value = '0';
  6063. right.appendChild(yInput);
  6064. row.appendChild(left);
  6065. row.appendChild(right);
  6066. tbody.appendChild(row);
  6067. row = document.createElement('tr');
  6068. left = document.createElement('td');
  6069. right = document.createElement('td');
  6070. mxUtils.write(left, mxResources.get('right') + ':');
  6071. var wInput = document.createElement('input');
  6072. wInput.setAttribute('type', 'text');
  6073. wInput.style.width = '100px';
  6074. wInput.value = '0';
  6075. right.appendChild(wInput);
  6076. row.appendChild(left);
  6077. row.appendChild(right);
  6078. tbody.appendChild(row);
  6079. row = document.createElement('tr');
  6080. left = document.createElement('td');
  6081. right = document.createElement('td');
  6082. mxUtils.write(left, mxResources.get('bottom') + ':');
  6083. var hInput = document.createElement('input');
  6084. hInput.setAttribute('type', 'text');
  6085. hInput.style.width = '100px';
  6086. hInput.value = '0';
  6087. right.appendChild(hInput);
  6088. row.appendChild(left);
  6089. row.appendChild(right);
  6090. tbody.appendChild(row);
  6091. row = document.createElement('tr');
  6092. left = document.createElement('td');
  6093. right = document.createElement('td');
  6094. mxUtils.write(left, mxResources.get('circle') + ':');
  6095. row.appendChild(left);
  6096. var circleInput = document.createElement('input');
  6097. circleInput.setAttribute('type', 'checkbox');
  6098. right.appendChild(circleInput);
  6099. row.appendChild(right);
  6100. tbody.appendChild(row);
  6101. table.appendChild(tbody);
  6102. div.appendChild(table);
  6103. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  6104. {
  6105. editorUi.hideDialog();
  6106. });
  6107. cancelBtn.className = 'geBtn';
  6108. var imageObj = new Image();
  6109. var applyBtn = mxUtils.button(mxResources.get('apply'), function()
  6110. {
  6111. editorUi.hideDialog();
  6112. var canvas = document.createElement('canvas');
  6113. var context = canvas.getContext('2d');
  6114. var w = imageObj.width;
  6115. var h = imageObj.height;
  6116. // draw cropped image
  6117. var sourceX = parseInt(xInput.value);
  6118. var sourceY = parseInt(yInput.value);
  6119. var sourceWidth = Math.max(1, w - sourceX - parseInt(wInput.value));
  6120. var sourceHeight = Math.max(1, h - sourceY - parseInt(hInput.value));
  6121. canvas.width = sourceWidth;
  6122. canvas.height = sourceHeight;
  6123. if (circleInput.checked)
  6124. {
  6125. context.fillStyle = '#000000';
  6126. context.arc(sourceWidth / 2, sourceHeight / 2, Math.min(sourceWidth / 2,
  6127. sourceHeight / 2), 0, 2 * Math.PI);
  6128. context.fill();
  6129. context.globalCompositeOperation = 'source-in';
  6130. }
  6131. context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, 0, 0, sourceWidth, sourceHeight);
  6132. fn(canvas.toDataURL());
  6133. });
  6134. applyBtn.className = 'geBtn gePrimaryBtn';
  6135. applyBtn.setAttribute('disabled', 'disabled');
  6136. imageObj.onload = function()
  6137. {
  6138. applyBtn.removeAttribute('disabled');
  6139. size.innerHTML = '';
  6140. mxUtils.write(size, mxResources.get('width') + ': ' + imageObj.width + ' ' +
  6141. mxResources.get('height') + ': ' + imageObj.height);
  6142. };
  6143. imageObj.src = image;
  6144. mxEvent.addListener(div, 'keypress', function(e)
  6145. {
  6146. if (e.keyCode == 13)
  6147. {
  6148. applyBtn.click();
  6149. }
  6150. });
  6151. var buttons = document.createElement('div');
  6152. buttons.style.marginTop = '20px';
  6153. buttons.style.textAlign = 'right';
  6154. if (editorUi.editor.cancelFirst)
  6155. {
  6156. buttons.appendChild(cancelBtn);
  6157. buttons.appendChild(applyBtn);
  6158. }
  6159. else
  6160. {
  6161. buttons.appendChild(applyBtn);
  6162. buttons.appendChild(cancelBtn);
  6163. }
  6164. div.appendChild(buttons);
  6165. this.container = div;
  6166. };
  6167. var EditGeometryDialog = function(editorUi, vertices)
  6168. {
  6169. var graph = editorUi.editor.graph;
  6170. var geo = (vertices.length == 1) ? graph.getCellGeometry(vertices[0]) : null;
  6171. var div = document.createElement('div');
  6172. var table = document.createElement('table');
  6173. var tbody = document.createElement('tbody');
  6174. var row = document.createElement('tr');
  6175. var left = document.createElement('td');
  6176. var right = document.createElement('td');
  6177. table.style.paddingLeft = '6px';
  6178. mxUtils.write(left, mxResources.get('relative') + ':');
  6179. var relInput = document.createElement('input');
  6180. relInput.setAttribute('type', 'checkbox');
  6181. if (geo != null && geo.relative)
  6182. {
  6183. relInput.setAttribute('checked', 'checked');
  6184. relInput.defaultChecked = true;
  6185. }
  6186. this.init = function()
  6187. {
  6188. relInput.focus();
  6189. };
  6190. right.appendChild(relInput);
  6191. row.appendChild(left);
  6192. row.appendChild(right);
  6193. tbody.appendChild(row);
  6194. row = document.createElement('tr');
  6195. left = document.createElement('td');
  6196. right = document.createElement('td');
  6197. mxUtils.write(left, mxResources.get('left') + ':');
  6198. var xInput = document.createElement('input');
  6199. xInput.setAttribute('type', 'text');
  6200. xInput.style.width = '100px';
  6201. xInput.value = (geo != null) ? geo.x : '';
  6202. right.appendChild(xInput);
  6203. row.appendChild(left);
  6204. row.appendChild(right);
  6205. tbody.appendChild(row);
  6206. row = document.createElement('tr');
  6207. left = document.createElement('td');
  6208. right = document.createElement('td');
  6209. mxUtils.write(left, mxResources.get('top') + ':');
  6210. var yInput = document.createElement('input');
  6211. yInput.setAttribute('type', 'text');
  6212. yInput.style.width = '100px';
  6213. yInput.value = (geo != null) ? geo.y : '';
  6214. right.appendChild(yInput);
  6215. row.appendChild(left);
  6216. row.appendChild(right);
  6217. tbody.appendChild(row);
  6218. row = document.createElement('tr');
  6219. left = document.createElement('td');
  6220. right = document.createElement('td');
  6221. mxUtils.write(left, mxResources.get('dx') + ':');
  6222. var dxInput = document.createElement('input');
  6223. dxInput.setAttribute('type', 'text');
  6224. dxInput.style.width = '100px';
  6225. dxInput.value = (geo != null && geo.offset != null) ? geo.offset.x : '';
  6226. right.appendChild(dxInput);
  6227. row.appendChild(left);
  6228. row.appendChild(right);
  6229. tbody.appendChild(row);
  6230. row = document.createElement('tr');
  6231. left = document.createElement('td');
  6232. right = document.createElement('td');
  6233. mxUtils.write(left, mxResources.get('dy') + ':');
  6234. var dyInput = document.createElement('input');
  6235. dyInput.setAttribute('type', 'text');
  6236. dyInput.style.width = '100px';
  6237. dyInput.value = (geo != null && geo.offset != null) ? geo.offset.y : '';
  6238. right.appendChild(dyInput);
  6239. row.appendChild(left);
  6240. row.appendChild(right);
  6241. tbody.appendChild(row);
  6242. row = document.createElement('tr');
  6243. left = document.createElement('td');
  6244. right = document.createElement('td');
  6245. mxUtils.write(left, mxResources.get('width') + ':');
  6246. var wInput = document.createElement('input');
  6247. wInput.setAttribute('type', 'text');
  6248. wInput.style.width = '100px';
  6249. wInput.value = (geo != null) ? geo.width : '';
  6250. right.appendChild(wInput);
  6251. row.appendChild(left);
  6252. row.appendChild(right);
  6253. tbody.appendChild(row);
  6254. row = document.createElement('tr');
  6255. left = document.createElement('td');
  6256. right = document.createElement('td');
  6257. mxUtils.write(left, mxResources.get('height') + ':');
  6258. var hInput = document.createElement('input');
  6259. hInput.setAttribute('type', 'text');
  6260. hInput.style.width = '100px';
  6261. hInput.value = (geo != null) ? geo.height : '';
  6262. right.appendChild(hInput);
  6263. row.appendChild(left);
  6264. row.appendChild(right);
  6265. tbody.appendChild(row);
  6266. row = document.createElement('tr');
  6267. left = document.createElement('td');
  6268. right = document.createElement('td');
  6269. mxUtils.write(left, mxResources.get('rotation') + ':');
  6270. var rotInput = document.createElement('input');
  6271. rotInput.setAttribute('type', 'text');
  6272. rotInput.style.width = '100px';
  6273. rotInput.value = (vertices.length == 1) ? mxUtils.getValue(graph.getCellStyle(vertices[0]),
  6274. mxConstants.STYLE_ROTATION, 0) : '';
  6275. right.appendChild(rotInput);
  6276. row.appendChild(left);
  6277. row.appendChild(right);
  6278. tbody.appendChild(row);
  6279. table.appendChild(tbody);
  6280. div.appendChild(table);
  6281. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  6282. {
  6283. editorUi.hideDialog();
  6284. });
  6285. cancelBtn.className = 'geBtn';
  6286. var applyBtn = mxUtils.button(mxResources.get('apply'), function()
  6287. {
  6288. editorUi.hideDialog();
  6289. graph.getModel().beginUpdate();
  6290. try
  6291. {
  6292. for (var i = 0; i < vertices.length; i++)
  6293. {
  6294. var g = graph.getCellGeometry(vertices[i]);
  6295. if (g != null)
  6296. {
  6297. g = g.clone();
  6298. if (graph.isCellMovable(vertices[i]))
  6299. {
  6300. g.relative = relInput.checked;
  6301. if (mxUtils.trim(xInput.value).length > 0)
  6302. {
  6303. g.x = Number(xInput.value);
  6304. }
  6305. if (mxUtils.trim(yInput.value).length > 0)
  6306. {
  6307. g.y = Number(yInput.value);
  6308. }
  6309. if (mxUtils.trim(dxInput.value).length > 0)
  6310. {
  6311. if (g.offset == null)
  6312. {
  6313. g.offset = new mxPoint();
  6314. }
  6315. g.offset.x = Number(dxInput.value);
  6316. }
  6317. if (mxUtils.trim(dyInput.value).length > 0)
  6318. {
  6319. if (g.offset == null)
  6320. {
  6321. g.offset = new mxPoint();
  6322. }
  6323. g.offset.y = Number(dyInput.value);
  6324. }
  6325. }
  6326. if (graph.isCellResizable(vertices[i]))
  6327. {
  6328. if (mxUtils.trim(wInput.value).length > 0)
  6329. {
  6330. g.width = Number(wInput.value);
  6331. }
  6332. if (mxUtils.trim(hInput.value).length > 0)
  6333. {
  6334. g.height = Number(hInput.value);
  6335. }
  6336. }
  6337. graph.getModel().setGeometry(vertices[i], g);
  6338. }
  6339. if (mxUtils.trim(rotInput.value).length > 0)
  6340. {
  6341. graph.setCellStyles(mxConstants.STYLE_ROTATION, Number(rotInput.value), [vertices[i]]);
  6342. }
  6343. }
  6344. }
  6345. finally
  6346. {
  6347. graph.getModel().endUpdate();
  6348. }
  6349. });
  6350. applyBtn.className = 'geBtn gePrimaryBtn';
  6351. mxEvent.addListener(div, 'keypress', function(e)
  6352. {
  6353. if (e.keyCode == 13)
  6354. {
  6355. applyBtn.click();
  6356. }
  6357. });
  6358. var buttons = document.createElement('div');
  6359. buttons.style.marginTop = '20px';
  6360. buttons.style.textAlign = 'right';
  6361. if (editorUi.editor.cancelFirst)
  6362. {
  6363. buttons.appendChild(cancelBtn);
  6364. buttons.appendChild(applyBtn);
  6365. }
  6366. else
  6367. {
  6368. buttons.appendChild(applyBtn);
  6369. buttons.appendChild(cancelBtn);
  6370. }
  6371. div.appendChild(buttons);
  6372. this.container = div;
  6373. };
  6374. /**
  6375. * Constructs a new dialog for creating files from templates.
  6376. */
  6377. var LibraryDialog = function(editorUi, name, library, initialImages, file, mode)
  6378. {
  6379. var images = [];
  6380. var graph = editorUi.editor.graph;
  6381. var outer = document.createElement('div');
  6382. outer.style.height = '100%';
  6383. var header = document.createElement('div');
  6384. header.style.whiteSpace = 'nowrap';
  6385. header.style.height = '40px';
  6386. outer.appendChild(header);
  6387. mxUtils.write(header, mxResources.get('filename') + ':');
  6388. var nameValue = name;
  6389. if (nameValue == null)
  6390. {
  6391. nameValue = editorUi.defaultLibraryName + '.xml';
  6392. }
  6393. var nameInput = document.createElement('input');
  6394. nameInput.setAttribute('value', nameValue);
  6395. nameInput.style.marginRight = '20px';
  6396. nameInput.style.marginLeft = '10px';
  6397. nameInput.style.width = '500px';
  6398. if (file != null && !file.isRenamable())
  6399. {
  6400. nameInput.setAttribute('disabled', 'true');
  6401. }
  6402. this.init = function()
  6403. {
  6404. if (file == null || file.isRenamable())
  6405. {
  6406. nameInput.focus();
  6407. if (mxClient.IS_GC || mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS)
  6408. {
  6409. nameInput.select();
  6410. }
  6411. else
  6412. {
  6413. document.execCommand('selectAll', false, null);
  6414. }
  6415. }
  6416. };
  6417. header.appendChild(nameInput);
  6418. var div = document.createElement('div');
  6419. div.style.borderWidth = '1px 0px 1px 0px';
  6420. div.style.borderColor = '#d3d3d3';
  6421. div.style.borderStyle = 'solid';
  6422. div.style.marginTop = '6px';
  6423. div.style.overflow = 'auto';
  6424. div.style.height = '340px';
  6425. div.style.backgroundPosition = 'center center';
  6426. div.style.backgroundRepeat = 'no-repeat';
  6427. if (images.length == 0 && Graph.fileSupport)
  6428. {
  6429. div.style.backgroundImage = 'url(\'' + IMAGE_PATH + '/droptarget.png\')';
  6430. }
  6431. var bg = document.createElement('div');
  6432. bg.style.position = 'absolute';
  6433. bg.style.width = '640px';
  6434. bg.style.top = '260px';
  6435. bg.style.textAlign = 'center';
  6436. bg.style.fontSize = '22px';
  6437. bg.style.color = '#a0c3ff';
  6438. mxUtils.write(bg, mxResources.get('dragImagesHere'));
  6439. outer.appendChild(bg);
  6440. var entries = {};
  6441. var ew = 100;
  6442. var eh = 100;
  6443. var dragSourceIndex = null;
  6444. var dropTargetIndex = null;
  6445. function getIndexForEvent(evt)
  6446. {
  6447. var dropTarget = document.elementFromPoint(evt.clientX, evt.clientY);
  6448. while (dropTarget != null && dropTarget.parentNode != div)
  6449. {
  6450. dropTarget = dropTarget.parentNode;
  6451. }
  6452. var result = null;
  6453. if (dropTarget != null)
  6454. {
  6455. var tmp = div.firstChild;
  6456. result = 0;
  6457. while (tmp != null && tmp != dropTarget)
  6458. {
  6459. tmp = tmp.nextSibling;
  6460. result++;
  6461. }
  6462. }
  6463. return result;
  6464. };
  6465. var stopEditing = null;
  6466. var stopWrapper = function(evt)
  6467. {
  6468. var source = mxEvent.getSource(evt);
  6469. if (source.getAttribute('contentEditable') != 'true' && stopEditing != null)
  6470. {
  6471. stopEditing();
  6472. stopEditing = null;
  6473. mxEvent.consume(evt);
  6474. }
  6475. };
  6476. mxEvent.addListener(div, 'mousedown', stopWrapper);
  6477. mxEvent.addListener(div, 'pointerdown', stopWrapper);
  6478. mxEvent.addListener(div, 'touchstart', stopWrapper);
  6479. // For converting image URLs
  6480. var converter = new mxUrlConverter();
  6481. var errorShowed = false;
  6482. function addButton(data, mimeType, x, y, w, h, img, aspect, title)
  6483. {
  6484. // Ignores duplicates
  6485. try
  6486. {
  6487. if (mimeType == null || mimeType.substring(0, 6) == 'image/')
  6488. {
  6489. if ((data == null && img != null) || entries[data] == null)
  6490. {
  6491. div.style.backgroundImage = '';
  6492. bg.style.display = 'none';
  6493. var iw = w;
  6494. var ih = h;
  6495. if (w > editorUi.maxImageSize || h > editorUi.maxImageSize)
  6496. {
  6497. var s = Math.min(1, Math.min(editorUi.maxImageSize / Math.max(1, w)),
  6498. editorUi.maxImageSize / Math.max(1, h));
  6499. w *= s;
  6500. h *= s;
  6501. }
  6502. if (iw > ih)
  6503. {
  6504. ih = Math.round(ih * ew / iw);
  6505. iw = ew;
  6506. }
  6507. else
  6508. {
  6509. iw = Math.round(iw * eh / ih);
  6510. ih = eh;
  6511. }
  6512. var wrapper = document.createElement('div');
  6513. wrapper.setAttribute('draggable', 'true');
  6514. wrapper.style.display = (mxClient.IS_QUIRKS) ? 'inline' : 'inline-block';
  6515. wrapper.style.position = 'relative';
  6516. wrapper.style.cursor = 'move';
  6517. mxUtils.setPrefixedStyle(wrapper.style, 'transition', 'transform .1s ease-in-out');
  6518. if (data != null)
  6519. {
  6520. var elt = document.createElement('img');
  6521. elt.setAttribute('src', converter.convert(data));
  6522. elt.style.width = iw + 'px';
  6523. elt.style.height = ih + 'px';
  6524. elt.style.margin = '10px';
  6525. elt.style.paddingBottom = Math.floor((eh - ih) / 2) + 'px';
  6526. elt.style.paddingLeft = Math.floor((ew - iw) / 2) + 'px';
  6527. wrapper.appendChild(elt);
  6528. }
  6529. else if (img != null)
  6530. {
  6531. var cells = editorUi.stringToCells(Graph.decompress(img.xml));
  6532. if (cells.length > 0)
  6533. {
  6534. editorUi.sidebar.createThumb(cells, ew, eh, wrapper, null, true, false);
  6535. // Needs inline block on SVG for delete icon to appear on same line
  6536. wrapper.firstChild.style.display = (mxClient.IS_QUIRKS) ? 'inline' : 'inline-block';
  6537. wrapper.firstChild.style.cursor = '';
  6538. }
  6539. }
  6540. var rem = document.createElement('img');
  6541. rem.setAttribute('src', Editor.closeImage);
  6542. rem.setAttribute('border', '0');
  6543. rem.setAttribute('title', mxResources.get('delete'));
  6544. rem.setAttribute('align', 'top');
  6545. rem.style.paddingTop = '4px';
  6546. rem.style.position = 'absolute';
  6547. rem.style.marginLeft = '-12px';
  6548. rem.style.zIndex = '1';
  6549. rem.style.cursor = 'pointer';
  6550. // Blocks dragging of remove icon
  6551. mxEvent.addListener(rem, 'dragstart', function(evt)
  6552. {
  6553. mxEvent.consume(evt);
  6554. });
  6555. (function(wrapperDiv, dataParam, imgParam)
  6556. {
  6557. mxEvent.addListener(rem, 'click', function(evt)
  6558. {
  6559. entries[dataParam] = null;
  6560. for (var i = 0; i < images.length; i++)
  6561. {
  6562. if ((images[i].data != null && images[i].data == dataParam) ||
  6563. (images[i].xml != null && imgParam != null &&
  6564. images[i].xml == imgParam.xml))
  6565. {
  6566. images.splice(i, 1);
  6567. break;
  6568. }
  6569. }
  6570. wrapper.parentNode.removeChild(wrapperDiv);
  6571. if (images.length == 0)
  6572. {
  6573. div.style.backgroundImage = 'url(\'' + IMAGE_PATH + '/droptarget.png\')';
  6574. bg.style.display = '';
  6575. }
  6576. mxEvent.consume(evt);
  6577. });
  6578. // Workaround for accidental select all
  6579. mxEvent.addListener(rem, 'dblclick', function(evt)
  6580. {
  6581. mxEvent.consume(evt);
  6582. });
  6583. })(wrapper, data, img);
  6584. wrapper.appendChild(rem);
  6585. wrapper.style.marginBottom = '30px';
  6586. var label = document.createElement('div');
  6587. label.style.position = 'absolute';
  6588. label.style.boxSizing = 'border-box';
  6589. label.style.bottom = '-18px';
  6590. label.style.left = '10px';
  6591. label.style.right = '10px';
  6592. label.style.backgroundColor = '#ffffff';
  6593. label.style.overflow = 'hidden';
  6594. label.style.textAlign = 'center';
  6595. var entry = null;
  6596. if (data != null)
  6597. {
  6598. entry = {data: data, w: w, h: h, title: title};
  6599. if (aspect != null)
  6600. {
  6601. entry.aspect = aspect;
  6602. }
  6603. entries[data] = elt;
  6604. images.push(entry);
  6605. }
  6606. else if (img != null)
  6607. {
  6608. img.aspect = 'fixed';
  6609. images.push(img);
  6610. entry = img;
  6611. }
  6612. function updateLabel()
  6613. {
  6614. label.innerHTML = '';
  6615. label.style.cursor = 'pointer';
  6616. label.style.whiteSpace = 'nowrap';
  6617. label.style.textOverflow = 'ellipsis';
  6618. mxUtils.write(label, (entry.title != null && entry.title.length > 0) ?
  6619. entry.title : mxResources.get('untitled'));
  6620. if (entry.title == null || entry.title.length == 0)
  6621. {
  6622. label.style.color = '#d0d0d0';
  6623. }
  6624. else
  6625. {
  6626. label.style.color = '';
  6627. }
  6628. };
  6629. mxEvent.addListener(label, 'keydown', function(evt)
  6630. {
  6631. if (evt.keyCode == 13 && stopEditing != null)
  6632. {
  6633. stopEditing();
  6634. stopEditing = null;
  6635. mxEvent.consume(evt);
  6636. }
  6637. });
  6638. updateLabel();
  6639. wrapper.appendChild(label);
  6640. // Blocks dragging of label
  6641. mxEvent.addListener(label, 'mousedown', function(evt)
  6642. {
  6643. if (label.getAttribute('contentEditable') != 'true')
  6644. {
  6645. mxEvent.consume(evt);
  6646. }
  6647. });
  6648. var startEditing = function(evt)
  6649. {
  6650. // Workaround for various issues in IE
  6651. if (!mxClient.IS_IOS && !mxClient.IS_QUIRKS && !mxClient.IS_FF &&
  6652. (document.documentMode == null || document.documentMode > 9))
  6653. {
  6654. if (label.getAttribute('contentEditable') != 'true')
  6655. {
  6656. if (stopEditing != null)
  6657. {
  6658. stopEditing();
  6659. stopEditing = null;
  6660. }
  6661. if (entry.title == null || entry.title.length == 0)
  6662. {
  6663. label.innerHTML = '';
  6664. }
  6665. label.style.textOverflow = '';
  6666. label.style.whiteSpace = '';
  6667. label.style.cursor = 'text';
  6668. label.style.color = '';
  6669. label.setAttribute('contentEditable', 'true');
  6670. label.focus();
  6671. document.execCommand('selectAll', false, null);
  6672. stopEditing = function()
  6673. {
  6674. label.removeAttribute('contentEditable');
  6675. label.style.cursor = 'pointer';
  6676. entry.title = label.innerHTML;
  6677. updateLabel();
  6678. }
  6679. mxEvent.consume(evt);
  6680. }
  6681. }
  6682. else
  6683. {
  6684. var dlg = new FilenameDialog(editorUi, entry.title || '', mxResources.get('ok'), function(newTitle)
  6685. {
  6686. if (newTitle != null)
  6687. {
  6688. entry.title = newTitle;
  6689. updateLabel();
  6690. }
  6691. }, mxResources.get('enterValue'));
  6692. editorUi.showDialog(dlg.container, 300, 80, true, true);
  6693. dlg.init();
  6694. mxEvent.consume(evt);
  6695. }
  6696. };
  6697. mxEvent.addListener(label, 'click', startEditing);
  6698. mxEvent.addListener(wrapper, 'dblclick', startEditing);
  6699. div.appendChild(wrapper);
  6700. mxEvent.addListener(wrapper, 'dragstart', function(evt)
  6701. {
  6702. if (data == null && img != null)
  6703. {
  6704. rem.style.visibility = 'hidden';
  6705. label.style.visibility = 'hidden';
  6706. }
  6707. // Workaround for no DnD on DIV in FF
  6708. if (mxClient.IS_FF && img.xml != null)
  6709. {
  6710. evt.dataTransfer.setData('Text', img.xml);
  6711. }
  6712. dragSourceIndex = getIndexForEvent(evt);
  6713. // Workaround for missing drag preview in Google Chrome
  6714. if (mxClient.IS_GC)
  6715. {
  6716. wrapper.style.opacity = '0.9';
  6717. }
  6718. window.setTimeout(function()
  6719. {
  6720. mxUtils.setPrefixedStyle(wrapper.style, 'transform', 'scale(0.5,0.5)');
  6721. mxUtils.setOpacity(wrapper, 30);
  6722. rem.style.visibility = '';
  6723. label.style.visibility = '';
  6724. }, 0);
  6725. });
  6726. mxEvent.addListener(wrapper, 'dragend', function(evt)
  6727. {
  6728. if (rem.style.visibility == 'hidden')
  6729. {
  6730. rem.style.visibility = '';
  6731. label.style.visibility = '';
  6732. }
  6733. dragSourceIndex = null;
  6734. mxUtils.setOpacity(wrapper, 100);
  6735. mxUtils.setPrefixedStyle(wrapper.style, 'transform', null);
  6736. });
  6737. }
  6738. else if (!errorShowed)
  6739. {
  6740. errorShowed = true;
  6741. editorUi.handleError({message: mxResources.get('fileExists')})
  6742. }
  6743. }
  6744. else
  6745. {
  6746. var done = false;
  6747. try
  6748. {
  6749. editorUi.spinner.stop();
  6750. var doc = mxUtils.parseXml(data);
  6751. if (doc.documentElement.nodeName == 'mxlibrary')
  6752. {
  6753. var temp = JSON.parse(mxUtils.getTextContent(doc.documentElement));
  6754. if (temp != null && temp.length > 0)
  6755. {
  6756. for (var i = 0; i < temp.length; i++)
  6757. {
  6758. if (temp[i].xml != null)
  6759. {
  6760. addButton(null, null, 0, 0, 0, 0, temp[i]);
  6761. }
  6762. else
  6763. {
  6764. addButton(temp[i].data, null, 0, 0, temp[i].w, temp[i].h, null, 'fixed', temp[i].title);
  6765. }
  6766. }
  6767. }
  6768. done = true;
  6769. }
  6770. else if (doc.documentElement.nodeName == 'mxfile')
  6771. {
  6772. var pages = doc.documentElement.getElementsByTagName('diagram');
  6773. for (var i = 0; i < pages.length; i++)
  6774. {
  6775. var temp = mxUtils.getTextContent(pages[i]);
  6776. var cells = editorUi.stringToCells(Graph.decompress(temp));
  6777. var size = editorUi.editor.graph.getBoundingBoxFromGeometry(cells);
  6778. addButton(null, null, 0, 0, 0, 0, {xml: temp, w: size.width, h: size.height});
  6779. }
  6780. done = true;
  6781. }
  6782. }
  6783. catch (e)
  6784. {
  6785. // ignore
  6786. }
  6787. if (!done)
  6788. {
  6789. editorUi.spinner.stop();
  6790. editorUi.handleError({message: mxResources.get('errorLoadingFile')})
  6791. }
  6792. }
  6793. }
  6794. catch (e)
  6795. {
  6796. // ignore
  6797. }
  6798. return null;
  6799. };
  6800. if (initialImages != null)
  6801. {
  6802. for (var i = 0; i < initialImages.length; i++)
  6803. {
  6804. var img = initialImages[i];
  6805. addButton(img.data, null, 0, 0, img.w, img.h, img, img.aspect, img.title);
  6806. }
  6807. }
  6808. // Setup the dnd listeners
  6809. mxEvent.addListener(div, 'dragleave', function(evt)
  6810. {
  6811. bg.style.cursor = '';
  6812. var source = mxEvent.getSource(evt);
  6813. while (source != null)
  6814. {
  6815. if (source == div || source == bg)
  6816. {
  6817. evt.stopPropagation();
  6818. evt.preventDefault();
  6819. break;
  6820. }
  6821. source = source.parentNode;
  6822. }
  6823. });
  6824. function dragOver(evt)
  6825. {
  6826. evt.dataTransfer.dropEffect = (dragSourceIndex != null) ? 'move' : 'copy';
  6827. evt.stopPropagation();
  6828. evt.preventDefault();
  6829. };
  6830. var createImportHandler = function(evt)
  6831. {
  6832. return function(data, mimeType, x, y, w, h, img, doneFn, file)
  6833. {
  6834. if (file != null && (/(\.vsdx)($|\?)/i.test(file.name) || /(\.vssx)($|\?)/i.test(file.name)))
  6835. {
  6836. editorUi.importVisio(file, mxUtils.bind(this, function(xml)
  6837. {
  6838. editorUi.spinner.stop();
  6839. addButton(xml, mimeType, x, y, w, h, img, 'fixed', (mxEvent.isAltDown(evt)) ?
  6840. null : img.substring(0, img.lastIndexOf('.')).replace(/_/g, ' '));
  6841. }));
  6842. }
  6843. else if (file != null && !editorUi.isOffline() && new XMLHttpRequest().upload && editorUi.isRemoteFileFormat(data, file.name))
  6844. {
  6845. editorUi.parseFile(file, mxUtils.bind(this, function(xhr)
  6846. {
  6847. if (xhr.readyState == 4)
  6848. {
  6849. editorUi.spinner.stop();
  6850. if (xhr.status >= 200 && xhr.status <= 299)
  6851. {
  6852. var xml = xhr.responseText;
  6853. addButton(xml, mimeType, x, y, w, h, img, 'fixed', (mxEvent.isAltDown(evt)) ?
  6854. null : img.substring(0, img.lastIndexOf('.')).replace(/_/g, ' '));
  6855. div.scrollTop = div.scrollHeight;
  6856. }
  6857. }
  6858. }));
  6859. }
  6860. else
  6861. {
  6862. addButton(data, mimeType, x, y, w, h, img, 'fixed', (mxEvent.isAltDown(evt)) ?
  6863. null : img.substring(0, img.lastIndexOf('.')).replace(/_/g, ' '));
  6864. div.scrollTop = div.scrollHeight;
  6865. }
  6866. };
  6867. };
  6868. function dropHandler(evt)
  6869. {
  6870. evt.stopPropagation();
  6871. evt.preventDefault();
  6872. errorShowed = false;
  6873. dropTargetIndex = getIndexForEvent(evt);
  6874. if (dragSourceIndex != null)
  6875. {
  6876. if (dropTargetIndex != null && dropTargetIndex < div.children.length)
  6877. {
  6878. images.splice((dropTargetIndex > dragSourceIndex) ? dropTargetIndex - 1 : dropTargetIndex,
  6879. 0, images.splice(dragSourceIndex, 1)[0]);
  6880. div.insertBefore(div.children[dragSourceIndex], div.children[dropTargetIndex]);
  6881. }
  6882. else
  6883. {
  6884. images.push(images.splice(dragSourceIndex, 1)[0]);
  6885. div.appendChild(div.children[dragSourceIndex]);
  6886. }
  6887. }
  6888. else if (evt.dataTransfer.files.length > 0)
  6889. {
  6890. editorUi.importFiles(evt.dataTransfer.files, 0, 0, editorUi.maxImageSize, createImportHandler(evt));
  6891. }
  6892. else if (mxUtils.indexOf(evt.dataTransfer.types, 'text/uri-list') >= 0)
  6893. {
  6894. var uri = decodeURIComponent(evt.dataTransfer.getData('text/uri-list'));
  6895. if (/(\.jpg)($|\?)/i.test(uri) || /(\.png)($|\?)/i.test(uri) ||
  6896. /(\.gif)($|\?)/i.test(uri) || /(\.svg)($|\?)/i.test(uri))
  6897. {
  6898. editorUi.loadImage(uri, function(img)
  6899. {
  6900. addButton(uri, null, 0, 0, img.width, img.height);
  6901. div.scrollTop = div.scrollHeight;
  6902. });
  6903. }
  6904. }
  6905. evt.stopPropagation();
  6906. evt.preventDefault();
  6907. };
  6908. mxEvent.addListener(div, 'dragover', dragOver);
  6909. mxEvent.addListener(div, 'drop', dropHandler);
  6910. mxEvent.addListener(bg, 'dragover', dragOver);
  6911. mxEvent.addListener(bg, 'drop', dropHandler);
  6912. outer.appendChild(div);
  6913. var btns = document.createElement('div');
  6914. btns.style.textAlign = 'right';
  6915. btns.style.marginTop = '20px';
  6916. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  6917. {
  6918. editorUi.hideDialog(true);
  6919. });
  6920. cancelBtn.setAttribute('id', 'btnCancel');
  6921. cancelBtn.className = 'geBtn';
  6922. if (editorUi.editor.cancelFirst)
  6923. {
  6924. btns.appendChild(cancelBtn);
  6925. }
  6926. var btn = mxUtils.button(mxResources.get('export'), function()
  6927. {
  6928. var data = editorUi.createLibraryDataFromImages(images);
  6929. var filename = nameInput.value;
  6930. if (!/(\.xml)$/i.test(filename))
  6931. {
  6932. filename += '.xml';
  6933. }
  6934. if (editorUi.isLocalFileSave())
  6935. {
  6936. editorUi.saveLocalFile(data, filename, 'text/xml', null, null, true);
  6937. }
  6938. else
  6939. {
  6940. new mxXmlRequest(SAVE_URL, 'filename=' + encodeURIComponent(filename) +
  6941. '&format=xml&xml=' + encodeURIComponent(data)).simulate(document, '_blank');
  6942. }
  6943. });
  6944. btn.setAttribute('id', 'btnDownload');
  6945. btn.className = 'geBtn';
  6946. btns.appendChild(btn);
  6947. var fileInput = document.createElement('input');
  6948. fileInput.setAttribute('multiple', 'multiple');
  6949. fileInput.setAttribute('type', 'file');
  6950. if (document.documentMode == null)
  6951. {
  6952. mxEvent.addListener(fileInput, 'change', function(evt)
  6953. {
  6954. errorShowed = false;
  6955. editorUi.importFiles(fileInput.files, 0, 0, editorUi.maxImageSize, function(data, mimeType, x, y, w, h, img, doneFn, file)
  6956. {
  6957. createImportHandler(evt)(data, mimeType, x, y, w, h, img, doneFn, file);
  6958. // Resets input to force change event for same file
  6959. fileInput.value = '';
  6960. });
  6961. div.scrollTop = div.scrollHeight;
  6962. });
  6963. var btn = mxUtils.button(mxResources.get('import'), function()
  6964. {
  6965. if (stopEditing != null)
  6966. {
  6967. stopEditing();
  6968. stopEditing = null;
  6969. }
  6970. fileInput.click();
  6971. });
  6972. btn.setAttribute('id', 'btnAddImage');
  6973. btn.className = 'geBtn';
  6974. btns.appendChild(btn);
  6975. }
  6976. var btn = mxUtils.button(mxResources.get('addImageUrl'), function()
  6977. {
  6978. if (stopEditing != null)
  6979. {
  6980. stopEditing();
  6981. stopEditing = null;
  6982. }
  6983. editorUi.showImageDialog(mxResources.get('addImageUrl'), '', function(url, w, h)
  6984. {
  6985. errorShowed = false;
  6986. if (url != null)
  6987. {
  6988. // Image dialog returns modified data URLs which
  6989. // must be converted back to real data URL
  6990. if (url.substring(0, 11) == 'data:image/')
  6991. {
  6992. var comma = url.indexOf(',');
  6993. if (comma > 0)
  6994. {
  6995. url = url.substring(0, comma) + ';base64,' + url.substring(comma + 1);
  6996. }
  6997. }
  6998. addButton(url, null, 0, 0, w, h);
  6999. div.scrollTop = div.scrollHeight;
  7000. }
  7001. });
  7002. });
  7003. btn.setAttribute('id', 'btnAddImageUrl');
  7004. btn.className = 'geBtn';
  7005. btns.appendChild(btn);
  7006. // Indirection for overriding
  7007. this.saveBtnClickHandler = function(name, images, file, mode)
  7008. {
  7009. editorUi.saveLibrary(name, images, file, mode);
  7010. };
  7011. var btn = mxUtils.button(mxResources.get('save'),mxUtils.bind(this, function()
  7012. {
  7013. if (stopEditing != null)
  7014. {
  7015. stopEditing();
  7016. stopEditing = null;
  7017. }
  7018. this.saveBtnClickHandler(nameInput.value, images, file, mode);
  7019. }));
  7020. btn.setAttribute('id', 'btnSave');
  7021. btn.className = 'geBtn gePrimaryBtn';
  7022. btns.appendChild(btn);
  7023. if (!editorUi.editor.cancelFirst)
  7024. {
  7025. btns.appendChild(cancelBtn);
  7026. }
  7027. outer.appendChild(btns);
  7028. this.container = outer;
  7029. };
  7030. /**
  7031. * Constructs a new textarea dialog.
  7032. */
  7033. var EditShapeDialog = function(editorUi, cell, title, w, h)
  7034. {
  7035. w = (w != null) ? w : 300;
  7036. h = (h != null) ? h : 120;
  7037. var row, td;
  7038. var table = document.createElement('table');
  7039. var tbody = document.createElement('tbody');
  7040. table.style.cellPadding = '4px';
  7041. row = document.createElement('tr');
  7042. td = document.createElement('td');
  7043. td.setAttribute('colspan', '2');
  7044. td.style.fontSize = '10pt';
  7045. mxUtils.write(td, title);
  7046. row.appendChild(td);
  7047. tbody.appendChild(row);
  7048. row = document.createElement('tr');
  7049. td = document.createElement('td');
  7050. var nameInput = document.createElement('textarea');
  7051. nameInput.style.outline = 'none';
  7052. nameInput.style.resize = 'none';
  7053. nameInput.style.width = (w - 200) + 'px';
  7054. nameInput.style.height = h + 'px';
  7055. this.textarea = nameInput;
  7056. this.init = function()
  7057. {
  7058. nameInput.focus();
  7059. nameInput.scrollTop = 0;
  7060. };
  7061. td.appendChild(nameInput);
  7062. row.appendChild(td);
  7063. td = document.createElement('td');
  7064. var container = document.createElement('div');
  7065. container.style.position = 'relative';
  7066. container.style.border = '1px solid gray';
  7067. container.style.top = '6px';
  7068. container.style.width = '200px';
  7069. container.style.height = (h + 4) + 'px';
  7070. container.style.overflow = 'hidden';
  7071. container.style.marginBottom = '16px';
  7072. mxEvent.disableContextMenu(container);
  7073. td.appendChild(container);
  7074. var graph = new Graph(container);
  7075. graph.setEnabled(false);
  7076. var clone = editorUi.editor.graph.cloneCell(cell);
  7077. graph.addCells([clone]);
  7078. var state = graph.view.getState(clone);
  7079. var stencil = '';
  7080. if (state.shape != null && state.shape.stencil != null)
  7081. {
  7082. stencil = mxUtils.getPrettyXml(state.shape.stencil.desc);
  7083. }
  7084. mxUtils.write(nameInput, stencil || '');
  7085. var b = graph.getGraphBounds();
  7086. var ns = Math.min((200 - 40) / b.width, (h - 40) / b.height);
  7087. graph.view.scaleAndTranslate(ns, 20 / ns - b.x, 20 / ns - b.y);
  7088. row.appendChild(td);
  7089. tbody.appendChild(row);
  7090. row = document.createElement('tr');
  7091. td = document.createElement('td');
  7092. td.setAttribute('colspan', '2');
  7093. td.style.paddingTop = '2px';
  7094. td.style.whiteSpace = 'nowrap';
  7095. td.setAttribute('align', 'right');
  7096. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  7097. {
  7098. editorUi.hideDialog();
  7099. });
  7100. cancelBtn.className = 'geBtn';
  7101. if (editorUi.editor.cancelFirst)
  7102. {
  7103. td.appendChild(cancelBtn);
  7104. }
  7105. if (!editorUi.isOffline())
  7106. {
  7107. var helpBtn = mxUtils.button(mxResources.get('help'), function()
  7108. {
  7109. editorUi.openLink('https://desk.draw.io/support/solutions/articles/16000052874');
  7110. });
  7111. helpBtn.className = 'geBtn';
  7112. td.appendChild(helpBtn);
  7113. }
  7114. var updateShape = function(targetGraph, targetCell, hide)
  7115. {
  7116. var newValue = nameInput.value;
  7117. // Checks if XML has changed (getPrettyXml "normalizes" DOM)
  7118. var doc = mxUtils.parseXml(newValue);
  7119. newValue = mxUtils.getPrettyXml(doc.documentElement);
  7120. // Checks for validation errors
  7121. // LATER: Validate against XSD
  7122. var errors = doc.documentElement.getElementsByTagName('parsererror');
  7123. if (errors != null && errors.length > 0)
  7124. {
  7125. editorUi.showError(mxResources.get('error'), mxResources.get('containsValidationErrors'), mxResources.get('ok'));
  7126. }
  7127. else
  7128. {
  7129. if (hide)
  7130. {
  7131. editorUi.hideDialog();
  7132. }
  7133. var isNew = !targetGraph.model.contains(targetCell);
  7134. if (!hide || isNew || newValue != stencil)
  7135. {
  7136. // Transform XML value to be used in cell style
  7137. newValue = Graph.compress(newValue);
  7138. targetGraph.getModel().beginUpdate();
  7139. try
  7140. {
  7141. // Inserts cell if required
  7142. if (isNew)
  7143. {
  7144. var pt = editorUi.editor.graph.getInsertPoint();
  7145. targetCell.geometry.x = pt.x;
  7146. targetCell.geometry.y = pt.y;
  7147. targetGraph.addCell(targetCell)
  7148. }
  7149. targetGraph.setCellStyles(mxConstants.STYLE_SHAPE, 'stencil(' + newValue + ')', [targetCell]);
  7150. }
  7151. catch (e)
  7152. {
  7153. throw e;
  7154. }
  7155. finally
  7156. {
  7157. // Updates the display
  7158. targetGraph.getModel().endUpdate();
  7159. }
  7160. // Updates selection after stencil was created for rendering
  7161. if (isNew)
  7162. {
  7163. targetGraph.setSelectionCell(targetCell);
  7164. }
  7165. }
  7166. }
  7167. };
  7168. var previewBtn = mxUtils.button(mxResources.get('preview'), function()
  7169. {
  7170. updateShape(graph, clone, false);
  7171. });
  7172. previewBtn.className = 'geBtn';
  7173. td.appendChild(previewBtn);
  7174. var applyBtn = mxUtils.button(mxResources.get('apply'), function()
  7175. {
  7176. updateShape(editorUi.editor.graph, cell, true);
  7177. });
  7178. applyBtn.className = 'geBtn gePrimaryBtn';
  7179. td.appendChild(applyBtn);
  7180. if (!editorUi.editor.cancelFirst)
  7181. {
  7182. td.appendChild(cancelBtn);
  7183. }
  7184. row.appendChild(td);
  7185. tbody.appendChild(row);
  7186. table.appendChild(tbody);
  7187. this.container = table;
  7188. };
  7189. var CustomDialog = function(editorUi, content, okFn, cancelFn, okButtonText, helpLink, buttonsContent, hideCancel)
  7190. {
  7191. var div = document.createElement('div');
  7192. div.appendChild(content);
  7193. var btns = document.createElement('div');
  7194. btns.style.marginTop = '16px';
  7195. btns.style.textAlign = 'center';
  7196. if (buttonsContent != null)
  7197. {
  7198. btns.appendChild(buttonsContent);
  7199. }
  7200. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  7201. {
  7202. editorUi.hideDialog();
  7203. if (cancelFn != null)
  7204. {
  7205. cancelFn();
  7206. }
  7207. });
  7208. cancelBtn.className = 'geBtn';
  7209. if (hideCancel)
  7210. {
  7211. cancelBtn.style.display = 'none';
  7212. }
  7213. if (editorUi.editor.cancelFirst)
  7214. {
  7215. btns.appendChild(cancelBtn);
  7216. }
  7217. if (!editorUi.isOffline() && helpLink != null)
  7218. {
  7219. var helpBtn = mxUtils.button(mxResources.get('help'), function()
  7220. {
  7221. editorUi.openLink(helpLink);
  7222. });
  7223. helpBtn.className = 'geBtn';
  7224. btns.appendChild(helpBtn);
  7225. }
  7226. var okBtn = mxUtils.button(okButtonText || mxResources.get('ok'), function()
  7227. {
  7228. editorUi.hideDialog();
  7229. if (okFn != null)
  7230. {
  7231. okFn();
  7232. }
  7233. });
  7234. btns.appendChild(okBtn);
  7235. okBtn.className = 'geBtn gePrimaryBtn';
  7236. if (!editorUi.editor.cancelFirst)
  7237. {
  7238. btns.appendChild(cancelBtn);
  7239. }
  7240. div.appendChild(btns);
  7241. this.cancelBtn = cancelBtn;
  7242. this.okButton = okBtn;
  7243. this.container = div;
  7244. };
  7245. var TemplatesDialog = function()
  7246. {
  7247. var dialogSkeleton =
  7248. '<div class="geTempDlgHeader">' +
  7249. '<img src="/images/draw.io-logo.svg" class="geTempDlgHeaderLogo">' +
  7250. '<input type="search" class="geTempDlgSearchBox" placeholder="'+ mxResources.get('search', null, 'Search') +'">' +
  7251. '</div>' +
  7252. '<div class="geTemplatesList">' +
  7253. '<div class="geTempDlgNewDiagramlbl">'+ mxResources.get('newDiagram', null, 'New Diagram') + '</div>' +
  7254. '<div class="geTempDlgHLine"></div>' +
  7255. '<div class="geTemplatesLbl">'+ mxResources.get('templates', null, 'Templates') + '</div>' +
  7256. '</div>' +
  7257. '<div class="geTempDlgContent">' +
  7258. '<div class="geTempDlgNewDiagramCat">' +
  7259. '<div class="geTempDlgNewDiagramCatLbl">'+ mxResources.get('newDiagram', null, 'New Diagram') +'</div>' +
  7260. '<div class="geTempDlgNewDiagramCatList">' +
  7261. '</div>' +
  7262. '<div class="geTempDlgNewDiagramCatFooter">' +
  7263. '<div class="geTempDlgShowAllBtn">'+ mxResources.get('showAll', null, '+ Show all') +'</div>' +
  7264. '</div>' +
  7265. '</div>' +
  7266. '<div class="geTempDlgDiagramsList">' +
  7267. '<div class="geTempDlgDiagramsListHeader">' +
  7268. '<div class="geTempDlgDiagramsListTitle"></div>' +
  7269. '<div class="geTempDlgDiagramsListBtns">' +
  7270. '<div class="geTempDlgRadioBtn geTempDlgRadioBtnLarge" data-id="myDiagramsBtn">' +
  7271. '<img src="/images/my-diagrams.svg" class="geTempDlgMyDiagramsBtnImg"> <span>'+ mxResources.get('myDiagrams', null, 'My diagrams') + '</span>' +
  7272. '</div><div class="geTempDlgRadioBtn geTempDlgRadioBtnLarge geTempDlgRadioBtnActive" data-id="allDiagramsBtn">' +
  7273. '<img src="/images/all-diagrams-sel.svg" class="geTempDlgAllDiagramsBtnImg"> <span>'+ mxResources.get('allDiagrams', null, 'All diagrams') + '</span>' +
  7274. '</div><div class="geTempDlgSpacer"> </div><div class="geTempDlgRadioBtn geTempDlgRadioBtnSmall geTempDlgRadioBtnActive" data-id="tilesBtn">' +
  7275. '<img src="/images/tiles-sel.svg" class="geTempDlgTilesBtnImg">' +
  7276. '</div><div class="geTempDlgRadioBtn geTempDlgRadioBtnSmall" data-id="listBtn">' +
  7277. '<img src="/images/list.svg" class="geTempDlgListBtnImg">' +
  7278. '</div>' +
  7279. '</div>' +
  7280. '</div>' +
  7281. '<div class="geTempDlgDiagramsTiles">' +
  7282. '</div>'+
  7283. '</div>' +
  7284. '</div>' +
  7285. '<br style="clear:both;"/>' +
  7286. '<div class="geTempDlgFooter">' +
  7287. '<span class="geTempDlgLinkToDiagram geTempDlgLinkToDiagramHint">&#x1F6C8; ' + mxResources.get('linkToDiagramHint', null, 'Add a link to this diagram. The diagram can only be edited from the page that owns it.') + '</span>' +
  7288. '<button class="geTempDlgLinkToDiagram geTempDlgLinkToDiagramBtn">'+ mxResources.get('linkToDiagram', null, 'Link to Diagram') + '</button>' +
  7289. '<div class="geTempDlgCreateBtn">'+ mxResources.get('create', null, 'Create') + '</div>' +
  7290. '<div class="geTempDlgCancelBtn">'+ mxResources.get('cancel', null, 'Cancel') + '</div>' +
  7291. '</div>';
  7292. var div = document.createElement('div');
  7293. div.innerHTML = dialogSkeleton;
  7294. div.className = "geTemplateDlg";
  7295. //override default dialog size based on screen size if needed
  7296. var ww = window.innerWidth;
  7297. var wh = window.innerHeight;
  7298. var dw = 987, dh = 712;
  7299. if (ww * 0.9 < dw)
  7300. {
  7301. dw = Math.max(ww * 0.9, 600);
  7302. div.style.width = dw + "px";
  7303. }
  7304. if (wh * 0.9 < dh)
  7305. {
  7306. dh = Math.max(wh * 0.9, 300);
  7307. div.style.height = dh + "px";
  7308. }
  7309. this.width = dw;
  7310. this.height = dh;
  7311. this.container = div;
  7312. };
  7313. TemplatesDialog.prototype.init = function(editorUi, callback, cancelCallback,
  7314. templateFile, newDiagramCatsFile, username, recentDocsCallback, searchDocsCallback,
  7315. openExtDocCallback, linkToDiagramCallback)
  7316. {
  7317. templateFile = (templateFile != null) ? templateFile : (TEMPLATE_PATH + '/index.xml');
  7318. newDiagramCatsFile = (newDiagramCatsFile != null) ? newDiagramCatsFile : NEW_DIAGRAM_CATS_PATH + '/index.xml';
  7319. var dlgDiv = this.container;
  7320. var callInitiated = false;
  7321. var cancelPendingCall = false;
  7322. var currentEntry = null;
  7323. var currentItem = null;
  7324. var currentItemInfo = null;
  7325. var showingAll = false;
  7326. var isGetAll = true;
  7327. var showAsList = false;
  7328. var curDiagList = [];
  7329. var lastSearchStr;
  7330. var categorySelected = true;
  7331. var showAllBtn = dlgDiv.querySelector(".geTempDlgShowAllBtn");
  7332. var diagramsTiles = dlgDiv.querySelector('.geTempDlgDiagramsTiles');
  7333. var diagramsListTitle = dlgDiv.querySelector('.geTempDlgDiagramsListTitle');
  7334. var diagramsListBtns = dlgDiv.querySelector('.geTempDlgDiagramsListBtns');
  7335. var tempDlgContent = dlgDiv.querySelector('.geTempDlgContent');
  7336. var diagramsList = dlgDiv.querySelector('.geTempDlgDiagramsList');
  7337. var newDiagramCat = dlgDiv.querySelector('.geTempDlgNewDiagramCat');
  7338. var newDiagramCatList = dlgDiv.querySelector(".geTempDlgNewDiagramCatList");
  7339. var createBtn = dlgDiv.querySelector('.geTempDlgCreateBtn');
  7340. var spinner = new Spinner({
  7341. lines: 12, // The number of lines to draw
  7342. length: 10, // The length of each line
  7343. width: 5, // The line thickness
  7344. radius: 10, // The radius of the inner circle
  7345. rotate: 0, // The rotation offset
  7346. color: '#000', // #rgb or #rrggbb
  7347. speed: 1.5, // Rounds per second
  7348. trail: 60, // Afterglow percentage
  7349. shadow: false, // Whether to render a shadow
  7350. hwaccel: false, // Whether to use hardware acceleration
  7351. top: '50px',
  7352. zIndex: 2e9 // The z-index (defaults to 2000000000)
  7353. });
  7354. function deselectTempCat()
  7355. {
  7356. if (currentEntry != null)
  7357. {
  7358. currentEntry.style.fontWeight = 'normal';
  7359. currentEntry.style.textDecoration = 'none';
  7360. currentEntry = null;
  7361. }
  7362. };
  7363. mxEvent.addListener(dlgDiv.querySelector('.geTempDlgNewDiagramlbl'), 'click', function()
  7364. {
  7365. deselectTempCat();
  7366. newDiagramCat.style.display = '';
  7367. diagramsList.style.minHeight = 'calc(100% - 280px)';
  7368. getRecentDocs(isGetAll);
  7369. });
  7370. function radioClick(btn, btnImgId, btnImgFile, otherBtnId, otherBtnImgId, otherBtnImgFile, isLarge)
  7371. {
  7372. if (btn.className.indexOf('geTempDlgRadioBtnActive') > -1)
  7373. {
  7374. return false;
  7375. }
  7376. else
  7377. {
  7378. btn.className += ' geTempDlgRadioBtnActive';
  7379. dlgDiv.querySelector('.geTempDlgRadioBtn[data-id='+ otherBtnId +']').className = "geTempDlgRadioBtn " +
  7380. (isLarge? "geTempDlgRadioBtnLarge" : "geTempDlgRadioBtnSmall");
  7381. dlgDiv.querySelector('.'+ btnImgId).src = "/images/"+ btnImgFile +"-sel.svg";
  7382. dlgDiv.querySelector('.'+ otherBtnImgId).src = "/images/"+ otherBtnImgFile +".svg";
  7383. return true;
  7384. }
  7385. };
  7386. mxEvent.addListener(dlgDiv.querySelector('.geTempDlgRadioBtn[data-id=allDiagramsBtn]'), 'click', function()
  7387. {
  7388. if (radioClick(this, 'geTempDlgAllDiagramsBtnImg', 'all-diagrams', 'myDiagramsBtn', 'geTempDlgMyDiagramsBtnImg', 'my-diagrams', true))
  7389. {
  7390. isGetAll = true;
  7391. lastSearchStr == null? getRecentDocs(isGetAll) : doSearch(lastSearchStr);
  7392. }
  7393. });
  7394. mxEvent.addListener(dlgDiv.querySelector('.geTempDlgRadioBtn[data-id=myDiagramsBtn]'), 'click', function()
  7395. {
  7396. if (radioClick(this, 'geTempDlgMyDiagramsBtnImg', 'my-diagrams', 'allDiagramsBtn', 'geTempDlgAllDiagramsBtnImg', 'all-diagrams', true))
  7397. {
  7398. isGetAll = false;
  7399. lastSearchStr == null? getRecentDocs(isGetAll) : doSearch(lastSearchStr);
  7400. }
  7401. });
  7402. mxEvent.addListener(dlgDiv.querySelector('.geTempDlgRadioBtn[data-id=listBtn]'), 'click', function()
  7403. {
  7404. if (radioClick(this, 'geTempDlgListBtnImg', 'list', 'tilesBtn', 'geTempDlgTilesBtnImg', 'tiles', false))
  7405. {
  7406. showAsList = true;
  7407. fillDiagramsList(curDiagList, false, showAsList);
  7408. }
  7409. });
  7410. mxEvent.addListener(dlgDiv.querySelector('.geTempDlgRadioBtn[data-id=tilesBtn]'), 'click', function()
  7411. {
  7412. if (radioClick(this, 'geTempDlgTilesBtnImg', 'tiles', 'listBtn', 'geTempDlgListBtnImg', 'list', false))
  7413. {
  7414. showAsList = false;
  7415. fillDiagramsList(curDiagList, false, showAsList);
  7416. }
  7417. });
  7418. function createPreview(diagram)
  7419. {
  7420. var imgUrl = diagram.prevImgUrl || diagram.imgUrl || (TEMPLATE_PATH + '/' + diagram.url.substring(0, diagram.url.length - 4) + '.png');
  7421. var mask = document.createElement('div');
  7422. mask.className = "geTempDlgDialogMask";
  7423. dlgDiv.appendChild(mask);
  7424. var prevBox = document.createElement('div');
  7425. prevBox.className = "geTempDlgDiagramPreviewBox";
  7426. var img = document.createElement('img');
  7427. img.src = imgUrl;
  7428. prevBox.appendChild(img);
  7429. var closeBtn = document.createElement('img');
  7430. closeBtn.src = "/images/close.png";
  7431. closeBtn.className = "geTempDlgPreviewCloseBtn";
  7432. closeBtn.setAttribute('title', mxResources.get("close"));
  7433. prevBox.appendChild(closeBtn);
  7434. var scrollTop = tempDlgContent.scrollTop;
  7435. function closeBox(evt)
  7436. {
  7437. tempDlgContent.removeChild(prevBox);
  7438. dlgDiv.removeChild(mask);
  7439. tempDlgContent.scrollTop = scrollTop;
  7440. };
  7441. mxEvent.addListener(closeBtn, 'click', closeBox);
  7442. mxEvent.addListener(mask, 'click', closeBox);
  7443. tempDlgContent.appendChild(prevBox);
  7444. tempDlgContent.scrollTop = 0;
  7445. //for centering the image
  7446. prevBox.style.lineHeight = prevBox.clientHeight + "px";
  7447. };
  7448. function swapActiveItem(newItem, activeCls, itemInfo)
  7449. {
  7450. if (currentItem != null)
  7451. {
  7452. var classes = currentItem.className.split(" ");
  7453. for (var i = 0; i < classes.length; i++)
  7454. {
  7455. if (classes[i].indexOf("Active") > -1)
  7456. {
  7457. classes.splice(i, 1);
  7458. break;
  7459. }
  7460. }
  7461. currentItem.className = classes.join(" ");
  7462. }
  7463. if (newItem != null)
  7464. {
  7465. currentItem = newItem;
  7466. currentItem.className += " " + activeCls;
  7467. currentItemInfo = itemInfo;
  7468. categorySelected = itemInfo.isCategory;
  7469. //activate create button
  7470. createBtn.className = "geTempDlgCreateBtn";
  7471. }
  7472. else
  7473. {
  7474. currentItem = null;
  7475. currentItemInfo = null;
  7476. //disable create button
  7477. createBtn.className = "geTempDlgCreateBtn geTempDlgCreateBtnDisabled";
  7478. }
  7479. };
  7480. function handleDialogOK(linkToDiagram)
  7481. {
  7482. if (currentItemInfo != null)
  7483. {
  7484. var itemInfo = currentItemInfo;
  7485. //disable create button
  7486. currentItemInfo = null;
  7487. createBtn.className = "geTempDlgCreateBtn geTempDlgCreateBtnDisabled geTempDlgCreateBtnBusy";
  7488. if (itemInfo.isExternal)
  7489. {
  7490. if (linkToDiagram == true)
  7491. {
  7492. linkToDiagramCallback(itemInfo.url, itemInfo, "nameInput.value");
  7493. }
  7494. else
  7495. {
  7496. openExtDocCallback(itemInfo.url, itemInfo, "nameInput.value");
  7497. }
  7498. editorUi.hideDialog(true);
  7499. }
  7500. else
  7501. {
  7502. mxUtils.get(TEMPLATE_PATH + '/' + itemInfo.url, mxUtils.bind(this, function(req)
  7503. {
  7504. if (req.getStatus() >= 200 && req.getStatus() <= 299)
  7505. {
  7506. callback(req.getText(), "nameInput.value");
  7507. editorUi.hideDialog(true);
  7508. }
  7509. else
  7510. {
  7511. //TODO Handle errors
  7512. }
  7513. }));
  7514. }
  7515. }
  7516. };
  7517. function showLinkToDiagram(isShown)
  7518. {
  7519. var linkDisplay = isShown? '' : 'none';
  7520. var elems = dlgDiv.querySelectorAll(".geTempDlgLinkToDiagram");
  7521. for(var i = 0; i < elems.length; i++)
  7522. {
  7523. elems[i].style.display = linkDisplay;
  7524. }
  7525. };
  7526. function fillDiagramsList(diagrams, isTemplate, asList)
  7527. {
  7528. function setSubmitBtnLbl()
  7529. {
  7530. if (isTemplate)
  7531. {
  7532. createBtn.innerHTML = mxUtils.htmlEntities(mxResources.get('create'));
  7533. }
  7534. else
  7535. {
  7536. createBtn.innerHTML = mxUtils.htmlEntities(mxResources.get('copy'));
  7537. }
  7538. showLinkToDiagram (!isTemplate);
  7539. };
  7540. diagramsTiles.innerHTML = '';
  7541. swapActiveItem();
  7542. curDiagList = diagrams;
  7543. var grid = null;
  7544. if (asList)
  7545. {
  7546. grid = document.createElement('table');
  7547. grid.className = 'geTempDlgDiagramsListGrid';
  7548. //create header row
  7549. var hrow = document.createElement('tr');
  7550. var th = document.createElement('th');
  7551. th.style.width = "50%";
  7552. th.innerHTML = mxUtils.htmlEntities(mxResources.get('diagram', null, 'Diagram'));
  7553. hrow.appendChild(th);
  7554. th = document.createElement('th');
  7555. th.style.width = "25%";
  7556. th.innerHTML = mxUtils.htmlEntities(mxResources.get('changedBy', null, 'Changed By'));
  7557. hrow.appendChild(th);
  7558. th = document.createElement('th');
  7559. th.style.width = "25%";
  7560. th.innerHTML = mxUtils.htmlEntities(mxResources.get('lastModifiedOn', null, 'Last modified on'));
  7561. hrow.appendChild(th);
  7562. grid.appendChild(hrow);
  7563. diagramsTiles.appendChild(grid);
  7564. }
  7565. //TODO support paging
  7566. for (var i = 0; i < diagrams.length; i++)
  7567. {
  7568. diagrams[i].isExternal = !isTemplate;
  7569. var url = diagrams[i].url;
  7570. var title = mxUtils.htmlEntities(diagrams[i].title);
  7571. var tooltip = diagrams[i].tooltip || diagrams[i].title;
  7572. var imgUrl = diagrams[i].imgUrl;
  7573. var changedBy = mxUtils.htmlEntities(diagrams[i].changedBy || "");
  7574. var lastModifiedOn = mxUtils.htmlEntities(diagrams[i].lastModifiedOn || "");
  7575. if (!imgUrl)
  7576. {
  7577. imgUrl = TEMPLATE_PATH + '/' + url.substring(0, url.length - 4) + '.png';
  7578. }
  7579. var titleLimit = asList? 50 : 15;
  7580. if (title != null && title.length > titleLimit)
  7581. {
  7582. title = title.substring(0, titleLimit) + '&hellip;';
  7583. }
  7584. if (asList)
  7585. {
  7586. var row = document.createElement('tr');
  7587. var td = document.createElement('td');
  7588. var prevImg = document.createElement('img');
  7589. prevImg.src = "/images/icon-search.svg";
  7590. prevImg.className = "geTempDlgDiagramListPreviewBtn";
  7591. prevImg.setAttribute('title', mxResources.get("preview"));
  7592. td.appendChild(prevImg);
  7593. var titleSpan = document.createElement('span');
  7594. titleSpan.className = "geTempDlgDiagramTitle";
  7595. titleSpan.innerHTML = title;
  7596. td.appendChild(titleSpan);
  7597. row.appendChild(td);
  7598. td = document.createElement('td');
  7599. td.innerHTML = changedBy;
  7600. row.appendChild(td);
  7601. td = document.createElement('td');
  7602. td.innerHTML = lastModifiedOn;
  7603. row.appendChild(td);
  7604. grid.appendChild(row);
  7605. if (currentItem == null)
  7606. {
  7607. setSubmitBtnLbl();
  7608. swapActiveItem(row, "geTempDlgDiagramsListGridActive", diagrams[i]);
  7609. }
  7610. (function(diagram2, row2)
  7611. {
  7612. mxEvent.addListener(row, 'click', function()
  7613. {
  7614. if (currentItem != row2)
  7615. {
  7616. setSubmitBtnLbl();
  7617. swapActiveItem(row2, "geTempDlgDiagramsListGridActive", diagram2);
  7618. }
  7619. });
  7620. mxEvent.addListener(row, 'dblclick', handleDialogOK);
  7621. mxEvent.addListener(prevImg, 'click', function()
  7622. {
  7623. createPreview(diagram2);
  7624. });
  7625. })(diagrams[i], row);
  7626. }
  7627. else
  7628. {
  7629. var tile = document.createElement('div');
  7630. tile.className = "geTempDlgDiagramTile";
  7631. tile.setAttribute('title', tooltip);
  7632. if (currentItem == null)
  7633. {
  7634. setSubmitBtnLbl();
  7635. swapActiveItem(tile, "geTempDlgDiagramTileActive", diagrams[i]);
  7636. }
  7637. var imgDiv = document.createElement('div');
  7638. imgDiv.className = "geTempDlgDiagramTileImg geTempDlgDiagramTileImgLoading";
  7639. var img = document.createElement('img');
  7640. img.style.display = "none";
  7641. (function(img2, imgDiv2)
  7642. {
  7643. img.onload = function()
  7644. {
  7645. imgDiv2.className = "geTempDlgDiagramTileImg";
  7646. img2.style.display = "";
  7647. }
  7648. img.onerror = function()
  7649. {
  7650. imgDiv2.className = "geTempDlgDiagramTileImg geTempDlgDiagramTileImgError";
  7651. }
  7652. })(img, imgDiv);
  7653. img.src = imgUrl;
  7654. imgDiv.appendChild(img);
  7655. tile.appendChild(imgDiv);
  7656. var lblDiv = document.createElement('div');
  7657. lblDiv.className = "geTempDlgDiagramTileLbl";
  7658. lblDiv.innerHTML = title != null? title : "";
  7659. tile.appendChild(lblDiv);
  7660. var prevImg = document.createElement('img');
  7661. prevImg.src = "/images/icon-search.svg";
  7662. prevImg.className = "geTempDlgDiagramPreviewBtn";
  7663. prevImg.setAttribute('title', mxResources.get("preview"));
  7664. tile.appendChild(prevImg);
  7665. (function(diagram2, tile2)
  7666. {
  7667. mxEvent.addListener(tile, 'click', function()
  7668. {
  7669. if (currentItem != tile2)
  7670. {
  7671. setSubmitBtnLbl();
  7672. swapActiveItem(tile2, "geTempDlgDiagramTileActive", diagram2);
  7673. }
  7674. });
  7675. mxEvent.addListener(tile, 'dblclick', handleDialogOK);
  7676. mxEvent.addListener(prevImg, 'click', function()
  7677. {
  7678. createPreview(diagram2);
  7679. });
  7680. })(diagrams[i], tile);
  7681. diagramsTiles.appendChild(tile);
  7682. }
  7683. }
  7684. };
  7685. function fillNewDiagramCats(newDiagramCats, showAll)
  7686. {
  7687. newDiagramCatList.innerHTML = "";
  7688. swapActiveItem();
  7689. var catCount = !showAll && newDiagramCats.length > 5 ? 5 : newDiagramCats.length;
  7690. for (var i = 0; i < catCount; i++)
  7691. {
  7692. var cat = newDiagramCats[i];
  7693. cat.isCategory = true;
  7694. var entry = document.createElement('div');
  7695. var label = mxResources.get(cat.title);
  7696. if (label == null)
  7697. {
  7698. label = cat.title.substring(0, 1).toUpperCase() + cat.title.substring(1);
  7699. }
  7700. entry.className = 'geTempDlgNewDiagramCatItem';
  7701. entry.setAttribute('title', label);
  7702. label = mxUtils.htmlEntities(label);
  7703. if (label.length > 15)
  7704. {
  7705. label = label.substring(0, 15) + '&hellip;';
  7706. }
  7707. if (currentItem == null)
  7708. {
  7709. createBtn.innerHTML = mxUtils.htmlEntities(mxResources.get('create'));
  7710. showLinkToDiagram();
  7711. swapActiveItem(entry, "geTempDlgNewDiagramCatItemActive", cat);
  7712. }
  7713. var imgDiv = document.createElement('div');
  7714. imgDiv.className = "geTempDlgNewDiagramCatItemImg";
  7715. var img = document.createElement('img');
  7716. img.src = NEW_DIAGRAM_CATS_PATH + '/' + cat.img;
  7717. imgDiv.appendChild(img);
  7718. entry.appendChild(imgDiv);
  7719. var lblDiv = document.createElement('div');
  7720. lblDiv.className = "geTempDlgNewDiagramCatItemLbl";
  7721. lblDiv.innerHTML = label;
  7722. entry.appendChild(lblDiv);
  7723. newDiagramCatList.appendChild(entry);
  7724. (function(cat2, entry2)
  7725. {
  7726. mxEvent.addListener(entry, 'click', function()
  7727. {
  7728. if (currentItem != entry2)
  7729. {
  7730. createBtn.innerHTML = mxUtils.htmlEntities(mxResources.get('create'));
  7731. showLinkToDiagram();
  7732. swapActiveItem(entry2, "geTempDlgNewDiagramCatItemActive", cat2);
  7733. }
  7734. });
  7735. mxEvent.addListener(entry, 'dblclick', handleDialogOK);
  7736. })(cat, entry);
  7737. }
  7738. showAllBtn.style.display = newDiagramCats.length < 5 ? "none" : "";
  7739. };
  7740. mxEvent.addListener(showAllBtn, 'click', function()
  7741. {
  7742. if (showingAll)
  7743. {
  7744. newDiagramCat.style.height = "280px";
  7745. newDiagramCatList.style.height = "190px";
  7746. showAllBtn.innerHTML = mxUtils.htmlEntities(mxResources.get('showAll', null, '+ Show all'));
  7747. fillNewDiagramCats(newDiagramCats);
  7748. }
  7749. else
  7750. {
  7751. newDiagramCat.style.height = "440px";
  7752. newDiagramCatList.style.height = "355px";
  7753. showAllBtn.innerHTML = mxUtils.htmlEntities(mxResources.get('showLess', null, '- Show less'));
  7754. fillNewDiagramCats(newDiagramCats, true);
  7755. }
  7756. showingAll = !showingAll;
  7757. });
  7758. function fillTemplatesList(categories)
  7759. {
  7760. var list = dlgDiv.querySelector(".geTemplatesList");
  7761. for (var cat in categories)
  7762. {
  7763. var entry = document.createElement('div');
  7764. var label = mxResources.get(cat);
  7765. var templateList = categories[cat];
  7766. if (label == null)
  7767. {
  7768. label = cat.substring(0, 1).toUpperCase() + cat.substring(1);
  7769. }
  7770. entry.className = 'geTemplateCatLink';
  7771. entry.setAttribute('title', label + ' (' + templateList.length + ')');
  7772. label = mxUtils.htmlEntities(label);
  7773. if (label.length > 15)
  7774. {
  7775. label = label.substring(0, 15) + '&hellip;';
  7776. }
  7777. entry.innerHTML = label + ' (' + templateList.length + ')';
  7778. list.appendChild(entry);
  7779. (function(cat2, label2, entry2)
  7780. {
  7781. mxEvent.addListener(entry, 'click', function()
  7782. {
  7783. if (currentEntry != entry2)
  7784. {
  7785. if (currentEntry != null)
  7786. {
  7787. currentEntry.style.fontWeight = 'normal';
  7788. currentEntry.style.textDecoration = 'none';
  7789. }
  7790. else
  7791. {
  7792. newDiagramCat.style.display = 'none';
  7793. diagramsList.style.minHeight = '100%';
  7794. }
  7795. currentEntry = entry2;
  7796. currentEntry.style.fontWeight = 'bold';
  7797. currentEntry.style.textDecoration = 'underline';
  7798. tempDlgContent.scrollTop = 0;
  7799. if (callInitiated)
  7800. {
  7801. cancelPendingCall = true;
  7802. }
  7803. diagramsListTitle.innerHTML = label2;
  7804. diagramsListBtns.style.display = 'none';
  7805. fillDiagramsList(categories[cat2], true);
  7806. }
  7807. });
  7808. })(cat, label, entry);
  7809. }
  7810. };
  7811. var indexLoaded = false, indexLoaded2 = false;
  7812. var categories = {};
  7813. var newDiagramCats = [];
  7814. var categoryCount = 1;
  7815. mxUtils.get(templateFile, function(req)
  7816. {
  7817. // Workaround for index loaded 3 times in iOS offline mode
  7818. if (!indexLoaded)
  7819. {
  7820. indexLoaded = true;
  7821. var tmpDoc = req.getXml();
  7822. var node = tmpDoc.documentElement.firstChild;
  7823. while (node != null)
  7824. {
  7825. if (typeof(node.getAttribute) !== 'undefined')
  7826. {
  7827. var url = node.getAttribute('url');
  7828. if (url != null)
  7829. {
  7830. var slash = url.indexOf('/');
  7831. var category = url.substring(0, slash);
  7832. var list = categories[category];
  7833. if (list == null)
  7834. {
  7835. categoryCount++;
  7836. list = [];
  7837. categories[category] = list;
  7838. }
  7839. list.push({url: node.getAttribute('url'), libs: node.getAttribute('libs'),
  7840. title: node.getAttribute('title'), tooltip: node.getAttribute('url'), imgUrl: node.getAttribute('imgUrl')});
  7841. }
  7842. }
  7843. node = node.nextSibling;
  7844. }
  7845. fillTemplatesList(categories);
  7846. }
  7847. });
  7848. mxUtils.get(newDiagramCatsFile, function(req)
  7849. {
  7850. // Workaround for index loaded 3 times in iOS offline mode
  7851. if (!indexLoaded2)
  7852. {
  7853. indexLoaded2 = true;
  7854. var tmpDoc = req.getXml();
  7855. var node = tmpDoc.documentElement.firstChild;
  7856. while (node != null)
  7857. {
  7858. if (typeof(node.getAttribute) !== 'undefined')
  7859. {
  7860. var title = node.getAttribute('title');
  7861. if (title != null)
  7862. {
  7863. newDiagramCats.push({img: node.getAttribute('img'), libs: node.getAttribute('libs'),
  7864. title: node.getAttribute('title')});
  7865. }
  7866. }
  7867. node = node.nextSibling;
  7868. }
  7869. fillNewDiagramCats(newDiagramCats);
  7870. }
  7871. });
  7872. var extDiagramsCallback = function(list, errorMsg)
  7873. {
  7874. diagramsListBtns.style.display = '';
  7875. spinner.stop();
  7876. callInitiated = false;
  7877. if (cancelPendingCall)
  7878. {
  7879. cancelPendingCall = false;
  7880. return;
  7881. }
  7882. if (errorMsg)
  7883. {
  7884. diagramsTiles.innerHTML = errorMsg;
  7885. }
  7886. else if (list.length == 0)
  7887. {
  7888. diagramsTiles.innerHTML = mxUtils.htmlEntities(mxResources.get('noDiagrams', null, 'No Diagrams Found'));
  7889. }
  7890. else
  7891. {
  7892. fillDiagramsList(list, false, showAsList);
  7893. }
  7894. };
  7895. function getRecentDocs(getAll)
  7896. {
  7897. if (recentDocsCallback)
  7898. {
  7899. tempDlgContent.scrollTop = 0;
  7900. diagramsTiles.innerHTML = '';
  7901. spinner.spin(diagramsTiles);
  7902. cancelPendingCall = false;
  7903. callInitiated = true;
  7904. diagramsListTitle.innerHTML = mxUtils.htmlEntities(mxResources.get('recentDiag', null, 'Recent Diagrams'));
  7905. lastSearchStr = null;
  7906. recentDocsCallback(extDiagramsCallback, getAll? null : username);
  7907. }
  7908. };
  7909. getRecentDocs(isGetAll);
  7910. var delayTimer = null;
  7911. function doSearch(searchStr)
  7912. {
  7913. deselectTempCat();
  7914. tempDlgContent.scrollTop = 0;
  7915. diagramsTiles.innerHTML = '';
  7916. spinner.spin(diagramsTiles);
  7917. cancelPendingCall = false;
  7918. callInitiated = true;
  7919. delayTimer = null;
  7920. diagramsListTitle.innerHTML = mxUtils.htmlEntities(mxResources.get('searchResults', null, 'Search Results')) +
  7921. ' "' + mxUtils.htmlEntities(searchStr) + '"';
  7922. searchDocsCallback(searchStr, extDiagramsCallback, isGetAll? null : username);
  7923. lastSearchStr = searchStr;
  7924. };
  7925. //TODO use request id to allow only last request to show results
  7926. if (searchDocsCallback)
  7927. {
  7928. //Use keyup to detect delete and backspace
  7929. mxEvent.addListener(dlgDiv.querySelector(".geTempDlgSearchBox"), 'keyup', function(evt)
  7930. {
  7931. var searchInout = this;
  7932. if (delayTimer != null)
  7933. {
  7934. clearTimeout(delayTimer);
  7935. }
  7936. if (evt.keyCode == 13)
  7937. {
  7938. doSearch(searchInout.value);
  7939. }
  7940. else
  7941. {
  7942. delayTimer = setTimeout(function()
  7943. {
  7944. doSearch(searchInout.value);
  7945. }, 500);
  7946. }
  7947. });
  7948. }
  7949. mxEvent.addListener(createBtn, 'click', handleDialogOK);
  7950. mxEvent.addListener(dlgDiv.querySelector(".geTempDlgLinkToDiagramBtn"), 'click', function(evt)
  7951. {
  7952. handleDialogOK(true);
  7953. });
  7954. mxEvent.addListener(dlgDiv.querySelector('.geTempDlgCancelBtn'), 'click', function()
  7955. {
  7956. if (cancelCallback != null)
  7957. {
  7958. cancelCallback();
  7959. }
  7960. editorUi.hideDialog(true);
  7961. });
  7962. };
  7963. /**
  7964. * Constructs a new popup opener button dialog.
  7965. */
  7966. var BtnDialog = function(editorUi, peer, btnLbl, fn)
  7967. {
  7968. var div = document.createElement('div');
  7969. div.style.textAlign = 'center';
  7970. var hd = document.createElement('p');
  7971. hd.style.fontSize = '16pt';
  7972. hd.style.padding = '0px';
  7973. hd.style.margin = '0px';
  7974. hd.style.color = 'gray';
  7975. mxUtils.write(hd, mxResources.get('done'));
  7976. var service = 'Unknown';
  7977. var img = document.createElement('img');
  7978. img.setAttribute('border', '0');
  7979. img.setAttribute('align', 'absmiddle');
  7980. img.style.marginRight = '10px';
  7981. if (peer == editorUi.drive)
  7982. {
  7983. service = mxResources.get('googleDrive');
  7984. img.src = IMAGE_PATH + '/google-drive-logo-white.svg';
  7985. }
  7986. else if (peer == editorUi.dropbox)
  7987. {
  7988. service = mxResources.get('dropbox');
  7989. img.src = IMAGE_PATH + '/dropbox-logo-white.svg';
  7990. }
  7991. else if (peer == editorUi.oneDrive)
  7992. {
  7993. service = mxResources.get('oneDrive');
  7994. img.src = IMAGE_PATH + '/onedrive-logo-white.svg';
  7995. }
  7996. else if (peer == editorUi.gitHub)
  7997. {
  7998. service = mxResources.get('github');
  7999. img.src = IMAGE_PATH + '/github-logo-white.svg';
  8000. }
  8001. else if (peer == editorUi.trello)
  8002. {
  8003. service = mxResources.get('trello');
  8004. img.src = IMAGE_PATH + '/trello-logo-white.svg';
  8005. }
  8006. var p = document.createElement('p');
  8007. mxUtils.write(p, mxResources.get('authorizedIn', [service], 'You are now authorized in {1}'));
  8008. var button = mxUtils.button(btnLbl, fn);
  8009. button.insertBefore(img, button.firstChild);
  8010. button.style.marginTop = '6px';
  8011. button.className = 'geBigButton';
  8012. div.appendChild(hd);
  8013. div.appendChild(p);
  8014. div.appendChild(button);
  8015. this.container = div;
  8016. };