undoRedo.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. 'use strict';
  2. var _pluginHooks = require('./../../pluginHooks');
  3. var _pluginHooks2 = _interopRequireDefault(_pluginHooks);
  4. var _array = require('./../../helpers/array');
  5. var _number = require('./../../helpers/number');
  6. var _object = require('./../../helpers/object');
  7. var _event = require('./../../helpers/dom/event');
  8. var _src = require('./../../3rdparty/walkontable/src');
  9. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  10. /**
  11. * @description
  12. * Handsontable UndoRedo plugin. It allows to undo and redo certain actions done in the table.
  13. * Please note, that not all actions are currently undo-able.
  14. *
  15. * @example
  16. * ```js
  17. * ...
  18. * undo: true
  19. * ...
  20. * ```
  21. * @class UndoRedo
  22. * @plugin UndoRedo
  23. */
  24. /**
  25. * Handsontable UndoRedo class
  26. */
  27. function UndoRedo(instance) {
  28. var plugin = this;
  29. this.instance = instance;
  30. this.doneActions = [];
  31. this.undoneActions = [];
  32. this.ignoreNewActions = false;
  33. instance.addHook('afterChange', function (changes, source) {
  34. if (changes && source !== 'UndoRedo.undo' && source !== 'UndoRedo.redo') {
  35. plugin.done(new UndoRedo.ChangeAction(changes));
  36. }
  37. });
  38. instance.addHook('afterCreateRow', function (index, amount, source) {
  39. if (source === 'UndoRedo.undo' || source === 'UndoRedo.undo' || source === 'auto') {
  40. return;
  41. }
  42. var action = new UndoRedo.CreateRowAction(index, amount);
  43. plugin.done(action);
  44. });
  45. instance.addHook('beforeRemoveRow', function (index, amount, logicRows, source) {
  46. if (source === 'UndoRedo.undo' || source === 'UndoRedo.redo' || source === 'auto') {
  47. return;
  48. }
  49. var originalData = plugin.instance.getSourceDataArray();
  50. index = (originalData.length + index) % originalData.length;
  51. var removedData = (0, _object.deepClone)(originalData.slice(index, index + amount));
  52. plugin.done(new UndoRedo.RemoveRowAction(index, removedData));
  53. });
  54. instance.addHook('afterCreateCol', function (index, amount, source) {
  55. if (source === 'UndoRedo.undo' || source === 'UndoRedo.redo' || source === 'auto') {
  56. return;
  57. }
  58. plugin.done(new UndoRedo.CreateColumnAction(index, amount));
  59. });
  60. instance.addHook('beforeRemoveCol', function (index, amount, logicColumns, source) {
  61. if (source === 'UndoRedo.undo' || source === 'UndoRedo.redo' || source === 'auto') {
  62. return;
  63. }
  64. var originalData = plugin.instance.getSourceDataArray();
  65. index = (plugin.instance.countCols() + index) % plugin.instance.countCols();
  66. var removedData = [];
  67. var headers = [];
  68. var indexes = [];
  69. (0, _number.rangeEach)(originalData.length - 1, function (i) {
  70. var column = [];
  71. var origRow = originalData[i];
  72. (0, _number.rangeEach)(index, index + (amount - 1), function (j) {
  73. column.push(origRow[instance.runHooks('modifyCol', j)]);
  74. });
  75. removedData.push(column);
  76. });
  77. (0, _number.rangeEach)(amount - 1, function (i) {
  78. indexes.push(instance.runHooks('modifyCol', index + i));
  79. });
  80. if (Array.isArray(instance.getSettings().colHeaders)) {
  81. (0, _number.rangeEach)(amount - 1, function (i) {
  82. headers.push(instance.getSettings().colHeaders[instance.runHooks('modifyCol', index + i)] || null);
  83. });
  84. }
  85. var manualColumnMovePlugin = plugin.instance.getPlugin('manualColumnMove');
  86. var columnsMap = manualColumnMovePlugin.isEnabled() ? manualColumnMovePlugin.columnsMapper.__arrayMap : [];
  87. var action = new UndoRedo.RemoveColumnAction(index, indexes, removedData, headers, columnsMap);
  88. plugin.done(action);
  89. });
  90. instance.addHook('beforeCellAlignment', function (stateBefore, range, type, alignment) {
  91. var action = new UndoRedo.CellAlignmentAction(stateBefore, range, type, alignment);
  92. plugin.done(action);
  93. });
  94. instance.addHook('beforeFilter', function (formulaStacks) {
  95. plugin.done(new UndoRedo.FiltersAction(formulaStacks));
  96. });
  97. instance.addHook('beforeRowMove', function (movedRows, target) {
  98. if (movedRows === false) {
  99. return;
  100. }
  101. plugin.done(new UndoRedo.RowMoveAction(movedRows, target));
  102. });
  103. };
  104. UndoRedo.prototype.done = function (action) {
  105. if (!this.ignoreNewActions) {
  106. this.doneActions.push(action);
  107. this.undoneActions.length = 0;
  108. }
  109. };
  110. /**
  111. * Undo last edit.
  112. *
  113. * @function undo
  114. * @memberof UndoRedo#
  115. */
  116. UndoRedo.prototype.undo = function () {
  117. if (this.isUndoAvailable()) {
  118. var action = this.doneActions.pop();
  119. var actionClone = (0, _object.deepClone)(action);
  120. var instance = this.instance;
  121. var continueAction = instance.runHooks('beforeUndo', actionClone);
  122. if (continueAction === false) {
  123. return;
  124. }
  125. this.ignoreNewActions = true;
  126. var that = this;
  127. action.undo(this.instance, function () {
  128. that.ignoreNewActions = false;
  129. that.undoneActions.push(action);
  130. });
  131. instance.runHooks('afterUndo', actionClone);
  132. }
  133. };
  134. /**
  135. * Redo edit (used to reverse an undo).
  136. *
  137. * @function redo
  138. * @memberof UndoRedo#
  139. */
  140. UndoRedo.prototype.redo = function () {
  141. if (this.isRedoAvailable()) {
  142. var action = this.undoneActions.pop();
  143. var actionClone = (0, _object.deepClone)(action);
  144. var instance = this.instance;
  145. var continueAction = instance.runHooks('beforeRedo', actionClone);
  146. if (continueAction === false) {
  147. return;
  148. }
  149. this.ignoreNewActions = true;
  150. var that = this;
  151. action.redo(this.instance, function () {
  152. that.ignoreNewActions = false;
  153. that.doneActions.push(action);
  154. });
  155. instance.runHooks('afterRedo', actionClone);
  156. }
  157. };
  158. /**
  159. * Check if undo action is available.
  160. *
  161. * @function isUndoAvailable
  162. * @memberof UndoRedo#
  163. * @return {Boolean} Return `true` if undo can be performed, `false` otherwise
  164. */
  165. UndoRedo.prototype.isUndoAvailable = function () {
  166. return this.doneActions.length > 0;
  167. };
  168. /**
  169. * Check if redo action is available.
  170. *
  171. * @function isRedoAvailable
  172. * @memberof UndoRedo#
  173. * @return {Boolean} Return `true` if redo can be performed, `false` otherwise.
  174. */
  175. UndoRedo.prototype.isRedoAvailable = function () {
  176. return this.undoneActions.length > 0;
  177. };
  178. /**
  179. * Clears undo history.
  180. *
  181. * @function clear
  182. * @memberof UndoRedo#
  183. */
  184. UndoRedo.prototype.clear = function () {
  185. this.doneActions.length = 0;
  186. this.undoneActions.length = 0;
  187. };
  188. UndoRedo.Action = function () {};
  189. UndoRedo.Action.prototype.undo = function () {};
  190. UndoRedo.Action.prototype.redo = function () {};
  191. /**
  192. * Change action.
  193. */
  194. UndoRedo.ChangeAction = function (changes) {
  195. this.changes = changes;
  196. this.actionType = 'change';
  197. };
  198. (0, _object.inherit)(UndoRedo.ChangeAction, UndoRedo.Action);
  199. UndoRedo.ChangeAction.prototype.undo = function (instance, undoneCallback) {
  200. var data = (0, _object.deepClone)(this.changes),
  201. emptyRowsAtTheEnd = instance.countEmptyRows(true),
  202. emptyColsAtTheEnd = instance.countEmptyCols(true);
  203. for (var i = 0, len = data.length; i < len; i++) {
  204. data[i].splice(3, 1);
  205. }
  206. instance.addHookOnce('afterChange', undoneCallback);
  207. instance.setDataAtRowProp(data, null, null, 'UndoRedo.undo');
  208. for (var _i = 0, _len = data.length; _i < _len; _i++) {
  209. if (instance.getSettings().minSpareRows && data[_i][0] + 1 + instance.getSettings().minSpareRows === instance.countRows() && emptyRowsAtTheEnd == instance.getSettings().minSpareRows) {
  210. instance.alter('remove_row', parseInt(data[_i][0] + 1, 10), instance.getSettings().minSpareRows);
  211. instance.undoRedo.doneActions.pop();
  212. }
  213. if (instance.getSettings().minSpareCols && data[_i][1] + 1 + instance.getSettings().minSpareCols === instance.countCols() && emptyColsAtTheEnd == instance.getSettings().minSpareCols) {
  214. instance.alter('remove_col', parseInt(data[_i][1] + 1, 10), instance.getSettings().minSpareCols);
  215. instance.undoRedo.doneActions.pop();
  216. }
  217. }
  218. };
  219. UndoRedo.ChangeAction.prototype.redo = function (instance, onFinishCallback) {
  220. var data = (0, _object.deepClone)(this.changes);
  221. for (var i = 0, len = data.length; i < len; i++) {
  222. data[i].splice(2, 1);
  223. }
  224. instance.addHookOnce('afterChange', onFinishCallback);
  225. instance.setDataAtRowProp(data, null, null, 'UndoRedo.redo');
  226. };
  227. /**
  228. * Create row action.
  229. */
  230. UndoRedo.CreateRowAction = function (index, amount) {
  231. this.index = index;
  232. this.amount = amount;
  233. this.actionType = 'insert_row';
  234. };
  235. (0, _object.inherit)(UndoRedo.CreateRowAction, UndoRedo.Action);
  236. UndoRedo.CreateRowAction.prototype.undo = function (instance, undoneCallback) {
  237. var rowCount = instance.countRows(),
  238. minSpareRows = instance.getSettings().minSpareRows;
  239. if (this.index >= rowCount && this.index - minSpareRows < rowCount) {
  240. this.index -= minSpareRows; // work around the situation where the needed row was removed due to an 'undo' of a made change
  241. }
  242. instance.addHookOnce('afterRemoveRow', undoneCallback);
  243. instance.alter('remove_row', this.index, this.amount, 'UndoRedo.undo');
  244. };
  245. UndoRedo.CreateRowAction.prototype.redo = function (instance, redoneCallback) {
  246. instance.addHookOnce('afterCreateRow', redoneCallback);
  247. instance.alter('insert_row', this.index, this.amount, 'UndoRedo.redo');
  248. };
  249. /**
  250. * Remove row action.
  251. */
  252. UndoRedo.RemoveRowAction = function (index, data) {
  253. this.index = index;
  254. this.data = data;
  255. this.actionType = 'remove_row';
  256. };
  257. (0, _object.inherit)(UndoRedo.RemoveRowAction, UndoRedo.Action);
  258. UndoRedo.RemoveRowAction.prototype.undo = function (instance, undoneCallback) {
  259. instance.alter('insert_row', this.index, this.data.length, 'UndoRedo.undo');
  260. instance.addHookOnce('afterRender', undoneCallback);
  261. instance.populateFromArray(this.index, 0, this.data, void 0, void 0, 'UndoRedo.undo');
  262. };
  263. UndoRedo.RemoveRowAction.prototype.redo = function (instance, redoneCallback) {
  264. instance.addHookOnce('afterRemoveRow', redoneCallback);
  265. instance.alter('remove_row', this.index, this.data.length, 'UndoRedo.redo');
  266. };
  267. /**
  268. * Create column action.
  269. */
  270. UndoRedo.CreateColumnAction = function (index, amount) {
  271. this.index = index;
  272. this.amount = amount;
  273. this.actionType = 'insert_col';
  274. };
  275. (0, _object.inherit)(UndoRedo.CreateColumnAction, UndoRedo.Action);
  276. UndoRedo.CreateColumnAction.prototype.undo = function (instance, undoneCallback) {
  277. instance.addHookOnce('afterRemoveCol', undoneCallback);
  278. instance.alter('remove_col', this.index, this.amount, 'UndoRedo.undo');
  279. };
  280. UndoRedo.CreateColumnAction.prototype.redo = function (instance, redoneCallback) {
  281. instance.addHookOnce('afterCreateCol', redoneCallback);
  282. instance.alter('insert_col', this.index, this.amount, 'UndoRedo.redo');
  283. };
  284. /**
  285. * Remove column action.
  286. */
  287. UndoRedo.RemoveColumnAction = function (index, indexes, data, headers, columnPositions) {
  288. this.index = index;
  289. this.indexes = indexes;
  290. this.data = data;
  291. this.amount = this.data[0].length;
  292. this.headers = headers;
  293. this.columnPositions = columnPositions.slice(0);
  294. this.actionType = 'remove_col';
  295. };
  296. (0, _object.inherit)(UndoRedo.RemoveColumnAction, UndoRedo.Action);
  297. UndoRedo.RemoveColumnAction.prototype.undo = function (instance, undoneCallback) {
  298. var _this = this;
  299. var row = void 0;
  300. var ascendingIndexes = this.indexes.slice(0).sort();
  301. var sortByIndexes = function sortByIndexes(elem, j, arr) {
  302. return arr[_this.indexes.indexOf(ascendingIndexes[j])];
  303. };
  304. var sortedData = [];
  305. (0, _number.rangeEach)(this.data.length - 1, function (i) {
  306. sortedData[i] = (0, _array.arrayMap)(_this.data[i], sortByIndexes);
  307. });
  308. var sortedHeaders = [];
  309. sortedHeaders = (0, _array.arrayMap)(this.headers, sortByIndexes);
  310. var changes = [];
  311. // TODO: Temporary hook for undo/redo mess
  312. instance.runHooks('beforeCreateCol', this.indexes[0], this.indexes[this.indexes.length - 1], 'UndoRedo.undo');
  313. (0, _number.rangeEach)(this.data.length - 1, function (i) {
  314. row = instance.getSourceDataAtRow(i);
  315. (0, _number.rangeEach)(ascendingIndexes.length - 1, function (j) {
  316. row.splice(ascendingIndexes[j], 0, sortedData[i][j]);
  317. changes.push([i, ascendingIndexes[j], null, sortedData[i][j]]);
  318. });
  319. });
  320. // TODO: Temporary hook for undo/redo mess
  321. if (instance.getPlugin('formulas')) {
  322. instance.getPlugin('formulas').onAfterSetDataAtCell(changes);
  323. }
  324. if (typeof this.headers !== 'undefined') {
  325. (0, _number.rangeEach)(sortedHeaders.length - 1, function (j) {
  326. instance.getSettings().colHeaders.splice(ascendingIndexes[j], 0, sortedHeaders[j]);
  327. });
  328. }
  329. if (instance.getPlugin('manualColumnMove')) {
  330. instance.getPlugin('manualColumnMove').columnsMapper.__arrayMap = this.columnPositions;
  331. }
  332. instance.addHookOnce('afterRender', undoneCallback);
  333. // TODO: Temporary hook for undo/redo mess
  334. instance.runHooks('afterCreateCol', this.indexes[0], this.indexes[this.indexes.length - 1], 'UndoRedo.undo');
  335. if (instance.getPlugin('formulas')) {
  336. instance.getPlugin('formulas').recalculateFull();
  337. }
  338. instance.render();
  339. };
  340. UndoRedo.RemoveColumnAction.prototype.redo = function (instance, redoneCallback) {
  341. instance.addHookOnce('afterRemoveCol', redoneCallback);
  342. instance.alter('remove_col', this.index, this.amount, 'UndoRedo.redo');
  343. };
  344. /**
  345. * Cell alignment action.
  346. */
  347. UndoRedo.CellAlignmentAction = function (stateBefore, range, type, alignment) {
  348. this.stateBefore = stateBefore;
  349. this.range = range;
  350. this.type = type;
  351. this.alignment = alignment;
  352. };
  353. UndoRedo.CellAlignmentAction.prototype.undo = function (instance, undoneCallback) {
  354. if (!instance.getPlugin('contextMenu').isEnabled()) {
  355. return;
  356. }
  357. for (var row = this.range.from.row; row <= this.range.to.row; row++) {
  358. for (var col = this.range.from.col; col <= this.range.to.col; col++) {
  359. instance.setCellMeta(row, col, 'className', this.stateBefore[row][col] || ' htLeft');
  360. }
  361. }
  362. instance.addHookOnce('afterRender', undoneCallback);
  363. instance.render();
  364. };
  365. UndoRedo.CellAlignmentAction.prototype.redo = function (instance, undoneCallback) {
  366. if (!instance.getPlugin('contextMenu').isEnabled()) {
  367. return;
  368. }
  369. instance.selectCell(this.range.from.row, this.range.from.col, this.range.to.row, this.range.to.col);
  370. instance.getPlugin('contextMenu').executeCommand('alignment:' + this.alignment.replace('ht', '').toLowerCase());
  371. instance.addHookOnce('afterRender', undoneCallback);
  372. instance.render();
  373. };
  374. /**
  375. * Filters action.
  376. */
  377. UndoRedo.FiltersAction = function (formulaStacks) {
  378. this.formulaStacks = formulaStacks;
  379. this.actionType = 'filter';
  380. };
  381. (0, _object.inherit)(UndoRedo.FiltersAction, UndoRedo.Action);
  382. UndoRedo.FiltersAction.prototype.undo = function (instance, undoneCallback) {
  383. var filters = instance.getPlugin('filters');
  384. instance.addHookOnce('afterRender', undoneCallback);
  385. filters.formulaCollection.importAllFormulas(this.formulaStacks.slice(0, this.formulaStacks.length - 1));
  386. filters.filter();
  387. };
  388. UndoRedo.FiltersAction.prototype.redo = function (instance, redoneCallback) {
  389. var filters = instance.getPlugin('filters');
  390. instance.addHookOnce('afterRender', redoneCallback);
  391. filters.formulaCollection.importAllFormulas(this.formulaStacks);
  392. filters.filter();
  393. };
  394. /**
  395. * ManualRowMove action.
  396. * @TODO: removeRow undo should works on logical index
  397. */
  398. UndoRedo.RowMoveAction = function (movedRows, target) {
  399. this.rows = movedRows.slice();
  400. this.target = target;
  401. };
  402. (0, _object.inherit)(UndoRedo.RowMoveAction, UndoRedo.Action);
  403. UndoRedo.RowMoveAction.prototype.undo = function (instance, undoneCallback) {
  404. var manualRowMove = instance.getPlugin('manualRowMove');
  405. instance.addHookOnce('afterRender', undoneCallback);
  406. var mod = this.rows[0] < this.target ? -1 * this.rows.length : 0;
  407. var newTarget = this.rows[0] > this.target ? this.rows[0] + this.rows.length : this.rows[0];
  408. var newRows = [];
  409. var rowsLen = this.rows.length + mod;
  410. for (var i = mod; i < rowsLen; i++) {
  411. newRows.push(this.target + i);
  412. }
  413. manualRowMove.moveRows(newRows.slice(), newTarget);
  414. instance.render();
  415. instance.selection.setRangeStartOnly(new _src.CellCoords(this.rows[0], 0));
  416. instance.selection.setRangeEnd(new _src.CellCoords(this.rows[this.rows.length - 1], instance.countCols() - 1));
  417. };
  418. UndoRedo.RowMoveAction.prototype.redo = function (instance, redoneCallback) {
  419. var manualRowMove = instance.getPlugin('manualRowMove');
  420. instance.addHookOnce('afterRender', redoneCallback);
  421. manualRowMove.moveRows(this.rows.slice(), this.target);
  422. instance.render();
  423. var startSelection = this.rows[0] < this.target ? this.target - this.rows.length : this.target;
  424. instance.selection.setRangeStartOnly(new _src.CellCoords(startSelection, 0));
  425. instance.selection.setRangeEnd(new _src.CellCoords(startSelection + this.rows.length - 1, instance.countCols() - 1));
  426. };
  427. function init() {
  428. var instance = this;
  429. var pluginEnabled = typeof instance.getSettings().undo == 'undefined' || instance.getSettings().undo;
  430. if (pluginEnabled) {
  431. if (!instance.undoRedo) {
  432. /**
  433. * Instance of Handsontable.UndoRedo Plugin {@link Handsontable.UndoRedo}
  434. *
  435. * @alias undoRedo
  436. * @memberof! Handsontable.Core#
  437. * @type {UndoRedo}
  438. */
  439. instance.undoRedo = new UndoRedo(instance);
  440. exposeUndoRedoMethods(instance);
  441. instance.addHook('beforeKeyDown', onBeforeKeyDown);
  442. instance.addHook('afterChange', onAfterChange);
  443. }
  444. } else if (instance.undoRedo) {
  445. delete instance.undoRedo;
  446. removeExposedUndoRedoMethods(instance);
  447. instance.removeHook('beforeKeyDown', onBeforeKeyDown);
  448. instance.removeHook('afterChange', onAfterChange);
  449. }
  450. }
  451. function onBeforeKeyDown(event) {
  452. var instance = this;
  453. var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey;
  454. if (ctrlDown) {
  455. if (event.keyCode === 89 || event.shiftKey && event.keyCode === 90) {
  456. // CTRL + Y or CTRL + SHIFT + Z
  457. instance.undoRedo.redo();
  458. (0, _event.stopImmediatePropagation)(event);
  459. } else if (event.keyCode === 90) {
  460. // CTRL + Z
  461. instance.undoRedo.undo();
  462. (0, _event.stopImmediatePropagation)(event);
  463. }
  464. }
  465. }
  466. function onAfterChange(changes, source) {
  467. var instance = this;
  468. if (source === 'loadData') {
  469. return instance.undoRedo.clear();
  470. }
  471. }
  472. function exposeUndoRedoMethods(instance) {
  473. /**
  474. * {@link UndoRedo#undo}
  475. * @alias undo
  476. * @memberof! Handsontable.Core#
  477. */
  478. instance.undo = function () {
  479. return instance.undoRedo.undo();
  480. };
  481. /**
  482. * {@link UndoRedo#redo}
  483. * @alias redo
  484. * @memberof! Handsontable.Core#
  485. */
  486. instance.redo = function () {
  487. return instance.undoRedo.redo();
  488. };
  489. /**
  490. * {@link UndoRedo#isUndoAvailable}
  491. * @alias isUndoAvailable
  492. * @memberof! Handsontable.Core#
  493. */
  494. instance.isUndoAvailable = function () {
  495. return instance.undoRedo.isUndoAvailable();
  496. };
  497. /**
  498. * {@link UndoRedo#isRedoAvailable}
  499. * @alias isRedoAvailable
  500. * @memberof! Handsontable.Core#
  501. */
  502. instance.isRedoAvailable = function () {
  503. return instance.undoRedo.isRedoAvailable();
  504. };
  505. /**
  506. * {@link UndoRedo#clear}
  507. * @alias clearUndo
  508. * @memberof! Handsontable.Core#
  509. */
  510. instance.clearUndo = function () {
  511. return instance.undoRedo.clear();
  512. };
  513. }
  514. function removeExposedUndoRedoMethods(instance) {
  515. delete instance.undo;
  516. delete instance.redo;
  517. delete instance.isUndoAvailable;
  518. delete instance.isRedoAvailable;
  519. delete instance.clearUndo;
  520. }
  521. var hook = _pluginHooks2.default.getSingleton();
  522. hook.add('afterInit', init);
  523. hook.add('afterUpdateSettings', init);
  524. hook.register('beforeUndo');
  525. hook.register('afterUndo');
  526. hook.register('beforeRedo');
  527. hook.register('afterRedo');