8
0
Просмотр исходного кода

Fix: The filler logic in the renderer should not interfere the 2-step caret movement.

Aleksander Nowodzinski 7 лет назад
Родитель
Сommit
1b4200c79e

+ 9 - 2
packages/ckeditor5-engine/src/utils/bindtwostepcarettoattribute.js

@@ -87,7 +87,14 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 	const twoStepCaretHandler = new TwoStepCaretHandler( model, emitter, attribute );
 	const modelSelection = model.document.selection;
 
-	// Listen to keyboard events and handle cursor before the move.
+	// Listen to keyboard events and handle the caret movement according to the 2-step caret logic.
+	//
+	// Note: This listener has the "high" priority. This because of the filler logic
+	// implemented in the renderer which also engages on #keydown. When the gravity is overridden
+	// the attributes of the (model) selection attributes are reset. It may end up with the
+	// filler kicking in and breaking the selection.
+	//
+	// Find out more in https://github.com/ckeditor/ckeditor5-engine/issues/1301.
 	emitter.listenTo( view.document, 'keydown', ( evt, data ) => {
 		// This implementation works only for collapsed selection.
 		if ( !modelSelection.isCollapsed ) {
@@ -115,7 +122,7 @@ export default function bindTwoStepCaretToAttribute( view, model, emitter, attri
 		} else {
 			twoStepCaretHandler.handleBackwardMovement( position, data );
 		}
-	} );
+	}, { priority: 'high' } );
 }
 
 /**

+ 3 - 0
packages/ckeditor5-engine/tests/manual/tickets/1301/1.html

@@ -0,0 +1,3 @@
+<div id="editor">
+	<p><b>bold</b><i>i</i></p>
+</div>

+ 28 - 0
packages/ckeditor5-engine/tests/manual/tickets/1301/1.js

@@ -0,0 +1,28 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* global console, document */
+
+import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
+import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
+import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
+import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
+import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
+
+import bindTwoStepCaretToAttribute from '../../../../src/utils/bindtwostepcarettoattribute';
+
+ClassicEditor
+	.create( document.querySelector( '#editor' ), {
+		plugins: [ Essentials, Paragraph, Bold, Italic ],
+		toolbar: [ 'undo', 'redo', '|', 'bold', 'italic' ]
+	} )
+	.then( editor => {
+		const bold = editor.plugins.get( Bold );
+
+		bindTwoStepCaretToAttribute( editor.editing.view, editor.model, bold, 'bold' );
+	} )
+	.catch( err => {
+		console.error( err.stack );
+	} );

+ 8 - 0
packages/ckeditor5-engine/tests/manual/tickets/1301/1.md

@@ -0,0 +1,8 @@
+## Two-steps caret movement [#1301](https://github.com/ckeditor/ckeditor5-engine/issues/1301)
+
+1. Put the selection at the end of the content.
+2. Press the <kbd>←</kbd> key 3 times.
+
+## Expected:
+
+The selection should be `<b>bol{}d</b><i>i</i>` (after "l" but before "d").

+ 1 - 1
packages/ckeditor5-engine/tests/manual/two-step-caret.md

@@ -1,4 +1,4 @@
-## Two-steps caret movment [#1286](https://github.com/ckeditor/ckeditor5-engine/issues/1289)
+## Two-steps caret movement [#1286](https://github.com/ckeditor/ckeditor5-engine/issues/1289)
 
 ### Moving right
 1. Put selection one character before the underline

+ 23 - 0
packages/ckeditor5-engine/tests/utils/bindtwostepcarettoattribute.js

@@ -598,6 +598,29 @@ describe( 'bindTwoStepCaretToAttribute()', () => {
 		} );
 	} );
 
+	it( 'should listen with the high priority on view.document#keydown', () => {
+		const highestPrioritySpy = sinon.spy();
+		const highPrioritySpy = sinon.spy();
+		const normalPrioritySpy = sinon.spy();
+
+		setData( model, '<$text c="true">foo[]</$text><$text a="true" b="true">bar</$text>' );
+
+		emitter.listenTo( viewDoc, 'keydown', highestPrioritySpy, { priority: 'highest' } );
+		emitter.listenTo( viewDoc, 'keydown', highPrioritySpy, { priority: 'high' } );
+		emitter.listenTo( viewDoc, 'keydown', normalPrioritySpy, { priority: 'normal' } );
+
+		fireKeyDownEvent( {
+			keyCode: keyCodes.arrowright,
+			preventDefault: preventDefaultSpy
+		} );
+
+		sinon.assert.callOrder(
+			highestPrioritySpy,
+			preventDefaultSpy,
+			highPrioritySpy,
+			normalPrioritySpy );
+	} );
+
 	it( 'should do nothing when key other then arrow left and right is pressed', () => {
 		setData( model, '<$text a="true">foo[]</$text>' );