Browse Source

Added getSelectedElement method to view selection.

Szymon Kupś 9 years ago
parent
commit
3b725351ca

+ 20 - 0
packages/ckeditor5-engine/src/view/selection.js

@@ -8,6 +8,7 @@ import Range from './range.js';
 import Position from './position.js';
 import mix from '../../utils/mix.js';
 import EmitterMixin from '../../utils/emittermixin.js';
+import Element from './element.js';
 
 /**
  * Class representing selection in tree view.
@@ -461,6 +462,25 @@ export default class Selection {
 	}
 
 	/**
+	 * Returns selected element. {@link engine.view.Element Element} is considered as selected if there is only
+	 * one range in selection, and that range is placed exactly on one element.
+	 * Returns `null` if there is no selected element.
+	 *
+	 * @return {engine.view.Element|null}
+	 */
+	getSelectedElement() {
+		if ( this.rangeCount == 1 ) {
+			const range = this.getFirstRange();
+			const nodeAfterStart = range.start.nodeAfter;
+			const nodeBeforeEnd = range.end.nodeBefore;
+
+			return nodeAfterStart instanceof Element && nodeAfterStart == nodeBeforeEnd ? nodeAfterStart : null;
+		}
+
+		return null;
+	}
+
+	/**
 	 * 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.
 	 *

+ 32 - 0
packages/ckeditor5-engine/tests/view/selection.js

@@ -13,6 +13,7 @@ import Text from 'ckeditor5/engine/view/text.js';
 import Position from 'ckeditor5/engine/view/position.js';
 import CKEditorError from 'ckeditor5/utils/ckeditorerror.js';
 import count from 'ckeditor5/utils/count.js';
+import { parse } from 'ckeditor5/engine/dev-utils/view.js';
 
 describe( 'Selection', () => {
 	let selection;
@@ -778,4 +779,35 @@ describe( 'Selection', () => {
 			selection.setFake( true, { label: 'foo bar baz' } );
 		} );
 	} );
+
+	describe( 'getSelectedElement', () => {
+		it( 'should return selected element', () => {
+			const { selection, view } = parse( 'foo [<b>bar</b>] baz' );
+			const p = view.getChild( 1 );
+
+			expect( selection.getSelectedElement() ).to.equal( p );
+		} );
+
+		it( 'should return null if there is more than one range', () => {
+			const { selection } = parse( 'foo [<b>bar</b>] [<i>baz</i>]' );
+
+			expect( selection.getSelectedElement() ).to.be.null;
+		} );
+
+		it( 'should return null if there is no selection', () => {
+			expect( selection.getSelectedElement() ).to.be.null;
+		} );
+
+		it( 'should return null if selection is not over single element #1', () => {
+			const { selection } = parse( 'foo [<b>bar</b> ba}z' );
+
+			expect( selection.getSelectedElement() ).to.be.null;
+		} );
+
+		it( 'should return null if selection is not over single element #2', () => {
+			const { selection } = parse( 'foo <b>{bar}</b> baz' );
+
+			expect( selection.getSelectedElement() ).to.be.null;
+		} );
+	} );
 } );