8
0
Maciej Bukowski 8 лет назад
Родитель
Сommit
e18ba05918

+ 1 - 1
packages/ckeditor5-engine/src/model/selection.js

@@ -376,7 +376,7 @@ export default class Selection {
 				/**
 				/**
 				 * Required second parameter when setting selection to node.
 				 * Required second parameter when setting selection to node.
 				 *
 				 *
-				 * @error
+				 * @error model-selection-setTo-required-second-parameter
 				 */
 				 */
 				throw new CKEditorError(
 				throw new CKEditorError(
 					'model-selection-setTo-required-second-parameter: Required second parameter when setting selection to node.' );
 					'model-selection-setTo-required-second-parameter: Required second parameter when setting selection to node.' );

+ 56 - 17
packages/ckeditor5-engine/src/view/selection.js

@@ -12,8 +12,8 @@ import Range from './range';
 import Position from './position';
 import Position from './position';
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
 import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
 import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
+import Node from './node';
 import Element from './element';
 import Element from './element';
-import Text from './text';
 import count from '@ckeditor/ckeditor5-utils/src/count';
 import count from '@ckeditor/ckeditor5-utils/src/count';
 import isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';
 import isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';
 
 
@@ -55,15 +55,26 @@ export default class Selection {
 	 *		const position = new Position( root, path );
 	 *		const position = new Position( root, path );
 	 *		const selection = new Selection( position );
 	 *		const selection = new Selection( position );
 	 *
 	 *
-	 * 		// Creates selection at the start position of given element.
+	 * 		// Sets collapsed range at the position of given item and offset.
 	 *		const paragraph = writer.createElement( 'paragraph' );
 	 *		const paragraph = writer.createElement( 'paragraph' );
-	 *		const selection = new Selection( paragraph, offset );
+	 *		selection.setTo( paragraph, offset );
 	 *
 	 *
-	 * @param {module:engine/view/selection~Selection|module:engine/view/position~Position|
-	 * Iterable.<module:engine/view/range~Range>|module:engine/view/range~Range|module:engine/view/item~Item} [selectable]
-	 * @param {Boolean|Number|'before'|'end'|'after'} [backwardSelectionOrOffset]
+	 *		// Sets range inside the item.
+	 *		const paragraph = writer.createElement( 'paragraph' );
+	 *		selection.setTo( paragraph, 'in' );
+	 *
+	 *		// Sets range on the item.
+	 *		const paragraph = writer.createElement( 'paragraph' );
+	 *		selection.setTo( paragraph, 'on' );
+	 *
+	* @param {module:engine/view/selection~Selection|module:engine/view/position~Position|
+	 * Iterable.<module:engine/view/range~Range>|module:engine/view/range~Range|module:engine/view/item~Item|null} selectable
+	 * @param {Object|Number|'before'|'end'|'after'|'on'|'in'} [optionsOrPlaceOrOffset]
+	 * @param {Boolean} [optionsOrPlaceOrOffset.backward]
+	 * @param {Object} [options]
+	 * @param {Boolean} [options.backward]
 	 */
 	 */
-	constructor( selectable, backwardSelectionOrOffset ) {
+	constructor( selectable, optionsOrPlaceOrOffset, options ) {
 		/**
 		/**
 		 * Stores all ranges that are selected.
 		 * Stores all ranges that are selected.
 		 *
 		 *
@@ -97,7 +108,7 @@ export default class Selection {
 		this._fakeSelectionLabel = '';
 		this._fakeSelectionLabel = '';
 
 
 		if ( selectable ) {
 		if ( selectable ) {
-			this._setTo( selectable, backwardSelectionOrOffset );
+			this._setTo( selectable, optionsOrPlaceOrOffset, options );
 		}
 		}
 	}
 	}
 
 
@@ -422,19 +433,30 @@ export default class Selection {
 	 *		const position = new Position( root, path );
 	 *		const position = new Position( root, path );
 	 *		selection.setTo( position );
 	 *		selection.setTo( position );
 	 *
 	 *
-	 * 		// Sets collapsed range on the given item.
+	 * 		// Sets collapsed range at the position of given item and offset.
 	 *		const paragraph = writer.createElement( 'paragraph' );
 	 *		const paragraph = writer.createElement( 'paragraph' );
 	 *		selection.setTo( paragraph, offset );
 	 *		selection.setTo( paragraph, offset );
 	 *
 	 *
+	 *		// Sets range inside the item.
+	 *		const paragraph = writer.createElement( 'paragraph' );
+	 *		selection.setTo( paragraph, 'in' );
+	 *
+	 *		// Sets range on the item.
+	 *		const paragraph = writer.createElement( 'paragraph' );
+	 *		selection.setTo( paragraph, 'on' );
+	 *
 	 * 		// Removes all ranges.
 	 * 		// Removes all ranges.
 	 *		selection.setTo( null );
 	 *		selection.setTo( null );
 	 *
 	 *
 	 * @protected
 	 * @protected
 	 * @param {module:engine/view/selection~Selection|module:engine/view/position~Position|
 	 * @param {module:engine/view/selection~Selection|module:engine/view/position~Position|
 	 * Iterable.<module:engine/view/range~Range>|module:engine/view/range~Range|module:engine/view/item~Item|null} selectable
 	 * Iterable.<module:engine/view/range~Range>|module:engine/view/range~Range|module:engine/view/item~Item|null} selectable
-	 * @param {Boolean|Number|'before'|'end'|'after'} [backwardSelectionOrOffset]
+	 * @param {Object|Number|'before'|'end'|'after'|'on'|'in'} [optionsOrPlaceOrOffset]
+	 * @param {Boolean} [optionsOrPlaceOrOffset.backward]
+	 * @param {Object} [options]
+	 * @param {Boolean} [options.backward]
 	 */
 	 */
-	_setTo( selectable, backwardSelectionOrOffset ) {
+	_setTo( selectable, optionsOrPlaceOrOffset, options ) {
 		if ( selectable === null ) {
 		if ( selectable === null ) {
 			this._removeAllRanges();
 			this._removeAllRanges();
 		} else if ( selectable instanceof Selection ) {
 		} else if ( selectable instanceof Selection ) {
@@ -442,16 +464,33 @@ export default class Selection {
 			this._fakeSelectionLabel = selectable.fakeSelectionLabel;
 			this._fakeSelectionLabel = selectable.fakeSelectionLabel;
 			this._setRanges( selectable.getRanges(), selectable.isBackward );
 			this._setRanges( selectable.getRanges(), selectable.isBackward );
 		} else if ( selectable instanceof Range ) {
 		} else if ( selectable instanceof Range ) {
-			this._setRanges( [ selectable ], backwardSelectionOrOffset );
+			this._setRanges( [ selectable ], !!optionsOrPlaceOrOffset && !!optionsOrPlaceOrOffset.backward );
 		} else if ( selectable instanceof Position ) {
 		} else if ( selectable instanceof Position ) {
 			this._setRanges( [ new Range( selectable ) ] );
 			this._setRanges( [ new Range( selectable ) ] );
-		} else if ( selectable instanceof Text ) {
-			this._setRanges( [ Range.createCollapsedAt( selectable, backwardSelectionOrOffset ) ] );
-		} else if ( selectable instanceof Element ) {
-			this._setRanges( [ Range.createCollapsedAt( selectable, backwardSelectionOrOffset ) ] );
+		} else if ( selectable instanceof Node ) {
+			const backward = !!options && !!options.backward;
+			let range;
+
+			if ( optionsOrPlaceOrOffset == 'in' ) {
+				range = Range.createIn( selectable );
+			} else if ( optionsOrPlaceOrOffset == 'on' ) {
+				range = Range.createOn( selectable );
+			} else if ( optionsOrPlaceOrOffset !== undefined ) {
+				range = Range.createCollapsedAt( selectable, optionsOrPlaceOrOffset );
+			} else {
+				/**
+				 * Required second parameter when setting selection to node.
+				 *
+				 * @error view-selection-setTo-required-second-parameter
+				 */
+				throw new CKEditorError(
+					'view-selection-setTo-required-second-parameter: Required second parameter when setting selection to node.' );
+			}
+
+			this._setRanges( [ range ], backward );
 		} else if ( isIterable( selectable ) ) {
 		} else if ( isIterable( selectable ) ) {
 			// We assume that the selectable is an iterable of ranges.
 			// We assume that the selectable is an iterable of ranges.
-			this._setRanges( selectable, backwardSelectionOrOffset );
+			this._setRanges( selectable, optionsOrPlaceOrOffset && !!optionsOrPlaceOrOffset.backward );
 		} else {
 		} else {
 			/**
 			/**
 			 * Cannot set selection to given place.
 			 * Cannot set selection to given place.

+ 24 - 16
packages/ckeditor5-engine/tests/view/selection.js

@@ -44,13 +44,13 @@ describe( 'Selection', () => {
 
 
 		it( 'should be able to create a selection from the given ranges and isLastBackward flag', () => {
 		it( 'should be able to create a selection from the given ranges and isLastBackward flag', () => {
 			const ranges = [ range1, range2, range3 ];
 			const ranges = [ range1, range2, range3 ];
-			const selection = new Selection( ranges, true );
+			const selection = new Selection( ranges, { backward: true } );
 
 
 			expect( selection.isBackward ).to.be.true;
 			expect( selection.isBackward ).to.be.true;
 		} );
 		} );
 
 
 		it( 'should be able to create a selection from the given range and isLastBackward flag', () => {
 		it( 'should be able to create a selection from the given range and isLastBackward flag', () => {
-			const selection = new Selection( range1, true );
+			const selection = new Selection( range1, { backward: true } );
 
 
 			expect( Array.from( selection.getRanges() ) ).to.deep.equal( [ range1 ] );
 			expect( Array.from( selection.getRanges() ) ).to.deep.equal( [ range1 ] );
 			expect( selection.isBackward ).to.be.true;
 			expect( selection.isBackward ).to.be.true;
@@ -58,7 +58,7 @@ describe( 'Selection', () => {
 
 
 		it( 'should be able to create a selection from the given iterable of ranges and isLastBackward flag', () => {
 		it( 'should be able to create a selection from the given iterable of ranges and isLastBackward flag', () => {
 			const ranges = new Set( [ range1, range2, range3 ] );
 			const ranges = new Set( [ range1, range2, range3 ] );
-			const selection = new Selection( ranges, false );
+			const selection = new Selection( ranges, { backward: false } );
 
 
 			expect( Array.from( selection.getRanges() ) ).to.deep.equal( [ range1, range2, range3 ] );
 			expect( Array.from( selection.getRanges() ) ).to.deep.equal( [ range1, range2, range3 ] );
 			expect( selection.isBackward ).to.be.false;
 			expect( selection.isBackward ).to.be.false;
@@ -85,7 +85,7 @@ describe( 'Selection', () => {
 		} );
 		} );
 
 
 		it( 'should be able to create a selection from the other selection', () => {
 		it( 'should be able to create a selection from the other selection', () => {
-			const otherSelection = new Selection( [ range2, range3 ], true );
+			const otherSelection = new Selection( [ range2, range3 ], { backward: true } );
 			const selection = new Selection( otherSelection );
 			const selection = new Selection( otherSelection );
 
 
 			expect( Array.from( selection.getRanges() ) ).to.deep.equal( [ range2, range3 ] );
 			expect( Array.from( selection.getRanges() ) ).to.deep.equal( [ range2, range3 ] );
@@ -140,7 +140,7 @@ describe( 'Selection', () => {
 		} );
 		} );
 
 
 		it( 'should return end of single range in selection when added as backward', () => {
 		it( 'should return end of single range in selection when added as backward', () => {
-			selection._setTo( range1, true );
+			selection._setTo( range1, { backward: true } );
 			const anchor = selection.anchor;
 			const anchor = selection.anchor;
 
 
 			expect( anchor.isEqual( range1.end ) ).to.be.true;
 			expect( anchor.isEqual( range1.end ) ).to.be.true;
@@ -167,7 +167,7 @@ describe( 'Selection', () => {
 		} );
 		} );
 
 
 		it( 'should return start of single range in selection when added as backward', () => {
 		it( 'should return start of single range in selection when added as backward', () => {
-			selection._setTo( range1, true );
+			selection._setTo( range1, { backward: true } );
 			const focus = selection.focus;
 			const focus = selection.focus;
 
 
 			expect( focus.isEqual( range1.start ) ).to.be.true;
 			expect( focus.isEqual( range1.start ) ).to.be.true;
@@ -254,7 +254,7 @@ describe( 'Selection', () => {
 			const endPos = Position.createAt( el, 2 );
 			const endPos = Position.createAt( el, 2 );
 			const newEndPos = Position.createAt( el, 3 );
 			const newEndPos = Position.createAt( el, 3 );
 
 
-			selection._setTo( new Range( startPos, endPos ), true );
+			selection._setTo( new Range( startPos, endPos ), { backward: true } );
 
 
 			selection._setFocus( newEndPos );
 			selection._setFocus( newEndPos );
 
 
@@ -268,7 +268,7 @@ describe( 'Selection', () => {
 			const endPos = Position.createAt( el, 2 );
 			const endPos = Position.createAt( el, 2 );
 			const newEndPos = Position.createAt( el, 0 );
 			const newEndPos = Position.createAt( el, 0 );
 
 
-			selection._setTo( new Range( startPos, endPos ), true );
+			selection._setTo( new Range( startPos, endPos ), { backward: true } );
 
 
 			selection._setFocus( newEndPos );
 			selection._setFocus( newEndPos );
 
 
@@ -376,7 +376,7 @@ describe( 'Selection', () => {
 			const range1 = Range.createFromParentsAndOffsets( el, 5, el, 10 );
 			const range1 = Range.createFromParentsAndOffsets( el, 5, el, 10 );
 			const range2 = Range.createFromParentsAndOffsets( el, 15, el, 16 );
 			const range2 = Range.createFromParentsAndOffsets( el, 15, el, 16 );
 
 
-			selection._setTo( range1, true );
+			selection._setTo( range1, { backward: true } );
 			expect( selection ).to.have.property( 'isBackward', true );
 			expect( selection ).to.have.property( 'isBackward', true );
 
 
 			selection._setTo( [ range1, range2 ] );
 			selection._setTo( [ range1, range2 ] );
@@ -386,7 +386,7 @@ describe( 'Selection', () => {
 		it( 'is false when last range is collapsed', () => {
 		it( 'is false when last range is collapsed', () => {
 			const range = Range.createFromParentsAndOffsets( el, 5, el, 5 );
 			const range = Range.createFromParentsAndOffsets( el, 5, el, 5 );
 
 
-			selection._setTo( range, true );
+			selection._setTo( range, { backward: true } );
 
 
 			expect( selection.isBackward ).to.be.false;
 			expect( selection.isBackward ).to.be.false;
 		} );
 		} );
@@ -478,9 +478,9 @@ describe( 'Selection', () => {
 		} );
 		} );
 
 
 		it( 'should return true if backward selections equal', () => {
 		it( 'should return true if backward selections equal', () => {
-			selection._setTo( range1, true );
+			selection._setTo( range1, { backward: true } );
 
 
-			const otherSelection = new Selection( [ range1 ], true );
+			const otherSelection = new Selection( [ range1 ], { backward: true } );
 
 
 			expect( selection.isEqual( otherSelection ) ).to.be.true;
 			expect( selection.isEqual( otherSelection ) ).to.be.true;
 		} );
 		} );
@@ -504,7 +504,7 @@ describe( 'Selection', () => {
 		it( 'should return false if directions do not equal', () => {
 		it( 'should return false if directions do not equal', () => {
 			selection._setTo( range1 );
 			selection._setTo( range1 );
 
 
-			const otherSelection = new Selection( [ range1 ], true );
+			const otherSelection = new Selection( [ range1 ], { backward: true } );
 
 
 			expect( selection.isEqual( otherSelection ) ).to.be.false;
 			expect( selection.isEqual( otherSelection ) ).to.be.false;
 		} );
 		} );
@@ -569,7 +569,7 @@ describe( 'Selection', () => {
 		it( 'should return false if directions are not equal', () => {
 		it( 'should return false if directions are not equal', () => {
 			selection._setTo( range1 );
 			selection._setTo( range1 );
 
 
-			const otherSelection = new Selection( [ range1 ], true );
+			const otherSelection = new Selection( [ range1 ], { backward: true } );
 
 
 			expect( selection.isSimilar( otherSelection ) ).to.be.false;
 			expect( selection.isSimilar( otherSelection ) ).to.be.false;
 		} );
 		} );
@@ -646,7 +646,7 @@ describe( 'Selection', () => {
 			it( 'should set selection ranges from the given selection', () => {
 			it( 'should set selection ranges from the given selection', () => {
 				selection._setTo( range1 );
 				selection._setTo( range1 );
 
 
-				const otherSelection = new Selection( [ range2, range3 ], true );
+				const otherSelection = new Selection( [ range2, range3 ], { backward: true } );
 
 
 				selection._setTo( otherSelection );
 				selection._setTo( otherSelection );
 
 
@@ -753,7 +753,7 @@ describe( 'Selection', () => {
 				const foo = new Text( 'foo' );
 				const foo = new Text( 'foo' );
 				const p = new Element( 'p', null, foo );
 				const p = new Element( 'p', null, foo );
 
 
-				selection._setTo( foo );
+				selection._setTo( foo, 0 );
 				let range = selection.getFirstRange();
 				let range = selection.getFirstRange();
 
 
 				expect( range.start.parent ).to.equal( foo );
 				expect( range.start.parent ).to.equal( foo );
@@ -768,6 +768,14 @@ describe( 'Selection', () => {
 				expect( range.start.isEqual( range.end ) ).to.be.true;
 				expect( range.start.isEqual( range.end ) ).to.be.true;
 			} );
 			} );
 
 
+			it( 'should throw an error when the second parameter is not passed and first is an item', () => {
+				const foo = new Text( 'foo' );
+
+				expect( () => {
+					selection._setTo( foo );
+				} ).to.throw( CKEditorError, /view-selection-setTo-required-second-parameter/ );
+			} );
+
 			it( 'should collapse selection at node and flag', () => {
 			it( 'should collapse selection at node and flag', () => {
 				const foo = new Text( 'foo' );
 				const foo = new Text( 'foo' );
 				const p = new Element( 'p', null, foo );
 				const p = new Element( 'p', null, foo );