Browse Source

Docs and API improvements for the DataController.

Piotr Jasiun 9 years ago
parent
commit
c3974abed1

+ 116 - 13
packages/ckeditor5-engine/src/datacontroller.js

@@ -21,32 +21,114 @@ import { NBSP_FILLER } from './treeview/filler.js';
 import ModelRange from './treemodel/range.js';
 import ModelPosition from './treemodel/position.js';
 
+/**
+ * Data pipeline controlling class. The main usage for this class is to let user {@link engine.DataController#get get}
+ * and {@link engine.DataController#set set} data of the {@link engine.DataController#model model}
+ * using given {@link engine.dataProcessor.DataProcessor DataProcessor} and
+ * {@link engine.treeController.ModelConversionDispatcher model to view} and
+ * {@link engine.treeController.ViewConversionDispatcher view to model} converters.
+ *
+ * @memberOf engine
+ */
 export default class DataController {
+	/**
+	 * Creates data controller instance for {@link engine.DataController#get getting} data from and
+	 * {@link engine.DataController#set setting} data to the given {@link engine.treeModel.document document model},
+	 * using given {@link engine.dataProcessor.DataProcessor DataProcessor}.
+	 *
+	 * @param {engine.treeModel.Document} modelDocument Controlled model document.
+	 * @param {engine.dataProcessor.DataProcessor} dataProcessor Data processor which should used by the controller.
+	 */
 	constructor( modelDocument, dataProcessor ) {
+		/**
+		 * Controlled model document.
+		 *
+		 * @readonly
+		 * @member {engine.treeModel.document} engine.DataController#model
+		 */
 		this.model = modelDocument;
 
+		/**
+		 * DataProcessor used during the conversion.
+		 *
+		 * @readonly
+		 * @member {engine.dataProcessor.DataProcessor} engine.DataController#processor
+		 */
+		this.processor = dataProcessor;
+
+		/**
+		 * Mapper used for the conversion. In has no permanent bindings, because they are created on getting data and cleared
+		 * directly after data are converted. However, the mapper is defined as class property, because it need to be
+		 * passed to the `ModelConversionDispatcher` as a conversion API.
+		 *
+		 * @private
+		 * @member {engine.treeController.Mapper} engine.DataController#_mapper
+		 */
 		this._mapper = new Mapper();
 
+		/**
+		 * Writer used during the conversion.
+		 *
+		 * @private
+		 * @member {engine.treeView.Writer} engine.DataController#_writer
+		 */
 		this._writer = new Writer();
 
+		/**
+		 * DomConverter used during the conversion.
+		 *
+		 * @private
+		 * @member {engine.treeView.DomConverter} engine.DataController#_domConverter
+		 */
 		this._domConverter = new DomConverter( { blockFiller: NBSP_FILLER } );
 
-		this._processor = dataProcessor;
-
-		this.toView = new ModelConversionDispatcher( {
+		/**
+		 * Model to view conversion dispatcher used by the {@link engine.DataController#get get method}.
+		 * To attach model to view converter to the data pipeline you need to add lister to this property:
+		 *
+		 *		data.modelToView( 'insert:$element', customInsertConverter );
+		 *
+		 * Or use {@link engine.treeController.ModelConverterBuilder}:
+		 *
+		 *		BuildModelConverterFor( data.modelToView ).fromAttribute( 'bold' ).toElement( 'b' );
+		 *
+		 * @readonly
+		 * @member {engine.treeController.ModelConversionDispatcher} engine.DataController#modelToView
+		 */
+		this.modelToView = new ModelConversionDispatcher( {
 			writer: this._writer,
 			mapper: this._mapper
 		} );
-		this.toView.on( 'insert:$text', insertText() );
-
-		this.toModel = new ViewConversionDispatcher( {
+		this.modelToView.on( 'insert:$text', insertText() );
+
+		/**
+		 * View to model conversion dispatcher used by the {@link engine.DataController#set set method}.
+		 * To attach view to model converter to the data pipeline you need to add lister to this property:
+		 *
+		 *		data.viewToModel( 'element', customElementConverter );
+		 *
+		 * Or use {@link engine.treeController.ViewConverterBuilder}:
+		 *
+		 *		BuildViewConverterFor( data.viewToModel ).fromElement( 'b' ).toAttribute( 'bold', true );
+		 *
+		 * @readonly
+		 * @member {engine.treeController.ViewConversionDispatcher} engine.DataController#viewToModel
+		 */
+		this.viewToModel = new ViewConversionDispatcher( {
 			schema: modelDocument.schema
 		} );
-		this.toModel.on( 'text', convertText() );
-		this.toModel.on( 'element', convertToModelFragment(), null, 9999 );
-		this.toModel.on( 'documentFragment', convertToModelFragment(), null, 9999 );
+		this.viewToModel.on( 'text', convertText() );
+		this.viewToModel.on( 'element', convertToModelFragment(), null, 9999 );
+		this.viewToModel.on( 'documentFragment', convertToModelFragment(), null, 9999 );
 	}
 
+	/**
+	 * Returns model data converted by {@link engine.DataController#modelToView model to view converters} and
+	 * formated by the {@link engine.DataController#processor data processor}.
+	 *
+	 * @param {String} [rootName='main'] Root name.
+	 * @returns {String} Output data.
+	 */
 	get( rootName = 'main' ) {
 		// Get model range
 		const modelRoot = this.model.getRoot( rootName );
@@ -56,7 +138,7 @@ export default class DataController {
 		const viewDocumentFragment = new ViewDocumentFragment();
 		this._mapper.bindElements( modelRoot, viewDocumentFragment );
 
-		this.toView.convertInsert( modelRange );
+		this.modelToView.convertInsert( modelRange );
 
 		this._mapper.clearBindings();
 
@@ -64,9 +146,19 @@ export default class DataController {
 		const domDocumentFragment = this._domConverter.viewToDom( viewDocumentFragment, document );
 
 		// DOM -> data
-		return this._processor.toData( domDocumentFragment );
+		return this.processor.toData( domDocumentFragment );
 	}
 
+	/**
+	 * Sets input data parsed by the {@link engine.DataController#processor data processor} and
+	 * converted by {@link engine.DataController#viewToModel view to model converters}.
+	 *
+	 * This method also creates a batch with applied changes. If all you need is to parse data use
+	 * {@link engine.dataController#parse}.
+	 *
+	 * @param {String} [rootName='main'] Roots name.
+	 * @param {String} data Input data.
+	 */
 	set( rootName, data ) {
 		if ( !data ) {
 			data = rootName;
@@ -81,18 +173,29 @@ export default class DataController {
 			.insert( ModelPosition.createAt( modelRoot, 0 ), this.parse( data ) );
 	}
 
+	/**
+	 * Returns data parsed by the {@link engine.DataController#processor data processor} and then
+	 * converted by {@link engine.DataController#viewToModel view to model converters}.
+	 *
+	 * @see engine.dataController#set
+	 * @param {String} data Data to parse.
+	 * @returns {engine.treeModel.DocumentFragment} Parsed data.
+	 */
 	parse( data ) {
 		// data -> DOM
-		const domDocumentFragment = this._processor.toDom( data );
+		const domDocumentFragment = this.processor.toDom( data );
 
 		// DOM -> view
 		const viewDocumentFragment = this._domConverter.domToView( domDocumentFragment );
 
 		// view -> model
-		const modelDocumentFragment = this.toModel.convert( viewDocumentFragment, { context: [ '$root' ] } );
+		const modelDocumentFragment = this.viewToModel.convert( viewDocumentFragment, { context: [ '$root' ] } );
 
 		return modelDocumentFragment;
 	}
 
+	/**
+	 * Removes all events listeners set by the DataController.
+	 */
 	destroy() {}
 }

+ 12 - 12
packages/ckeditor5-engine/tests/datacontroller.js

@@ -44,7 +44,7 @@ describe( 'DataController', () => {
 		it( 'should set paragraph', () => {
 			schema.registerItem( 'paragraph', '$block' );
 
-			BuildViewConverterFor( data.toModel ).fromElement( 'p' ).toElement( 'paragraph' );
+			BuildViewConverterFor( data.viewToModel ).fromElement( 'p' ).toElement( 'paragraph' );
 
 			const model = data.parse( '<p>foo<b>bar</b></p>' );
 
@@ -54,7 +54,7 @@ describe( 'DataController', () => {
 		it( 'should set two paragraphs', () => {
 			schema.registerItem( 'paragraph', '$block' );
 
-			BuildViewConverterFor( data.toModel ).fromElement( 'p' ).toElement( 'paragraph' );
+			BuildViewConverterFor( data.viewToModel ).fromElement( 'p' ).toElement( 'paragraph' );
 
 			const model = data.parse( '<p>foo</p><p>bar</p>' );
 
@@ -66,8 +66,8 @@ describe( 'DataController', () => {
 			schema.registerItem( 'paragraph', '$block' );
 			schema.allow( { name: '$text', attributes: [ 'bold' ], inside: '$block' } );
 
-			BuildViewConverterFor( data.toModel ).fromElement( 'p' ).toElement( 'paragraph' );
-			BuildViewConverterFor( data.toModel ).fromElement( 'b' ).toAttribute( 'bold', true );
+			BuildViewConverterFor( data.viewToModel ).fromElement( 'p' ).toElement( 'paragraph' );
+			BuildViewConverterFor( data.viewToModel ).fromElement( 'b' ).toAttribute( 'bold', true );
 
 			const model = data.parse( '<p>foo<b>bar</b></p>' );
 
@@ -107,7 +107,7 @@ describe( 'DataController', () => {
 		it( 'should get paragraph with text', () => {
 			setData( modelDocument, '<paragraph>foo</paragraph>' );
 
-			BuildModelConverterFor( data.toView ).fromElement( 'paragraph' ).toElement( 'p' );
+			BuildModelConverterFor( data.modelToView ).fromElement( 'paragraph' ).toElement( 'p' );
 
 			expect( data.get() ).to.equal( '<p>foo</p>' );
 		} );
@@ -115,7 +115,7 @@ describe( 'DataController', () => {
 		it( 'should get empty paragraph', () => {
 			setData( modelDocument, '<paragraph></paragraph>' );
 
-			BuildModelConverterFor( data.toView ).fromElement( 'paragraph' ).toElement( 'p' );
+			BuildModelConverterFor( data.modelToView ).fromElement( 'paragraph' ).toElement( 'p' );
 
 			expect( data.get() ).to.equal( '<p>&nbsp;</p>' );
 		} );
@@ -123,7 +123,7 @@ describe( 'DataController', () => {
 		it( 'should get two paragraphs', () => {
 			setData( modelDocument, '<paragraph>foo</paragraph><paragraph>bar</paragraph>' );
 
-			BuildModelConverterFor( data.toView ).fromElement( 'paragraph' ).toElement( 'p' );
+			BuildModelConverterFor( data.modelToView ).fromElement( 'paragraph' ).toElement( 'p' );
 
 			expect( data.get() ).to.equal( '<p>foo</p><p>bar</p>' );
 		} );
@@ -137,7 +137,7 @@ describe( 'DataController', () => {
 		it( 'should get paragraphs without bold', () => {
 			setData( modelDocument, '<paragraph>foo<$text bold=true>bar</$text></paragraph>' );
 
-			BuildModelConverterFor( data.toView ).fromElement( 'paragraph' ).toElement( 'p' );
+			BuildModelConverterFor( data.modelToView ).fromElement( 'paragraph' ).toElement( 'p' );
 
 			expect( data.get() ).to.equal( '<p>foobar</p>' );
 		} );
@@ -145,8 +145,8 @@ describe( 'DataController', () => {
 		it( 'should get paragraphs with bold', () => {
 			setData( modelDocument, '<paragraph>foo<$text bold=true>bar</$text></paragraph>' );
 
-			BuildModelConverterFor( data.toView ).fromElement( 'paragraph' ).toElement( 'p' );
-			BuildModelConverterFor( data.toView ).fromAttribute( 'bold' ).toElement( 'b' );
+			BuildModelConverterFor( data.modelToView ).fromElement( 'paragraph' ).toElement( 'p' );
+			BuildModelConverterFor( data.modelToView ).fromAttribute( 'bold' ).toElement( 'b' );
 
 			expect( data.get() ).to.equal( '<p>foo<b>bar</b></p>' );
 		} );
@@ -155,8 +155,8 @@ describe( 'DataController', () => {
 			setData( modelDocument, '<paragraph>foo</paragraph>', { rootName: 'main' } );
 			setData( modelDocument, 'Bar', { rootName: 'title' } );
 
-			BuildModelConverterFor( data.toView ).fromElement( 'paragraph' ).toElement( 'p' );
-			BuildModelConverterFor( data.toView ).fromAttribute( 'bold' ).toElement( 'b' );
+			BuildModelConverterFor( data.modelToView ).fromElement( 'paragraph' ).toElement( 'p' );
+			BuildModelConverterFor( data.modelToView ).fromAttribute( 'bold' ).toElement( 'b' );
 
 			expect( data.get() ).to.equal( '<p>foo</p>' );
 			expect( data.get( 'main' ) ).to.equal( '<p>foo</p>' );