moveoperation.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. 'use strict';
  6. CKEDITOR.define( [
  7. 'document/operation',
  8. 'document/nodelist',
  9. 'ckeditorerror',
  10. 'utils'
  11. ], function( Operation, NodeList, CKEditorError, utils ) {
  12. /**
  13. * Operation to move list of following nodes from the one position in the document to another.
  14. *
  15. * @class document.Operation
  16. */
  17. class MoveOperation extends Operation {
  18. /**
  19. * Creates a move operation.
  20. *
  21. * Note that this constructor is used not only to create an operation on the current state of the document,
  22. * but also to create reverse operation or the result of the operational transformation. The operation also
  23. * needs to keep data needed to transform it (creates an insert operation from the move & remove combination).
  24. * This is why this constructor contains list of nodes instead of length.
  25. *
  26. * @param {document.Position} sourcePosition Source move position.
  27. * @param {document.Position} targetPosition Target move position.
  28. * @param {document.Node|document.Text|document.NodeList|String|Iterable} nodes List of nodes to be moved.
  29. * List of nodes can be any type accepted by the {@link document.NodeList} constructor.
  30. * @param {Number} baseVersion {@link document.Document#version} on which operation can be applied.
  31. * @constructor
  32. */
  33. constructor( sourcePosition, targetPosition, nodes, baseVersion ) {
  34. super( baseVersion );
  35. /**
  36. * Source move position.
  37. *
  38. * @type {document.Position}
  39. */
  40. this.sourcePosition = sourcePosition;
  41. /**
  42. * Target move position.
  43. *
  44. * @type {document.Position}
  45. */
  46. this.targetPosition = targetPosition;
  47. /**
  48. * List of nodes to move.
  49. *
  50. * @type {document.NodeList}
  51. */
  52. this.nodeList = new NodeList( nodes );
  53. }
  54. /**
  55. * Execute operation.
  56. *
  57. * @protected
  58. */
  59. _execute() {
  60. var sourceElement = this.sourcePosition.parent;
  61. var targetElement = this.targetPosition.parent;
  62. var sourceOffset = this.sourcePosition.offset;
  63. var targetOffset = this.targetPosition.offset;
  64. var nodeList = this.nodeList;
  65. if ( CKEDITOR.isDebug ) {
  66. var i = 0;
  67. for ( var node of this.nodeList ) {
  68. if ( !utils.isEqual( sourceElement.getChild( sourceOffset + i ), node ) ) {
  69. /**
  70. * The node which should be removed does not exists.
  71. *
  72. * @error operation-move-node-does-not-exists:
  73. * @param {document.MoveOperation} moveOperation
  74. * @param {document.Node} node
  75. */
  76. throw new CKEditorError(
  77. 'operation-move-node-does-not-exists: The node which should be moved does not exists.',
  78. { moveOperation: this, node: this.node } );
  79. }
  80. i++;
  81. }
  82. }
  83. sourceElement.removeChildren( sourceOffset, nodeList.length );
  84. // If we move children in the same element and we remove elements on the position before the target we
  85. // need to update a target offset.
  86. if ( sourceElement === targetElement && sourceOffset < targetOffset ) {
  87. targetOffset -= nodeList.length;
  88. }
  89. targetElement.insertChildren( targetOffset, this.nodeList );
  90. }
  91. /**
  92. * Creates an reverse move operation.
  93. *
  94. * @returns {document.MoveOperation} Reverse operation.
  95. */
  96. reverseOperation() {
  97. return new MoveOperation( this.targetPosition, this.sourcePosition, this.nodeList, this.baseVersion + 1 );
  98. }
  99. }
  100. return MoveOperation;
  101. } );