Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

T/1063: Introduce Selection#isEntireContentSelected( element ) #1064

Merged
merged 4 commits into from
Aug 15, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions src/controller/deletecontent.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
14 changes: 14 additions & 0 deletions src/model/selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,20 @@ export default class Selection {
}
}

/**
* Checks whether the entire content in specified element is selected.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This description is not accurate. In such case, the <b>'s content is also fully selected:

<div>[x<b>y</b>z]</div>

It's hard to explain this in just one paragraph, but we should try with something like:

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.

*
* @param {module:engine/model/element~Element} element
* @returns {Boolean}
*/
isEntireContentSelected( element ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This element should default to the root of the selection's root (this.anchor.root will be fine).

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.
Expand Down
52 changes: 52 additions & 0 deletions tests/model/selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -1237,4 +1237,56 @@ describe( 'Selection', () => {
} );
} );
} );

describe( 'isEntireContentSelected()', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing tests:

  • empty content,
  • empty selection at a boundary of non-empty content

Copy link
Member Author

@pomek pomek Aug 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 9ee9e12.

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>' );

const root = doc.getRoot();

expect( doc.selection.isEntireContentSelected( root ) ).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>' );

const root = doc.getRoot();

expect( doc.selection.isEntireContentSelected( root ) ).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>' );

const root = doc.getRoot();

expect( doc.selection.isEntireContentSelected( root ) ).to.equal( false );
} );
} );
} );