Dialogs.js 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487
  1. /**
  2. * Copyright (c) 2006-2012, JGraph Ltd
  3. */
  4. /**
  5. * Constructs a new open dialog.
  6. */
  7. var OpenDialog = function()
  8. {
  9. var iframe = document.createElement('iframe');
  10. iframe.style.backgroundColor = 'transparent';
  11. iframe.allowTransparency = 'true';
  12. iframe.style.borderStyle = 'none';
  13. iframe.style.borderWidth = '0px';
  14. iframe.style.overflow = 'hidden';
  15. iframe.frameBorder = '0';
  16. // Adds padding as a workaround for box model in older IE versions
  17. var dx = (mxClient.IS_VML && (document.documentMode == null || document.documentMode < 8)) ? 20 : 0;
  18. iframe.setAttribute('width', (((Editor.useLocalStorage) ? 640 : 320) + dx) + 'px');
  19. iframe.setAttribute('height', (((Editor.useLocalStorage) ? 480 : 220) + dx) + 'px');
  20. iframe.setAttribute('src', OPEN_FORM);
  21. this.container = iframe;
  22. };
  23. /**
  24. * Constructs a new color dialog.
  25. */
  26. var ColorDialog = function(editorUi, color, apply, cancelFn)
  27. {
  28. this.editorUi = editorUi;
  29. var input = document.createElement('input');
  30. input.style.marginBottom = '10px';
  31. input.style.width = '216px';
  32. // Required for picker to render in IE
  33. if (mxClient.IS_IE)
  34. {
  35. input.style.marginTop = '10px';
  36. document.body.appendChild(input);
  37. }
  38. this.init = function()
  39. {
  40. if (!mxClient.IS_TOUCH)
  41. {
  42. input.focus();
  43. }
  44. };
  45. var picker = new jscolor.color(input);
  46. picker.pickerOnfocus = false;
  47. picker.showPicker();
  48. var div = document.createElement('div');
  49. jscolor.picker.box.style.position = 'relative';
  50. jscolor.picker.box.style.width = '230px';
  51. jscolor.picker.box.style.height = '100px';
  52. jscolor.picker.box.style.paddingBottom = '10px';
  53. div.appendChild(jscolor.picker.box);
  54. var center = document.createElement('center');
  55. function createRecentColorTable()
  56. {
  57. var table = addPresets((ColorDialog.recentColors.length == 0) ? ['FFFFFF'] :
  58. ColorDialog.recentColors, 11, 'FFFFFF', true);
  59. table.style.marginBottom = '8px';
  60. return table;
  61. };
  62. function addPresets(presets, rowLength, defaultColor, addResetOption)
  63. {
  64. rowLength = (rowLength != null) ? rowLength : 12;
  65. var table = document.createElement('table');
  66. table.style.borderCollapse = 'collapse';
  67. table.setAttribute('cellspacing', '0');
  68. table.style.marginBottom = '20px';
  69. table.style.cellSpacing = '0px';
  70. var tbody = document.createElement('tbody');
  71. table.appendChild(tbody);
  72. var rows = presets.length / rowLength;
  73. for (var row = 0; row < rows; row++)
  74. {
  75. var tr = document.createElement('tr');
  76. for (var i = 0; i < rowLength; i++)
  77. {
  78. (function(clr)
  79. {
  80. var td = document.createElement('td');
  81. td.style.border = '1px solid black';
  82. td.style.padding = '0px';
  83. td.style.width = '16px';
  84. td.style.height = '16px';
  85. if (clr == null)
  86. {
  87. clr = defaultColor;
  88. }
  89. if (clr == 'none')
  90. {
  91. td.style.background = 'url(\'' + Dialog.prototype.noColorImage + '\')';
  92. }
  93. else
  94. {
  95. td.style.backgroundColor = '#' + clr;
  96. }
  97. tr.appendChild(td);
  98. if (clr != null)
  99. {
  100. td.style.cursor = 'pointer';
  101. mxEvent.addListener(td, 'click', function()
  102. {
  103. if (clr == 'none')
  104. {
  105. picker.fromString('ffffff');
  106. input.value = 'none';
  107. }
  108. else
  109. {
  110. picker.fromString(clr);
  111. }
  112. });
  113. }
  114. })(presets[row * rowLength + i]);
  115. }
  116. tbody.appendChild(tr);
  117. }
  118. if (addResetOption)
  119. {
  120. var td = document.createElement('td');
  121. td.setAttribute('title', mxResources.get('reset'));
  122. td.style.border = '1px solid black';
  123. td.style.padding = '0px';
  124. td.style.width = '16px';
  125. td.style.height = '16px';
  126. td.style.backgroundImage = 'url(\'' + Dialog.prototype.closeImage + '\')';
  127. td.style.backgroundPosition = 'center center';
  128. td.style.backgroundRepeat = 'no-repeat';
  129. td.style.cursor = 'pointer';
  130. tr.appendChild(td);
  131. mxEvent.addListener(td, 'click', function()
  132. {
  133. ColorDialog.resetRecentColors();
  134. table.parentNode.replaceChild(createRecentColorTable(), table);
  135. });
  136. }
  137. center.appendChild(table);
  138. return table;
  139. };
  140. div.appendChild(input);
  141. mxUtils.br(div);
  142. // Adds recent colors
  143. createRecentColorTable();
  144. // Adds presets
  145. var table = addPresets(this.presetColors);
  146. table.style.marginBottom = '8px';
  147. table = addPresets(this.defaultColors);
  148. table.style.marginBottom = '16px';
  149. div.appendChild(center);
  150. var buttons = document.createElement('div');
  151. buttons.style.textAlign = 'right';
  152. buttons.style.whiteSpace = 'nowrap';
  153. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  154. {
  155. editorUi.hideDialog();
  156. if (cancelFn != null)
  157. {
  158. cancelFn();
  159. }
  160. });
  161. cancelBtn.className = 'geBtn';
  162. if (editorUi.editor.cancelFirst)
  163. {
  164. buttons.appendChild(cancelBtn);
  165. }
  166. var applyFunction = (apply != null) ? apply : this.createApplyFunction();
  167. var applyBtn = mxUtils.button(mxResources.get('apply'), function()
  168. {
  169. var color = input.value;
  170. ColorDialog.addRecentColor(color, 12);
  171. if (color != 'none' && color.charAt(0) != '#')
  172. {
  173. color = '#' + color;
  174. }
  175. applyFunction(color);
  176. editorUi.hideDialog();
  177. });
  178. applyBtn.className = 'geBtn gePrimaryBtn';
  179. buttons.appendChild(applyBtn);
  180. if (!editorUi.editor.cancelFirst)
  181. {
  182. buttons.appendChild(cancelBtn);
  183. }
  184. if (color != null)
  185. {
  186. if (color == 'none')
  187. {
  188. picker.fromString('ffffff');
  189. input.value = 'none';
  190. }
  191. else
  192. {
  193. picker.fromString(color);
  194. }
  195. }
  196. div.appendChild(buttons);
  197. this.picker = picker;
  198. this.colorInput = input;
  199. // LATER: Only fires if input if focused, should always
  200. // fire if this dialog is showing.
  201. mxEvent.addListener(div, 'keydown', function(e)
  202. {
  203. if (e.keyCode == 27)
  204. {
  205. editorUi.hideDialog();
  206. if (cancelFn != null)
  207. {
  208. cancelFn();
  209. }
  210. mxEvent.consume(e);
  211. }
  212. });
  213. this.container = div;
  214. };
  215. /**
  216. * Creates function to apply value
  217. */
  218. ColorDialog.prototype.presetColors = ['E6D0DE', 'CDA2BE', 'B5739D', 'E1D5E7', 'C3ABD0', 'A680B8', 'D4E1F5', 'A9C4EB', '7EA6E0', 'D5E8D4', '9AC7BF', '67AB9F', 'D5E8D4', 'B9E0A5', '97D077', 'FFF2CC', 'FFE599', 'FFD966', 'FFF4C3', 'FFCE9F', 'FFB570', 'F8CECC', 'F19C99', 'EA6B66'];
  219. /**
  220. * Creates function to apply value
  221. */
  222. ColorDialog.prototype.defaultColors = ['none', 'FFFFFF', 'E6E6E6', 'CCCCCC', 'B3B3B3', '999999', '808080', '666666', '4D4D4D', '333333', '1A1A1A', '000000', 'FFCCCC', 'FFE6CC', 'FFFFCC', 'E6FFCC', 'CCFFCC', 'CCFFE6', 'CCFFFF', 'CCE5FF', 'CCCCFF', 'E5CCFF', 'FFCCFF', 'FFCCE6',
  223. 'FF9999', 'FFCC99', 'FFFF99', 'CCFF99', '99FF99', '99FFCC', '99FFFF', '99CCFF', '9999FF', 'CC99FF', 'FF99FF', 'FF99CC', 'FF6666', 'FFB366', 'FFFF66', 'B3FF66', '66FF66', '66FFB3', '66FFFF', '66B2FF', '6666FF', 'B266FF', 'FF66FF', 'FF66B3', 'FF3333', 'FF9933', 'FFFF33',
  224. '99FF33', '33FF33', '33FF99', '33FFFF', '3399FF', '3333FF', '9933FF', 'FF33FF', 'FF3399', 'FF0000', 'FF8000', 'FFFF00', '80FF00', '00FF00', '00FF80', '00FFFF', '007FFF', '0000FF', '7F00FF', 'FF00FF', 'FF0080', 'CC0000', 'CC6600', 'CCCC00', '66CC00', '00CC00', '00CC66',
  225. '00CCCC', '0066CC', '0000CC', '6600CC', 'CC00CC', 'CC0066', '990000', '994C00', '999900', '4D9900', '009900', '00994D', '009999', '004C99', '000099', '4C0099', '990099', '99004D', '660000', '663300', '666600', '336600', '006600', '006633', '006666', '003366', '000066',
  226. '330066', '660066', '660033', '330000', '331A00', '333300', '1A3300', '003300', '00331A', '003333', '001933', '000033', '190033', '330033', '33001A'];
  227. /**
  228. * Creates function to apply value
  229. */
  230. ColorDialog.prototype.createApplyFunction = function()
  231. {
  232. return mxUtils.bind(this, function(color)
  233. {
  234. var graph = this.editorUi.editor.graph;
  235. graph.getModel().beginUpdate();
  236. try
  237. {
  238. graph.setCellStyles(this.currentColorKey, color);
  239. this.editorUi.fireEvent(new mxEventObject('styleChanged', 'keys', [this.currentColorKey],
  240. 'values', [color], 'cells', graph.getSelectionCells()));
  241. }
  242. finally
  243. {
  244. graph.getModel().endUpdate();
  245. }
  246. });
  247. };
  248. /**
  249. *
  250. */
  251. ColorDialog.recentColors = [];
  252. /**
  253. * Adds recent color for later use.
  254. */
  255. ColorDialog.addRecentColor = function(color, max)
  256. {
  257. if (color != null)
  258. {
  259. mxUtils.remove(color, ColorDialog.recentColors);
  260. ColorDialog.recentColors.splice(0, 0, color);
  261. if (ColorDialog.recentColors.length >= max)
  262. {
  263. ColorDialog.recentColors.pop();
  264. }
  265. }
  266. };
  267. /**
  268. * Adds recent color for later use.
  269. */
  270. ColorDialog.resetRecentColors = function()
  271. {
  272. ColorDialog.recentColors = [];
  273. };
  274. /**
  275. * Constructs a new about dialog.
  276. */
  277. var AboutDialog = function(editorUi)
  278. {
  279. var div = document.createElement('div');
  280. div.setAttribute('align', 'center');
  281. var h3 = document.createElement('h3');
  282. mxUtils.write(h3, mxResources.get('about') + ' GraphEditor');
  283. div.appendChild(h3);
  284. var img = document.createElement('img');
  285. img.style.border = '0px';
  286. img.setAttribute('width', '176');
  287. img.setAttribute('width', '151');
  288. img.setAttribute('src', IMAGE_PATH + '/logo.png');
  289. div.appendChild(img);
  290. mxUtils.br(div);
  291. mxUtils.write(div, 'Powered by mxGraph ' + mxClient.VERSION);
  292. mxUtils.br(div);
  293. var link = document.createElement('a');
  294. link.setAttribute('href', 'http://www.jgraph.com/');
  295. link.setAttribute('target', '_blank');
  296. mxUtils.write(link, 'www.jgraph.com');
  297. div.appendChild(link);
  298. mxUtils.br(div);
  299. mxUtils.br(div);
  300. var closeBtn = mxUtils.button(mxResources.get('close'), function()
  301. {
  302. editorUi.hideDialog();
  303. });
  304. closeBtn.className = 'geBtn gePrimaryBtn';
  305. div.appendChild(closeBtn);
  306. this.container = div;
  307. };
  308. /**
  309. * Constructs a new filename dialog.
  310. */
  311. var FilenameDialog = function(editorUi, filename, buttonText, fn, label, validateFn, content, helpLink, closeOnBtn, cancelFn)
  312. {
  313. closeOnBtn = (closeOnBtn != null) ? closeOnBtn : true;
  314. var row, td;
  315. var table = document.createElement('table');
  316. var tbody = document.createElement('tbody');
  317. table.style.marginTop = '8px';
  318. row = document.createElement('tr');
  319. td = document.createElement('td');
  320. td.style.whiteSpace = 'nowrap';
  321. td.style.fontSize = '10pt';
  322. td.style.width = '120px';
  323. mxUtils.write(td, (label || mxResources.get('filename')) + ':');
  324. row.appendChild(td);
  325. var nameInput = document.createElement('input');
  326. nameInput.setAttribute('value', filename || '');
  327. nameInput.style.marginLeft = '4px';
  328. nameInput.style.width = '180px';
  329. var genericBtn = mxUtils.button(buttonText, function()
  330. {
  331. if (validateFn == null || validateFn(nameInput.value))
  332. {
  333. if (closeOnBtn)
  334. {
  335. editorUi.hideDialog();
  336. }
  337. fn(nameInput.value);
  338. }
  339. });
  340. genericBtn.className = 'geBtn gePrimaryBtn';
  341. this.init = function()
  342. {
  343. if (label == null && content != null)
  344. {
  345. return;
  346. }
  347. nameInput.focus();
  348. if (mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS)
  349. {
  350. nameInput.select();
  351. }
  352. else
  353. {
  354. document.execCommand('selectAll', false, null);
  355. }
  356. // Installs drag and drop handler for links
  357. if (Graph.fileSupport)
  358. {
  359. // Setup the dnd listeners
  360. var dlg = table.parentNode;
  361. var graph = editorUi.editor.graph;
  362. var dropElt = null;
  363. mxEvent.addListener(dlg, 'dragleave', function(evt)
  364. {
  365. if (dropElt != null)
  366. {
  367. dropElt.style.backgroundColor = '';
  368. dropElt = null;
  369. }
  370. evt.stopPropagation();
  371. evt.preventDefault();
  372. });
  373. mxEvent.addListener(dlg, 'dragover', mxUtils.bind(this, function(evt)
  374. {
  375. // IE 10 does not implement pointer-events so it can't have a drop highlight
  376. if (dropElt == null && (!mxClient.IS_IE || document.documentMode > 10))
  377. {
  378. dropElt = nameInput;
  379. dropElt.style.backgroundColor = '#ebf2f9';
  380. }
  381. evt.stopPropagation();
  382. evt.preventDefault();
  383. }));
  384. mxEvent.addListener(dlg, 'drop', mxUtils.bind(this, function(evt)
  385. {
  386. if (dropElt != null)
  387. {
  388. dropElt.style.backgroundColor = '';
  389. dropElt = null;
  390. }
  391. if (mxUtils.indexOf(evt.dataTransfer.types, 'text/uri-list') >= 0)
  392. {
  393. nameInput.value = decodeURIComponent(evt.dataTransfer.getData('text/uri-list'));
  394. genericBtn.click();
  395. }
  396. evt.stopPropagation();
  397. evt.preventDefault();
  398. }));
  399. }
  400. };
  401. td = document.createElement('td');
  402. td.appendChild(nameInput);
  403. row.appendChild(td);
  404. if (label != null || content == null)
  405. {
  406. tbody.appendChild(row);
  407. }
  408. if (content != null)
  409. {
  410. row = document.createElement('tr');
  411. td = document.createElement('td');
  412. td.colSpan = 2;
  413. td.appendChild(content);
  414. row.appendChild(td);
  415. tbody.appendChild(row);
  416. }
  417. row = document.createElement('tr');
  418. td = document.createElement('td');
  419. td.colSpan = 2;
  420. td.style.paddingTop = '20px';
  421. td.style.whiteSpace = 'nowrap';
  422. td.setAttribute('align', 'right');
  423. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  424. {
  425. editorUi.hideDialog();
  426. if (cancelFn != null)
  427. {
  428. cancelFn();
  429. }
  430. });
  431. cancelBtn.className = 'geBtn';
  432. if (editorUi.editor.cancelFirst)
  433. {
  434. td.appendChild(cancelBtn);
  435. }
  436. if (helpLink != null)
  437. {
  438. var helpBtn = mxUtils.button(mxResources.get('help'), function()
  439. {
  440. window.open(helpLink);
  441. });
  442. helpBtn.className = 'geBtn';
  443. td.appendChild(helpBtn);
  444. }
  445. mxEvent.addListener(nameInput, 'keypress', function(e)
  446. {
  447. if (e.keyCode == 13)
  448. {
  449. genericBtn.click();
  450. }
  451. });
  452. td.appendChild(genericBtn);
  453. if (!editorUi.editor.cancelFirst)
  454. {
  455. td.appendChild(cancelBtn);
  456. }
  457. row.appendChild(td);
  458. tbody.appendChild(row);
  459. table.appendChild(tbody);
  460. this.container = table;
  461. };
  462. /**
  463. * Constructs a new textarea dialog.
  464. */
  465. var TextareaDialog = function(editorUi, title, url, fn, cancelFn, cancelTitle, w, h, addButtons, noHide, noWrap, applyTitle)
  466. {
  467. w = (w != null) ? w : 300;
  468. h = (h != null) ? h : 120;
  469. noHide = (noHide != null) ? noHide : false;
  470. var row, td;
  471. var table = document.createElement('table');
  472. var tbody = document.createElement('tbody');
  473. row = document.createElement('tr');
  474. td = document.createElement('td');
  475. td.style.fontSize = '10pt';
  476. td.style.width = '100px';
  477. mxUtils.write(td, title);
  478. row.appendChild(td);
  479. tbody.appendChild(row);
  480. row = document.createElement('tr');
  481. td = document.createElement('td');
  482. var nameInput = document.createElement('textarea');
  483. if (noWrap)
  484. {
  485. nameInput.setAttribute('wrap', 'off');
  486. }
  487. nameInput.setAttribute('spellcheck', 'false');
  488. nameInput.setAttribute('autocorrect', 'off');
  489. nameInput.setAttribute('autocomplete', 'off');
  490. nameInput.setAttribute('autocapitalize', 'off');
  491. mxUtils.write(nameInput, url || '');
  492. nameInput.style.resize = 'none';
  493. nameInput.style.width = w + 'px';
  494. nameInput.style.height = h + 'px';
  495. this.textarea = nameInput;
  496. this.init = function()
  497. {
  498. nameInput.focus();
  499. nameInput.scrollTop = 0;
  500. };
  501. td.appendChild(nameInput);
  502. row.appendChild(td);
  503. tbody.appendChild(row);
  504. row = document.createElement('tr');
  505. td = document.createElement('td');
  506. td.style.paddingTop = '14px';
  507. td.style.whiteSpace = 'nowrap';
  508. td.setAttribute('align', 'right');
  509. var cancelBtn = mxUtils.button(cancelTitle || mxResources.get('cancel'), function()
  510. {
  511. editorUi.hideDialog();
  512. if (cancelFn != null)
  513. {
  514. cancelFn();
  515. }
  516. });
  517. cancelBtn.className = 'geBtn';
  518. if (editorUi.editor.cancelFirst)
  519. {
  520. td.appendChild(cancelBtn);
  521. }
  522. if (addButtons != null)
  523. {
  524. addButtons(td);
  525. }
  526. if (fn != null)
  527. {
  528. var genericBtn = mxUtils.button(applyTitle || mxResources.get('apply'), function()
  529. {
  530. if (!noHide)
  531. {
  532. editorUi.hideDialog();
  533. }
  534. fn(nameInput.value);
  535. });
  536. genericBtn.className = 'geBtn gePrimaryBtn';
  537. td.appendChild(genericBtn);
  538. }
  539. if (!editorUi.editor.cancelFirst)
  540. {
  541. td.appendChild(cancelBtn);
  542. }
  543. row.appendChild(td);
  544. tbody.appendChild(row);
  545. table.appendChild(tbody);
  546. this.container = table;
  547. };
  548. /**
  549. * Constructs a new edit file dialog.
  550. */
  551. var EditDiagramDialog = function(editorUi)
  552. {
  553. var div = document.createElement('div');
  554. div.style.textAlign = 'right';
  555. var textarea = document.createElement('textarea');
  556. textarea.setAttribute('wrap', 'off');
  557. textarea.setAttribute('spellcheck', 'false');
  558. textarea.setAttribute('autocorrect', 'off');
  559. textarea.setAttribute('autocomplete', 'off');
  560. textarea.setAttribute('autocapitalize', 'off');
  561. textarea.style.overflow = 'auto';
  562. textarea.style.resize = 'none';
  563. textarea.style.width = '600px';
  564. textarea.style.height = '370px';
  565. textarea.style.marginBottom = '16px';
  566. textarea.value = mxUtils.getPrettyXml(editorUi.editor.getGraphXml());
  567. div.appendChild(textarea);
  568. this.init = function()
  569. {
  570. textarea.focus();
  571. };
  572. // Enables dropping files
  573. if (Graph.fileSupport)
  574. {
  575. function handleDrop(evt)
  576. {
  577. evt.stopPropagation();
  578. evt.preventDefault();
  579. if (evt.dataTransfer.files.length > 0)
  580. {
  581. var file = evt.dataTransfer.files[0];
  582. var reader = new FileReader();
  583. reader.onload = function(e)
  584. {
  585. textarea.value = e.target.result;
  586. };
  587. reader.readAsText(file);
  588. }
  589. else
  590. {
  591. textarea.value = editorUi.extractGraphModelFromEvent(evt);
  592. }
  593. };
  594. function handleDragOver(evt)
  595. {
  596. evt.stopPropagation();
  597. evt.preventDefault();
  598. };
  599. // Setup the dnd listeners.
  600. textarea.addEventListener('dragover', handleDragOver, false);
  601. textarea.addEventListener('drop', handleDrop, false);
  602. }
  603. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  604. {
  605. editorUi.hideDialog();
  606. });
  607. cancelBtn.className = 'geBtn';
  608. if (editorUi.editor.cancelFirst)
  609. {
  610. div.appendChild(cancelBtn);
  611. }
  612. var select = document.createElement('select');
  613. select.style.width = '180px';
  614. select.className = 'geBtn';
  615. if (editorUi.editor.graph.isEnabled())
  616. {
  617. var replaceOption = document.createElement('option');
  618. replaceOption.setAttribute('value', 'replace');
  619. mxUtils.write(replaceOption, mxResources.get('replaceExistingDrawing'));
  620. select.appendChild(replaceOption);
  621. }
  622. var newOption = document.createElement('option');
  623. newOption.setAttribute('value', 'new');
  624. mxUtils.write(newOption, mxResources.get('openInNewWindow'));
  625. if (EditDiagramDialog.showNewWindowOption)
  626. {
  627. select.appendChild(newOption);
  628. }
  629. if (editorUi.editor.graph.isEnabled())
  630. {
  631. var importOption = document.createElement('option');
  632. importOption.setAttribute('value', 'import');
  633. mxUtils.write(importOption, mxResources.get('addToExistingDrawing'));
  634. select.appendChild(importOption);
  635. }
  636. div.appendChild(select);
  637. var okBtn = mxUtils.button(mxResources.get('ok'), function()
  638. {
  639. // Removes all illegal control characters before parsing
  640. var data = editorUi.editor.graph.zapGremlins(mxUtils.trim(textarea.value));
  641. var error = null;
  642. if (select.value == 'new')
  643. {
  644. window.openFile = new OpenFile(function()
  645. {
  646. editorUi.hideDialog();
  647. window.openFile = null;
  648. });
  649. window.openFile.setData(data, null);
  650. window.open(editorUi.getUrl());
  651. }
  652. else if (select.value == 'replace')
  653. {
  654. editorUi.editor.graph.model.beginUpdate();
  655. try
  656. {
  657. editorUi.editor.setGraphXml(mxUtils.parseXml(data).documentElement);
  658. // LATER: Why is hideDialog between begin-/endUpdate faster?
  659. editorUi.hideDialog();
  660. }
  661. catch (e)
  662. {
  663. error = e;
  664. }
  665. finally
  666. {
  667. editorUi.editor.graph.model.endUpdate();
  668. }
  669. }
  670. else if (select.value == 'import')
  671. {
  672. editorUi.editor.graph.model.beginUpdate();
  673. try
  674. {
  675. var doc = mxUtils.parseXml(data);
  676. var model = new mxGraphModel();
  677. var codec = new mxCodec(doc);
  678. codec.decode(doc.documentElement, model);
  679. var children = model.getChildren(model.getChildAt(model.getRoot(), 0));
  680. editorUi.editor.graph.setSelectionCells(editorUi.editor.graph.importCells(children));
  681. // LATER: Why is hideDialog between begin-/endUpdate faster?
  682. editorUi.hideDialog();
  683. }
  684. catch (e)
  685. {
  686. error = e;
  687. }
  688. finally
  689. {
  690. editorUi.editor.graph.model.endUpdate();
  691. }
  692. }
  693. if (error != null)
  694. {
  695. mxUtils.alert(error.message);
  696. }
  697. });
  698. okBtn.className = 'geBtn gePrimaryBtn';
  699. div.appendChild(okBtn);
  700. if (!editorUi.editor.cancelFirst)
  701. {
  702. div.appendChild(cancelBtn);
  703. }
  704. this.container = div;
  705. };
  706. /**
  707. *
  708. */
  709. EditDiagramDialog.showNewWindowOption = true;
  710. /**
  711. * Constructs a new export dialog.
  712. */
  713. var ExportDialog = function(editorUi)
  714. {
  715. var graph = editorUi.editor.graph;
  716. var bounds = graph.getGraphBounds();
  717. var scale = graph.view.scale;
  718. var width = Math.ceil(bounds.width / scale);
  719. var height = Math.ceil(bounds.height / scale);
  720. var row, td;
  721. var table = document.createElement('table');
  722. var tbody = document.createElement('tbody');
  723. table.setAttribute('cellpadding', (mxClient.IS_SF) ? '0' : '2');
  724. row = document.createElement('tr');
  725. td = document.createElement('td');
  726. td.style.fontSize = '10pt';
  727. td.style.width = '100px';
  728. mxUtils.write(td, mxResources.get('filename') + ':');
  729. row.appendChild(td);
  730. var nameInput = document.createElement('input');
  731. nameInput.setAttribute('value', editorUi.editor.getOrCreateFilename());
  732. nameInput.style.width = '180px';
  733. td = document.createElement('td');
  734. td.appendChild(nameInput);
  735. row.appendChild(td);
  736. tbody.appendChild(row);
  737. row = document.createElement('tr');
  738. td = document.createElement('td');
  739. td.style.fontSize = '10pt';
  740. mxUtils.write(td, mxResources.get('format') + ':');
  741. row.appendChild(td);
  742. var imageFormatSelect = document.createElement('select');
  743. imageFormatSelect.style.width = '180px';
  744. var pngOption = document.createElement('option');
  745. pngOption.setAttribute('value', 'png');
  746. mxUtils.write(pngOption, mxResources.get('formatPng'));
  747. imageFormatSelect.appendChild(pngOption);
  748. var gifOption = document.createElement('option');
  749. if (ExportDialog.showGifOption)
  750. {
  751. gifOption.setAttribute('value', 'gif');
  752. mxUtils.write(gifOption, mxResources.get('formatGif'));
  753. imageFormatSelect.appendChild(gifOption);
  754. }
  755. var jpgOption = document.createElement('option');
  756. jpgOption.setAttribute('value', 'jpg');
  757. mxUtils.write(jpgOption, mxResources.get('formatJpg'));
  758. imageFormatSelect.appendChild(jpgOption);
  759. var pdfOption = document.createElement('option');
  760. pdfOption.setAttribute('value', 'pdf');
  761. mxUtils.write(pdfOption, mxResources.get('formatPdf'));
  762. imageFormatSelect.appendChild(pdfOption);
  763. var svgOption = document.createElement('option');
  764. svgOption.setAttribute('value', 'svg');
  765. mxUtils.write(svgOption, mxResources.get('formatSvg'));
  766. imageFormatSelect.appendChild(svgOption);
  767. if (ExportDialog.showXmlOption)
  768. {
  769. var xmlOption = document.createElement('option');
  770. xmlOption.setAttribute('value', 'xml');
  771. mxUtils.write(xmlOption, mxResources.get('formatXml'));
  772. imageFormatSelect.appendChild(xmlOption);
  773. }
  774. td = document.createElement('td');
  775. td.appendChild(imageFormatSelect);
  776. row.appendChild(td);
  777. tbody.appendChild(row);
  778. row = document.createElement('tr');
  779. td = document.createElement('td');
  780. td.style.fontSize = '10pt';
  781. mxUtils.write(td, mxResources.get('zoom') + ' (%):');
  782. row.appendChild(td);
  783. var zoomInput = document.createElement('input');
  784. zoomInput.setAttribute('type', 'number');
  785. zoomInput.setAttribute('value', '100');
  786. zoomInput.style.width = '180px';
  787. td = document.createElement('td');
  788. td.appendChild(zoomInput);
  789. row.appendChild(td);
  790. tbody.appendChild(row);
  791. row = document.createElement('tr');
  792. td = document.createElement('td');
  793. td.style.fontSize = '10pt';
  794. mxUtils.write(td, mxResources.get('width') + ':');
  795. row.appendChild(td);
  796. var widthInput = document.createElement('input');
  797. widthInput.setAttribute('value', width);
  798. widthInput.style.width = '180px';
  799. td = document.createElement('td');
  800. td.appendChild(widthInput);
  801. row.appendChild(td);
  802. tbody.appendChild(row);
  803. row = document.createElement('tr');
  804. td = document.createElement('td');
  805. td.style.fontSize = '10pt';
  806. mxUtils.write(td, mxResources.get('height') + ':');
  807. row.appendChild(td);
  808. var heightInput = document.createElement('input');
  809. heightInput.setAttribute('value', height);
  810. heightInput.style.width = '180px';
  811. td = document.createElement('td');
  812. td.appendChild(heightInput);
  813. row.appendChild(td);
  814. tbody.appendChild(row);
  815. row = document.createElement('tr');
  816. td = document.createElement('td');
  817. td.style.fontSize = '10pt';
  818. mxUtils.write(td, mxResources.get('background') + ':');
  819. row.appendChild(td);
  820. var transparentCheckbox = document.createElement('input');
  821. transparentCheckbox.setAttribute('type', 'checkbox');
  822. transparentCheckbox.checked = graph.background == null || graph.background == mxConstants.NONE;
  823. td = document.createElement('td');
  824. td.appendChild(transparentCheckbox);
  825. mxUtils.write(td, mxResources.get('transparent'));
  826. row.appendChild(td);
  827. tbody.appendChild(row);
  828. row = document.createElement('tr');
  829. td = document.createElement('td');
  830. td.style.fontSize = '10pt';
  831. mxUtils.write(td, mxResources.get('borderWidth') + ':');
  832. row.appendChild(td);
  833. var borderInput = document.createElement('input');
  834. borderInput.setAttribute('type', 'number');
  835. borderInput.setAttribute('value', ExportDialog.lastBorderValue);
  836. borderInput.style.width = '180px';
  837. td = document.createElement('td');
  838. td.appendChild(borderInput);
  839. row.appendChild(td);
  840. tbody.appendChild(row);
  841. table.appendChild(tbody);
  842. // Handles changes in the export format
  843. function formatChanged()
  844. {
  845. var name = nameInput.value;
  846. var dot = name.lastIndexOf('.');
  847. if (dot > 0)
  848. {
  849. nameInput.value = name.substring(0, dot + 1) + imageFormatSelect.value;
  850. }
  851. else
  852. {
  853. nameInput.value = name + '.' + imageFormatSelect.value;
  854. }
  855. if (imageFormatSelect.value === 'xml')
  856. {
  857. zoomInput.setAttribute('disabled', 'true');
  858. widthInput.setAttribute('disabled', 'true');
  859. heightInput.setAttribute('disabled', 'true');
  860. borderInput.setAttribute('disabled', 'true');
  861. }
  862. else
  863. {
  864. zoomInput.removeAttribute('disabled');
  865. widthInput.removeAttribute('disabled');
  866. heightInput.removeAttribute('disabled');
  867. borderInput.removeAttribute('disabled');
  868. }
  869. if (imageFormatSelect.value === 'png' || imageFormatSelect.value === 'svg')
  870. {
  871. transparentCheckbox.removeAttribute('disabled');
  872. }
  873. else
  874. {
  875. transparentCheckbox.setAttribute('disabled', 'disabled');
  876. }
  877. };
  878. mxEvent.addListener(imageFormatSelect, 'change', formatChanged);
  879. formatChanged();
  880. function checkValues()
  881. {
  882. if (widthInput.value * heightInput.value > MAX_AREA || widthInput.value <= 0)
  883. {
  884. widthInput.style.backgroundColor = 'red';
  885. }
  886. else
  887. {
  888. widthInput.style.backgroundColor = '';
  889. }
  890. if (widthInput.value * heightInput.value > MAX_AREA || heightInput.value <= 0)
  891. {
  892. heightInput.style.backgroundColor = 'red';
  893. }
  894. else
  895. {
  896. heightInput.style.backgroundColor = '';
  897. }
  898. };
  899. mxEvent.addListener(zoomInput, 'change', function()
  900. {
  901. var s = Math.max(0, parseFloat(zoomInput.value) || 100) / 100;
  902. zoomInput.value = parseFloat((s * 100).toFixed(2));
  903. if (width > 0)
  904. {
  905. widthInput.value = Math.floor(width * s);
  906. heightInput.value = Math.floor(height * s);
  907. }
  908. else
  909. {
  910. zoomInput.value = '100';
  911. widthInput.value = width;
  912. heightInput.value = height;
  913. }
  914. checkValues();
  915. });
  916. mxEvent.addListener(widthInput, 'change', function()
  917. {
  918. var s = parseInt(widthInput.value) / width;
  919. if (s > 0)
  920. {
  921. zoomInput.value = parseFloat((s * 100).toFixed(2));
  922. heightInput.value = Math.floor(height * s);
  923. }
  924. else
  925. {
  926. zoomInput.value = '100';
  927. widthInput.value = width;
  928. heightInput.value = height;
  929. }
  930. checkValues();
  931. });
  932. mxEvent.addListener(heightInput, 'change', function()
  933. {
  934. var s = parseInt(heightInput.value) / height;
  935. if (s > 0)
  936. {
  937. zoomInput.value = parseFloat((s * 100).toFixed(2));
  938. widthInput.value = Math.floor(width * s);
  939. }
  940. else
  941. {
  942. zoomInput.value = '100';
  943. widthInput.value = width;
  944. heightInput.value = height;
  945. }
  946. checkValues();
  947. });
  948. row = document.createElement('tr');
  949. td = document.createElement('td');
  950. td.setAttribute('align', 'right');
  951. td.style.paddingTop = '22px';
  952. td.colSpan = 2;
  953. var saveBtn = mxUtils.button(mxResources.get('export'), mxUtils.bind(this, function()
  954. {
  955. if (parseInt(zoomInput.value) <= 0)
  956. {
  957. mxUtils.alert(mxResources.get('drawingEmpty'));
  958. }
  959. else
  960. {
  961. var name = nameInput.value;
  962. var format = imageFormatSelect.value;
  963. var s = Math.max(0, parseFloat(zoomInput.value) || 100) / 100;
  964. var b = Math.max(0, parseInt(borderInput.value));
  965. var bg = graph.background;
  966. if ((format == 'svg' || format == 'png') && transparentCheckbox.checked)
  967. {
  968. bg = null;
  969. }
  970. else if (bg == null || bg == mxConstants.NONE)
  971. {
  972. bg = '#ffffff';
  973. }
  974. ExportDialog.lastBorderValue = b;
  975. ExportDialog.exportFile(editorUi, name, format, bg, s, b);
  976. }
  977. }));
  978. saveBtn.className = 'geBtn gePrimaryBtn';
  979. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  980. {
  981. editorUi.hideDialog();
  982. });
  983. cancelBtn.className = 'geBtn';
  984. if (editorUi.editor.cancelFirst)
  985. {
  986. td.appendChild(cancelBtn);
  987. td.appendChild(saveBtn);
  988. }
  989. else
  990. {
  991. td.appendChild(saveBtn);
  992. td.appendChild(cancelBtn);
  993. }
  994. row.appendChild(td);
  995. tbody.appendChild(row);
  996. table.appendChild(tbody);
  997. this.container = table;
  998. };
  999. /**
  1000. * Remembers last value for border.
  1001. */
  1002. ExportDialog.lastBorderValue = 0;
  1003. /**
  1004. * Global switches for the export dialog.
  1005. */
  1006. ExportDialog.showGifOption = true;
  1007. /**
  1008. * Global switches for the export dialog.
  1009. */
  1010. ExportDialog.showXmlOption = true;
  1011. /**
  1012. * Hook for getting the export format. Returns null for the default
  1013. * intermediate XML export format or a function that returns the
  1014. * parameter and value to be used in the request in the form
  1015. * key=value, where value should be URL encoded.
  1016. */
  1017. ExportDialog.exportFile = function(editorUi, name, format, bg, s, b)
  1018. {
  1019. var graph = editorUi.editor.graph;
  1020. if (format == 'xml')
  1021. {
  1022. ExportDialog.saveLocalFile(editorUi, mxUtils.getXml(editorUi.editor.getGraphXml()), name, format);
  1023. }
  1024. else if (format == 'svg')
  1025. {
  1026. ExportDialog.saveLocalFile(editorUi, mxUtils.getXml(graph.getSvg(bg, s, b)), name, format);
  1027. }
  1028. else
  1029. {
  1030. var bounds = graph.getGraphBounds();
  1031. // New image export
  1032. var xmlDoc = mxUtils.createXmlDocument();
  1033. var root = xmlDoc.createElement('output');
  1034. xmlDoc.appendChild(root);
  1035. // Renders graph. Offset will be multiplied with state's scale when painting state.
  1036. var xmlCanvas = new mxXmlCanvas2D(root);
  1037. xmlCanvas.translate(Math.floor((b / s - bounds.x) / graph.view.scale),
  1038. Math.floor((b / s - bounds.y) / graph.view.scale));
  1039. xmlCanvas.scale(s / graph.view.scale);
  1040. var imgExport = new mxImageExport()
  1041. imgExport.drawState(graph.getView().getState(graph.model.root), xmlCanvas);
  1042. // Puts request data together
  1043. var param = 'xml=' + encodeURIComponent(mxUtils.getXml(root));
  1044. var w = Math.ceil(bounds.width * s / graph.view.scale + 2 * b);
  1045. var h = Math.ceil(bounds.height * s / graph.view.scale + 2 * b);
  1046. // Requests image if request is valid
  1047. if (param.length <= MAX_REQUEST_SIZE && w * h < MAX_AREA)
  1048. {
  1049. editorUi.hideDialog();
  1050. var req = new mxXmlRequest(EXPORT_URL, 'format=' + format +
  1051. '&filename=' + encodeURIComponent(name) +
  1052. '&bg=' + ((bg != null) ? bg : 'none') +
  1053. '&w=' + w + '&h=' + h + '&' + param);
  1054. req.simulate(document, '_blank');
  1055. }
  1056. else
  1057. {
  1058. mxUtils.alert(mxResources.get('drawingTooLarge'));
  1059. }
  1060. }
  1061. };
  1062. /**
  1063. * Hook for getting the export format. Returns null for the default
  1064. * intermediate XML export format or a function that returns the
  1065. * parameter and value to be used in the request in the form
  1066. * key=value, where value should be URL encoded.
  1067. */
  1068. ExportDialog.saveLocalFile = function(editorUi, data, filename, format)
  1069. {
  1070. if (data.length < MAX_REQUEST_SIZE)
  1071. {
  1072. editorUi.hideDialog();
  1073. var req = new mxXmlRequest(SAVE_URL, 'xml=' + encodeURIComponent(data) + '&filename=' +
  1074. encodeURIComponent(filename) + '&format=' + format);
  1075. req.simulate(document, '_blank');
  1076. }
  1077. else
  1078. {
  1079. mxUtils.alert(mxResources.get('drawingTooLarge'));
  1080. mxUtils.popup(xml);
  1081. }
  1082. };
  1083. /**
  1084. * Constructs a new metadata dialog.
  1085. */
  1086. var EditDataDialog = function(ui, cell)
  1087. {
  1088. var div = document.createElement('div');
  1089. var graph = ui.editor.graph;
  1090. div.style.height = '310px';
  1091. div.style.overflow = 'auto';
  1092. var value = graph.getModel().getValue(cell);
  1093. // Converts the value to an XML node
  1094. if (!mxUtils.isNode(value))
  1095. {
  1096. var doc = mxUtils.createXmlDocument();
  1097. var obj = doc.createElement('object');
  1098. obj.setAttribute('label', value || '');
  1099. value = obj;
  1100. }
  1101. // Creates the dialog contents
  1102. var form = new mxForm('properties');
  1103. form.table.style.width = '100%';
  1104. form.table.style.paddingRight = '20px';
  1105. var attrs = value.attributes;
  1106. var names = [];
  1107. var texts = [];
  1108. var count = 0;
  1109. // FIXME: Fix remove button for quirks mode
  1110. var addRemoveButton = function(text, name)
  1111. {
  1112. text.parentNode.style.marginRight = '12px';
  1113. var removeAttr = document.createElement('a');
  1114. var img = mxUtils.createImage(Dialog.prototype.closeImage);
  1115. img.style.height = '9px';
  1116. img.style.fontSize = '9px';
  1117. img.style.marginBottom = (mxClient.IS_IE11) ? '-1px' : '5px';
  1118. removeAttr.className = 'geButton';
  1119. removeAttr.setAttribute('title', mxResources.get('delete'));
  1120. removeAttr.style.margin = '0px';
  1121. removeAttr.style.width = '14px';
  1122. removeAttr.style.height = '14px';
  1123. removeAttr.style.fontSize = '14px';
  1124. removeAttr.style.cursor = 'pointer';
  1125. removeAttr.style.marginLeft = '6px';
  1126. removeAttr.appendChild(img);
  1127. var removeAttrFn = (function(name)
  1128. {
  1129. return function()
  1130. {
  1131. var count = 0;
  1132. for (var j = 0; j < names.length; j++)
  1133. {
  1134. if (names[j] == name)
  1135. {
  1136. texts[j] = null;
  1137. form.table.deleteRow(count);
  1138. break;
  1139. }
  1140. if (texts[j] != null)
  1141. {
  1142. count++;
  1143. }
  1144. }
  1145. };
  1146. })(name);
  1147. mxEvent.addListener(removeAttr, 'click', removeAttrFn);
  1148. text.parentNode.style.whiteSpace = 'nowrap';
  1149. text.parentNode.appendChild(removeAttr);
  1150. };
  1151. var addTextArea = function(index, name, value)
  1152. {
  1153. names[index] = name;
  1154. texts[index] = form.addTextarea(names[count] + ':', value, 2);
  1155. texts[index].style.width = '100%';
  1156. addRemoveButton(texts[index], name);
  1157. };
  1158. var temp = [];
  1159. for (var i = 0; i < attrs.length; i++)
  1160. {
  1161. if (attrs[i].nodeName != 'label' && attrs[i].nodeName != 'placeholders')
  1162. {
  1163. temp.push({name: attrs[i].nodeName, value: attrs[i].nodeValue});
  1164. }
  1165. }
  1166. // Sorts by name
  1167. temp.sort(function(a, b)
  1168. {
  1169. if (a.name < b.name)
  1170. {
  1171. return -1;
  1172. }
  1173. else if (a.name > b.name)
  1174. {
  1175. return 1;
  1176. }
  1177. else
  1178. {
  1179. return 0;
  1180. }
  1181. });
  1182. for (var i = 0; i < temp.length; i++)
  1183. {
  1184. addTextArea(count, temp[i].name, temp[i].value);
  1185. count++;
  1186. }
  1187. div.appendChild(form.table);
  1188. var newProp = document.createElement('div');
  1189. newProp.style.whiteSpace = 'nowrap';
  1190. newProp.style.marginTop = '6px';
  1191. var nameInput = document.createElement('input');
  1192. nameInput.setAttribute('placeholder', mxResources.get('enterPropertyName'));
  1193. nameInput.setAttribute('type', 'text');
  1194. nameInput.setAttribute('size', (mxClient.IS_IE || mxClient.IS_IE11) ? '18' : '22');
  1195. nameInput.style.marginLeft = '2px';
  1196. newProp.appendChild(nameInput);
  1197. div.appendChild(newProp);
  1198. var addBtn = mxUtils.button(mxResources.get('addProperty'), function()
  1199. {
  1200. var name = nameInput.value;
  1201. // Avoid ':' in attribute names which seems to be valid in Chrome
  1202. if (name.length > 0 && name != 'label' && name != 'placeholders' && name.indexOf(':') < 0)
  1203. {
  1204. try
  1205. {
  1206. var idx = mxUtils.indexOf(names, name);
  1207. if (idx >= 0 && texts[idx] != null)
  1208. {
  1209. texts[idx].focus();
  1210. }
  1211. else
  1212. {
  1213. // Checks if the name is valid
  1214. var clone = value.cloneNode(false);
  1215. clone.setAttribute(name, '');
  1216. if (idx >= 0)
  1217. {
  1218. names.splice(idx, 1);
  1219. texts.splice(idx, 1);
  1220. }
  1221. names.push(name);
  1222. var text = form.addTextarea(name + ':', '', 2);
  1223. text.style.width = '100%';
  1224. texts.push(text);
  1225. addRemoveButton(text, name);
  1226. text.focus();
  1227. }
  1228. nameInput.value = '';
  1229. }
  1230. catch (e)
  1231. {
  1232. mxUtils.alert(e);
  1233. }
  1234. }
  1235. else
  1236. {
  1237. mxUtils.alert(mxResources.get('invalidName'));
  1238. }
  1239. });
  1240. this.init = function()
  1241. {
  1242. if (texts.length > 0)
  1243. {
  1244. texts[0].focus();
  1245. }
  1246. else
  1247. {
  1248. nameInput.focus();
  1249. }
  1250. };
  1251. addBtn.setAttribute('disabled', 'disabled');
  1252. addBtn.style.marginLeft = '10px';
  1253. addBtn.style.width = '144px';
  1254. newProp.appendChild(addBtn);
  1255. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  1256. {
  1257. ui.hideDialog.apply(ui, arguments);
  1258. });
  1259. cancelBtn.className = 'geBtn';
  1260. var applyBtn = mxUtils.button(mxResources.get('apply'), function()
  1261. {
  1262. try
  1263. {
  1264. ui.hideDialog.apply(ui, arguments);
  1265. // Clones and updates the value
  1266. value = value.cloneNode(true);
  1267. var removeLabel = false;
  1268. for (var i = 0; i < names.length; i++)
  1269. {
  1270. if (texts[i] == null)
  1271. {
  1272. value.removeAttribute(names[i]);
  1273. }
  1274. else
  1275. {
  1276. value.setAttribute(names[i], texts[i].value);
  1277. removeLabel = removeLabel || (names[i] == 'placeholder' &&
  1278. value.getAttribute('placeholders') == '1');
  1279. }
  1280. }
  1281. // Removes label if placeholder is assigned
  1282. if (removeLabel)
  1283. {
  1284. value.removeAttribute('label');
  1285. }
  1286. // Updates the value of the cell (undoable)
  1287. graph.getModel().setValue(cell, value);
  1288. }
  1289. catch (e)
  1290. {
  1291. mxUtils.alert(e);
  1292. }
  1293. });
  1294. applyBtn.className = 'geBtn gePrimaryBtn';
  1295. function updateAddBtn()
  1296. {
  1297. if (nameInput.value.length > 0)
  1298. {
  1299. addBtn.removeAttribute('disabled');
  1300. }
  1301. else
  1302. {
  1303. addBtn.setAttribute('disabled', 'disabled');
  1304. }
  1305. };
  1306. mxEvent.addListener(nameInput, 'keyup', updateAddBtn);
  1307. // Catches all changes that don't fire a keyup (such as paste via mouse)
  1308. mxEvent.addListener(nameInput, 'change', updateAddBtn);
  1309. var buttons = document.createElement('div');
  1310. buttons.style.marginTop = '18px';
  1311. buttons.style.textAlign = 'right';
  1312. if (ui.editor.graph.getModel().isVertex(cell) || ui.editor.graph.getModel().isEdge(cell))
  1313. {
  1314. var replace = document.createElement('span');
  1315. replace.style.marginRight = '10px';
  1316. var input = document.createElement('input');
  1317. input.setAttribute('type', 'checkbox');
  1318. input.style.marginRight = '6px';
  1319. if (value.getAttribute('placeholders') == '1')
  1320. {
  1321. input.setAttribute('checked', 'checked');
  1322. input.defaultChecked = true;
  1323. }
  1324. mxEvent.addListener(input, 'click', function()
  1325. {
  1326. if (value.getAttribute('placeholders') == '1')
  1327. {
  1328. value.removeAttribute('placeholders');
  1329. }
  1330. else
  1331. {
  1332. value.setAttribute('placeholders', '1');
  1333. }
  1334. });
  1335. replace.appendChild(input);
  1336. mxUtils.write(replace, mxResources.get('placeholders'));
  1337. if (EditDataDialog.placeholderHelpLink != null)
  1338. {
  1339. var link = document.createElement('a');
  1340. link.setAttribute('href', EditDataDialog.placeholderHelpLink);
  1341. link.setAttribute('title', mxResources.get('help'));
  1342. link.setAttribute('target', '_blank');
  1343. link.style.marginLeft = '10px';
  1344. link.style.cursor = 'help';
  1345. var icon = document.createElement('img');
  1346. icon.setAttribute('border', '0');
  1347. icon.setAttribute('valign', 'middle');
  1348. icon.style.marginTop = (mxClient.IS_IE11) ? '0px' : '-4px';
  1349. icon.setAttribute('src', Editor.helpImage);
  1350. link.appendChild(icon);
  1351. replace.appendChild(link);
  1352. }
  1353. buttons.appendChild(replace);
  1354. }
  1355. if (ui.editor.cancelFirst)
  1356. {
  1357. buttons.appendChild(cancelBtn);
  1358. buttons.appendChild(applyBtn);
  1359. }
  1360. else
  1361. {
  1362. buttons.appendChild(applyBtn);
  1363. buttons.appendChild(cancelBtn);
  1364. }
  1365. div.appendChild(buttons);
  1366. this.container = div;
  1367. };
  1368. /**
  1369. * Optional help link.
  1370. */
  1371. EditDataDialog.placeholderHelpLink = null;
  1372. /**
  1373. * Constructs a new link dialog.
  1374. */
  1375. var LinkDialog = function(editorUi, initialValue, btnLabel, fn)
  1376. {
  1377. var div = document.createElement('div');
  1378. mxUtils.write(div, mxResources.get('editLink') + ':');
  1379. var inner = document.createElement('div');
  1380. inner.className = 'geTitle';
  1381. inner.style.backgroundColor = 'transparent';
  1382. inner.style.borderColor = 'transparent';
  1383. inner.style.whiteSpace = 'nowrap';
  1384. inner.style.textOverflow = 'clip';
  1385. inner.style.cursor = 'default';
  1386. if (!mxClient.IS_VML)
  1387. {
  1388. inner.style.paddingRight = '20px';
  1389. }
  1390. var linkInput = document.createElement('input');
  1391. linkInput.setAttribute('value', initialValue);
  1392. linkInput.setAttribute('placeholder', 'http://www.example.com/');
  1393. linkInput.setAttribute('type', 'text');
  1394. linkInput.style.marginTop = '6px';
  1395. linkInput.style.width = '400px';
  1396. linkInput.style.backgroundImage = 'url(\'' + Dialog.prototype.clearImage + '\')';
  1397. linkInput.style.backgroundRepeat = 'no-repeat';
  1398. linkInput.style.backgroundPosition = '100% 50%';
  1399. linkInput.style.paddingRight = '14px';
  1400. var cross = document.createElement('div');
  1401. cross.setAttribute('title', mxResources.get('reset'));
  1402. cross.style.position = 'relative';
  1403. cross.style.left = '-16px';
  1404. cross.style.width = '12px';
  1405. cross.style.height = '14px';
  1406. cross.style.cursor = 'pointer';
  1407. // Workaround for inline-block not supported in IE
  1408. cross.style.display = (mxClient.IS_VML) ? 'inline' : 'inline-block';
  1409. cross.style.top = ((mxClient.IS_VML) ? 0 : 3) + 'px';
  1410. // Needed to block event transparency in IE
  1411. cross.style.background = 'url(' + IMAGE_PATH + '/transparent.gif)';
  1412. mxEvent.addListener(cross, 'click', function()
  1413. {
  1414. linkInput.value = '';
  1415. linkInput.focus();
  1416. });
  1417. inner.appendChild(linkInput);
  1418. inner.appendChild(cross);
  1419. div.appendChild(inner);
  1420. this.init = function()
  1421. {
  1422. linkInput.focus();
  1423. if (mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS)
  1424. {
  1425. linkInput.select();
  1426. }
  1427. else
  1428. {
  1429. document.execCommand('selectAll', false, null);
  1430. }
  1431. };
  1432. var btns = document.createElement('div');
  1433. btns.style.marginTop = '18px';
  1434. btns.style.textAlign = 'right';
  1435. mxEvent.addListener(linkInput, 'keypress', function(e)
  1436. {
  1437. if (e.keyCode == 13)
  1438. {
  1439. editorUi.hideDialog();
  1440. fn(linkInput.value);
  1441. }
  1442. });
  1443. var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
  1444. {
  1445. editorUi.hideDialog();
  1446. });
  1447. cancelBtn.className = 'geBtn';
  1448. if (editorUi.editor.cancelFirst)
  1449. {
  1450. btns.appendChild(cancelBtn);
  1451. }
  1452. var mainBtn = mxUtils.button(btnLabel, function()
  1453. {
  1454. editorUi.hideDialog();
  1455. fn(linkInput.value);
  1456. });
  1457. mainBtn.className = 'geBtn gePrimaryBtn';
  1458. btns.appendChild(mainBtn);
  1459. if (!editorUi.editor.cancelFirst)
  1460. {
  1461. btns.appendChild(cancelBtn);
  1462. }
  1463. div.appendChild(btns);
  1464. this.container = div;
  1465. };
  1466. /**
  1467. *
  1468. */
  1469. var OutlineWindow = function(editorUi, x, y, w, h)
  1470. {
  1471. var graph = editorUi.editor.graph;
  1472. var div = document.createElement('div');
  1473. div.style.position = 'absolute';
  1474. div.style.width = '100%';
  1475. div.style.height = '100%';
  1476. div.style.border = '1px solid whiteSmoke';
  1477. div.style.overflow = 'hidden';
  1478. this.window = new mxWindow(mxResources.get('outline'), div, x, y, w, h, true, true);
  1479. this.window.destroyOnClose = false;
  1480. this.window.setMaximizable(false);
  1481. this.window.setResizable(true);
  1482. this.window.setClosable(true);
  1483. this.window.setVisible(true);
  1484. this.window.setLocation = function(x, y)
  1485. {
  1486. var iw = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
  1487. var ih = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
  1488. x = Math.max(0, Math.min(x, iw - this.table.clientWidth));
  1489. y = Math.max(0, Math.min(y, ih - this.table.clientHeight - 48));
  1490. if (this.getX() != x || this.getY() != y)
  1491. {
  1492. mxWindow.prototype.setLocation.apply(this, arguments);
  1493. }
  1494. };
  1495. mxEvent.addListener(window, 'resize', mxUtils.bind(this, function()
  1496. {
  1497. var x = this.window.getX();
  1498. var y = this.window.getY();
  1499. this.window.setLocation(x, y);
  1500. }));
  1501. var outline = editorUi.createOutline(this.window);
  1502. this.window.addListener(mxEvent.RESIZE, mxUtils.bind(this, function()
  1503. {
  1504. outline.update(false);
  1505. outline.outline.sizeDidChange();
  1506. }));
  1507. this.window.addListener(mxEvent.SHOW, mxUtils.bind(this, function()
  1508. {
  1509. outline.suspended = false;
  1510. outline.outline.refresh();
  1511. outline.update();
  1512. }));
  1513. this.window.addListener(mxEvent.HIDE, mxUtils.bind(this, function()
  1514. {
  1515. outline.suspended = true;
  1516. }));
  1517. this.window.addListener(mxEvent.NORMALIZE, mxUtils.bind(this, function()
  1518. {
  1519. outline.suspended = false;
  1520. outline.update();
  1521. }));
  1522. this.window.addListener(mxEvent.MINIMIZE, mxUtils.bind(this, function()
  1523. {
  1524. outline.suspended = true;
  1525. }));
  1526. var outlineCreateGraph = outline.createGraph;
  1527. outline.createGraph = function(container)
  1528. {
  1529. var g = outlineCreateGraph.apply(this, arguments);
  1530. g.gridEnabled = false;
  1531. g.pageScale = graph.pageScale;
  1532. g.pageFormat = graph.pageFormat;
  1533. g.background = graph.background;
  1534. g.pageVisible = graph.pageVisible;
  1535. var current = mxUtils.getCurrentStyle(graph.container);
  1536. div.style.backgroundColor = current.backgroundColor;
  1537. return g;
  1538. };
  1539. function update()
  1540. {
  1541. outline.outline.pageScale = graph.pageScale;
  1542. outline.outline.pageFormat = graph.pageFormat;
  1543. outline.outline.pageVisible = graph.pageVisible;
  1544. outline.outline.background = graph.background;
  1545. var current = mxUtils.getCurrentStyle(graph.container);
  1546. div.style.backgroundColor = current.backgroundColor;
  1547. if (graph.view.backgroundPageShape != null && outline.outline.view.backgroundPageShape != null)
  1548. {
  1549. outline.outline.view.backgroundPageShape.fill = graph.view.backgroundPageShape.fill;
  1550. }
  1551. outline.outline.refresh();
  1552. };
  1553. outline.init(div);
  1554. editorUi.editor.addListener('resetGraphView', update);
  1555. editorUi.addListener('pageFormatChanged', update);
  1556. editorUi.addListener('backgroundColorChanged', update);
  1557. editorUi.addListener('backgroundImageChanged', update);
  1558. editorUi.addListener('pageViewChanged', function()
  1559. {
  1560. update();
  1561. outline.update(true);
  1562. });
  1563. if (outline.outline.dialect == mxConstants.DIALECT_SVG)
  1564. {
  1565. var zoomInAction = editorUi.actions.get('zoomIn');
  1566. var zoomOutAction = editorUi.actions.get('zoomOut');
  1567. mxEvent.addMouseWheelListener(function(evt, up)
  1568. {
  1569. var outlineWheel = false;
  1570. var source = mxEvent.getSource(evt);
  1571. while (source != null)
  1572. {
  1573. if (source == outline.outline.view.canvas.ownerSVGElement)
  1574. {
  1575. outlineWheel = true;
  1576. break;
  1577. }
  1578. source = source.parentNode;
  1579. }
  1580. if (outlineWheel)
  1581. {
  1582. if (up)
  1583. {
  1584. zoomInAction.funct();
  1585. }
  1586. else
  1587. {
  1588. zoomOutAction.funct();
  1589. }
  1590. mxEvent.consume(evt);
  1591. }
  1592. });
  1593. }
  1594. };
  1595. /**
  1596. *
  1597. */
  1598. var LayersWindow = function(editorUi, x, y, w, h)
  1599. {
  1600. var graph = editorUi.editor.graph;
  1601. var div = document.createElement('div');
  1602. div.style.userSelect = 'none';
  1603. div.style.background = 'whiteSmoke';
  1604. div.style.border = '1px solid whiteSmoke';
  1605. div.style.height = '100%';
  1606. div.style.marginBottom = '10px';
  1607. div.style.overflow = 'auto';
  1608. var tbarHeight = (!EditorUi.compactUi) ? '30px' : '26px';
  1609. var listDiv = document.createElement('div')
  1610. listDiv.style.backgroundColor = '#e5e5e5';
  1611. listDiv.style.position = 'absolute';
  1612. listDiv.style.overflow = 'auto';
  1613. listDiv.style.left = '0px';
  1614. listDiv.style.right = '0px';
  1615. listDiv.style.top = '0px';
  1616. listDiv.style.bottom = (parseInt(tbarHeight) + 7) + 'px';
  1617. div.appendChild(listDiv);
  1618. var dragSource = null;
  1619. var dropIndex = null;
  1620. mxEvent.addListener(div, 'dragover', function(evt)
  1621. {
  1622. evt.dataTransfer.dropEffect = 'move';
  1623. dropIndex = 0;
  1624. evt.stopPropagation();
  1625. evt.preventDefault();
  1626. });
  1627. // Workaround for "no element found" error in FF
  1628. mxEvent.addListener(div, 'drop', function(evt)
  1629. {
  1630. evt.stopPropagation();
  1631. evt.preventDefault();
  1632. });
  1633. var layerCount = null;
  1634. var selectionLayer = null;
  1635. var ldiv = document.createElement('div');
  1636. ldiv.className = 'geToolbarContainer';
  1637. ldiv.style.position = 'absolute';
  1638. ldiv.style.bottom = '0px';
  1639. ldiv.style.left = '0px';
  1640. ldiv.style.right = '0px';
  1641. ldiv.style.height = tbarHeight;
  1642. ldiv.style.overflow = 'hidden';
  1643. ldiv.style.padding = (!EditorUi.compactUi) ? '1px' : '4px 0px 3px 0px';
  1644. ldiv.style.backgroundColor = 'whiteSmoke';
  1645. ldiv.style.borderWidth = '1px 0px 0px 0px';
  1646. ldiv.style.borderColor = '#c3c3c3';
  1647. ldiv.style.borderStyle = 'solid';
  1648. ldiv.style.display = 'block';
  1649. ldiv.style.whiteSpace = 'nowrap';
  1650. if (mxClient.IS_QUIRKS)
  1651. {
  1652. ldiv.style.filter = 'none';
  1653. }
  1654. var link = document.createElement('a');
  1655. link.className = 'geButton';
  1656. if (mxClient.IS_QUIRKS)
  1657. {
  1658. link.style.filter = 'none';
  1659. }
  1660. var removeLink = link.cloneNode();
  1661. removeLink.innerHTML = '<div class="geSprite geSprite-delete" style="display:inline-block;"></div>';
  1662. mxEvent.addListener(removeLink, 'click', function(evt)
  1663. {
  1664. if (graph.isEnabled())
  1665. {
  1666. graph.model.beginUpdate();
  1667. try
  1668. {
  1669. var index = graph.model.root.getIndex(selectionLayer);
  1670. graph.removeCells([selectionLayer], false);
  1671. // Creates default layer if no layer exists
  1672. if (graph.model.getChildCount(graph.model.root) == 0)
  1673. {
  1674. graph.model.add(graph.model.root, new mxCell());
  1675. graph.setDefaultParent(null);
  1676. }
  1677. else if (index > 0 && index <= graph.model.getChildCount(graph.model.root))
  1678. {
  1679. graph.setDefaultParent(graph.model.getChildAt(graph.model.root, index - 1));
  1680. }
  1681. else
  1682. {
  1683. graph.setDefaultParent(null);
  1684. }
  1685. }
  1686. finally
  1687. {
  1688. graph.model.endUpdate();
  1689. }
  1690. }
  1691. mxEvent.consume(evt);
  1692. });
  1693. if (!graph.isEnabled())
  1694. {
  1695. removeLink.className = 'geButton mxDisabled';
  1696. }
  1697. ldiv.appendChild(removeLink);
  1698. var insertLink = link.cloneNode();
  1699. insertLink.innerHTML = '<div class="geSprite geSprite-insert" style="display:inline-block;"></div>';
  1700. mxEvent.addListener(insertLink, 'click', function(evt)
  1701. {
  1702. if (graph.isEnabled() && !graph.isSelectionEmpty())
  1703. {
  1704. graph.moveCells(graph.getSelectionCells(), 0, 0, false, selectionLayer);
  1705. }
  1706. });
  1707. ldiv.appendChild(insertLink);
  1708. var renameLink = link.cloneNode();
  1709. renameLink.innerHTML = '<div class="geSprite geSprite-dots" style="display:inline-block;"></div>';
  1710. renameLink.setAttribute('title', mxResources.get('rename'));
  1711. function renameLayer(layer)
  1712. {
  1713. if (graph.isEnabled() && layer != null)
  1714. {
  1715. var dlg = new FilenameDialog(editorUi, layer.value || mxResources.get('background'), mxResources.get('rename'), mxUtils.bind(this, function(newValue)
  1716. {
  1717. if (newValue != null)
  1718. {
  1719. graph.getModel().setValue(layer, newValue);
  1720. }
  1721. }), mxResources.get('enterName'));
  1722. editorUi.showDialog(dlg.container, 300, 100, true, true);
  1723. dlg.init();
  1724. }
  1725. };
  1726. mxEvent.addListener(renameLink, 'click', function(evt)
  1727. {
  1728. if (graph.isEnabled())
  1729. {
  1730. renameLayer(selectionLayer);
  1731. }
  1732. mxEvent.consume(evt);
  1733. });
  1734. if (!graph.isEnabled())
  1735. {
  1736. renameLink.className = 'geButton mxDisabled';
  1737. }
  1738. ldiv.appendChild(renameLink);
  1739. var duplicateLink = link.cloneNode();
  1740. duplicateLink.innerHTML = '<div class="geSprite geSprite-duplicate" style="display:inline-block;"></div>';
  1741. mxEvent.addListener(duplicateLink, 'click', function(evt)
  1742. {
  1743. if (graph.isEnabled())
  1744. {
  1745. var newCell = null;
  1746. graph.model.beginUpdate();
  1747. try
  1748. {
  1749. newCell = graph.cloneCells([selectionLayer])[0];
  1750. newCell.value = mxResources.get('untitledLayer');
  1751. newCell.setVisible(true);
  1752. newCell = graph.addCell(newCell, graph.model.root);
  1753. graph.setDefaultParent(newCell);
  1754. }
  1755. finally
  1756. {
  1757. graph.model.endUpdate();
  1758. }
  1759. if (newCell != null && !graph.isCellLocked(newCell))
  1760. {
  1761. graph.selectAll(newCell);
  1762. }
  1763. }
  1764. });
  1765. if (!graph.isEnabled())
  1766. {
  1767. duplicateLink.className = 'geButton mxDisabled';
  1768. }
  1769. ldiv.appendChild(duplicateLink);
  1770. var addLink = link.cloneNode();
  1771. addLink.innerHTML = '<div class="geSprite geSprite-plus" style="display:inline-block;"></div>';
  1772. addLink.setAttribute('title', mxResources.get('addLayer'));
  1773. mxEvent.addListener(addLink, 'click', function(evt)
  1774. {
  1775. if (graph.isEnabled())
  1776. {
  1777. graph.model.beginUpdate();
  1778. try
  1779. {
  1780. var cell = graph.addCell(new mxCell(mxResources.get('untitledLayer')), graph.model.root);
  1781. graph.setDefaultParent(cell);
  1782. }
  1783. finally
  1784. {
  1785. graph.model.endUpdate();
  1786. }
  1787. }
  1788. mxEvent.consume(evt);
  1789. });
  1790. if (!graph.isEnabled())
  1791. {
  1792. addLink.className = 'geButton mxDisabled';
  1793. }
  1794. ldiv.appendChild(addLink);
  1795. div.appendChild(ldiv);
  1796. function refresh()
  1797. {
  1798. layerCount = graph.model.getChildCount(graph.model.root)
  1799. listDiv.innerHTML = '';
  1800. function addLayer(index, label, child, defaultParent)
  1801. {
  1802. var ldiv = document.createElement('div');
  1803. ldiv.className = 'geToolbarContainer';
  1804. ldiv.style.overflow = 'hidden';
  1805. ldiv.style.position = 'relative';
  1806. ldiv.style.padding = '4px';
  1807. ldiv.style.height = '22px';
  1808. ldiv.style.display = 'block';
  1809. ldiv.style.backgroundColor = 'whiteSmoke';
  1810. ldiv.style.borderWidth = '0px 0px 1px 0px';
  1811. ldiv.style.borderColor = '#c3c3c3';
  1812. ldiv.style.borderStyle = 'solid';
  1813. ldiv.style.whiteSpace = 'nowrap';
  1814. var left = document.createElement('div');
  1815. left.style.display = 'inline-block';
  1816. left.style.width = '100%';
  1817. left.style.textOverflow = 'ellipsis';
  1818. left.style.overflow = 'hidden';
  1819. mxEvent.addListener(ldiv, 'dragover', function(evt)
  1820. {
  1821. evt.dataTransfer.dropEffect = 'move';
  1822. dropIndex = index;
  1823. evt.stopPropagation();
  1824. evt.preventDefault();
  1825. });
  1826. mxEvent.addListener(ldiv, 'dragstart', function(evt)
  1827. {
  1828. dragSource = ldiv;
  1829. // Workaround for no DnD on DIV in FF
  1830. if (mxClient.IS_FF)
  1831. {
  1832. // LATER: Check what triggers a parse as XML on this in FF after drop
  1833. evt.dataTransfer.setData('Text', '<layer/>');
  1834. }
  1835. });
  1836. mxEvent.addListener(ldiv, 'dragend', function(evt)
  1837. {
  1838. if (dragSource != null && dropIndex != null)
  1839. {
  1840. graph.addCell(child, graph.model.root, dropIndex);
  1841. }
  1842. dragSource = null;
  1843. dropIndex = null;
  1844. evt.stopPropagation();
  1845. evt.preventDefault();
  1846. });
  1847. var btn = document.createElement('img');
  1848. btn.setAttribute('draggable', 'false');
  1849. btn.setAttribute('align', 'top');
  1850. btn.setAttribute('border', '0');
  1851. btn.style.cursor = 'pointer';
  1852. btn.style.padding = '4px';
  1853. btn.setAttribute('title', mxResources.get('lockUnlock'));
  1854. var state = graph.view.getState(child);
  1855. var style = (state != null) ? state.style : graph.getCellStyle(child);
  1856. if (mxUtils.getValue(style, 'locked', '0') == '1')
  1857. {
  1858. btn.setAttribute('src', Dialog.prototype.lockedImage);
  1859. }
  1860. else
  1861. {
  1862. btn.setAttribute('src', Dialog.prototype.unlockedImage);
  1863. }
  1864. mxEvent.addListener(btn, 'click', function(evt)
  1865. {
  1866. if (graph.isEnabled())
  1867. {
  1868. var value = null;
  1869. graph.getModel().beginUpdate();
  1870. try
  1871. {
  1872. value = (mxUtils.getValue(style, 'locked', '0') == '1') ? null : '1';
  1873. graph.setCellStyles('locked', value, [child]);
  1874. }
  1875. finally
  1876. {
  1877. graph.getModel().endUpdate();
  1878. }
  1879. if (value == '1')
  1880. {
  1881. graph.removeSelectionCells(graph.getModel().getDescendants(child));
  1882. }
  1883. mxEvent.consume(evt);
  1884. }
  1885. });
  1886. left.appendChild(btn);
  1887. var inp = document.createElement('input');
  1888. inp.setAttribute('type', 'checkbox');
  1889. inp.setAttribute('title', mxResources.get('hideIt', [child.value || mxResources.get('background')]));
  1890. inp.style.marginLeft = '4px';
  1891. inp.style.marginRight = '6px';
  1892. inp.style.marginTop = '4px';
  1893. left.appendChild(inp);
  1894. if (!graph.isEnabled())
  1895. {
  1896. inp.setAttribute('disabled', 'disabled');
  1897. }
  1898. if (graph.model.isVisible(child))
  1899. {
  1900. inp.setAttribute('checked', 'checked');
  1901. inp.defaultChecked = true;
  1902. }
  1903. mxEvent.addListener(inp, 'click', function(evt)
  1904. {
  1905. if (graph.isEnabled())
  1906. {
  1907. graph.model.setVisible(child, !graph.model.isVisible(child));
  1908. mxEvent.consume(evt);
  1909. }
  1910. });
  1911. mxUtils.write(left, label);
  1912. ldiv.appendChild(left);
  1913. if (graph.isEnabled())
  1914. {
  1915. // Fallback if no drag and drop is available
  1916. if (mxClient.IS_TOUCH || mxClient.IS_POINTER || mxClient.IS_VML ||
  1917. (mxClient.IS_IE && document.documentMode < 10))
  1918. {
  1919. var right = document.createElement('div');
  1920. right.style.display = 'block';
  1921. right.style.textAlign = 'right';
  1922. right.style.whiteSpace = 'nowrap';
  1923. right.style.position = 'absolute';
  1924. right.style.right = '6px';
  1925. right.style.top = '6px';
  1926. // Poor man's change layer order
  1927. if (index > 0)
  1928. {
  1929. var img2 = document.createElement('a');
  1930. img2.setAttribute('title', mxResources.get('toBack'));
  1931. img2.className = 'geButton';
  1932. img2.style.cssFloat = 'none';
  1933. img2.innerHTML = '&#9660;';
  1934. img2.style.width = '14px';
  1935. img2.style.height = '14px';
  1936. img2.style.fontSize = '14px';
  1937. img2.style.margin = '0px';
  1938. img2.style.marginTop = '-1px';
  1939. right.appendChild(img2);
  1940. mxEvent.addListener(img2, 'click', function(evt)
  1941. {
  1942. if (graph.isEnabled())
  1943. {
  1944. graph.addCell(child, graph.model.root, index - 1);
  1945. }
  1946. mxEvent.consume(evt);
  1947. });
  1948. }
  1949. if (index >= 0 && index < layerCount - 1)
  1950. {
  1951. var img1 = document.createElement('a');
  1952. img1.setAttribute('title', mxResources.get('toFront'));
  1953. img1.className = 'geButton';
  1954. img1.style.cssFloat = 'none';
  1955. img1.innerHTML = '&#9650;';
  1956. img1.style.width = '14px';
  1957. img1.style.height = '14px';
  1958. img1.style.fontSize = '14px';
  1959. img1.style.margin = '0px';
  1960. img1.style.marginTop = '-1px';
  1961. right.appendChild(img1);
  1962. mxEvent.addListener(img1, 'click', function(evt)
  1963. {
  1964. if (graph.isEnabled())
  1965. {
  1966. graph.addCell(child, graph.model.root, index + 1);
  1967. }
  1968. mxEvent.consume(evt);
  1969. });
  1970. }
  1971. ldiv.appendChild(right);
  1972. }
  1973. if (mxClient.IS_SVG && (!mxClient.IS_IE || document.documentMode >= 10))
  1974. {
  1975. ldiv.setAttribute('draggable', 'true');
  1976. ldiv.style.cursor = 'move';
  1977. }
  1978. }
  1979. mxEvent.addListener(ldiv, 'dblclick', function(evt)
  1980. {
  1981. var nodeName = mxEvent.getSource(evt).nodeName;
  1982. if (nodeName != 'INPUT' && nodeName != 'IMG')
  1983. {
  1984. renameLayer(child);
  1985. mxEvent.consume(evt);
  1986. }
  1987. });
  1988. if (graph.getDefaultParent() == child)
  1989. {
  1990. ldiv.style.background = '#e6eff8';
  1991. ldiv.style.fontWeight = 'bold';
  1992. selectionLayer = child;
  1993. }
  1994. else
  1995. {
  1996. mxEvent.addListener(ldiv, 'click', function(evt)
  1997. {
  1998. if (graph.isEnabled())
  1999. {
  2000. graph.setDefaultParent(defaultParent);
  2001. graph.view.setCurrentRoot(null);
  2002. refresh();
  2003. }
  2004. });
  2005. }
  2006. listDiv.appendChild(ldiv);
  2007. };
  2008. // Cannot be moved or deleted
  2009. for (var i = layerCount - 1; i >= 0; i--)
  2010. {
  2011. (mxUtils.bind(this, function(child)
  2012. {
  2013. addLayer(i, child.value || mxResources.get('background'), child, child);
  2014. }))(graph.model.getChildAt(graph.model.root, i));
  2015. }
  2016. removeLink.setAttribute('title', mxResources.get('removeIt', [selectionLayer.value || mxResources.get('background')]));
  2017. insertLink.setAttribute('title', mxResources.get('moveSelectionTo', [selectionLayer.value || mxResources.get('background')]));
  2018. duplicateLink.setAttribute('title', mxResources.get('duplicateIt', [selectionLayer.value || mxResources.get('background')]));
  2019. renameLink.setAttribute('title', mxResources.get('renameIt', [selectionLayer.value || mxResources.get('background')]));
  2020. if (graph.isSelectionEmpty())
  2021. {
  2022. insertLink.className = 'geButton mxDisabled';
  2023. }
  2024. };
  2025. refresh();
  2026. graph.model.addListener(mxEvent.CHANGE, function()
  2027. {
  2028. refresh();
  2029. });
  2030. graph.selectionModel.addListener(mxEvent.CHANGE, function()
  2031. {
  2032. if (graph.isSelectionEmpty())
  2033. {
  2034. insertLink.className = 'geButton mxDisabled';
  2035. }
  2036. else
  2037. {
  2038. insertLink.className = 'geButton';
  2039. }
  2040. });
  2041. this.window = new mxWindow(mxResources.get('layers'), div, x, y, w, h, true, true);
  2042. this.window.destroyOnClose = false;
  2043. this.window.setMaximizable(false);
  2044. this.window.setResizable(true);
  2045. this.window.setClosable(true);
  2046. this.window.setVisible(true);
  2047. // Make refresh available via instance
  2048. this.refreshLayers = refresh;
  2049. this.window.setLocation = function(x, y)
  2050. {
  2051. var iw = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
  2052. var ih = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
  2053. x = Math.max(0, Math.min(x, iw - this.table.clientWidth));
  2054. y = Math.max(0, Math.min(y, ih - this.table.clientHeight - 48));
  2055. if (this.getX() != x || this.getY() != y)
  2056. {
  2057. mxWindow.prototype.setLocation.apply(this, arguments);
  2058. }
  2059. };
  2060. mxEvent.addListener(window, 'resize', mxUtils.bind(this, function()
  2061. {
  2062. var x = this.window.getX();
  2063. var y = this.window.getY();
  2064. this.window.setLocation(x, y);
  2065. }));
  2066. };