movedelta.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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 Delta from './delta.js';
  7. import { register } from '../batch.js';
  8. import MoveOperation from '../operation/moveoperation.js';
  9. import Position from '../position.js';
  10. import Range from '../range.js';
  11. import CKEditorError from '../../../utils/ckeditorerror.js';
  12. /**
  13. * @classdesc
  14. * To provide specific OT behavior and better collisions solving, {@link engine.treeModel.Batch#move} method
  15. * uses the `MoveDelta` class which inherits from the `Delta` class and may overwrite some methods.
  16. *
  17. * @memberOf engine.treeModel.delta
  18. */
  19. export default class MoveDelta extends Delta {
  20. /**
  21. * How many nodes are moved by the delta or `null` if there are no operations in the delta.
  22. *
  23. * @type {Number|null}
  24. */
  25. get howMany() {
  26. return this._moveOperation ? this._moveOperation.howMany : null;
  27. }
  28. /**
  29. * {@link engine.treeModel.delta.MoveDelta#_moveOperation Move operation}
  30. * {@link engine.treeModel.operation.MoveOperation#sourcePosition source position} or `null` if there are
  31. * no operations in the delta.
  32. *
  33. * @type {engine.treeModel.Position|null}
  34. */
  35. get sourcePosition() {
  36. return this._moveOperation ? this._moveOperation.sourcePosition : null;
  37. }
  38. /**
  39. * {@link engine.treeModel.delta.MoveDelta#_moveOperation Move operation}
  40. * {@link engine.treeModel.operation.MoveOperation#targetPosition target position} or `null` if there are
  41. * no operations in the delta.
  42. *
  43. * @type {engine.treeModel.Position|null}
  44. */
  45. get targetPosition() {
  46. return this._moveOperation ? this._moveOperation.targetPosition : null;
  47. }
  48. /**
  49. * Move operation that is saved in this delta or `null` if there are no operations in the delta.
  50. *
  51. * @protected
  52. * @type {engine.treeModel.operation.MoveOperation|null}
  53. */
  54. get _moveOperation() {
  55. return this.operations[ 0 ] || null;
  56. }
  57. get _reverseDeltaClass() {
  58. return MoveDelta;
  59. }
  60. static get _priority() {
  61. return 20;
  62. }
  63. }
  64. function addMoveOperation( batch, delta, sourcePosition, howMany, targetPosition ) {
  65. const operation = new MoveOperation( sourcePosition, howMany, targetPosition, batch.doc.version );
  66. delta.addOperation( operation );
  67. batch.doc.applyOperation( operation );
  68. }
  69. /**
  70. * Moves given node or given range of nodes to target position.
  71. *
  72. * @chainable
  73. * @method engine.treeModel.Batch#move
  74. * @param {engine.treeModel.Node|engine.treeModel.Range} nodeOrRange Node or range of nodes to move.
  75. * @param {engine.treeModel.Position} targetPosition Position where moved nodes will be inserted.
  76. */
  77. register( 'move', function( nodeOrRange, targetPosition ) {
  78. const delta = new MoveDelta();
  79. this.addDelta( delta );
  80. if ( nodeOrRange instanceof Range ) {
  81. if ( !nodeOrRange.isFlat ) {
  82. /**
  83. * Range to move is not flat.
  84. *
  85. * @error batch-move-range-not-flat
  86. */
  87. throw new CKEditorError( 'batch-move-range-not-flat: Range to move is not flat.' );
  88. }
  89. addMoveOperation( this, delta, nodeOrRange.start, nodeOrRange.end.offset - nodeOrRange.start.offset, targetPosition );
  90. } else {
  91. addMoveOperation( this, delta, Position.createBefore( nodeOrRange ), 1, targetPosition );
  92. }
  93. return this;
  94. } );