replay.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /**
  2. * Replay plugin. To record steps in the Editor, click on Extras, Record.
  3. * To stop recording click Extras, Record again. Enter the delay between
  4. * the steps and use the URL that opens in the new window.
  5. */
  6. Draw.loadPlugin(function(ui) {
  7. var graph = ui.editor.graph;
  8. var codec = new mxCodec();
  9. var model = graph.model;
  10. codec.lookup = function(id)
  11. {
  12. return model.getCell(id);
  13. };
  14. if (ui.editor.chromeless)
  15. {
  16. function decodeChanges(delta)
  17. {
  18. var codec2 = new mxCodec(delta.ownerDocument);
  19. codec2.lookup = function(id)
  20. {
  21. return model.getCell(id);
  22. };
  23. var changeNode = delta.firstChild.firstChild;
  24. var changes = [];
  25. while (changeNode != null)
  26. {
  27. var change = codec2.decode(changeNode);
  28. change.model = model;
  29. change.execute();
  30. changes.push(change);
  31. changeNode = changeNode.nextSibling;
  32. }
  33. return changes;
  34. };
  35. function createUndoableEdit(changes)
  36. {
  37. var edit = new mxUndoableEdit(model);
  38. edit.changes = changes;
  39. edit.notify = function()
  40. {
  41. // LATER: Remove changes property (deprecated)
  42. edit.source.fireEvent(new mxEventObject(mxEvent.CHANGE,
  43. 'edit', edit, 'changes', edit.changes));
  44. edit.source.fireEvent(new mxEventObject(mxEvent.NOTIFY,
  45. 'edit', edit, 'changes', edit.changes));
  46. };
  47. return edit;
  48. };
  49. function processDelta(delta)
  50. {
  51. var changes = decodeChanges(delta);
  52. if (changes.length > 0)
  53. {
  54. var edit = createUndoableEdit(changes);
  55. // No notify event here to avoid the edit from being encoded and transmitted
  56. // LATER: Remove changes property (deprecated)
  57. model.fireEvent(new mxEventObject(mxEvent.CHANGE,
  58. 'edit', edit, 'changes', changes));
  59. model.fireEvent(new mxEventObject(mxEvent.UNDO, 'edit', edit));
  60. ui.chromelessResize();
  61. }
  62. };
  63. var replayData = urlParams['replay-data'];
  64. var delay = parseInt(urlParams['delay-delay'] || 1000);
  65. if (replayData != null)
  66. {
  67. var xmlDoc = mxUtils.parseXml(graph.decompress(replayData));
  68. // LATER: Avoid duplicate parsing
  69. ui.fileLoaded(new LocalFile(ui, mxUtils.getXml(xmlDoc.documentElement.firstChild.firstChild)));
  70. // Process deltas
  71. var delta = xmlDoc.documentElement.firstChild.nextSibling;
  72. function nextStep()
  73. {
  74. if (delta != null)
  75. {
  76. window.setTimeout(function()
  77. {
  78. processDelta(delta);
  79. delta = delta.nextSibling;
  80. nextStep();
  81. }, delay);
  82. }
  83. };
  84. nextStep();
  85. }
  86. }
  87. else
  88. {
  89. var tape = null;
  90. model.addListener(mxEvent.CHANGE, function(sender, evt)
  91. {
  92. if (tape != null)
  93. {
  94. var changes = evt.getProperty('changes');
  95. var node = codec.encode(changes);
  96. var delta = codec.document.createElement('delta');
  97. delta.appendChild(node);
  98. tape.push(mxUtils.getXml(delta));
  99. }
  100. });
  101. // Extends View menu
  102. mxResources.parse('record=Record');
  103. // Adds action
  104. var action = ui.actions.addAction('record...', function()
  105. {
  106. if (tape == null)
  107. {
  108. var node = codec.encode(model);
  109. var state = codec.document.createElement('state');
  110. state.appendChild(node);
  111. tape =[mxUtils.getXml(state)];
  112. }
  113. else if (tape != null)
  114. {
  115. var tmp = tape;
  116. tape = null;
  117. var dlg = new FilenameDialog(ui, 1000, mxResources.get('apply'), function(newValue)
  118. {
  119. if (newValue != null)
  120. {
  121. var dlg = new EmbedDialog(ui, 'https://www.draw.io/?p=replay&lightbox=1&replay-delay=' +
  122. parseFloat(newValue) + '&replay-data=' + graph.compress('<recording>' +
  123. tmp.join('') + '</recording>'));
  124. ui.showDialog(dlg.container, 440, 240, true, true);
  125. dlg.init();
  126. }
  127. }, 'Delay');
  128. ui.showDialog(dlg.container, 300, 80, true, true);
  129. dlg.init();
  130. }
  131. });
  132. action.setToggleAction(true);
  133. action.setSelectedCallback(function() { return tape != null; });
  134. var menu = ui.menus.get('extras');
  135. var oldFunct = menu.funct;
  136. menu.funct = function(menu, parent)
  137. {
  138. oldFunct.apply(this, arguments);
  139. ui.menus.addMenuItems(menu, ['-', 'record'], parent);
  140. };
  141. }
  142. });