浏览代码

Merge pull request #160 from ckeditor/t/154

Feature: Added support for toolbar item separators. Closes #154.
Piotrek Koszuliński 8 年之前
父节点
当前提交
bb35f716bb

+ 34 - 0
packages/ckeditor5-ui/src/toolbar/toolbarseparatorview.js

@@ -0,0 +1,34 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * @module ui/toolbar/toolbarseparatorview
+ */
+
+import View from '../view';
+import Template from '../template';
+
+/**
+ * The toolbar separator view class.
+ *
+ * @extends module:ui/view~View
+ */
+export default class ToolbarSeparatorView extends View {
+	/**
+	 * @inheritDoc
+	 */
+	constructor( locale ) {
+		super( locale );
+
+		this.template = new Template( {
+			tag: 'span',
+			attributes: {
+				class: [
+					'ck-toolbar__separator'
+				]
+			}
+		} );
+	}
+}

+ 21 - 0
packages/ckeditor5-ui/src/toolbar/toolbarview.js

@@ -12,6 +12,7 @@ import Template from '../template';
 import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
 import FocusCycler from '../focuscycler';
 import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';
+import ToolbarSeparatorView from './toolbarseparatorview';
 
 /**
  * The toolbar view class.
@@ -105,5 +106,25 @@ export default class ToolbarView extends View {
 	focus() {
 		this._focusCycler.focusFirst();
 	}
+
+	/**
+	 * A utility which expands a plain toolbar configuration into
+	 * {@link module:ui/toolbar/toolbarview~ToolbarView#items} using a given component factory.
+	 *
+	 * @param {Array} config The toolbar config.
+	 * @param {module:ui/componentfactory~ComponentFactory} factory A factory producing toolbar items.
+	 * @returns {Promise} A promise resolved when created toolbar items are initialized.
+	 */
+	fillFromConfig( config, factory ) {
+		if ( !config ) {
+			return Promise.resolve();
+		}
+
+		return Promise.all( config.map( name => {
+			const component = name == '|' ? new ToolbarSeparatorView() : factory.create( name );
+
+			return this.items.add( component );
+		} ) );
+	}
 }
 

+ 1 - 3
packages/ckeditor5-ui/tests/manual/contextualtoolbar/contextualtoolbar.js

@@ -77,9 +77,7 @@ function createContextualToolbar( editor ) {
 		const editingView = editor.editing.view;
 
 		// Fill the toolbar with some buttons. Simply copy default editor toolbar.
-		for ( let name of editor.config.get( 'toolbar' ) ) {
-			toolbar.items.add( editor.ui.componentFactory.create( name ) );
-		}
+		toolbar.fillFromConfig( editor.config.get( 'toolbar' ), editor.ui.componentFactory );
 
 		// Let the focusTracker know about new focusable UI element.
 		editor.ui.focusTracker.add( panel.element );

+ 1 - 3
packages/ckeditor5-ui/tests/manual/imagetoolbar/imagetoolbar.js

@@ -79,9 +79,7 @@ function createImageToolbar( editor ) {
 		const editingView = editor.editing.view;
 
 		// Fill the toolbar with some buttons. Simply copy default editor toolbar.
-		for ( let name of editor.config.get( 'toolbar' ) ) {
-			toolbar.items.add( editor.ui.componentFactory.create( name ) );
-		}
+		toolbar.fillFromConfig( editor.config.get( 'toolbar' ), editor.ui.componentFactory );
 
 		// Let the focusTracker know about new focusable UI element.
 		editor.ui.focusTracker.add( panel.element );

+ 24 - 0
packages/ckeditor5-ui/tests/toolbar/toolbarseparatorview.js

@@ -0,0 +1,24 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+import ToolbarSeparatorView from '../../src/toolbar/toolbarseparatorview';
+
+describe( 'ToolbarSeparatorView', () => {
+	let locale, view;
+
+	beforeEach( () => {
+		locale = {};
+		view = new ToolbarSeparatorView();
+
+		return view.init();
+	} );
+
+	describe( 'template', () => {
+		it( 'should create element from template', () => {
+			expect( view.element.tagName ).to.equal( 'SPAN' );
+			expect( view.element.classList.contains( 'ck-toolbar__separator' ) ).to.true;
+		} );
+	} );
+} );

+ 41 - 0
packages/ckeditor5-ui/tests/toolbar/toolbarview.js

@@ -6,7 +6,9 @@
 /* global document */
 
 import ToolbarView from '../../src/toolbar/toolbarview';
+import ToolbarSeparatorView from '../../src/toolbar/toolbarseparatorview';
 import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';
+import ComponentFactory from '../../src/componentfactory';
 import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
 import FocusCycler from '../../src/focuscycler';
 import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
@@ -209,6 +211,34 @@ describe( 'ToolbarView', () => {
 			sinon.assert.calledOnce( spy );
 		} );
 	} );
+
+	describe( 'fillFromConfig()', () => {
+		let factory;
+
+		beforeEach( () => {
+			factory = new ComponentFactory( {} );
+
+			factory.add( 'foo', namedFactory( 'foo' ) );
+			factory.add( 'bar', namedFactory( 'bar' ) );
+		} );
+
+		it( 'returns a promise', () => {
+			expect( view.fillFromConfig() ).to.be.instanceOf( Promise );
+		} );
+
+		it( 'expands the config into collection', () => {
+			return view.fillFromConfig( [ 'foo', 'bar', '|', 'foo' ], factory )
+				.then( () => {
+					const items = view.items;
+
+					expect( items ).to.have.length( 4 );
+					expect( items.get( 0 ).name ).to.equal( 'foo' );
+					expect( items.get( 1 ).name ).to.equal( 'bar' );
+					expect( items.get( 2 ) ).to.be.instanceOf( ToolbarSeparatorView );
+					expect( items.get( 3 ).name ).to.equal( 'foo' );
+				} );
+		} );
+	} );
 } );
 
 function focusable() {
@@ -225,3 +255,14 @@ function nonFocusable() {
 
 	return view;
 }
+
+function namedFactory( name ) {
+	return ( locale ) => {
+		const view = new View( locale );
+
+		view.name = name;
+		view.element = document.createElement( 'a' );
+
+		return view;
+	};
+}

+ 2 - 2
packages/ckeditor5-ui/theme/components/toolbar.scss

@@ -4,11 +4,11 @@
 .ck-toolbar {
 	@include ck-unselectable();
 
-	&-separator {
+	&__separator {
 		display: inline-block;
 	}
 
-	&-newline {
+	&__newline {
 		display: block;
 		clear: left;
 	}