瀏覽代碼

Merge branch 'master' into t/ckeditor5-engine/1210

Szymon Kupś 8 年之前
父節點
當前提交
cb8b85aafd
共有 36 個文件被更改,包括 168 次插入147 次删除
  1. 1 1
      packages/ckeditor5-typing/.eslintrc.js
  2. 1 1
      packages/ckeditor5-typing/LICENSE.md
  3. 2 2
      packages/ckeditor5-typing/package.json
  4. 22 34
      packages/ckeditor5-typing/src/changebuffer.js
  5. 1 1
      packages/ckeditor5-typing/src/delete.js
  6. 5 5
      packages/ckeditor5-typing/src/deletecommand.js
  7. 11 1
      packages/ckeditor5-typing/src/deleteobserver.js
  8. 1 1
      packages/ckeditor5-typing/src/input.js
  9. 4 4
      packages/ckeditor5-typing/src/inputcommand.js
  10. 1 1
      packages/ckeditor5-typing/src/typing.js
  11. 7 7
      packages/ckeditor5-typing/tests/bogusbr-integration.js
  12. 4 4
      packages/ckeditor5-typing/tests/changebuffer.js
  13. 1 1
      packages/ckeditor5-typing/tests/delete.js
  14. 1 1
      packages/ckeditor5-typing/tests/deletecommand-integration.js
  15. 4 7
      packages/ckeditor5-typing/tests/deletecommand.js
  16. 25 1
      packages/ckeditor5-typing/tests/deleteobserver.js
  17. 44 46
      packages/ckeditor5-typing/tests/input.js
  18. 4 2
      packages/ckeditor5-typing/tests/inputcommand-integration.js
  19. 1 1
      packages/ckeditor5-typing/tests/inputcommand.js
  20. 1 1
      packages/ckeditor5-typing/tests/manual/20/1.js
  21. 1 1
      packages/ckeditor5-typing/tests/manual/21/1.js
  22. 1 1
      packages/ckeditor5-typing/tests/manual/40/1.js
  23. 1 1
      packages/ckeditor5-typing/tests/manual/52/1.js
  24. 1 1
      packages/ckeditor5-typing/tests/manual/59/1.js
  25. 1 1
      packages/ckeditor5-typing/tests/manual/82/1.js
  26. 1 1
      packages/ckeditor5-typing/tests/manual/86/1.js
  27. 1 1
      packages/ckeditor5-typing/tests/manual/delete.js
  28. 1 1
      packages/ckeditor5-typing/tests/manual/input.js
  29. 2 2
      packages/ckeditor5-typing/tests/manual/nbsp.js
  30. 1 1
      packages/ckeditor5-typing/tests/manual/rtl.js
  31. 1 1
      packages/ckeditor5-typing/tests/manual/selection.js
  32. 1 1
      packages/ckeditor5-typing/tests/manual/spellchecking.js
  33. 1 1
      packages/ckeditor5-typing/tests/manual/unicode.js
  34. 11 9
      packages/ckeditor5-typing/tests/spellchecking.js
  35. 1 1
      packages/ckeditor5-typing/tests/tickets/59.js
  36. 1 1
      packages/ckeditor5-typing/tests/typing.js

+ 1 - 1
packages/ckeditor5-typing/.eslintrc.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/LICENSE.md

@@ -2,7 +2,7 @@ Software License Agreement
 ==========================
 
 **CKEditor 5 Typing Feature** – https://github.com/ckeditor/ckeditor5-typing <br>
-Copyright (c) 2003-2017, [CKSource](http://cksource.com) Frederico Knabben. All rights reserved.
+Copyright (c) 2003-2018, [CKSource](http://cksource.com) Frederico Knabben. All rights reserved.
 
 Licensed under the terms of any of the following licenses at your choice:
 

+ 2 - 2
packages/ckeditor5-typing/package.json

@@ -20,10 +20,10 @@
     "@ckeditor/ckeditor5-link": "^1.0.0-alpha.2",
     "@ckeditor/ckeditor5-paragraph": "^1.0.0-alpha.2",
     "@ckeditor/ckeditor5-undo": "^1.0.0-alpha.2",
-    "eslint": "^4.8.0",
+    "eslint": "^4.15.0",
     "eslint-config-ckeditor5": "^1.0.7",
     "husky": "^0.14.3",
-    "lint-staged": "^4.2.3"
+    "lint-staged": "^6.0.0"
   },
   "engines": {
     "node": ">=6.0.0",

+ 22 - 34
packages/ckeditor5-typing/src/changebuffer.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -7,7 +7,6 @@
  * @module typing/changebuffer
  */
 
-import count from '@ckeditor/ckeditor5-utils/src/count';
 import Batch from '@ckeditor/ckeditor5-engine/src/model/batch';
 
 /**
@@ -21,7 +20,7 @@ import Batch from '@ckeditor/ckeditor5-engine/src/model/batch';
  *
  * To use the change buffer you need to let it know about the number of changes that were added to the batch:
  *
- *		const buffer = new ChangeBuffer( document, LIMIT );
+ *		const buffer = new ChangeBuffer( model, LIMIT );
  *
  *		// Later on in your feature:
  *		buffer.batch.insert( pos, insertedCharacters );
@@ -35,14 +34,14 @@ export default class ChangeBuffer {
 	 * @param {module:engine/model/document~Document} doc
 	 * @param {Number} [limit=20] The maximum number of atomic changes which can be contained in one batch.
 	 */
-	constructor( doc, limit = 20 ) {
+	constructor( model, limit = 20 ) {
 		/**
-		 * The document instance.
+		 * The model instance.
 		 *
 		 * @readonly
-		 * @member {module:engine/model/document~Document} #document
+		 * @member {module:engine/model/model~Model} #model
 		 */
-		this.document = doc;
+		this.model = model;
 
 		/**
 		 * The number of atomic changes in the buffer. Once it exceeds the {@link #limit},
@@ -69,19 +68,26 @@ export default class ChangeBuffer {
 		 */
 		this.isLocked = false;
 
-		this._changeCallback = ( evt, type, changes, batch ) => {
-			this._onBatch( batch );
+		// The function to be called in order to notify the buffer about batches which appeared in the document.
+		// The callback will check whether it is a new batch and in that case the buffer will be flushed.
+		//
+		// The reason why the buffer needs to be flushed whenever a new batch appears is that the changes added afterwards
+		// should be added to a new batch. For instance, when the  user types, then inserts an image, and then types again,
+		// the characters typed after inserting the image should be added to a different batch than the characters typed before.
+		this._changeCallback = ( evt, batch ) => {
+			if ( batch.type != 'transparent' && batch !== this._batch ) {
+				this._reset( true );
+			}
 		};
 
 		this._selectionChangeCallback = () => {
 			this._reset();
 		};
 
-		doc.on( 'change', this._changeCallback );
+		this.model.document.on( 'change', this._changeCallback );
 
-		doc.selection.on( 'change:range', this._selectionChangeCallback );
-
-		doc.selection.on( 'change:attribute', this._selectionChangeCallback );
+		this.model.document.selection.on( 'change:range', this._selectionChangeCallback );
+		this.model.document.selection.on( 'change:attribute', this._selectionChangeCallback );
 
 		/**
 		 * The current batch instance.
@@ -151,27 +157,9 @@ export default class ChangeBuffer {
 	 * Destroys the buffer.
 	 */
 	destroy() {
-		this.document.off( 'change', this._changeCallback );
-		this.document.selection.off( 'change:range', this._selectionChangeCallback );
-		this.document.selection.off( 'change:attribute', this._selectionChangeCallback );
-	}
-
-	/**
-	 * The method to be called in order to notify the buffer about batches which appeared in the document.
-	 * The method will check whether it is a new batch and in that case the buffer will be flushed.
-	 *
-	 * The reason why the buffer needs to be flushed whenever a new batch appears is that the changes added afterwards
-	 * should be added to a new batch. For instance, when the  user types, then inserts an image, and then types again,
-	 * the characters typed after inserting the image should be added to a different batch than the characters typed before.
-	 *
-	 * @private
-	 * @param {module:engine/model/batch~Batch} batch The batch which appears in the document.
-	 */
-	_onBatch( batch ) {
-		// One operation means a newly created batch.
-		if ( batch.type != 'transparent' && batch !== this._batch && count( batch.getOperations() ) <= 1 ) {
-			this._reset( true );
-		}
+		this.model.document.off( 'change', this._changeCallback );
+		this.model.document.selection.off( 'change:range', this._selectionChangeCallback );
+		this.model.document.selection.off( 'change:attribute', this._selectionChangeCallback );
 	}
 
 	/**

+ 1 - 1
packages/ckeditor5-typing/src/delete.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 5 - 5
packages/ckeditor5-typing/src/deletecommand.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -47,7 +47,7 @@ export default class DeleteCommand extends Command {
 		 * @private
 		 * @member {typing.ChangeBuffer} #buffer
 		 */
-		this._buffer = new ChangeBuffer( editor.model.document, editor.config.get( 'typing.undoStep' ) );
+		this._buffer = new ChangeBuffer( editor.model, editor.config.get( 'typing.undoStep' ) );
 	}
 
 	/**
@@ -67,7 +67,7 @@ export default class DeleteCommand extends Command {
 		model.enqueueChange( this._buffer.batch, writer => {
 			this._buffer.lock();
 
-			const selection = Selection.createFromSelection( doc.selection );
+			const selection = new Selection( doc.selection );
 
 			// Do not replace the whole selected content if selection was collapsed.
 			// This prevents such situation:
@@ -104,7 +104,7 @@ export default class DeleteCommand extends Command {
 			model.deleteContent( selection, { doNotResetEntireContent } );
 			this._buffer.input( changeCount );
 
-			doc.selection.setRanges( selection.getRanges(), selection.isBackward );
+			writer.setSelection( selection );
 
 			this._buffer.unlock();
 		} );
@@ -178,6 +178,6 @@ export default class DeleteCommand extends Command {
 		writer.remove( Range.createIn( limitElement ) );
 		writer.insert( paragraph, limitElement );
 
-		selection.setCollapsedAt( paragraph );
+		writer.setSelection( paragraph );
 	}
 }

+ 11 - 1
packages/ckeditor5-typing/src/deleteobserver.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -44,7 +44,17 @@ export default class DeleteObserver extends Observer {
 			deleteData.unit = data.altKey ? 'word' : deleteData.unit;
 			deleteData.sequence = ++sequence;
 
+			// Save the event object to check later if it was stopped or not.
+			let event;
+			document.once( 'delete', evt => ( event = evt ), { priority: 'highest' } );
+
 			document.fire( 'delete', new DomEventData( document, data.domEvent, deleteData ) );
+
+			// Stop `keydown` event if `delete` event was stopped.
+			// https://github.com/ckeditor/ckeditor5/issues/753
+			if ( event && event.stop.called ) {
+				evt.stop();
+			}
 		} );
 	}
 

+ 1 - 1
packages/ckeditor5-typing/src/input.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 4 - 4
packages/ckeditor5-typing/src/inputcommand.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -33,7 +33,7 @@ export default class InputCommand extends Command {
 		 * @private
 		 * @member {module:typing/changebuffer~ChangeBuffer} #_buffer
 		 */
-		this._buffer = new ChangeBuffer( editor.model.document, undoStepSize );
+		this._buffer = new ChangeBuffer( editor.model, undoStepSize );
 	}
 
 	/**
@@ -90,10 +90,10 @@ export default class InputCommand extends Command {
 			}
 
 			if ( resultRange ) {
-				doc.selection.setRanges( [ resultRange ] );
+				writer.setSelection( resultRange );
 			} else if ( isCollapsedRange ) {
 				// If range was collapsed just shift the selection by the number of inserted characters.
-				doc.selection.setCollapsedAt( range.start.getShiftedBy( textInsertions ) );
+				writer.setSelection( range.start.getShiftedBy( textInsertions ) );
 			}
 
 			this._buffer.unlock();

+ 1 - 1
packages/ckeditor5-typing/src/typing.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 7 - 7
packages/ckeditor5-typing/tests/bogusbr-integration.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -49,7 +49,7 @@ describe( 'Typing – bogus BR integration', () => {
 				setData( editor.model, '<paragraph>Foo[]</paragraph>' );
 			} );
 
-			editor.model.document.once( 'changesDone', () => {
+			editor.model.document.once( 'change', () => {
 				expect( editor.getData() ).to.equal( '<p>Foo&nbsp;</p>' );
 				done();
 			}, { priority: 'low' } );
@@ -63,7 +63,7 @@ describe( 'Typing – bogus BR integration', () => {
 				setData( editor.model, '<paragraph>[]</paragraph>' );
 			} );
 
-			editor.model.document.once( 'changesDone', () => {
+			editor.model.document.once( 'change', () => {
 				expect( editor.getData() ).to.equal( '<p>&nbsp;</p>' );
 				done();
 			}, { priority: 'low' } );
@@ -77,7 +77,7 @@ describe( 'Typing – bogus BR integration', () => {
 				setData( editor.model, '<paragraph><$text bold="true">Foo[]</$text></paragraph>' );
 			} );
 
-			editor.model.document.once( 'changesDone', () => {
+			editor.model.document.once( 'change', () => {
 				expect( editor.getData() ).to.equal( '<p><strong>Foo&nbsp;</strong></p>' );
 				done();
 			}, { priority: 'low' } );
@@ -95,7 +95,7 @@ describe( 'Typing – bogus BR integration', () => {
 				setData( editor.model, '<paragraph>Foo[]</paragraph>' );
 			} );
 
-			editor.model.document.once( 'changesDone', () => {
+			editor.model.document.once( 'change', () => {
 				expect( editor.getData() ).to.equal( '<p>Foo&nbsp;</p>' );
 				done();
 			}, { priority: 'low' } );
@@ -121,7 +121,7 @@ describe( 'Typing – bogus BR integration', () => {
 				setData( editor.model, '<paragraph>Foo[]</paragraph>' );
 			} );
 
-			editor.model.document.once( 'changesDone', () => {
+			editor.model.document.once( 'change', () => {
 				expect( editor.getData() ).to.equal( '<p>Foo&nbsp;</p>' );
 				done();
 			}, { priority: 'low' } );
@@ -150,7 +150,7 @@ describe( 'Typing – bogus BR integration', () => {
 				setData( editor.model, '<paragraph>Foo hous[]</paragraph>' );
 			} );
 
-			editor.model.document.once( 'changesDone', () => {
+			editor.model.document.once( 'change', () => {
 				expect( editor.getData() ).to.equal( '<p>Foo house</p>' );
 				done();
 			}, { priority: 'low' } );

+ 4 - 4
packages/ckeditor5-typing/tests/changebuffer.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -15,19 +15,19 @@ describe( 'ChangeBuffer', () => {
 		model = new Model();
 		doc = model.document;
 		root = doc.createRoot();
-		buffer = new ChangeBuffer( doc, CHANGE_LIMIT );
+		buffer = new ChangeBuffer( model, CHANGE_LIMIT );
 	} );
 
 	describe( 'constructor()', () => {
 		it( 'sets all properties', () => {
-			expect( buffer ).to.have.property( 'document', doc );
+			expect( buffer ).to.have.property( 'model', model );
 			expect( buffer ).to.have.property( 'limit', CHANGE_LIMIT );
 			expect( buffer ).to.have.property( 'size', 0 );
 			expect( buffer ).to.have.property( 'isLocked', false );
 		} );
 
 		it( 'sets limit property according to default value', () => {
-			buffer = new ChangeBuffer( doc );
+			buffer = new ChangeBuffer( model );
 
 			expect( buffer ).to.have.property( 'limit', 20 );
 		} );

+ 1 - 1
packages/ckeditor5-typing/tests/delete.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/deletecommand-integration.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 4 - 7
packages/ckeditor5-typing/tests/deletecommand.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -244,12 +244,9 @@ describe( 'DeleteCommand', () => {
 		} );
 
 		it( 'does not replace an element if a paragraph is not allowed in current position', () => {
-			model.schema.on( 'checkChild', ( evt, args ) => {
-				const def = model.schema.getDefinition( args[ 1 ] );
-
-				if ( args[ 0 ].endsWith( '$root' ) && def.name == 'paragraph' ) {
-					evt.stop();
-					evt.return = false;
+			model.schema.addChildCheck( ( ctx, childDef ) => {
+				if ( ctx.endsWith( '$root' ) && childDef.name == 'paragraph' ) {
+					return false;
 				}
 			} );
 

+ 25 - 1
packages/ckeditor5-typing/tests/deleteobserver.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -169,6 +169,30 @@ describe( 'DeleteObserver', () => {
 			expect( spy.args[ 0 ][ 1 ] ).to.have.property( 'sequence', 1 );
 			expect( spy.args[ 1 ][ 1 ] ).to.have.property( 'sequence', 2 );
 		} );
+
+		it( 'should stop keydown event when delete event is stopped', () => {
+			const keydownSpy = sinon.spy();
+			viewDocument.on( 'keydown', keydownSpy );
+			viewDocument.on( 'delete', evt => evt.stop() );
+
+			viewDocument.fire( 'keydown', new DomEventData( viewDocument, getDomEvent(), {
+				keyCode: getCode( 'delete' )
+			} ) );
+
+			sinon.assert.notCalled( keydownSpy );
+		} );
+
+		it( 'should not stop keydown event when delete event is not stopped', () => {
+			const keydownSpy = sinon.spy();
+			viewDocument.on( 'keydown', keydownSpy );
+			viewDocument.on( 'delete', evt => evt.stop() );
+
+			viewDocument.fire( 'keydown', new DomEventData( viewDocument, getDomEvent(), {
+				keyCode: getCode( 'x' )
+			} ) );
+
+			sinon.assert.calledOnce( keydownSpy );
+		} );
 	} );
 
 	function getDomEvent() {

+ 44 - 46
packages/ckeditor5-typing/tests/input.js

@@ -1,5 +1,5 @@
 /*
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -70,10 +70,10 @@ describe( 'Input feature', () => {
 	beforeEach( () => {
 		editor.setData( '<p>foobar</p>' );
 
-		model.change( () => {
-			model.document.selection.setRanges( [
+		model.change( writer => {
+			writer.setSelection(
 				ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 3, modelRoot.getChild( 0 ), 3 )
-			] );
+			);
 		} );
 	} );
 
@@ -271,7 +271,7 @@ describe( 'Input feature', () => {
 			// This test case emulates spellchecker correction.
 
 			const viewSelection = new ViewSelection();
-			viewSelection.setCollapsedAt( viewRoot.getChild( 0 ).getChild( 0 ), 6 );
+			viewSelection.setTo( viewRoot.getChild( 0 ).getChild( 0 ), 6 );
 
 			view.fire( 'mutations',
 				[ {
@@ -291,7 +291,7 @@ describe( 'Input feature', () => {
 			// This test case emulates spellchecker correction.
 
 			const viewSelection = new ViewSelection();
-			viewSelection.setCollapsedAt( viewRoot.getChild( 0 ).getChild( 0 ), 6 );
+			viewSelection.setTo( viewRoot.getChild( 0 ).getChild( 0 ), 6 );
 
 			testUtils.sinon.spy( Writer.prototype, 'insert' );
 			testUtils.sinon.spy( Writer.prototype, 'remove' );
@@ -315,7 +315,7 @@ describe( 'Input feature', () => {
 			editor.setData( '<p>Foo hous a</p>' );
 
 			const viewSelection = new ViewSelection();
-			viewSelection.setCollapsedAt( viewRoot.getChild( 0 ).getChild( 0 ), 9 );
+			viewSelection.setTo( viewRoot.getChild( 0 ).getChild( 0 ), 9 );
 
 			view.fire( 'mutations',
 				[ {
@@ -336,7 +336,7 @@ describe( 'Input feature', () => {
 			editor.setData( '<p>Bar athat foo</p>' );
 
 			const viewSelection = new ViewSelection();
-			viewSelection.setCollapsedAt( viewRoot.getChild( 0 ).getChild( 0 ), 8 );
+			viewSelection.setTo( viewRoot.getChild( 0 ).getChild( 0 ), 8 );
 
 			view.fire( 'mutations',
 				[ {
@@ -357,7 +357,7 @@ describe( 'Input feature', () => {
 			editor.setData( '<p>Foo hous e</p>' );
 
 			const viewSelection = new ViewSelection();
-			viewSelection.setCollapsedAt( viewRoot.getChild( 0 ).getChild( 0 ), 9 );
+			viewSelection.setTo( viewRoot.getChild( 0 ).getChild( 0 ), 9 );
 
 			view.fire( 'mutations',
 				[ {
@@ -377,8 +377,8 @@ describe( 'Input feature', () => {
 			editor.setData( '<p>Foo house</p>' );
 
 			const viewSelection = new ViewSelection();
-			viewSelection.setCollapsedAt( viewRoot.getChild( 0 ).getChild( 0 ), 8 );
-			viewSelection.moveFocusTo( viewRoot.getChild( 0 ).getChild( 0 ), 9 );
+			viewSelection.setTo( viewRoot.getChild( 0 ).getChild( 0 ), 8 );
+			viewSelection.setFocus( viewRoot.getChild( 0 ).getChild( 0 ), 9 );
 
 			view.fire( 'mutations',
 				[ {
@@ -395,10 +395,10 @@ describe( 'Input feature', () => {
 		} );
 
 		it( 'should replace last &nbsp; with space', () => {
-			model.change( () => {
-				model.document.selection.setRanges( [
+			model.change( writer => {
+				writer.setSelection(
 					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 6, modelRoot.getChild( 0 ), 6 )
-				] );
+				);
 			} );
 
 			view.fire( 'mutations', [
@@ -415,10 +415,10 @@ describe( 'Input feature', () => {
 		} );
 
 		it( 'should replace first &nbsp; with space', () => {
-			model.change( () => {
-				model.document.selection.setRanges( [
+			model.change( writer => {
+				writer.setSelection(
 					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 0, modelRoot.getChild( 0 ), 0 )
-				] );
+				);
 			} );
 
 			view.fire( 'mutations', [
@@ -435,10 +435,10 @@ describe( 'Input feature', () => {
 		} );
 
 		it( 'should replace all &nbsp; with spaces', () => {
-			model.change( () => {
-				model.document.selection.setRanges( [
+			model.change( writer => {
+				writer.setSelection(
 					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 6, modelRoot.getChild( 0 ), 6 )
-				] );
+				);
 			} );
 
 			view.fire( 'mutations', [
@@ -457,9 +457,9 @@ describe( 'Input feature', () => {
 
 	describe( 'keystroke handling', () => {
 		it( 'should remove contents', () => {
-			model.change( () => {
-				model.document.selection.setRanges( [
-					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) ] );
+			model.change( writer => {
+				writer.setSelection(
+					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) );
 			} );
 
 			listenter.listenTo( view, 'keydown', () => {
@@ -491,9 +491,9 @@ describe( 'Input feature', () => {
 		} );
 
 		it( 'should do nothing on arrow key', () => {
-			model.change( () => {
-				model.document.selection.setRanges( [
-					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) ] );
+			model.change( writer => {
+				writer.setSelection(
+					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) );
 			} );
 
 			view.fire( 'keydown', { keyCode: getCode( 'arrowdown' ) } );
@@ -502,9 +502,9 @@ describe( 'Input feature', () => {
 		} );
 
 		it( 'should do nothing on ctrl combinations', () => {
-			model.change( () => {
-				model.document.selection.setRanges( [
-					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) ] );
+			model.change( writer => {
+				writer.setSelection(
+					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) );
 			} );
 
 			view.fire( 'keydown', { ctrlKey: true, keyCode: getCode( 'c' ) } );
@@ -513,9 +513,9 @@ describe( 'Input feature', () => {
 		} );
 
 		it( 'should do nothing on non printable keys', () => {
-			model.change( () => {
-				model.document.selection.setRanges( [
-					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) ] );
+			model.change( writer => {
+				writer.setSelection(
+					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) );
 			} );
 
 			view.fire( 'keydown', { keyCode: 16 } ); // Shift
@@ -527,9 +527,9 @@ describe( 'Input feature', () => {
 
 		// #69
 		it( 'should do nothing on tab key', () => {
-			model.change( () => {
-				model.document.selection.setRanges( [
-					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) ] );
+			model.change( writer => {
+				writer.setSelection(
+					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) );
 			} );
 
 			view.fire( 'keydown', { keyCode: 9 } ); // Tab
@@ -539,9 +539,9 @@ describe( 'Input feature', () => {
 
 		// #82
 		it( 'should do nothing on composition start key', () => {
-			model.change( () => {
-				model.document.selection.setRanges( [
-					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) ] );
+			model.change( writer => {
+				writer.setSelection(
+					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) );
 			} );
 
 			view.fire( 'keydown', { keyCode: 229 } );
@@ -560,9 +560,9 @@ describe( 'Input feature', () => {
 			const lockSpy = testUtils.sinon.spy( buffer, 'lock' );
 			const unlockSpy = testUtils.sinon.spy( buffer, 'unlock' );
 
-			model.change( () => {
-				model.document.selection.setRanges( [
-					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) ] );
+			model.change( writer => {
+				writer.setSelection(
+					ModelRange.createFromParentsAndOffsets( modelRoot.getChild( 0 ), 2, modelRoot.getChild( 0 ), 4 ) );
 			} );
 
 			view.fire( 'keydown', { keyCode: getCode( 'y' ) } );
@@ -994,8 +994,7 @@ describe( 'Input feature', () => {
 
 			const paragraph = viewRoot.getChild( 0 );
 			const strong = paragraph.getChild( 0 );
-			const viewSelection = new ViewSelection();
-			viewSelection.setCollapsedAt( paragraph, 0 );
+			const viewSelection = new ViewSelection( paragraph, 0 );
 
 			// Simulate mutations and DOM change.
 			domRoot.childNodes[ 0 ].innerHTML = '<b>textx</b>';
@@ -1015,12 +1014,11 @@ describe( 'Input feature', () => {
 
 		// #117.
 		it( 'should handle mixed mutations', () => {
-			setModelData( model, '<paragraph><$text bold="true">Foo bar aple</$text></paragraph>' );
+			setModelData( model, '<paragraph>[]<$text bold="true">Foo bar aple</$text></paragraph>' );
 
 			const paragraph = viewRoot.getChild( 0 );
 			const strong = paragraph.getChild( 0 );
-			const viewSelection = new ViewSelection();
-			viewSelection.setCollapsedAt( paragraph, 0 );
+			const viewSelection = new ViewSelection( paragraph );
 
 			// Simulate mutations and DOM change.
 			domRoot.childNodes[ 0 ].innerHTML = '<strong>Foo bar </strong><b>apple</b>';

+ 4 - 2
packages/ckeditor5-typing/tests/inputcommand-integration.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -73,7 +73,9 @@ describe( 'Typing – InputCommand integration', () => {
 	}
 
 	function setSelection( pathA, pathB ) {
-		doc.selection.setRanges( [ new Range( new Position( doc.getRoot(), pathA ), new Position( doc.getRoot(), pathB ) ) ] );
+		model.change( writer => {
+			writer.setSelection( new Range( new Position( doc.getRoot(), pathA ), new Position( doc.getRoot(), pathB ) ) );
+		} );
 	}
 
 	describe( 'InputCommand integration', () => {

+ 1 - 1
packages/ckeditor5-typing/tests/inputcommand.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/manual/20/1.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/manual/21/1.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/manual/40/1.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/manual/52/1.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/manual/59/1.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/manual/82/1.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/manual/86/1.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/manual/delete.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/manual/input.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 2 - 2
packages/ckeditor5-typing/tests/manual/nbsp.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -31,7 +31,7 @@ ClassicEditor
 			} );
 		} );
 
-		editor.model.document.on( 'changesDone', () => {
+		editor.model.document.once( 'change', () => {
 			console.clear();
 
 			const modelData = getModelData( editor.model.document, { withoutSelection: true } );

+ 1 - 1
packages/ckeditor5-typing/tests/manual/rtl.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/manual/selection.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/manual/spellchecking.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/manual/unicode.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 11 - 9
packages/ckeditor5-typing/tests/spellchecking.js

@@ -1,9 +1,9 @@
 /*
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
-/* globals window, document */
+/* globals window, document, setTimeout */
 
 import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
 import Enter from '@ckeditor/ckeditor5-enter/src/enter';
@@ -43,7 +43,7 @@ describe( 'Typing – spellchecking integration', () => {
 
 	beforeEach( () => {
 		if ( onChangesDone ) {
-			editor.model.document.off( 'changesDone', onChangesDone );
+			editor.model.document.off( 'change', onChangesDone );
 			onChangesDone = null;
 		}
 
@@ -236,7 +236,7 @@ function emulateSpellcheckerMutation( editor, nodeIndex, resultPositionIndex, ol
 	const viewRoot = view.getRoot();
 	const viewSelection = new ViewSelection();
 
-	viewSelection.setCollapsedAt( viewRoot.getChild( nodeIndex ).getChild( 0 ), resultPositionIndex );
+	viewSelection.setTo( viewRoot.getChild( nodeIndex ).getChild( 0 ), resultPositionIndex );
 
 	view.fire( 'mutations',
 		[ {
@@ -253,15 +253,18 @@ function emulateSpellcheckerInsertText( editor, nodeIndex, rangeStart, rangeEnd,
 	const model = editor.model;
 	const modelRoot = model.document.getRoot();
 
+	window.focus();
 	editor.editing.view.focus();
 
-	model.change( () => {
-		model.document.selection.setRanges( [
+	model.change( writer => {
+		writer.setSelection(
 			ModelRange.createFromParentsAndOffsets( modelRoot.getChild( nodeIndex ), rangeStart, modelRoot.getChild( nodeIndex ), rangeEnd )
-		] );
+		);
 	} );
 
-	editor.model.document.once( 'changesDone', onChangesDoneCallback, { priority: 'low' } );
+	model.document.once( 'change', () => {
+		setTimeout( onChangesDoneCallback, 100 );
+	}, { priority: 'low' } );
 
 	window.document.execCommand( 'insertText', false, text );
 }
@@ -270,4 +273,3 @@ function expectContent( editor, expectedModel, expectedView ) {
 	expect( getModelData( editor.model ) ).to.equal( expectedModel );
 	expect( getViewData( editor.editing.view ) ).to.equal( expectedView );
 }
-

+ 1 - 1
packages/ckeditor5-typing/tests/tickets/59.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-typing/tests/typing.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */