Bladeren bron

Merge pull request #9 from ckeditor/t/4

Fix: The position of the floating toolbar should be updated after the editable has grown. Closes #4.
Oskar Wróbel 8 jaren geleden
bovenliggende
commit
5959bdc67f

+ 1 - 0
packages/ckeditor5-editor-inline/package.json

@@ -14,6 +14,7 @@
     "@ckeditor/ckeditor5-dev-lint": "^2.0.2",
     "@ckeditor/ckeditor5-basic-styles": "^0.8.0",
     "@ckeditor/ckeditor5-paragraph": "^0.7.0",
+    "@ckeditor/ckeditor5-presets": "^0.2.1",
     "gulp": "^3.9.0",
     "guppy-pre-commit": "^0.4.0"
   },

+ 13 - 2
packages/ckeditor5-editor-inline/src/inlineeditorui.js

@@ -45,8 +45,19 @@ export default class InlineEditorUI {
 		this.focusTracker = new FocusTracker();
 
 		// Set–up the view#panel.
-		view.panel.bind( 'isActive' ).to( this.focusTracker, 'isFocused' );
-		view.panel.targetElement = view.editableElement;
+		view.panel.bind( 'isVisible' ).to( this.focusTracker, 'isFocused' );
+
+		// https://github.com/ckeditor/ckeditor5-editor-inline/issues/4
+		view.listenTo( editor.editing.view, 'render', () => {
+			// Don't pin if the panel is not already visible. It prevents the panel
+			// showing up when there's no focus in the UI.
+			if ( view.panel.isVisible ) {
+				view.panel.pin( {
+					target: view.editableElement,
+					positions: view.panelPositions
+				} );
+			}
+		} );
 
 		// Setup the editable.
 		const editingRoot = editor.editing.createRoot( view.editableElement );

+ 75 - 4
packages/ckeditor5-editor-inline/src/inlineeditoruiview.js

@@ -9,7 +9,7 @@
 
 import EditorUIView from '@ckeditor/ckeditor5-ui/src/editorui/editoruiview';
 import InlineEditableUIView from '@ckeditor/ckeditor5-ui/src/editableui/inline/inlineeditableuiview';
-import FloatingPanelView from '@ckeditor/ckeditor5-ui/src/panel/floating/floatingpanelview';
+import BalloonPanelView from '@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview';
 import ToolbarView from '@ckeditor/ckeditor5-ui/src/toolbar/toolbarview';
 import Template from '@ckeditor/ckeditor5-ui/src/template';
 
@@ -36,12 +36,14 @@ export default class InlineEditorUIView extends EditorUIView {
 		this.toolbar = new ToolbarView( locale );
 
 		/**
-		 * A floating panel view instance.
+		 * A balloon panel view instance.
 		 *
 		 * @readonly
-		 * @member {module:ui/panel/floating/floatingpanelview~FloatingPanelView}
+		 * @member {module:ui/panel/balloon/balloonpanelview~BalloonPanelView}
 		 */
-		this.panel = new FloatingPanelView( locale );
+		this.panel = new BalloonPanelView( locale );
+
+		this.panel.withArrow = false;
 
 		Template.extend( this.panel.template, {
 			attributes: {
@@ -75,4 +77,73 @@ export default class InlineEditorUIView extends EditorUIView {
 	get editableElement() {
 		return this.editable.element;
 	}
+
+	/**
+	 * A set of positioning functions used by the {@link #panel} to float around
+	 * {@link #editableElement}.
+	 *
+	 * The positioning functions are as follows:
+	 *
+	 * * South east:
+	 *
+	 *		+------------------+
+	 *		| #editableElement |
+	 *		+------------------+
+	 *		           [ Panel ]
+	 *
+	 * * South west:
+	 *
+	 *		+------------------+
+	 *		| #editableElement |
+	 *		+------------------+
+	 *		[ Panel ]
+	 *
+	 * * North east:
+	 *
+	 *		           [ Panel ]
+	 *		+------------------+
+	 *		| #editableElement |
+	 *		+------------------+
+	 *
+	 *
+	 * * North west:
+	 *
+	 *		[ Panel ]
+	 *		+------------------+
+	 *		| #editableElement |
+	 *		+------------------+
+	 *
+	 * @type {module:utils/dom/position~Options#positions}
+	 */
+	get panelPositions() {
+		return panelPositions;
+	}
 }
+
+// A set of positioning functions used by the
+// {@link module:editor-inline/inlineeditoruiview~InlineEditableUIView#panel}.
+//
+// @private
+// @type {module:utils/dom/position~Options#positions}
+const panelPositions = [
+	( editableRect, panelRect ) => ( {
+		top: editableRect.top - panelRect.height,
+		left: editableRect.left,
+		name: 'toolbar_nw'
+	} ),
+	( editableRect ) => ( {
+		top: editableRect.bottom,
+		left: editableRect.left,
+		name: 'toolbar_sw'
+	} ),
+	( editableRect, panelRect ) => ( {
+		top: editableRect.top - panelRect.height,
+		left: editableRect.left + editableRect.width - panelRect.width,
+		name: 'toolbar_ne'
+	} ),
+	( editableRect, panelRect ) => ( {
+		top: editableRect.bottom,
+		left: editableRect.left + editableRect.width - panelRect.width,
+		name: 'toolbar_se'
+	} )
+];

+ 20 - 5
packages/ckeditor5-editor-inline/tests/inlineeditorui.js

@@ -57,16 +57,31 @@ describe( 'InlineEditorUI', () => {
 		} );
 
 		describe( 'panel', () => {
-			it( 'binds view.panel#isActive to editor.ui#focusTracker', () => {
+			it( 'binds view.panel#isVisible to editor.ui#focusTracker', () => {
 				ui.focusTracker.isFocused = false;
-				expect( view.panel.isActive ).to.be.false;
+				expect( view.panel.isVisible ).to.be.false;
 
 				ui.focusTracker.isFocused = true;
-				expect( view.panel.isActive ).to.be.true;
+				expect( view.panel.isVisible ).to.be.true;
 			} );
 
-			it( 'sets view.panel#targetElement', () => {
-				expect( view.panel.targetElement ).to.equal( view.editableElement );
+			// https://github.com/ckeditor/ckeditor5-editor-inline/issues/4
+			it( 'pin() is called on editor.editable.view#render', () => {
+				const spy = sinon.spy( view.panel, 'pin' );
+
+				view.panel.hide();
+
+				editor.editing.view.fire( 'render' );
+				sinon.assert.notCalled( spy );
+
+				view.panel.show();
+
+				editor.editing.view.fire( 'render' );
+				sinon.assert.calledOnce( spy );
+				sinon.assert.calledWithExactly( spy, {
+					target: view.editableElement,
+					positions: sinon.match.array
+				} );
 			} );
 		} );
 

+ 55 - 3
packages/ckeditor5-editor-inline/tests/inlineeditoruiview.js

@@ -5,7 +5,7 @@
 
 import InlineEditorUIView from '../src/inlineeditoruiview';
 import ToolbarView from '@ckeditor/ckeditor5-ui/src/toolbar/toolbarview';
-import FloatingPanelView from '@ckeditor/ckeditor5-ui/src/panel/floating/floatingpanelview';
+import BalloonPanelView from '@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview';
 import InlineEditableUIView from '@ckeditor/ckeditor5-ui/src/editableui/inline/inlineeditableuiview';
 import Locale from '@ckeditor/ckeditor5-utils/src/locale';
 
@@ -30,7 +30,7 @@ describe( 'InlineEditorUIView', () => {
 
 		describe( '#panel', () => {
 			it( 'is created', () => {
-				expect( view.panel ).to.be.instanceof( FloatingPanelView );
+				expect( view.panel ).to.be.instanceof( BalloonPanelView );
 			} );
 
 			it( 'is given a locale object', () => {
@@ -44,6 +44,10 @@ describe( 'InlineEditorUIView', () => {
 			it( 'is put into the #body collection', () => {
 				expect( view.body.get( 0 ) ).to.equal( view.panel );
 			} );
+
+			it( 'gets view.panel#withArrow set', () => {
+				expect( view.panel.withArrow ).to.be.false;
+			} );
 		} );
 
 		describe( '#editable', () => {
@@ -67,7 +71,7 @@ describe( 'InlineEditorUIView', () => {
 		} );
 	} );
 
-	describe( 'init', () => {
+	describe( 'init()', () => {
 		it( 'appends #toolbar to panel#content', () => {
 			expect( view.panel.content ).to.have.length( 0 );
 
@@ -88,4 +92,52 @@ describe( 'InlineEditorUIView', () => {
 				.then( () => view.destroy() );
 		} );
 	} );
+
+	describe( 'panelPositions', () => {
+		it( 'returns the right positions in the right order', () => {
+			const positions = view.panelPositions;
+			const editableRect = {
+				top: 100,
+				bottom: 200,
+				left: 100,
+				right: 100,
+				width: 100,
+				height: 100
+			};
+			const panelRect = {
+				top: 0,
+				bottom: 0,
+				left: 0,
+				right: 0,
+				width: 50,
+				height: 50
+			};
+
+			expect( positions ).to.have.length( 4 );
+
+			expect( positions[ 0 ]( editableRect, panelRect ) ).to.deep.equal( {
+				name: 'toolbar_nw',
+				left: 100,
+				top: 50
+			} );
+
+			expect( positions[ 1 ]( editableRect, panelRect ) ).to.deep.equal( {
+				name: 'toolbar_sw',
+				left: 100,
+				top: 200
+			} );
+
+			expect( positions[ 2 ]( editableRect, panelRect ) ).to.deep.equal( {
+				name: 'toolbar_ne',
+				left: 150,
+				top: 50
+			} );
+
+			expect( positions[ 3 ]( editableRect, panelRect ) ).to.deep.equal( {
+				name: 'toolbar_se',
+				left: 150,
+				top: 200
+			} );
+		} );
+	} );
 } );

+ 10 - 0
packages/ckeditor5-editor-inline/tests/manual/tickets/4/1.html

@@ -0,0 +1,10 @@
+<style>
+	body {
+		height: 10000px;
+	}
+</style>
+
+<div id="editor">
+    <p>Content of the editor.</p>
+</div>
+

+ 20 - 0
packages/ckeditor5-editor-inline/tests/manual/tickets/4/1.js

@@ -0,0 +1,20 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals console:false, document, window */
+
+import InlineEditor from '../../../../src/inline';
+import ArticlePreset from '@ckeditor/ckeditor5-presets/src/article';
+
+InlineEditor.create( document.querySelector( '#editor' ), {
+	plugins: [ ArticlePreset ],
+	toolbar: [ 'headings', 'bold', 'italic', 'link', 'unlink', 'bulletedList', 'numberedList', 'blockQuote', 'undo', 'redo' ]
+} )
+.then( editor => {
+	window.editor = editor;
+} )
+.catch( err => {
+	console.error( err.stack );
+} );

+ 7 - 0
packages/ckeditor5-editor-inline/tests/manual/tickets/4/1.md

@@ -0,0 +1,7 @@
+### Issue [#4](https://github.com/ckeditor/ckeditor5-editor-inline/issues/4) manual test
+
+1. Focus the editor,
+2. Scroll the web page until the toolbar is visible below editable,
+3. Type a couple of new lines in the editor,
+
+Expected: The toolbar should stick to the bottom edge of editable as the editable has grown up.