Răsfoiți Sursa

Position.compareWith() introduced.

Szymon Cofalik 10 ani în urmă
părinte
comite
e6cc261b3e

+ 62 - 2
packages/ckeditor5-utils/src/document/position.js

@@ -6,6 +6,11 @@
 'use strict';
 
 CKEDITOR.define( [ 'document/rootelement', 'utils', 'ckeditorerror' ], ( RootElement, utils, CKEditorError ) => {
+	const SAME = 0,
+		AFTER = 1,
+		BEFORE = -1,
+		DIFFERENT = -2;
+
 	/**
 	 * Position in the tree. Position is always located before or after a node.
 	 * See {@link #path} property for more information.
@@ -114,13 +119,13 @@ CKEDITOR.define( [ 'document/rootelement', 'utils', 'ckeditorerror' ], ( RootEle
 		}
 
 		/**
-		 * Two positions equal if paths are equal.
+		 * Two positions equal if paths are equal and roots are the same.
 		 *
 		 * @param {document.Position} otherPosition Position to compare.
 		 * @returns {Boolean} True if positions equal.
 		 */
 		isEqual( otherPosition ) {
-			return utils.isEqual( this.path, otherPosition.path );
+			return this.compareWith( otherPosition ) == SAME;
 		}
 
 		/**
@@ -198,7 +203,62 @@ CKEDITOR.define( [ 'document/rootelement', 'utils', 'ckeditorerror' ], ( RootEle
 
 			return Position.createFromParentAndOffset( node.parent, node.getIndex() + 1 );
 		}
+
+		/**
+		 * Checks whether this position is before or after given position.
+		 *
+		 * @param {document.Position} otherPosition Position to compare with.
+		 * @returns {Number} A flag indicating whether this position is {@link #BEFORE} or
+		 * {@link #AFTER} or {@link #SAME} as given position. If positions are in different roots,
+		 * {@link #DIFFERENT} flag is returned.
+		 */
+		compareWith( otherPosition ) {
+			if ( this.root != otherPosition.root ) {
+				return DIFFERENT;
+			}
+
+			const result = utils.compareArrays( this.path, otherPosition.path );
+
+			switch ( result ) {
+				case utils.compareArrays.SAME:
+					return SAME;
+				case utils.compareArrays.PREFIX:
+					return BEFORE;
+				case utils.compareArrays.EXTENSION:
+					return AFTER;
+				default:
+					if ( this.path[ result ] < otherPosition.path[ result ] ) {
+						return BEFORE;
+					} else {
+						return AFTER;
+					}
+			}
+		}
 	}
 
+	/**
+	 * Flag for "are same" relation between Positions.
+	 * @type {Number}
+	 */
+	Position.SAME = SAME;
+
+	/**
+	 * Flag for "is before" relation between Positions.
+	 * @type {Number}
+	 */
+	Position.BEFORE = BEFORE;
+
+	/**
+	 * Flag for "is after" relation between Positions.
+	 * @type {Number}
+	 */
+	Position.AFTER = AFTER;
+
+	/**
+	 * Flag for "are in different roots" relation between Positions.
+	 * @type {Number}
+	 */
+	Position.DIFFERENT = DIFFERENT;
+
 	return Position;
 } );

+ 33 - 3
packages/ckeditor5-utils/tests/document/position.js

@@ -222,7 +222,7 @@ describe( 'position', () => {
 		expect( new Position( [ 1, 0, 3 ], root ) ).to.have.property( 'nodeAfter' ).that.is.null;
 	} );
 
-	it( 'should equals another position with the same path', () => {
+	it( 'should equals another position with the same path and root', () => {
 		let position = new Position( [ 1, 1, 2 ], root );
 		let samePosition = new Position( [ 1, 1, 2 ], root );
 
@@ -231,9 +231,16 @@ describe( 'position', () => {
 
 	it( 'should not equals another position with the different path', () => {
 		let position = new Position( [ 1, 1, 1 ], root );
-		let differentNode = new Position( [ 1, 2, 2 ], root );
+		let differentPosition = new Position( [ 1, 2, 2 ], root );
 
-		expect( position.isEqual( differentNode ) ).to.be.false;
+		expect( position.isEqual( differentPosition ) ).to.be.false;
+	} );
+
+	it( 'should not equals another position with the different root', () => {
+		let position = new Position( [ 1, 1, 1 ], root );
+		let differentPosition = new Position( [ 1, 1, 1 ], otherRoot );
+
+		expect( position.isEqual( differentPosition ) ).to.be.false;
 	} );
 
 	it( 'should have correct parent path property', () => {
@@ -250,4 +257,27 @@ describe( 'position', () => {
 		expect( clone.isEqual( position ) ).to.be.true; // but they are equal in the position-sense
 		expect( clone.path ).not.to.be.equal( position.path ); // make sure the paths are not the same array
 	} );
+
+	describe( 'compareWith', () => {
+		it( 'should return Position.SAME if positions are same', () => {
+			const position = new Position( [ 1, 2, 3 ], root );
+			const compared = new Position( [ 1, 2, 3 ], root );
+
+			expect( position.compareWith( compared ) ).to.equal( Position.SAME );
+		} );
+
+		it( 'should return Position.BEFORE if the position is before compared one', () => {
+			const position = new Position( [ 1, 2, 3 ], root );
+			const compared = new Position( [ 1, 3 ], root );
+
+			expect( position.compareWith( compared ) ).to.equal( Position.BEFORE );
+		} );
+
+		it( 'should return Position.AFTER if the position is after compared one', () => {
+			const position = new Position( [ 1, 2, 3, 4 ], root );
+			const compared = new Position( [ 1, 2, 3 ], root );
+
+			expect( position.compareWith( compared ) ).to.equal( Position.AFTER );
+		} );
+	} );
 } );