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

Added focus method to view.Document and _updateFocus method to view.Renderer.

Szymon Kupś 9 лет назад
Родитель
Сommit
ed5babee41

+ 11 - 0
packages/ckeditor5-engine/src/view/document.js

@@ -255,6 +255,17 @@ export default class Document {
 		this.enableObservers();
 	}
 
+	/**
+	 * Focuses document. It will focus {@link engine.view.EditableElement EditableElement} that is currently having
+	 * selection inside.
+	 *
+	 * @fires engine.view.Document#focus
+	 */
+	focus() {
+		this.fire( 'focus' );
+		this.render();
+	}
+
 	/**
 	 * Disables all added observers.
 	 */

+ 20 - 0
packages/ckeditor5-engine/src/view/renderer.js

@@ -188,6 +188,7 @@ export default class Renderer {
 		}
 
 		this._updateSelection();
+		this._updateFocus();
 
 		this.markedTexts.clear();
 		this.markedAttributes.clear();
@@ -443,6 +444,25 @@ export default class Renderer {
 			}
 		}
 	}
+
+	/**
+	 * Checks if focus needs to be updated and possibly updates it.
+	 *
+	 * @private
+	 */
+	_updateFocus() {
+		if ( this.isFocused ) {
+			const editable = this.selection.getEditableElement();
+
+			if ( editable ) {
+				const domElement = this.domConverter.getCorrespondingDomElement( editable );
+
+				if ( domElement && domElement.ownerDocument.activeElement !== domElement ) {
+					domElement.focus();
+				}
+			}
+		}
+	}
 }
 
 mix( Renderer, ObservableMixin );

+ 30 - 1
packages/ckeditor5-engine/tests/view/renderer.js

@@ -24,7 +24,7 @@ testUtils.createSinonSandbox();
 describe( 'Renderer', () => {
 	let selection, domConverter, renderer;
 
-	before( () => {
+	beforeEach( () => {
 		selection = new Selection();
 		domConverter = new DomConverter();
 		renderer = new Renderer( domConverter, selection );
@@ -905,6 +905,35 @@ describe( 'Renderer', () => {
 				renderer.render();
 			} ).to.throw();
 		} );
+
+		it( 'should handle focusing element', () => {
+			const domFocusSpy = testUtils.sinon.spy( domRoot, 'focus' );
+			const editable = selection.getEditableElement();
+
+			renderer.render();
+
+			expect( editable ).to.equal( viewRoot );
+			expect( domFocusSpy.calledOnce ).to.be.true;
+		} );
+
+		it( 'should not focus editable if isFocues is set to false', () => {
+			const domFocusSpy = testUtils.sinon.spy( domRoot, 'focus' );
+
+			renderer.isFocused = false;
+			renderer.render();
+
+			expect( domFocusSpy.calledOnce ).to.be.false;
+		} );
+
+		it( 'should not focus already focused DOM element', () => {
+			domRoot.setAttribute( 'contentEditable', true );
+			domRoot.focus();
+			const domFocusSpy = testUtils.sinon.spy( domRoot, 'focus' );
+
+			renderer.render();
+
+			expect( domFocusSpy.called ).to.be.false;
+		} );
 	} );
 } );