DrawioFile.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  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(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(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;">' +
  319. mxResources.get('unsavedChanges') + ' (' + err.message + ')</div>');
  320. }
  321. else
  322. {
  323. // FIXME: Handle multiple tabs
  324. // if (this.ui.mode == null && urlParams['splash'] == '0')
  325. // {
  326. // try
  327. // {
  328. // this.ui.updateDraft();
  329. // this.setModified(false);
  330. // }
  331. // catch (e)
  332. // {
  333. // // Keeps modified flag unchanged
  334. // }
  335. // }
  336. this.ui.editor.setStatus('<div class="geStatusMessage" style="cursor:pointer;">' +
  337. mxResources.get('unsavedChangesClickHereToSave') + '</div>');
  338. // Installs click handler for saving
  339. if (this.ui.statusContainer != null)
  340. {
  341. var links = this.ui.statusContainer.getElementsByTagName('div');
  342. if (links.length > 0)
  343. {
  344. mxEvent.addListener(links[0], 'click', mxUtils.bind(this, function()
  345. {
  346. this.ui.actions.get((this.ui.mode == null) ? 'saveAs' : 'save').funct();
  347. }));
  348. }
  349. }
  350. }
  351. };
  352. /**
  353. * Adds the listener for automatically saving the diagram for local changes.
  354. */
  355. DrawioFile.prototype.autosave = function(delay, maxDelay, success, error)
  356. {
  357. if (this.lastAutosave == null)
  358. {
  359. this.lastAutosave = new Date().getTime();
  360. }
  361. var tmp = (new Date().getTime() - this.lastAutosave < maxDelay) ? delay : 0;
  362. this.clearAutosave();
  363. // Starts new timer or executes immediately if not unsaved for maxDelay
  364. this.autosaveThread = window.setTimeout(mxUtils.bind(this, function()
  365. {
  366. this.autosaveThread = null;
  367. this.lastAutosave = null;
  368. // Workaround for duplicate save if UI is blocking
  369. // after save while pending autosave triggers
  370. if (this.isModified() && this.isAutosaveNow())
  371. {
  372. var rev = this.isAutosaveRevision();
  373. if (rev)
  374. {
  375. this.lastAutosaveRevision = new Date().getTime();
  376. }
  377. this.save(rev, mxUtils.bind(this, function(resp)
  378. {
  379. this.autosaveCompleted();
  380. if (success != null)
  381. {
  382. success(resp);
  383. }
  384. }), mxUtils.bind(this, function(resp)
  385. {
  386. if (error != null)
  387. {
  388. error(resp);
  389. }
  390. }));
  391. }
  392. else
  393. {
  394. if (success != null)
  395. {
  396. success(null);
  397. }
  398. }
  399. }), tmp);
  400. };
  401. /**
  402. * Returns true if an autosave is required at the time of execution.
  403. * This implementation returns true.
  404. */
  405. DrawioFile.prototype.isAutosaveNow = function()
  406. {
  407. return true;
  408. };
  409. /**
  410. * Hooks for subclassers after the autosave has completed.
  411. */
  412. DrawioFile.prototype.autosaveCompleted = function() { };
  413. /**
  414. * Adds the listener for automatically saving the diagram for local changes.
  415. */
  416. DrawioFile.prototype.clearAutosave = function()
  417. {
  418. if (this.autosaveThread != null)
  419. {
  420. window.clearTimeout(this.autosaveThread);
  421. this.autosaveThread = null;
  422. }
  423. };
  424. /**
  425. * Returns the location as a new object.
  426. * @type mx.Point
  427. */
  428. DrawioFile.prototype.isAutosaveRevision = function()
  429. {
  430. var now = new Date().getTime();
  431. return (this.lastAutosaveRevision == null) || (now - this.lastAutosaveRevision) > this.maxAutosaveRevisionDelay;
  432. };
  433. /**
  434. * Returns the location as a new object.
  435. */
  436. DrawioFile.prototype.close = function(unloading)
  437. {
  438. if (this.isAutosave() && this.isModified())
  439. {
  440. this.save(this.isAutosaveRevision(), null, null, unloading);
  441. }
  442. this.destroy();
  443. };
  444. /**
  445. * Returns the location as a new object.
  446. */
  447. DrawioFile.prototype.hasSameExtension = function(title, newTitle)
  448. {
  449. if (title != null && newTitle != null)
  450. {
  451. var dot = title.lastIndexOf('.');
  452. var ext = (dot > 0) ? title.substring(dot) : '';
  453. dot = newTitle.lastIndexOf('.');
  454. return ext === ((dot > 0) ? newTitle.substring(dot) : '');
  455. }
  456. return title == newTitle;
  457. };
  458. /**
  459. * Stops any pending autosaves and removes all listeners.
  460. */
  461. DrawioFile.prototype.destroy = function()
  462. {
  463. this.clearAutosave();
  464. if (this.changeListener != null)
  465. {
  466. this.ui.editor.graph.model.removeListener(this.changeListener);
  467. this.ui.editor.graph.removeListener(this.changeListener);
  468. this.ui.removeListener(this.changeListener);
  469. this.changeListener = null;
  470. }
  471. };