Dialogs.js 208 KB

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