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

Commit

Permalink
Implemented the Range#getContainedElement() method.
Browse files Browse the repository at this point in the history
  • Loading branch information
oleq committed Mar 6, 2020
1 parent f3d884e commit d063199
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/model/range.js
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,27 @@ export default class Range {
return this.start.getCommonAncestor( this.end );
}

/**
* Returns an element contained by a range. The element will be returned when it is the **only** node
* within the range and **fully–contained** at the same time.
*
* @returns {module:engine/model/element~Element|null}
*/
getContainedElement() {
if ( this.isCollapsed ) {
return null;
}

const nodeAfterStart = this.start.nodeAfter;
const nodeBeforeEnd = this.end.nodeBefore;

if ( nodeAfterStart && nodeAfterStart.is( 'element' ) && nodeAfterStart === nodeBeforeEnd ) {
return nodeAfterStart;
}

return null;
}

/**
* Converts `Range` to plain object and returns it.
*
Expand Down
41 changes: 41 additions & 0 deletions tests/model/range.js
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,47 @@ describe( 'Range', () => {
} );
} );

describe( 'getContainerElement()', () => {
beforeEach( () => {
prepareRichRoot( root );
} );

it( 'should return an element when it is fully contained by the range', () => {
// <div><h>first</h><p>lorem ipsum</p></div>[<p>foo</p>]<p>bar</p><div><h>second</h><p>lorem</p></div>
const range = new Range( new Position( root, [ 1 ] ), new Position( root, [ 2 ] ) );

expect( range.getContainedElement() ).to.equal( root.getNodeByPath( [ 1 ] ) );
} );

it( 'should return "null" if the range is collapsed', () => {
// <div><h>first</h><p>lorem ipsum</p></div>[]<p>foo</p><p>bar</p><div><h>second</h><p>lorem</p></div>
const range = new Range( new Position( root, [ 1 ] ) );

expect( range.getContainedElement() ).to.be.null;
} );

it( 'should return "null" if it contains 2+ elements', () => {
// <div><h>first</h><p>lorem ipsum</p></div>[<p>foo</p><p>bar</p>]<div><h>second</h><p>lorem</p></div>
const range = new Range( new Position( root, [ 1 ] ), new Position( root, [ 3 ] ) );

expect( range.getContainedElement() ).to.be.null;
} );

it( 'should return "null" if it contains an element and some other nodes', () => {
// <div><h>first</h><p>lorem ipsum</p></div>[<p>foo</p><p>ba]r</p><div><h>second</h><p>lorem</p></div>
const range = new Range( new Position( root, [ 1 ] ), new Position( root, [ 2, 2 ] ) );

expect( range.getContainedElement() ).to.be.null;
} );

it( 'should return "null" if it fully contains a node but the node is not an element', () => {
// <div><h>first</h><p>lorem ipsum</p></div><p>foo</p><p>[bar]</p><div><h>second</h><p>lorem</p></div>
const range = new Range( new Position( root, [ 2, 0 ] ), new Position( root, [ 2, 3 ] ) );

expect( range.getContainedElement() ).to.be.null;
} );
} );

function mapNodesToNames( nodes ) {
return nodes.map( node => {
return ( node instanceof Element ) ? 'E:' + node.name : 'T:' + node.data;
Expand Down

0 comments on commit d063199

Please sign in to comment.