浏览代码

Changed: Introduced `DataController#hasContent`.

Szymon Cofalik 8 年之前
父节点
当前提交
8825e61b71

+ 29 - 0
packages/ckeditor5-engine/src/controller/datacontroller.js

@@ -22,6 +22,7 @@ import ViewDocumentFragment from '../view/documentfragment';
 
 import ModelRange from '../model/range';
 import ModelPosition from '../model/position';
+import ModelElement from '../model/element';
 
 import insertContent from './insertcontent';
 import deleteContent from './deletecontent';
@@ -297,6 +298,34 @@ export default class DataController {
 	getSelectedContent( selection ) {
 		return getSelectedContent( selection );
 	}
+
+	/**
+	 * Checks whether given {@link module:engine/model/range~Range range} or {@link module:engine/model/element~Element element}
+	 * has any content.
+	 *
+	 * Content is any text node or element which is registered in {@link module:engine/model/schema~Schema schema}.
+	 *
+	 * @param {module:engine/model/range~Range|module:engine/model/element~Element} rangeOrElement Range or element to check.
+	 * @returns {Boolean}
+	 */
+	hasContent( rangeOrElement ) {
+		if ( rangeOrElement instanceof ModelElement ) {
+			rangeOrElement = ModelRange.createIn( rangeOrElement );
+		}
+
+		if ( rangeOrElement.isCollapsed ) {
+			return false;
+		}
+
+		for ( const item of rangeOrElement.getItems() ) {
+			// Remember, `TreeWalker` returns always `textProxy` nodes.
+			if ( item.is( 'textProxy' ) || this.model.schema.objects.has( item.name ) ) {
+				return true;
+			}
+		}
+
+		return false;
+	}
 }
 
 mix( DataController, ObservableMixin );

+ 84 - 0
packages/ckeditor5-engine/tests/controller/datacontroller.js

@@ -12,6 +12,7 @@ import buildModelConverter from '../../src/conversion/buildmodelconverter';
 
 import ModelDocumentFragment from '../../src/model/documentfragment';
 import ModelText from '../../src/model/text';
+import ModelRange from '../../src/model/range';
 import ModelSelection from '../../src/model/selection';
 
 import ViewDocumentFragment from '../../src/view/documentfragment';
@@ -439,4 +440,87 @@ describe( 'DataController', () => {
 			expect( stringify( content ) ).to.equal( 'ob' );
 		} );
 	} );
+
+	describe( 'hasContent', () => {
+		let root;
+
+		beforeEach( () => {
+			schema.registerItem( 'paragraph', '$block' );
+			schema.registerItem( 'div', '$block' );
+			schema.allow( { name: '$block', inside: 'div' } );
+			schema.registerItem( 'image' );
+			schema.allow( { name: 'image', inside: 'div' } );
+			schema.objects.add( 'image' );
+
+			setData(
+				modelDocument,
+
+				'<div>' +
+					'<paragraph></paragraph>' +
+				'</div>' +
+				'<paragraph>foo</paragraph>' +
+				'<div>' +
+					'<image></image>' +
+				'</div>'
+			);
+
+			root = modelDocument.getRoot();
+		} );
+
+		it( 'should return true if given element has text node', () => {
+			const pFoo = root.getChild( 1 );
+
+			expect( data.hasContent( pFoo ) ).to.be.true;
+		} );
+
+		it( 'should return true if given element has element that is an object', () => {
+			const divImg = root.getChild( 2 );
+
+			expect( data.hasContent( divImg ) ).to.be.true;
+		} );
+
+		it( 'should return false if given element has no elements', () => {
+			const pEmpty = root.getChild( 0 ).getChild( 0 );
+
+			expect( data.hasContent( pEmpty ) ).to.be.false;
+		} );
+
+		it( 'should return false if given element has only elements that are not objects', () => {
+			const divP = root.getChild( 0 );
+
+			expect( data.hasContent( divP ) ).to.be.false;
+		} );
+
+		it( 'should return true if there is a text node in given range', () => {
+			const range = ModelRange.createFromParentsAndOffsets( root, 1, root, 2 );
+
+			expect( data.hasContent( range ) ).to.be.true;
+		} );
+
+		it( 'should return true if there is a part of text node in given range', () => {
+			const pFoo = root.getChild( 1 );
+			const range = ModelRange.createFromParentsAndOffsets( pFoo, 1, pFoo, 2 );
+
+			expect( data.hasContent( range ) ).to.be.true;
+		} );
+
+		it( 'should return true if there is element that is an object in given range', () => {
+			const divImg = root.getChild( 2 );
+			const range = ModelRange.createFromParentsAndOffsets( divImg, 0, divImg, 1 );
+
+			expect( data.hasContent( range ) ).to.be.true;
+		} );
+
+		it( 'should return false if range is collapsed', () => {
+			const range = ModelRange.createFromParentsAndOffsets( root, 1, root, 1 );
+
+			expect( data.hasContent( range ) ).to.be.false;
+		} );
+
+		it( 'should return false if range has only elements that are not objects', () => {
+			const range = ModelRange.createFromParentsAndOffsets( root, 0, root, 1 );
+
+			expect( data.hasContent( range ) ).to.be.false;
+		} );
+	} );
 } );