瀏覽代碼

Fixed: Handle jumping over UI element if selection is in attribute element.

Szymon Cofalik 8 年之前
父節點
當前提交
b945e9c9c3

+ 17 - 2
packages/ckeditor5-engine/src/view/uielement.js

@@ -124,11 +124,26 @@ function jumpOverUiElement( evt, data, domConverter ) {
 			}
 
 			// Skip all following ui elements.
-			const nextViewPosition = viewPosition.getLastMatchingPosition( value => value.item.is( 'uiElement' ) );
+			let jumpedOverAnyUiElement = false;
+
+			const nextViewPosition = viewPosition.getLastMatchingPosition( value => {
+				if ( value.item.is( 'uiElement' ) ) {
+					// Remember that there was at least one ui element.
+					jumpedOverAnyUiElement = true;
+				}
+
+				// Jump over ui elements, jump over empty attribute elements, move up from inside of attribute element.
+				if ( value.item.is( 'uiElement' ) || value.item.is( 'attributeElement' ) ) {
+					return true;
+				}
+
+				// Don't jump over text or don't get out of container element.
+				return false;
+			} );
 
 			// If anything has been skipped, fix position.
 			// This `if` could be possibly omitted but maybe it is better not to mess with DOM selection if not needed.
-			if ( !viewPosition.isEqual( nextViewPosition ) ) {
+			if ( jumpedOverAnyUiElement ) {
 				const newDomPosition = domConverter.viewPositionToDom( nextViewPosition );
 
 				if ( domSelectionCollapsed ) {

+ 16 - 0
packages/ckeditor5-engine/tests/view/document/jumpoveruielement.js

@@ -92,6 +92,22 @@ describe( 'Document', () => {
 			expect( domSelection.focusOffset ).to.equal( 2 );
 		} );
 
+		it( 'jump over ui element if selection is in attribute element', () => {
+			setData( viewDocument, '<container:p><attribute:b>foo{}</attribute:b><ui:span></ui:span>bar</container:p>' );
+			viewDocument.render();
+
+			viewDocument.fire(
+				'keydown',
+				{ keyCode: keyCodes.arrowright, shiftKey: true, domTarget: viewDocument.domRoots.get( 'main' ) }
+			);
+
+			const domSelection = document.getSelection();
+
+			expect( domSelection.anchorNode.nodeName.toUpperCase() ).to.equal( 'P' );
+			expect( domSelection.anchorOffset ).to.equal( 2 );
+			expect( domSelection.isCollapsed ).to.be.true;
+		} );
+
 		it( 'should do nothing if caret is not directly before ui element', () => {
 			setData( viewDocument, '<container:p>fo{}o<ui:span></ui:span>bar</container:p>' );
 			viewDocument.render();