8
0

batch.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. 'use strict';
  6. import CKEditorError from '../../utils/ckeditorerror.js';
  7. /**
  8. * The Batch class groups document changes (deltas). All deltas grouped in a single Batch can be
  9. * reverted together, so you can think about the Batch as a single undo step. If you want to extend one
  10. * undo step you can call another method on the same Batch object. If you want to create a separate undo step
  11. * you can create a new Batch.
  12. *
  13. * For example to create two separate undo steps you can call:
  14. *
  15. * doc.batch().insert( firstPosition, 'foo' );
  16. * doc.batch().insert( secondPosition, 'bar' );
  17. *
  18. * To create a single undo step:
  19. *
  20. * const batch = doc.batch();
  21. * batch.insert( firstPosition, 'foo' );
  22. * batch.insert( secondPosition, 'bar' );
  23. *
  24. * Note that all document modification methods (insert, remove, split, etc.) are chainable so you can shorten code to:
  25. *
  26. * doc.batch().insert( firstPosition, 'foo' ).insert( secondPosition, 'bar' );
  27. *
  28. * @memberOf engine.treeModel
  29. */
  30. export default class Batch {
  31. /**
  32. * Creates Batch instance. Not recommended to use directly, use {@link engine.treeModel.Document#batch} instead.
  33. *
  34. * @param {engine.treeModel.Document} doc Document which this Batch changes.
  35. */
  36. constructor( doc ) {
  37. /**
  38. * Document which this Batch changes.
  39. *
  40. * @member {engine.treeModel.Document} engine.treeModel.Batch#doc
  41. * @readonly
  42. */
  43. this.doc = doc;
  44. /**
  45. * Array of deltas which compose Batch.
  46. *
  47. * @member {Array.<engine.treeModel.delta.Delta>} engine.treeModel.Batch#deltas
  48. * @readonly
  49. */
  50. this.deltas = [];
  51. }
  52. /**
  53. * Adds delta to the Batch instance. All modification methods (insert, remove, split, etc.) use this method
  54. * to add created deltas.
  55. *
  56. * @param {engine.treeModel.delta.Delta} delta Delta to add.
  57. * @return {engine.treeModel.delta.Delta} Added delta.
  58. */
  59. addDelta( delta ) {
  60. delta.batch = this;
  61. this.deltas.push( delta );
  62. return delta;
  63. }
  64. /**
  65. * Gets an iterable collection of operations.
  66. *
  67. * @returns {Iterable.<engine.treeModel.operation.Operation}
  68. */
  69. *getOperations() {
  70. for ( let delta of this.deltas ) {
  71. yield* delta.operations;
  72. }
  73. }
  74. }
  75. /**
  76. * Function to register Batch methods. To make code scalable Batch do not have modification
  77. * methods built in. They can be registered using this method.
  78. *
  79. * This method checks if there is no naming collision and throws `batch-register-taken` if the method name
  80. * is already taken.
  81. *
  82. * Besides that no magic happens here, the method is added to the `Batch` class prototype.
  83. *
  84. * For example:
  85. *
  86. * Batch.register( 'insert', function( position, nodes ) {
  87. * // You can use a class inherit from Delta if that class should handle OT in the special way.
  88. * const delta = new Delta();
  89. *
  90. * // Add delta to the Batch instance. It is important to add delta to batch before applying any operation.
  91. * this.addDelta( delta );
  92. *
  93. * // Create operations which should be components of this delta.
  94. * const operation = new InsertOperation( position, nodes, this.doc.version );
  95. *
  96. * // Add operation to the delta. It is important to add operation before applying it.
  97. * delta.addOperation( operation );
  98. *
  99. * // Remember to apply every operation, no magic, you need to do it manually.
  100. * this.doc.applyOperation( operation );
  101. *
  102. * // Make this method chainable.
  103. * return this;
  104. * } );
  105. *
  106. * @method engine.treeModel.Batch.register
  107. * @param {String} name Method name.
  108. * @param {Function} creator Method body.
  109. */
  110. export function register( name, creator ) {
  111. if ( Batch.prototype[ name ] ) {
  112. /**
  113. * This batch method name is already taken.
  114. *
  115. * @error batch-register-taken
  116. * @param {String} name
  117. */
  118. throw new CKEditorError(
  119. 'batch-register-taken: This batch method name is already taken.',
  120. { name: name } );
  121. }
  122. Batch.prototype[ name ] = creator;
  123. }