瀏覽代碼

Merge pull request #1064 from ckeditor/t/1063

Feature: Introduced the `Selection#isEntireContentSelected( element )` method. Closes #1063.
Piotrek Koszuliński 8 年之前
父節點
當前提交
1c86b7014b

+ 1 - 6
packages/ckeditor5-engine/src/controller/deletecontent.js

@@ -197,13 +197,8 @@ function replaceEntireContentWithParagraph( batch, selection ) {
 // * whether the paragraph is allowed in schema in the common ancestor.
 function shouldEntireContentBeReplacedWithParagraph( schema, selection ) {
 	const limitElement = schema.getLimitElement( selection );
-	const limitStartPosition = Position.createAt( limitElement );
-	const limitEndPosition = Position.createAt( limitElement, 'end' );
 
-	if (
-		!limitStartPosition.isTouching( selection.getFirstPosition() ) ||
-		!limitEndPosition.isTouching( selection.getLastPosition() )
-	) {
+	if ( !selection.isEntireContentSelected( limitElement ) ) {
 		return false;
 	}
 

+ 19 - 0
packages/ckeditor5-engine/src/model/selection.js

@@ -624,6 +624,25 @@ export default class Selection {
 		}
 	}
 
+	/**
+	 * Checks whether the selection contains the entire content of the given element. This means that selection must start
+	 * at a position {@link module:engine/model/position~Position#isTouching touching} the element's start and ends at position
+	 * touching the element's end.
+	 *
+	 * By default, this method will check whether the entire content of the selection's current root is selected.
+	 * Useful to check if e.g. the user has just pressed <kbd>Ctrl</kbd> + <kbd>A</kbd>.
+	 *
+	 * @param {module:engine/model/element~Element} [element=this.anchor.root]
+	 * @returns {Boolean}
+	 */
+	isEntireContentSelected( element = this.anchor.root ) {
+		const limitStartPosition = Position.createAt( element );
+		const limitEndPosition = Position.createAt( element, 'end' );
+
+		return limitStartPosition.isTouching( this.getFirstPosition() ) &&
+			limitEndPosition.isTouching( this.getLastPosition() );
+	}
+
 	/**
 	 * Creates and returns an instance of `Selection` that is a clone of given selection, meaning that it has same
 	 * ranges and same direction as this selection.

+ 58 - 0
packages/ckeditor5-engine/tests/model/selection.js

@@ -1237,4 +1237,62 @@ describe( 'Selection', () => {
 			} );
 		} );
 	} );
+
+	describe( 'isEntireContentSelected()', () => {
+		beforeEach( () => {
+			doc.schema.registerItem( 'p', '$block' );
+			doc.schema.allow( { name: 'p', inside: '$root' } );
+		} );
+
+		it( 'returns true if the entire content in $root is selected', () => {
+			setData( doc, '<p>[Foo</p><p>Bom</p><p>Bar]</p>' );
+
+			expect( doc.selection.isEntireContentSelected() ).to.equal( true );
+		} );
+
+		it( 'returns false when only a fragment of the content in $root is selected', () => {
+			setData( doc, '<p>Fo[o</p><p>Bom</p><p>Bar]</p>' );
+
+			expect( doc.selection.isEntireContentSelected() ).to.equal( false );
+		} );
+
+		it( 'returns true if the entire content in specified element is selected', () => {
+			setData( doc, '<p>Foo</p><p>[Bom]</p><p>Bar</p>' );
+
+			const root = doc.getRoot();
+			const secondParagraph = root.getNodeByPath( [ 1 ] );
+
+			expect( doc.selection.isEntireContentSelected( secondParagraph ) ).to.equal( true );
+		} );
+
+		it( 'returns false if the entire content in specified element is not selected', () => {
+			setData( doc, '<p>Foo</p><p>[Bom</p><p>B]ar</p>' );
+
+			const root = doc.getRoot();
+			const secondParagraph = root.getNodeByPath( [ 1 ] );
+
+			expect( doc.selection.isEntireContentSelected( secondParagraph ) ).to.equal( false );
+		} );
+
+		it( 'returns false when the entire content except an empty element is selected', () => {
+			doc.schema.registerItem( 'img', '$inline' );
+			doc.schema.allow( { name: 'img', inside: 'p' } );
+
+			setData( doc, '<p><img></img>[Foo]</p>' );
+
+			expect( doc.selection.isEntireContentSelected() ).to.equal( false );
+		} );
+
+		it( 'returns true if the content is empty', () => {
+			setData( doc, '[]' );
+
+			expect( doc.selection.isEntireContentSelected() ).to.equal( true );
+		} );
+
+		it( 'returns false if empty selection is at the end of non-empty content', () => {
+			setData( doc, '<p>Foo bar bom.</p>[]' );
+
+			expect( doc.selection.isEntireContentSelected() ).to.equal( false );
+		} );
+	} );
 } );