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

Commit

Permalink
Added view.roots -> model.roots binding to EditingController.
Browse files Browse the repository at this point in the history
  • Loading branch information
oskarwrobel committed Jan 9, 2018
1 parent 76e6666 commit f7765ed
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 88 deletions.
40 changes: 16 additions & 24 deletions src/controller/editingcontroller.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* @module engine/controller/editingcontroller
*/

import RootEditableElement from '../view/rooteditableelement';
import ModelDiffer from '../model/differ';
import ViewDocument from '../view/document';
import Mapper from '../conversion/mapper';
Expand All @@ -31,6 +32,8 @@ import mix from '@ckeditor/ckeditor5-utils/src/mix';
* including selection handling. It also creates {@link ~EditingController#view view document} which build a
* browser-independent virtualization over the DOM elements. Editing controller also attach default converters.
*
* Editing controller binds {@link model:engine/}
*
* @mixes module:utils/observablemixin~ObservableMixin
*/
export default class EditingController {
Expand Down Expand Up @@ -141,33 +144,22 @@ export default class EditingController {
this.modelToView.on( 'selection', clearFakeSelection(), { priority: 'low' } );
this.modelToView.on( 'selection', convertRangeSelection(), { priority: 'low' } );
this.modelToView.on( 'selection', convertCollapsedSelection(), { priority: 'low' } );
}

/**
* {@link module:engine/view/document~Document#createRoot Creates} a view root
* and {@link module:engine/conversion/mapper~Mapper#bindElements binds}
* the model root with view root and and view root with DOM element:
*
* editing.createRoot( document.querySelector( div#editor ) );
*
* If the DOM element is not available at the time you want to create a view root, for instance it is iframe body
* element, it is possible to create view element and bind the DOM element later:
*
* editing.createRoot( 'body' );
* editing.view.attachDomRoot( iframe.contentDocument.body );
*
* @param {Element|String} domRoot DOM root element or the name of view root element if the DOM element will be
* attached later.
* @param {String} [name='main'] Root name.
* @returns {module:engine/view/containerelement~ContainerElement} View root element.
*/
createRoot( domRoot, name = 'main' ) {
const viewRoot = this.view.createRoot( domRoot, name );
const modelRoot = this.model.document.getRoot( name );
// Bind model and view roots.
this.view.roots.bindTo( this.model.document.roots ).using( root => {
// $graveyard is a special root that has no reflection in the view.
if ( root.rootName == '$graveyard' ) {
return null;
}

this.mapper.bindElements( modelRoot, viewRoot );
const viewRoot = new RootEditableElement( root.name );

return viewRoot;
viewRoot.rootName = root.rootName;
viewRoot.document = this;
this.mapper.bindElements( root, viewRoot );

return viewRoot;
} );
}

/**
Expand Down
74 changes: 10 additions & 64 deletions tests/controller/editingcontroller.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import ModelPosition from '../../src/model/position';
import ModelRange from '../../src/model/range';
import ModelDocumentFragment from '../../src/model/documentfragment';

import createElement from '@ckeditor/ckeditor5-utils/src/dom/createelement';

import { parse, getData as getModelData } from '../../src/dev-utils/model';
import { getData as getViewData } from '../../src/dev-utils/view';

Expand Down Expand Up @@ -55,71 +53,17 @@ describe( 'EditingController', () => {

sinon.assert.calledOnce( spy );
} );
} );

describe( 'createRoot()', () => {
let model, modelRoot, editing;

beforeEach( () => {
model = new Model();
modelRoot = model.document.createRoot();
model.document.createRoot( '$root', 'header' );

editing = new EditingController( model );
} );

afterEach( () => {
editing.destroy();
model.markers.destroy();
} );

it( 'should create root', () => {
const domRoot = createElement( document, 'div', null, createElement( document, 'p' ) );

const viewRoot = editing.createRoot( domRoot );

expect( viewRoot ).to.equal( editing.view.getRoot() );
expect( domRoot ).to.equal( editing.view.getDomRoot() );

expect( editing.view.domConverter.mapViewToDom( viewRoot ) ).to.equal( domRoot );
expect( editing.view.renderer.markedChildren.has( viewRoot ) ).to.be.true;

expect( editing.mapper.toModelElement( viewRoot ) ).to.equal( modelRoot );
expect( editing.mapper.toViewElement( modelRoot ) ).to.equal( viewRoot );
} );

it( 'should create root with given name', () => {
const domRoot = createElement( document, 'div', null, createElement( document, 'p' ) );

const viewRoot = editing.createRoot( domRoot, 'header' );

expect( viewRoot ).to.equal( editing.view.getRoot( 'header' ) );
expect( domRoot ).to.equal( editing.view.getDomRoot( 'header' ) );

expect( editing.view.domConverter.mapViewToDom( viewRoot ) ).to.equal( domRoot );
expect( editing.view.renderer.markedChildren.has( viewRoot ) ).to.be.true;

expect( editing.mapper.toModelElement( viewRoot ) ).to.equal( model.document.getRoot( 'header' ) );
expect( editing.mapper.toViewElement( model.document.getRoot( 'header' ) ) ).to.equal( viewRoot );
} );

it( 'should be possible to attach DOM element later', () => {
const domRoot = createElement( document, 'div', null, createElement( document, 'p' ) );

const viewRoot = editing.createRoot( 'div' );

expect( viewRoot ).to.equal( editing.view.getRoot() );
expect( editing.view.getDomRoot() ).to.be.undefined;
it( 'should bind view roots to model roots', () => {
expect( model.document.roots ).to.length( 1 ); // $graveyard
expect( editing.view.roots ).to.length( 0 );

editing.view.attachDomRoot( domRoot );

expect( domRoot ).to.equal( editing.view.getDomRoot() );
const modelRoot = model.document.createRoot();

expect( editing.view.domConverter.mapViewToDom( viewRoot ) ).to.equal( domRoot );
expect( editing.view.renderer.markedChildren.has( viewRoot ) ).to.be.true;
expect( model.document.roots ).to.length( 2 );
expect( editing.view.roots ).to.length( 1 );

expect( editing.mapper.toModelElement( viewRoot ) ).to.equal( modelRoot );
expect( editing.mapper.toViewElement( modelRoot ) ).to.equal( viewRoot );
expect( editing.view.getRoot().name ).to.equal( modelRoot.name ).to.equal( '$root' );
} );
} );

Expand All @@ -138,7 +82,9 @@ describe( 'EditingController', () => {
domRoot.contentEditable = true;

document.body.appendChild( domRoot );
viewRoot = editing.createRoot( domRoot );

viewRoot = editing.view.getRoot();
editing.view.attachDomRoot( domRoot );

model.schema.register( 'paragraph', { inheritAllFrom: '$block' } );
model.schema.register( 'div', { inheritAllFrom: '$block' } );
Expand Down

0 comments on commit f7765ed

Please sign in to comment.