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

Commit

Permalink
Introduced view.Node#getCommonAncestor().
Browse files Browse the repository at this point in the history
  • Loading branch information
Reinmar committed Jul 21, 2017
1 parent 642d355 commit 537eac9
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/view/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,26 @@ export default class Node {
return ancestors;
}

/**
* Returns a {@link module:engine/view/element~Element} or {@link module:engine/view/documentfragment~DocumentFragment}
* which is a common ancestor of both nodes.
*
* @param {module:engine/view/node~Node} node The second node.
* @returns {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment|null}
*/
getCommonAncestor( node ) {
const ancestorsA = this.getAncestors();
const ancestorsB = node.getAncestors();

let i = 0;

while ( ancestorsA[ i ] == ancestorsB[ i ] && ancestorsA[ i ] ) {
i++;
}

return i === 0 ? null : ancestorsA[ i - 1 ];
}

/**
* Removes node from parent.
*/
Expand Down
51 changes: 51 additions & 0 deletions tests/view/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,57 @@ describe( 'Node', () => {
} );
} );

describe( 'getCommonAncestor()', () => {
it( 'should return the parent element for the same node', () => {
expect( img.getCommonAncestor( img ) ).to.equal( two );
} );

it( 'should return null for detached subtrees', () => {
const detached = new Element( 'foo' );

expect( img.getCommonAncestor( detached ) ).to.be.null;
expect( detached.getCommonAncestor( img ) ).to.be.null;
} );

it( 'should return null when one of the nodes is a tree root itself', () => {
expect( root.getCommonAncestor( img ) ).to.be.null;
expect( img.getCommonAncestor( root ) ).to.be.null;
expect( root.getCommonAncestor( root ) ).to.be.null;
} );

it( 'should return parent of the nodes at the same level', () => {
expect( img.getCommonAncestor( charA ) ).to.equal( two );
expect( charB.getCommonAncestor( charA ) ).to.equal( two );
} );

it( 'should return proper element for nodes in different branches and on different levels', () => {
const foo = new Text( 'foo' );
const bar = new Text( 'bar' );
const bom = new Text( 'bom' );
const d = new Element( 'd', null, [ bar ] );
const c = new Element( 'c', null, [ foo, d ] );
const b = new Element( 'b', null, [ c ] );
const e = new Element( 'e', null, [ bom ] );
const a = new Element( 'a', null, [ b, e ] );

// <a><b><c>foo<d>bar</d></c></b><e>bom</e></a>

expect( bar.getCommonAncestor( foo ), 1 ).to.equal( c );
expect( foo.getCommonAncestor( d ), 2 ).to.equal( c );
expect( c.getCommonAncestor( b ), 3 ).to.equal( a );
expect( bom.getCommonAncestor( d ), 4 ).to.equal( a );
expect( b.getCommonAncestor( bom ), 5 ).to.equal( a );
} );

it( 'should return document fragment', () => {
const foo = new Text( 'foo' );
const bar = new Text( 'bar' );
const df = new DocumentFragment( [ foo, bar ] );

expect( foo.getCommonAncestor( bar ) ).to.equal( df );
} );
} );

describe( 'getIndex()', () => {
it( 'should return null if the parent is null', () => {
expect( root.index ).to.be.null;
Expand Down

0 comments on commit 537eac9

Please sign in to comment.