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

Merge pull request #61 from ckeditor/t/60

Feature: The toolbar should support a vertical offset from the top of the web page. Closes #60.
Piotrek Koszuliński 8 лет назад
Родитель
Сommit
8ff192a340

+ 17 - 1
packages/ckeditor5-editor-classic/src/classiceditorui.js

@@ -10,6 +10,7 @@
 import ComponentFactory from '@ckeditor/ckeditor5-ui/src/componentfactory';
 import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
 import enableToolbarKeyboardFocus from '@ckeditor/ckeditor5-ui/src/toolbar/enabletoolbarkeyboardfocus';
+import normalizeToolbarConfig from '@ckeditor/ckeditor5-ui/src/toolbar/normalizetoolbarconfig';
 
 /**
  * The classic editor UI class.
@@ -44,6 +45,14 @@ export default class ClassicEditorUI {
 		 */
 		this.focusTracker = new FocusTracker();
 
+		/**
+		 * A normalized `config.toolbar` object.
+		 *
+		 * @type {Object}
+		 * @private
+		 */
+		this._toolbarConfig = normalizeToolbarConfig( editor.config.get( 'toolbar' ) );
+
 		// Set–up the view.
 		view.set( 'width', editor.config.get( 'ui.width' ) );
 		view.set( 'height', editor.config.get( 'ui.height' ) );
@@ -52,6 +61,10 @@ export default class ClassicEditorUI {
 		view.toolbar.bind( 'isActive' ).to( this.focusTracker, 'isFocused' );
 		view.toolbar.limiterElement = view.element;
 
+		if ( this._toolbarConfig && this._toolbarConfig.viewportTopOffset ) {
+			view.toolbar.viewportTopOffset = this._toolbarConfig.viewportTopOffset;
+		}
+
 		// Setup the editable.
 		const editingRoot = editor.editing.createRoot( 'div' );
 		view.editable.bind( 'isReadOnly' ).to( editingRoot );
@@ -67,7 +80,10 @@ export default class ClassicEditorUI {
 		const editor = this.editor;
 
 		this.view.init();
-		this.view.toolbar.fillFromConfig( editor.config.get( 'toolbar' ), this.componentFactory );
+
+		if ( this._toolbarConfig ) {
+			this.view.toolbar.fillFromConfig( this._toolbarConfig.items, this.componentFactory );
+		}
 
 		enableToolbarKeyboardFocus( {
 			origin: editor.editing.view,

+ 77 - 10
packages/ckeditor5-editor-classic/tests/classiceditorui.js

@@ -27,20 +27,29 @@ describe( 'ClassicEditorUI', () => {
 		editorElement = document.createElement( 'div' );
 		document.body.appendChild( editorElement );
 
-		editor = new ClassicTestEditor( editorElement, {
+		return ClassicTestEditor.create( editorElement, {
 			toolbar: [ 'foo', 'bar' ],
 			ui: {
 				width: 100,
 				height: 200
 			}
+		} )
+		.then( newEditor => {
+			editor = newEditor;
+
+			view = new ClassicEditorUIView( editor.locale );
+			ui = new ClassicEditorUI( editor, view );
+			editable = editor.editing.view.getRoot();
+
+			ui.componentFactory.add( 'foo', viewCreator( 'foo' ) );
+			ui.componentFactory.add( 'bar', viewCreator( 'bar' ) );
 		} );
+	} );
 
-		view = new ClassicEditorUIView( editor.locale );
-		ui = new ClassicEditorUI( editor, view );
-		editable = editor.editing.view.getRoot();
+	afterEach( () => {
+		editorElement.remove();
 
-		ui.componentFactory.add( 'foo', viewCreator( 'foo' ) );
-		ui.componentFactory.add( 'bar', viewCreator( 'bar' ) );
+		editor.destroy();
 	} );
 
 	describe( 'constructor()', () => {
@@ -77,6 +86,35 @@ describe( 'ClassicEditorUI', () => {
 			it( 'sets view.toolbar#limiterElement', () => {
 				expect( view.toolbar.limiterElement ).to.equal( view.element );
 			} );
+
+			it( 'doesn\'t set view.toolbar#viewportTopOffset, if not specified in the config', () => {
+				expect( view.toolbar.viewportTopOffset ).to.equal( 0 );
+			} );
+
+			it( 'sets view.toolbar#viewportTopOffset, when specified in the config', () => {
+				editorElement = document.createElement( 'div' );
+				document.body.appendChild( editorElement );
+
+				return ClassicTestEditor.create( editorElement, {
+					toolbar: {
+						items: [ 'foo', 'bar' ],
+						viewportTopOffset: 100
+					}
+				} )
+				.then( editor => {
+					view = new ClassicEditorUIView( editor.locale );
+					ui = new ClassicEditorUI( editor, view );
+					editable = editor.editing.view.getRoot();
+
+					ui.componentFactory.add( 'foo', viewCreator( 'foo' ) );
+					ui.componentFactory.add( 'bar', viewCreator( 'bar' ) );
+
+					expect( view.toolbar.viewportTopOffset ).to.equal( 100 );
+
+					editorElement.remove();
+					return editor.destroy();
+				} );
+			} );
 		} );
 
 		describe( 'editable', () => {
@@ -127,11 +165,40 @@ describe( 'ClassicEditorUI', () => {
 			sinon.assert.calledOnce( spy );
 		} );
 
-		it( 'fills view.toolbar#items with editor config', () => {
-			const spy = testUtils.sinon.spy( view.toolbar, 'fillFromConfig' );
+		describe( 'view.toolbar#items', () => {
+			it( 'are filled with the config.toolbar (specified as an Array)', () => {
+				const spy = testUtils.sinon.spy( view.toolbar, 'fillFromConfig' );
 
-			ui.init();
-			sinon.assert.calledWithExactly( spy, editor.config.get( 'toolbar' ), ui.componentFactory );
+				ui.init();
+				sinon.assert.calledWithExactly( spy, editor.config.get( 'toolbar' ), ui.componentFactory );
+			} );
+
+			it( 'are filled with the config.toolbar (specified as an Object)', () => {
+				editorElement = document.createElement( 'div' );
+				document.body.appendChild( editorElement );
+
+				return ClassicTestEditor.create( editorElement, {
+					toolbar: {
+						items: [ 'foo', 'bar' ],
+						viewportTopOffset: 100
+					}
+				} )
+				.then( editor => {
+					view = new ClassicEditorUIView( editor.locale );
+					ui = new ClassicEditorUI( editor, view );
+
+					ui.componentFactory.add( 'foo', viewCreator( 'foo' ) );
+					ui.componentFactory.add( 'bar', viewCreator( 'bar' ) );
+
+					const spy = testUtils.sinon.spy( view.toolbar, 'fillFromConfig' );
+
+					ui.init();
+					sinon.assert.calledWithExactly( spy,
+						editor.config.get( 'toolbar.items' ),
+						ui.componentFactory
+					);
+				} );
+			} );
 		} );
 
 		it( 'initializes keyboard navigation between view#toolbar and view#editable', () => {

+ 3 - 0
packages/ckeditor5-editor-classic/tests/classiceditoruiview.js

@@ -56,8 +56,11 @@ describe( 'ClassicEditorUIView', () => {
 		it( 'returns editable\'s view element', () => {
 			document.body.appendChild( view.element );
 
+			view.toolbar.limiterElement = view.element;
 			view.init();
+
 			expect( view.editableElement.getAttribute( 'contentEditable' ) ).to.equal( 'true' );
+
 			view.destroy();
 		} );
 	} );

+ 37 - 0
packages/ckeditor5-editor-classic/tests/manual/tickets/60/1.html

@@ -0,0 +1,37 @@
+<div id="editor">
+	<h2>Hello world!</h2>
+	<p>This is an editor instance.</p>
+	<p>This is an editor instance.</p>
+	<p>This is an editor instance.</p>
+	<p>This is an editor instance.</p>
+	<p>This is an editor instance.</p>
+	<p>This is an editor instance.</p>
+</div>
+
+<div id="fixed">The toolbar should stick to me instead of the viewport.</div>
+
+<style>
+	body {
+		height: 10000px;
+	}
+
+	.ck-editor {
+		margin-top: 200px;
+		margin-left: 100px;
+		margin-bottom: 200px;
+		width: 450px;
+	}
+
+	#fixed {
+		width: 100%;
+		height: 100px;
+		position: fixed;
+		top: 0;
+		z-index: 9999;
+		background: green;
+		opacity: .8;
+		color: #fff;
+		box-sizing: border-box;
+		padding: 40px;
+	}
+</style>

+ 32 - 0
packages/ckeditor5-editor-classic/tests/manual/tickets/60/1.js

@@ -0,0 +1,32 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals console:false, document, window */
+
+import ClassicEditor from '../../../../src/classiceditor';
+import Enter from '@ckeditor/ckeditor5-enter/src/enter';
+import Typing from '@ckeditor/ckeditor5-typing/src/typing';
+import Heading from '@ckeditor/ckeditor5-heading/src/heading';
+import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
+import Undo from '@ckeditor/ckeditor5-undo/src/undo';
+import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
+import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
+
+ClassicEditor.create( document.querySelector( '#editor' ), {
+	plugins: [ Enter, Typing, Paragraph, Undo, Heading, Bold, Italic ],
+	toolbar: {
+		items: [ 'headings', 'bold', 'italic', 'undo', 'redo' ],
+		viewportTopOffset: 100
+	}
+} )
+.then( newEditor => {
+	console.log( 'Editor was initialized', newEditor );
+	console.log( 'You can now play with it using global `editor` and `editable` variables.' );
+
+	window.editor = newEditor;
+} )
+.catch( err => {
+	console.error( err.stack );
+} );

+ 20 - 0
packages/ckeditor5-editor-classic/tests/manual/tickets/60/1.md

@@ -0,0 +1,20 @@
+### The toolbar should support a vertical offset from the top of the web page [#60](https://github.com/ckeditor/ckeditor5-editor-classic/issues/60)
+
+## Focus then scroll
+
+1. Focus the editor.
+2. Scroll the web page until the toolbar reaches the green box boundaries.
+
+**Expected:**
+
+1. The toolbar should stick to the green box instead of the viewport edge, respecting `toolbar.viewportTopOffset` configuration.
+2. At some point, the toolbar should disappear below the green box, leaving some space for the last paragraph of the content to remain visible.
+
+## Scroll then focus
+
+1. Scroll the web page until the toolbar is underneath the green box.
+2. Focus the editor.
+
+**Expected:**
+
+1. The toolbar should stick to the lower boundary of the green box.