history.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /**
  2. * @fileOverview
  3. *
  4. * 历史管理
  5. *
  6. * @author: techird
  7. * @copyright: Baidu FEX, 2014
  8. */
  9. define(function(require, exports, module) {
  10. var jsonDiff = require('../tool/jsondiff');
  11. function HistoryRuntime() {
  12. var minder = this.minder;
  13. var hotbox = this.hotbox;
  14. var MAX_HISTORY = 100;
  15. var lastSnap;
  16. var patchLock;
  17. var undoDiffs;
  18. var redoDiffs;
  19. function reset() {
  20. undoDiffs = [];
  21. redoDiffs = [];
  22. lastSnap = minder.exportJson();
  23. }
  24. function makeUndoDiff() {
  25. var headSnap = minder.exportJson();
  26. var diff = jsonDiff(headSnap, lastSnap);
  27. if (diff.length) {
  28. undoDiffs.push(diff);
  29. while (undoDiffs.length > MAX_HISTORY) {
  30. undoDiffs.shift();
  31. }
  32. lastSnap = headSnap;
  33. return true;
  34. }
  35. }
  36. function makeRedoDiff() {
  37. var revertSnap = minder.exportJson();
  38. redoDiffs.push(jsonDiff(revertSnap, lastSnap));
  39. lastSnap = revertSnap;
  40. }
  41. function undo() {
  42. patchLock = true;
  43. var undoDiff = undoDiffs.pop();
  44. if (undoDiff) {
  45. minder.applyPatches(undoDiff);
  46. makeRedoDiff();
  47. }
  48. patchLock = false;
  49. }
  50. function redo() {
  51. patchLock = true;
  52. var redoDiff = redoDiffs.pop();
  53. if (redoDiff) {
  54. minder.applyPatches(redoDiff);
  55. makeUndoDiff();
  56. }
  57. patchLock = false;
  58. }
  59. function changed() {
  60. if (patchLock) return;
  61. if (makeUndoDiff()) redoDiffs = [];
  62. }
  63. function hasUndo() {
  64. return !!undoDiffs.length;
  65. }
  66. function hasRedo() {
  67. return !!redoDiffs.length;
  68. }
  69. function updateSelection(e) {
  70. if (!patchLock) return;
  71. var patch = e.patch;
  72. switch (patch.express) {
  73. case 'node.add':
  74. minder.select(patch.node.getChild(patch.index), true);
  75. break;
  76. case 'node.remove':
  77. case 'data.replace':
  78. case 'data.remove':
  79. case 'data.add':
  80. minder.select(patch.node, true);
  81. break;
  82. }
  83. }
  84. this.history = {
  85. reset: reset,
  86. undo: undo,
  87. redo: redo,
  88. hasUndo: hasUndo,
  89. hasRedo: hasRedo
  90. };
  91. reset();
  92. minder.on('contentchange', changed);
  93. minder.on('import', reset);
  94. minder.on('patch', updateSelection);
  95. var main = hotbox.state('main');
  96. main.button({
  97. position: 'top',
  98. label: '撤销',
  99. key: 'Ctrl + Z',
  100. enable: hasUndo,
  101. action: undo,
  102. next: 'idle'
  103. });
  104. main.button({
  105. position: 'top',
  106. label: '重做',
  107. key: 'Ctrl + Y',
  108. enable: hasRedo,
  109. action: redo,
  110. next: 'idle'
  111. });
  112. }
  113. window.diff = jsonDiff;
  114. return module.exports = HistoryRuntime;
  115. });