DrawioFile.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. /**
  2. * Copyright (c) 2006-2017, JGraph Ltd
  3. * Copyright (c) 2006-2017, Gaudenz Alder
  4. */
  5. DrawioFile = function(ui, data)
  6. {
  7. mxEventSource.call(this);
  8. /**
  9. * Holds the x-coordinate of the point.
  10. * @type number
  11. * @default 0
  12. */
  13. this.ui = ui;
  14. /**
  15. * Holds the x-coordinate of the point.
  16. * @type number
  17. * @default 0
  18. */
  19. this.data = data || '';
  20. };
  21. //Extends mxEventSource
  22. mxUtils.extend(DrawioFile, mxEventSource);
  23. /**
  24. * Sets the delay for autosave in milliseconds. Default is 1500.
  25. */
  26. DrawioFile.prototype.autosaveDelay = 1500;
  27. /**
  28. * Sets the delay for autosave in milliseconds. Default is 30000.
  29. */
  30. DrawioFile.prototype.maxAutosaveDelay = 30000;
  31. /**
  32. * Sets the delay for autosave in milliseconds. Default is 2000.
  33. */
  34. DrawioFile.prototype.autosaveThread = null;
  35. /**
  36. * Sets the delay for autosave in milliseconds. Default is 500.
  37. */
  38. DrawioFile.prototype.lastAutosave = null;
  39. /**
  40. * Sets the delay for autosave in milliseconds. Default is 1500.
  41. */
  42. DrawioFile.prototype.modified = false;
  43. /**
  44. * Specifies if the graph change listener is enabled. Default is true.
  45. */
  46. DrawioFile.prototype.changeListenerEnabled = true;
  47. /**
  48. * Sets the delay for autosave in milliseconds. Default is 1500.
  49. */
  50. DrawioFile.prototype.lastAutosaveRevision = null;
  51. /**
  52. * Sets the delay for autosave in milliseconds. Default is 1000.
  53. */
  54. DrawioFile.prototype.maxAutosaveRevisionDelay = 1800000;
  55. /**
  56. * Translates this point by the given vector.
  57. *
  58. * @param {number} dx X-coordinate of the translation.
  59. * @param {number} dy Y-coordinate of the translation.
  60. */
  61. DrawioFile.prototype.descriptorChanged = function()
  62. {
  63. this.fireEvent(new mxEventObject('descriptorChanged'));
  64. };
  65. /**
  66. * Translates this point by the given vector.
  67. *
  68. * @param {number} dx X-coordinate of the translation.
  69. * @param {number} dy Y-coordinate of the translation.
  70. */
  71. DrawioFile.prototype.contentChanged = function()
  72. {
  73. this.fireEvent(new mxEventObject('contentChanged'));
  74. };
  75. /**
  76. * Adds the listener for automatically saving the diagram for local changes.
  77. */
  78. DrawioFile.prototype.save = function(revision, success, error, unloading)
  79. {
  80. this.updateFileData();
  81. this.clearAutosave();
  82. };
  83. /**
  84. * Translates this point by the given vector.
  85. *
  86. * @param {number} dx X-coordinate of the translation.
  87. * @param {number} dy Y-coordinate of the translation.
  88. */
  89. DrawioFile.prototype.updateFileData = function()
  90. {
  91. this.setData(this.ui.getFileData());
  92. };
  93. /**
  94. * Translates this point by the given vector.
  95. *
  96. * @param {number} dx X-coordinate of the translation.
  97. * @param {number} dy Y-coordinate of the translation.
  98. */
  99. DrawioFile.prototype.saveAs = function(filename, success, error) { };
  100. /**
  101. * Translates this point by the given vector.
  102. *
  103. * @param {number} dx X-coordinate of the translation.
  104. * @param {number} dy Y-coordinate of the translation.
  105. */
  106. DrawioFile.prototype.saveFile = function(title, revision, success, error) { };
  107. /**
  108. * Returns true if copy, export and print are not allowed for this file.
  109. */
  110. DrawioFile.prototype.getPublicUrl = function(fn)
  111. {
  112. fn(null);
  113. };
  114. /**
  115. * Returns true if copy, export and print are not allowed for this file.
  116. */
  117. DrawioFile.prototype.isRestricted = function()
  118. {
  119. return false;
  120. };
  121. /**
  122. * Translates this point by the given vector.
  123. *
  124. * @param {number} dx X-coordinate of the translation.
  125. * @param {number} dy Y-coordinate of the translation.
  126. */
  127. DrawioFile.prototype.isModified = function()
  128. {
  129. return this.modified;
  130. };
  131. /**
  132. * Translates this point by the given vector.
  133. *
  134. * @param {number} dx X-coordinate of the translation.
  135. * @param {number} dy Y-coordinate of the translation.
  136. */
  137. DrawioFile.prototype.setModified = function(value)
  138. {
  139. this.modified = value;
  140. };
  141. /**
  142. * Specifies if the autosave checkbox should be shown in the document
  143. * properties dialog. Default is false.
  144. */
  145. DrawioFile.prototype.isAutosaveOptional = function()
  146. {
  147. return false;
  148. };
  149. /**
  150. * Translates this point by the given vector.
  151. *
  152. * @param {number} dx X-coordinate of the translation.
  153. * @param {number} dy Y-coordinate of the translation.
  154. */
  155. DrawioFile.prototype.isAutosave = function()
  156. {
  157. return this.ui.editor.autosave;
  158. };
  159. /**
  160. * Translates this point by the given vector.
  161. *
  162. * @param {number} dx X-coordinate of the translation.
  163. * @param {number} dy Y-coordinate of the translation.
  164. */
  165. DrawioFile.prototype.isRenamable = function()
  166. {
  167. return false;
  168. };
  169. /**
  170. * Translates this point by the given vector.
  171. *
  172. * @param {number} dx X-coordinate of the translation.
  173. * @param {number} dy Y-coordinate of the translation.
  174. */
  175. DrawioFile.prototype.rename = function(title, success, error) { };
  176. /**
  177. * Translates this point by the given vector.
  178. *
  179. * @param {number} dx X-coordinate of the translation.
  180. * @param {number} dy Y-coordinate of the translation.
  181. */
  182. DrawioFile.prototype.isMovable = function()
  183. {
  184. return false;
  185. };
  186. /**
  187. * Translates this point by the given vector.
  188. *
  189. * @param {number} dx X-coordinate of the translation.
  190. * @param {number} dy Y-coordinate of the translation.
  191. */
  192. DrawioFile.prototype.move = function(folderId, success, error) { };
  193. /**
  194. * Translates this point by the given vector.
  195. *
  196. * @param {number} dx X-coordinate of the translation.
  197. * @param {number} dy Y-coordinate of the translation.
  198. */
  199. DrawioFile.prototype.getHash = function()
  200. {
  201. return '';
  202. };
  203. /**
  204. * Translates this point by the given vector.
  205. *
  206. * @param {number} dx X-coordinate of the translation.
  207. * @param {number} dy Y-coordinate of the translation.
  208. */
  209. DrawioFile.prototype.getId = function()
  210. {
  211. return '';
  212. };
  213. /**
  214. * Translates this point by the given vector.
  215. *
  216. * @param {number} dx X-coordinate of the translation.
  217. * @param {number} dy Y-coordinate of the translation.
  218. */
  219. DrawioFile.prototype.isEditable = function()
  220. {
  221. return !this.ui.editor.chromeless;
  222. };
  223. /**
  224. * Returns the location as a new object.
  225. * @type mx.Point
  226. */
  227. DrawioFile.prototype.getUi = function()
  228. {
  229. return this.ui;
  230. };
  231. /**
  232. * Translates this point by the given vector.
  233. *
  234. * @param {number} dx X-coordinate of the translation.
  235. * @param {number} dy Y-coordinate of the translation.
  236. */
  237. DrawioFile.prototype.getTitle = function()
  238. {
  239. return '';
  240. };
  241. /**
  242. * Sets the location of this point.
  243. *
  244. * @param {number} x New X-coordinate of the point.
  245. * @param {number} y New Y-coordinate of the point.
  246. */
  247. DrawioFile.prototype.setData = function(data)
  248. {
  249. this.data = data;
  250. };
  251. /**
  252. * Returns the location as a new object.
  253. * @type mx.Point
  254. */
  255. DrawioFile.prototype.getData = function()
  256. {
  257. return this.data;
  258. };
  259. /**
  260. * Returns the location as a new object.
  261. * @type mx.Point
  262. */
  263. DrawioFile.prototype.open = function()
  264. {
  265. this.ui.setFileData(this.getData());
  266. this.changeListener = mxUtils.bind(this, function(sender, eventObject)
  267. {
  268. var edit = (eventObject != null) ? eventObject.getProperty('edit') : null;
  269. if (this.changeListenerEnabled && this.isEditable() &&
  270. (edit == null || !edit.ignoreEdit))
  271. {
  272. this.setModified(true);
  273. if (this.isAutosave())
  274. {
  275. this.ui.editor.setStatus(mxUtils.htmlEntities(mxResources.get('saving')) + '...');
  276. this.autosave(this.autosaveDelay, this.maxAutosaveDelay, mxUtils.bind(this, function(resp)
  277. {
  278. // Does not update status if another autosave was scheduled
  279. if (this.autosaveThread == null && this.ui.getCurrentFile() == this && !this.isModified())
  280. {
  281. this.ui.editor.setStatus(mxUtils.htmlEntities(mxResources.get('allChangesSaved')));
  282. }
  283. }), mxUtils.bind(this, function(resp)
  284. {
  285. if (this.ui.getCurrentFile() == this)
  286. {
  287. this.addUnsavedStatus(resp);
  288. }
  289. }));
  290. }
  291. else
  292. {
  293. this.addUnsavedStatus();
  294. }
  295. }
  296. });
  297. this.ui.editor.graph.model.addListener(mxEvent.CHANGE, this.changeListener);
  298. // Some options trigger autosave
  299. this.ui.editor.graph.addListener('gridSizeChanged', this.changeListener);
  300. this.ui.editor.graph.addListener('shadowVisibleChanged', this.changeListener);
  301. this.ui.addListener('pageFormatChanged', this.changeListener);
  302. this.ui.addListener('pageScaleChanged', this.changeListener);
  303. this.ui.addListener('backgroundColorChanged', this.changeListener);
  304. this.ui.addListener('backgroundImageChanged', this.changeListener);
  305. this.ui.addListener('foldingEnabledChanged', this.changeListener);
  306. this.ui.addListener('mathEnabledChanged', this.changeListener);
  307. this.ui.addListener('gridEnabledChanged', this.changeListener);
  308. this.ui.addListener('guidesEnabledChanged', this.changeListener);
  309. this.ui.addListener('pageViewChanged', this.changeListener);
  310. };
  311. /**
  312. * Adds the listener for automatically saving the diagram for local changes.
  313. */
  314. DrawioFile.prototype.addUnsavedStatus = function(err)
  315. {
  316. if (err instanceof Error && err.message != null)
  317. {
  318. this.ui.editor.setStatus('<div class="geStatusAlert" style="cursor:pointer;overflow:hidden;">' +
  319. mxUtils.htmlEntities(mxResources.get('unsavedChanges')) +
  320. ' (' + mxUtils.htmlEntities(err.message) + ')</div>');
  321. }
  322. else
  323. {
  324. // FIXME: Handle multiple tabs
  325. // if (this.ui.mode == null && urlParams['splash'] == '0')
  326. // {
  327. // try
  328. // {
  329. // this.ui.updateDraft();
  330. // this.setModified(false);
  331. // }
  332. // catch (e)
  333. // {
  334. // // Keeps modified flag unchanged
  335. // }
  336. // }
  337. this.ui.editor.setStatus('<div class="geStatusAlert" style="cursor:pointer;overflow:hidden;">' +
  338. mxUtils.htmlEntities(mxResources.get('unsavedChangesClickHereToSave')) + '</div>');
  339. // Installs click handler for saving
  340. if (this.ui.statusContainer != null)
  341. {
  342. var links = this.ui.statusContainer.getElementsByTagName('div');
  343. if (links.length > 0)
  344. {
  345. mxEvent.addListener(links[0], 'click', mxUtils.bind(this, function()
  346. {
  347. this.ui.actions.get((this.ui.mode == null) ? 'saveAs' : 'save').funct();
  348. }));
  349. }
  350. }
  351. }
  352. };
  353. /**
  354. * Adds the listener for automatically saving the diagram for local changes.
  355. */
  356. DrawioFile.prototype.autosave = function(delay, maxDelay, success, error)
  357. {
  358. if (this.lastAutosave == null)
  359. {
  360. this.lastAutosave = new Date().getTime();
  361. }
  362. var tmp = (new Date().getTime() - this.lastAutosave < maxDelay) ? delay : 0;
  363. this.clearAutosave();
  364. // Starts new timer or executes immediately if not unsaved for maxDelay
  365. this.autosaveThread = window.setTimeout(mxUtils.bind(this, function()
  366. {
  367. this.autosaveThread = null;
  368. this.lastAutosave = null;
  369. // Workaround for duplicate save if UI is blocking
  370. // after save while pending autosave triggers
  371. if (this.isModified() && this.isAutosaveNow())
  372. {
  373. var rev = this.isAutosaveRevision();
  374. if (rev)
  375. {
  376. this.lastAutosaveRevision = new Date().getTime();
  377. }
  378. this.save(rev, mxUtils.bind(this, function(resp)
  379. {
  380. this.autosaveCompleted();
  381. if (success != null)
  382. {
  383. success(resp);
  384. }
  385. }), mxUtils.bind(this, function(resp)
  386. {
  387. if (error != null)
  388. {
  389. error(resp);
  390. }
  391. }));
  392. }
  393. else
  394. {
  395. if (success != null)
  396. {
  397. success(null);
  398. }
  399. }
  400. }), tmp);
  401. };
  402. /**
  403. * Returns true if an autosave is required at the time of execution.
  404. * This implementation returns true.
  405. */
  406. DrawioFile.prototype.isAutosaveNow = function()
  407. {
  408. return true;
  409. };
  410. /**
  411. * Hooks for subclassers after the autosave has completed.
  412. */
  413. DrawioFile.prototype.autosaveCompleted = function() { };
  414. /**
  415. * Adds the listener for automatically saving the diagram for local changes.
  416. */
  417. DrawioFile.prototype.clearAutosave = function()
  418. {
  419. if (this.autosaveThread != null)
  420. {
  421. window.clearTimeout(this.autosaveThread);
  422. this.autosaveThread = null;
  423. }
  424. };
  425. /**
  426. * Returns the location as a new object.
  427. * @type mx.Point
  428. */
  429. DrawioFile.prototype.isAutosaveRevision = function()
  430. {
  431. var now = new Date().getTime();
  432. return (this.lastAutosaveRevision == null) || (now - this.lastAutosaveRevision) > this.maxAutosaveRevisionDelay;
  433. };
  434. /**
  435. * Returns the location as a new object.
  436. */
  437. DrawioFile.prototype.close = function(unloading)
  438. {
  439. if (this.isAutosave() && this.isModified())
  440. {
  441. this.save(this.isAutosaveRevision(), null, null, unloading);
  442. }
  443. this.destroy();
  444. };
  445. /**
  446. * Returns the location as a new object.
  447. */
  448. DrawioFile.prototype.hasSameExtension = function(title, newTitle)
  449. {
  450. if (title != null && newTitle != null)
  451. {
  452. var dot = title.lastIndexOf('.');
  453. var ext = (dot > 0) ? title.substring(dot) : '';
  454. dot = newTitle.lastIndexOf('.');
  455. return ext === ((dot > 0) ? newTitle.substring(dot) : '');
  456. }
  457. return title == newTitle;
  458. };
  459. /**
  460. * Stops any pending autosaves and removes all listeners.
  461. */
  462. DrawioFile.prototype.destroy = function()
  463. {
  464. this.clearAutosave();
  465. if (this.changeListener != null)
  466. {
  467. this.ui.editor.graph.model.removeListener(this.changeListener);
  468. this.ui.editor.graph.removeListener(this.changeListener);
  469. this.ui.removeListener(this.changeListener);
  470. this.changeListener = null;
  471. }
  472. };