Jelajahi Sumber

Change event code.

Piotr Jasiun 10 tahun lalu
induk
melakukan
9ee6311120

+ 5 - 2
packages/ckeditor5-utils/src/document/document.js

@@ -88,9 +88,12 @@ CKEDITOR.define( [
 					{ operation: operation } );
 			}
 
-			operation._execute();
+			let changes = operation._execute();
+
 			this.version++;
-			this.fire( 'operationApplied', operation );
+
+			changes.type = operation.type;
+			this.fire( 'change', changes );
 		}
 
 		/**

+ 10 - 0
packages/ckeditor5-utils/src/document/operation/changeoperation.js

@@ -61,6 +61,10 @@ CKEDITOR.define( [
 			this.newAttr = newAttr;
 		}
 
+		get type() {
+			return 'attr';
+		}
+
 		clone() {
 			return new ChangeOperation( this.range.clone(), this.oldAttr, this.newAttr, this.baseVersion );
 		}
@@ -130,6 +134,12 @@ CKEDITOR.define( [
 					value.node.setAttr( newAttr );
 				}
 			}
+
+			return {
+				range: this.range,
+				oldAttr: oldAttr ? oldAttr : undefined,
+				newAttr: newAttr ? newAttr : undefined
+			};
 		}
 	}
 

+ 15 - 1
packages/ckeditor5-utils/src/document/operation/insertoperation.js

@@ -8,8 +8,10 @@
 CKEDITOR.define( [
 	'document/operation/operation',
 	'document/nodelist',
+	'document/range',
+	'document/position',
 	'document/operation/removeoperation'
-], ( Operation, NodeList ) => {
+], ( Operation, NodeList, Range, Position ) => {
 	/**
 	 * Operation to insert list of nodes on the given position in the tree data model.
 	 *
@@ -45,10 +47,22 @@ CKEDITOR.define( [
 			this.nodeList = new NodeList( nodes );
 		}
 
+		get type() {
+			return 'insert';
+		}
+
 		clone() {
 			return new InsertOperation( this.position, this.nodeList, this.baseVersion );
 		}
 
+		_execute() {
+			this.position.parent.insertChildren( this.position.offset, this.nodeList );
+
+			return {
+				range: new Range( this.position, Position.createFromPositionAndShift( this.position, this.nodeList.length ) )
+			};
+		}
+
 		getReversed() {
 			// Because of circular dependencies we need to re-require remove operation here.
 			const RemoveOperation = CKEDITOR.require( 'document/operation/removeoperation' );

+ 13 - 1
packages/ckeditor5-utils/src/document/operation/moveoperation.js

@@ -7,9 +7,12 @@
 
 CKEDITOR.define( [
 	'document/operation/operation',
+	'document/nodelist',
+	'document/position',
+	'document/range',
 	'ckeditorerror',
 	'utils'
-], ( Operation, CKEditorError, utils ) => {
+], ( Operation, NodeList, Position, Range, CKEditorError, utils ) => {
 	/**
 	 * Operation to move list of subsequent nodes from one position in the document to another.
 	 *
@@ -50,6 +53,10 @@ CKEDITOR.define( [
 			this.howMany = howMany;
 		}
 
+		get type() {
+			return 'move';
+		}
+
 		clone() {
 			return new MoveOperation( this.sourcePosition.clone(), this.targetPosition.clone(), this.howMany, this.baseVersion );
 		}
@@ -121,6 +128,11 @@ CKEDITOR.define( [
 			const removedNodes = sourceElement.removeChildren( sourceOffset, this.howMany );
 
 			targetElement.insertChildren( targetOffset, removedNodes );
+
+			return {
+				sourcePosition: this.sourcePosition,
+				range: new Range( this.targetPosition, Position.createFromPositionAndShift( this.targetPosition, this.howMany ) )
+			};
 		}
 	}
 

+ 4 - 0
packages/ckeditor5-utils/src/document/operation/reinsertoperation.js

@@ -27,6 +27,10 @@ CKEDITOR.define( [
 
 			return new RemoveOperation( this.targetPosition, this.howMany, this.baseVersion + 1 );
 		}
+
+		get type() {
+			return 'reinsert';
+		}
 	}
 
 	return ReinsertOperation;

+ 4 - 0
packages/ckeditor5-utils/src/document/operation/removeoperation.js

@@ -33,6 +33,10 @@ CKEDITOR.define( [
 			super( position, graveyardPosition, howMany, baseVersion );
 		}
 
+		get type() {
+			return 'remove';
+		}
+
 		getReversed() {
 			// Because of circular dependencies we need to re-require reinsert operation here.
 			const ReinsertOperation = CKEDITOR.require( 'document/operation/reinsertoperation' );

+ 7 - 0
packages/ckeditor5-utils/src/document/position.js

@@ -220,6 +220,13 @@ CKEDITOR.define( [ 'document/rootelement', 'utils', 'ckeditorerror' ], ( RootEle
 			return transformed;
 		}
 
+		static createFromPositionAndShift( position, shift ) {
+			let newPosition = new Position( utils.clone( position.path ), position.root );
+			newPosition.offset = newPosition.offset + shift;
+
+			return newPosition;
+		}
+
 		/**
 		 * Returns this position after being updated by inserting `howMany` nodes at `insertPosition`.
 		 *

+ 30 - 26
packages/ckeditor5-utils/tests/document/document-change-event.js

@@ -49,13 +49,13 @@ describe( 'Document change event', () => {
 
 		changes = [];
 
-		doc.on( 'change', ( evt ) => {
-			changes = evt.changes;
+		doc.on( 'change', ( evt, data ) => {
+			changes.push( data );
 		} );
 	} );
 
 	it( 'should be fired when text is inserted', () => {
-		this.doc.applyOperation( new InsertOperation( new Position( [ 0 ], root ), 'foo', this.doc.version ) );
+		doc.applyOperation( new InsertOperation( new Position( [ 0 ], root ), 'foo', doc.version ) );
 
 		expect( changes ).to.have.length( 1 );
 		expect( changes[ 0 ].type ).to.equal( 'insert' );
@@ -64,7 +64,7 @@ describe( 'Document change event', () => {
 
 	it( 'should be fired when element is inserted', () => {
 		const element = new Element( 'p' );
-		this.doc.applyOperation( new InsertOperation( new Position( [ 0 ], root ), element, this.doc.version ) );
+		doc.applyOperation( new InsertOperation( new Position( [ 0 ], root ), element, doc.version ) );
 
 		expect( changes ).to.have.length( 1 );
 		expect( changes[ 0 ].type ).to.equal( 'insert' );
@@ -73,14 +73,14 @@ describe( 'Document change event', () => {
 
 	it( 'should be fired when nodes are inserted', () => {
 		const element = new Element( 'p' );
-		this.doc.applyOperation( new InsertOperation( new Position( [ 0 ], root ), [ element, 'foo' ], this.doc.version ) );
+		doc.applyOperation( new InsertOperation( new Position( [ 0 ], root ), [ element, 'foo' ], doc.version ) );
 
 		expect( changes ).to.have.length( 1 );
 		expect( changes[ 0 ].type ).to.equal( 'insert' );
 		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 4 ) );
 	} );
 
-	it( 'should be fired when multiple nodes are moved', () => {
+	it( 'should be fired when nodes are moved', () => {
 		const p1 = new Element( 'p' );
 		p1.insertChildren( 0, [ new Element( 'p' ), 'foo' ] );
 
@@ -88,12 +88,12 @@ describe( 'Document change event', () => {
 
 		root.insertChildren( 0, [ p1, p2 ] );
 
-		this.doc.applyOperation(
+		doc.applyOperation(
 			new MoveOperation(
 				new Position( [ 0, 0 ], root ),
 				new Position( [ 1, 0 ], root ),
 				3,
-				this.doc.version
+				doc.version
 			)
 		);
 
@@ -106,11 +106,11 @@ describe( 'Document change event', () => {
 	it( 'should be fired when multiple nodes are removed and reinserted', () => {
 		root.insertChildren( 0, 'foo' );
 
-		const removeOperation = new RemoveOperation( new Position( [ 0 ], root ), 3, this.doc.version );
-		this.doc.applyOperation( removeOperation );
+		const removeOperation = new RemoveOperation( new Position( [ 0 ], root ), 3, doc.version );
+		doc.applyOperation( removeOperation );
 
 		const reinsertOperation = removeOperation.getReversed();
-		this.doc.applyOperation( reinsertOperation );
+		doc.applyOperation( reinsertOperation );
 
 		expect( changes ).to.have.length( 2 );
 
@@ -126,54 +126,58 @@ describe( 'Document change event', () => {
 	it( 'should be fired when attribute is inserted', () => {
 		root.insertChildren( 0, 'foo' );
 
-		this.doc.applyOperation(
+		doc.applyOperation(
 			new ChangeOperation(
 				Range.createFromParentsAndOffsets( root, 0, root, 3 ),
 				null,
 				new Attribute( 'key', 'new' ),
-				this.doc.version
+				doc.version
 			)
 		);
 
 		expect( changes ).to.have.length( 1 );
-		expect( changes[ 0 ].type ).to.equal( 'addAttr' );
+		expect( changes[ 0 ].type ).to.equal( 'attr' );
 		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 3 ) );
+		expect( changes[ 0 ].oldAttr ).to.be.undefined;
 		expect( changes[ 0 ].newAttr ).to.deep.equal( new Attribute( 'key', 'new' ) );
 	} );
 
 	it( 'should be fired when attribute is removed', () => {
-		root.insertChildren( 0, new Element( 'p', [ new Attribute( 'key', 'old' ) ] ) );
+		const elem = new Element( 'p', [ new Attribute( 'key', 'old' ) ] );
+		root.insertChildren( 0, elem );
 
-		this.doc.applyOperation(
+		doc.applyOperation(
 			new ChangeOperation(
-				Range.createFromParentsAndOffsets( root, 0, root, 3 ),
+				Range.createFromParentsAndOffsets( root, 0, elem, 0 ),
 				new Attribute( 'key', 'old' ),
 				null,
-				this.doc.version
+				doc.version
 			)
 		);
 
 		expect( changes ).to.have.length( 1 );
-		expect( changes[ 0 ].type ).to.equal( 'removeAttr' );
-		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 1 ) );
+		expect( changes[ 0 ].type ).to.equal( 'attr' );
+		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, elem, 0 ) );
 		expect( changes[ 0 ].oldAttr ).to.deep.equal( new Attribute( 'key', 'old' ) );
+		expect( changes[ 0 ].newAttr ).to.be.undefined;
 	}  );
 
 	it( 'should be fired when attribute changes', () => {
-		root.insertChildren( 0, new Element( 'p', [ new Attribute( 'key', 'old' ) ] ) );
+		const elem = new Element( 'p', [ new Attribute( 'key', 'old' ) ] );
+		root.insertChildren( 0, elem );
 
-		this.doc.applyOperation(
+		doc.applyOperation(
 			new ChangeOperation(
-				Range.createFromParentsAndOffsets( root, 0, root, 3 ),
+				Range.createFromParentsAndOffsets( root, 0, elem, 0 ),
 				new Attribute( 'key', 'old' ),
 				new Attribute( 'key', 'new' ),
-				this.doc.version
+				doc.version
 			)
 		);
 
 		expect( changes ).to.have.length( 1 );
-		expect( changes[ 0 ].type ).to.equal( 'changeAttr' );
-		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, root, 1 ) );
+		expect( changes[ 0 ].type ).to.equal( 'attr' );
+		expect( changes[ 0 ].range ).to.deep.equal( Range.createFromParentsAndOffsets( root, 0, elem, 0 ) );
 		expect( changes[ 0 ].oldAttr ).to.deep.equal( new Attribute( 'key', 'old' ) );
 		expect( changes[ 0 ].newAttr ).to.deep.equal( new Attribute( 'key', 'new' ) );
 	}  );