| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- /**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
- 'use strict';
- CKEDITOR.define( [
- 'document/operation/operation',
- 'ckeditorerror',
- 'utils'
- ], ( Operation, CKEditorError, utils ) => {
- /**
- * Operation to move list of subsequent nodes from one position in the document to another.
- *
- * @class document.operation.MoveOperation
- */
- class MoveOperation extends Operation {
- /**
- * Creates a move operation.
- *
- * @param {document.Position} sourcePosition Position before the first element to move.
- * @param {document.Position} targetPosition Position where moved elements will be inserted.
- * @param {Number} howMany How many consecutive nodes to move, starting from `sourcePosition`.
- * @param {Number} baseVersion {@link document.Document#version} on which operation can be applied.
- * @constructor
- */
- constructor( sourcePosition, targetPosition, howMany, baseVersion ) {
- super( baseVersion );
- /**
- * Source move position.
- *
- * @type {document.Position}
- */
- this.sourcePosition = sourcePosition;
- /**
- * Target move position.
- *
- * @type {document.Position}
- */
- this.targetPosition = targetPosition;
- /**
- * How many nodes to move.
- *
- * @type {Number}
- */
- this.howMany = howMany;
- }
- clone() {
- return new MoveOperation( this.sourcePosition.clone(), this.targetPosition.clone(), this.howMany, this.baseVersion );
- }
- getReversed() {
- return new MoveOperation( this.targetPosition.clone(), this.sourcePosition.clone(), this.howMany, this.baseVersion + 1 );
- }
- _execute() {
- let sourceElement = this.sourcePosition.parent;
- let targetElement = this.targetPosition.parent;
- let sourceOffset = this.sourcePosition.offset;
- let targetOffset = this.targetPosition.offset;
- // Validate whether move operation has correct parameters.
- // Validation is pretty complex but move operation is one of the core ways to manipulate the document state.
- // We expect that many errors might be connected with one of scenarios described below.
- if ( !sourceElement || !targetElement ) {
- /**
- * Source position or target position is invalid.
- *
- * @error operation-move-position-invalid
- */
- throw new CKEditorError(
- 'operation-move-position-invalid: Source position or target position is invalid.'
- );
- } else if ( sourceOffset + this.howMany > sourceElement.getChildCount() ) {
- /**
- * The nodes which should be moved do not exist.
- *
- * @error operation-move-nodes-do-not-exist
- */
- throw new CKEditorError(
- 'operation-move-nodes-do-not-exist: The nodes which should be moved do not exist.'
- );
- } else if ( sourceElement === targetElement && sourceOffset <= targetOffset && targetOffset < sourceOffset + this.howMany ) {
- /**
- * Trying to move a range of nodes into the middle of that range.
- *
- * @error operation-move-range-into-itself
- */
- throw new CKEditorError(
- 'operation-move-range-into-itself: Trying to move a range of nodes to the inside of that range.'
- );
- } else {
- if ( utils.compareArrays( this.sourcePosition.getParentPath(), this.targetPosition.getParentPath() ) == utils.compareArrays.PREFIX ) {
- let i = this.sourcePosition.path.length - 1;
- if ( this.targetPosition.path[ i ] >= sourceOffset && this.targetPosition.path[ i ] < sourceOffset + this.howMany ) {
- /**
- * Trying to move a range of nodes into one of nodes from that range.
- *
- * @error operation-move-node-into-itself
- */
- throw new CKEditorError(
- 'operation-move-node-into-itself: Trying to move a range of nodes into one of nodes from that range.'
- );
- }
- }
- }
- // End of validation.
- // If we move children in the same element and we remove elements on the position before the target we
- // need to update a target offset.
- if ( sourceElement === targetElement && sourceOffset < targetOffset ) {
- targetOffset -= this.howMany;
- }
- const removedNodes = sourceElement.removeChildren( sourceOffset, this.howMany );
- targetElement.insertChildren( targetOffset, removedNodes );
- }
- }
- return MoveOperation;
- } );
|