Sfoglia il codice sorgente

Changes in Position: constructor may throw error, setter for .offset, .getParentPath() to .parentPath, introduced .clone()

Szymon Cofalik 10 anni fa
parent
commit
869749bb4e

+ 31 - 4
packages/ckeditor5-utils/src/document/position.js

@@ -5,7 +5,7 @@
 
 'use strict';
 
-CKEDITOR.define( [ 'utils', 'ckeditorerror' ], ( utils, CKEditorError ) => {
+CKEDITOR.define( [ 'document/rootelement', 'utils', 'ckeditorerror' ], ( RootElement, utils, CKEditorError ) => {
 	/**
 	 * Position in the tree. Position is always located before or after a node.
 	 * See {@link #path} property for more information.
@@ -17,7 +17,7 @@ CKEDITOR.define( [ 'utils', 'ckeditorerror' ], ( utils, CKEditorError ) => {
 		 * Creates a position.
 		 *
 		 * @param {Array} path Position path. See {@link #path} property for more information.
-		 * @param {document.Element} root Root element for the path. Note that this element can not have a parent.
+		 * @param {document.RootElement} root Root element for the path. Note that this element can not have a parent.
 		 * @constructor
 		 */
 		constructor( path, root ) {
@@ -40,10 +40,20 @@ CKEDITOR.define( [ 'utils', 'ckeditorerror' ], ( utils, CKEditorError ) => {
 			 */
 			this.path = path;
 
+			if ( !( root instanceof RootElement ) ) {
+				/**
+				 * Position root has to be an instance of RootElement.
+				 *
+				 * @error position-root-not-rootelement
+				 * @param root
+				 */
+				throw new CKEditorError( 'position-root-not-rootelement: Position root has to be an instance of RootElement.', { root: root } );
+			}
+
 			/**
 			 * Root element for the path. Note that this element can not have a parent.
 			 *
-			 * @type {document.Element}
+			 * @type {document.RootElement}
 			 */
 			this.root = root;
 		}
@@ -76,6 +86,13 @@ CKEDITOR.define( [ 'utils', 'ckeditorerror' ], ( utils, CKEditorError ) => {
 			return utils.last( this.path );
 		}
 
+		/**
+		 * Sets offset in the parent, which is the last element of the path.
+		 */
+		set offset( newOffset ) {
+			this.path[ this.path.length - 1 ] = newOffset;
+		}
+
 		/**
 		 * Node directly before the position.
 		 *
@@ -113,10 +130,20 @@ CKEDITOR.define( [ 'utils', 'ckeditorerror' ], ( utils, CKEditorError ) => {
 		 *
 		 * @returns {Number[]} Path to the parent.
 		 */
-		getParentPath() {
+		get parentPath() {
 			return this.path.slice( 0, -1 );
 		}
 
+		/**
+		 * Creates and returns a new instance of {@link document.Position}
+		 * that is equal to this {@link document.Position position}.
+		 *
+		 * @returns {document.Position} Cloned {@link document.Position position}.
+		 */
+		clone() {
+			return new Position( this.path.slice(), this.root );
+		}
+
 		/**
 		 * Creates a new position from the parent element and the offset in that element.
 		 *

+ 37 - 13
packages/ckeditor5-utils/tests/document/position.js

@@ -19,7 +19,7 @@ const modules = bender.amd.require(
 describe( 'position', () => {
 	let Element, Character, Document, NodeList, Position, CKEditorError;
 
-	let doc, root, p, ul, li1, li2, f, o, z, b, a, r;
+	let doc, root, otherRoot, p, ul, li1, li2, f, o, z, b, a, r;
 
 	// root
 	//  |- p         Before: [ 0 ]       After: [ 1 ]
@@ -43,6 +43,7 @@ describe( 'position', () => {
 		doc = new Document();
 
 		root = doc.createRoot( 'root' );
+		otherRoot = doc.createRoot( 'otherRoot' );
 
 		f = new Character( 'f' );
 		o = new Character( 'o' );
@@ -70,6 +71,16 @@ describe( 'position', () => {
 		expect( position ).to.have.property( 'root' ).that.equals( root );
 	} );
 
+	it( 'should throw error if given root is not a RootElement instance', () => {
+		expect( () => {
+			new Position( [ 0 ] )
+		} ).to.throw( CKEditorError, /position-root-not-rootelement/ );
+
+		expect( () => {
+			new Position( [ 0 ], new Element( 'p' ) );
+		} ).to.throw( CKEditorError, /position-root-not-rootelement/ );
+	} );
+
 	it( 'should make positions form node and offset', () => {
 		expect( Position.createFromParentAndOffset( root, 0 ) ).to.have.property( 'path' ).that.deep.equals( [ 0 ] );
 		expect( Position.createFromParentAndOffset( root, 1 ) ).to.have.property( 'path' ).that.deep.equals( [ 1 ] );
@@ -106,11 +117,9 @@ describe( 'position', () => {
 	} );
 
 	it( 'should throw error if one try to make positions before root', () => {
-		expect(
-			() => {
-				Position.createBefore( root );
-			}
-		).to.throw( CKEditorError, /position-before-root/ );
+		expect( () => {
+			Position.createBefore( root );
+		} ).to.throw( CKEditorError, /position-before-root/ );
 	} );
 
 	it( 'should make positions after elements', () => {
@@ -132,11 +141,9 @@ describe( 'position', () => {
 	} );
 
 	it( 'should throw error if one try to make positions after root', () => {
-		expect(
-			() => {
-				Position.createAfter( root );
-			}
-		).to.throw( CKEditorError, /position-after-root/ );
+		expect( () => {
+			Position.createAfter( root );
+		} ).to.throw( CKEditorError, /position-after-root/ );
 	} );
 
 	it( 'should have parent', () => {
@@ -173,6 +180,14 @@ describe( 'position', () => {
 		expect( new Position( [ 1, 0, 3 ], root ) ).to.have.property( 'offset' ).that.equals( 3 );
 	} );
 
+	it( 'should be able to set offset', () => {
+		let position = new Position( [ 1, 0, 2 ], root );
+		position.offset = 4;
+
+		expect( position.offset ).to.equal( 4 );
+		expect( position.path ).to.deep.equal( [ 1, 0, 4 ] );
+	} );
+
 	it( 'should have nodeBefore', () => {
 		expect( new Position( [ 0 ], root ) ).to.have.property( 'nodeBefore' ).that.is.null;
 		expect( new Position( [ 1 ], root ) ).to.have.property( 'nodeBefore' ).that.equals( p );
@@ -221,9 +236,18 @@ describe( 'position', () => {
 		expect( position.isEqual( differentNode ) ).to.be.false;
 	} );
 
-	it( 'should have proper parent path', () => {
+	it( 'should have correct parent path property', () => {
 		let position = new Position( [ 1, 2, 3 ], root );
 
-		expect( position.getParentPath() ).to.deep.equal( [ 1, 2 ] );
+		expect( position.parentPath ).to.deep.equal( [ 1, 2 ] );
+	} );
+
+	it( 'should return a new, equal position when cloned', () => {
+		const position = new Position( [ 1, 2, 3 ], root );
+		const clone = position.clone();
+
+		expect( clone ).not.to.be.equal( position ); // clone is not pointing to the same object as 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
 	} );
 } );