8
0
Kamil Piechaczek 6 лет назад
Родитель
Сommit
a9187bf504

+ 42 - 22
packages/ckeditor5-special-characters/src/specialcharactersui.js

@@ -11,7 +11,8 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import { createDropdown } from '@ckeditor/ckeditor5-ui/src/dropdown/utils';
 import specialCharactersIcon from '../theme/icons/specialcharacters.svg';
 import InsertSpecialCharacterCommand from './insertspecialcharactercommand';
-import SelectView from '@ckeditor/ckeditor5-ui/src/selectview/selectview';
+import SpecialCharactersTableView from './ui/specialcharacterstableview';
+import SpecialCharactersSelectView from './ui/specialcharactersselectview';
 
 /**
  * The special characters UI plugin.
@@ -23,58 +24,77 @@ export default class SpecialCharactersUI extends Plugin {
 		const editor = this.editor;
 		const t = editor.t;
 		const specialCharacterPlugin = editor.plugins.get( 'SpecialCharacters' );
+		const label = t( 'Special characters' );
 
 		const command = new InsertSpecialCharacterCommand( editor );
 		editor.commands.add( 'specialCharacters', command );
 
 		// Add the `specialCharacters` dropdown button to feature components.
 		editor.ui.componentFactory.add( 'specialCharacters', locale => {
-			// Prepare all special characters groups for displaying in the select view.
-			const specialCharactersGroups = [ ...specialCharacterPlugin.getGroups() ]
-				.map( groupName => ( { label: groupName, value: groupName } ) );
-
+			// Prepare the dropdown element.
 			const dropdownView = createDropdown( locale );
-			const selectView = new SelectView( locale, specialCharactersGroups );
 
 			dropdownView.buttonView.set( {
-				label: t( 'Special characters' ),
+				label,
 				icon: specialCharactersIcon,
 				tooltip: true
 			} );
 
 			dropdownView.bind( 'isEnabled' ).to( command );
-			dropdownView.panelView.children.add( selectView );
 
-			// When a special character was clicked, insert it to the editor.
-			dropdownView.on( 'execute', ( evt, data ) => {
-				console.log( 'Clicked.', data );
+			const specialCharactersSelectView = new SpecialCharactersSelectView( locale, {
+				labelText: label,
+				selectOptions: getSelectViewOptions()
+			} );
+
+			const symbolTableView = new SpecialCharactersTableView( locale, {
+				columns: 10 // TODO: Read from config.
+			} );
+
+			symbolTableView.delegate( 'execute' ).to( dropdownView, 'execute' );
 
-				// command.execute( { item: data } );
+			// Insert a special character when a tile was clicked.
+			dropdownView.on( 'execute', ( evt, data ) => {
+				command.execute( { item: data.title } );
 			} );
 
+			// Draw special characters tiles when the dropdown is open.
 			dropdownView.on( 'change:isOpen', ( evt, name, isVisible ) => {
 				if ( !isVisible ) {
 					return;
 				}
 
-				// Draw special characters tiles when the dropdown is opened.
-				printCharacters( selectView );
+				printCharacters( specialCharactersSelectView, symbolTableView.symbolGridView );
 			} );
 
-			// Draw special characters when a user changed a category.
-			selectView.on( 'input', () => {
-				printCharacters( selectView );
+			// Draw special characters tiles for specified category (when a user has changed it).
+			specialCharactersSelectView.on( 'input', () => {
+				printCharacters( specialCharactersSelectView, symbolTableView.symbolGridView );
 			} );
 
+			dropdownView.panelView.children.add( specialCharactersSelectView );
+			dropdownView.panelView.children.add( symbolTableView );
+
 			return dropdownView;
 		} );
 
-		function printCharacters( selectView ) {
-			const groupName = selectView.element.value;
-			const characters = specialCharacterPlugin.getCharactersForGroup( groupName );
+		function printCharacters( selectView, gridView ) {
+			// TODO: Keyboard navigation.
+			gridView.items.clear();
+
+			const groupName = selectView.value;
+			const characterTitles = specialCharacterPlugin.getCharactersForGroup( groupName );
+
+			for ( const title of characterTitles ) {
+				const character = specialCharacterPlugin.getCharacter( title );
 
-			console.log( { groupName, characters } );
-			console.log( 'Draw!' );
+				gridView.items.add( gridView.createSymbolTile( character, title ) );
+			}
+		}
+
+		function getSelectViewOptions() {
+			return [ ...specialCharacterPlugin.getGroups() ]
+				.map( groupName => ( { label: groupName, value: groupName } ) );
 		}
 	}
 }

+ 83 - 0
packages/ckeditor5-special-characters/src/ui/specialcharactersselectview.js

@@ -0,0 +1,83 @@
+/**
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module special-characters/ui/specialcharactersselectview
+ */
+
+import View from '@ckeditor/ckeditor5-ui/src/view';
+import LabelView from '@ckeditor/ckeditor5-ui/src/label/labelview';
+import SelectView from '@ckeditor/ckeditor5-ui/src/selectview/selectview';
+import uid from '@ckeditor/ckeditor5-utils/src/uid';
+
+/**
+ * @extends module:ui/view~View
+ */
+export default class SpecialCharactersSelectView extends View {
+	/**
+	 * Creates a view to be inserted as a child of {@link module:ui/dropdown/dropdownview~DropdownView}.
+	 *
+	 * @param {module:utils/locale~Locale} [locale] The localization services instance.
+	 * @param {Object} options
+	 * @param {String} options.labelText A label for the select element.
+	 * @param {Array.<module:ui/selectview/selectview~SelectViewOption>} options.selectOptions Options to chose in the select view.
+	 */
+	constructor( locale, options ) {
+		super( locale );
+
+		const inputUid = `ck-select-${ uid() }`;
+
+		/**
+		 * A label for the select view.
+		 *
+		 * @member {module:ui/label/labelview~LabelView}
+		 */
+		this.label = new LabelView( this.locale );
+
+		/**
+		 * Select view for changing a category of special characters.
+		 *
+		 * @member {module:ui/selectview/selectview~SelectView}
+		 */
+		this.selectView = new SelectView( this.locale, options.selectOptions );
+		this.selectView.delegate( 'input' ).to( this );
+
+		this.label.for = inputUid;
+		this.label.text = options.labelText;
+		this.label.extendTemplate( {
+			attributes: {
+				class: [
+					'ck',
+					'ck-symbol-grid__label'
+				]
+			}
+		} );
+
+		this.selectView.id = inputUid;
+
+		this.setTemplate( {
+			tag: 'div',
+			attributes: {
+				class: [
+					'ck',
+					'ck-grid-table'
+				]
+			},
+			children: [
+				this.label,
+				this.selectView
+			]
+		} );
+	}
+
+	/**
+	 * Returns a value from the select view.
+	 *
+	 * @returns {String}
+	 */
+	get value() {
+		return this.selectView.element.value;
+	}
+}

+ 160 - 0
packages/ckeditor5-special-characters/src/ui/specialcharacterstableview.js

@@ -0,0 +1,160 @@
+/**
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module special-characters/ui/specialcharacterstableview
+ */
+
+import View from '@ckeditor/ckeditor5-ui/src/view';
+import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
+import FocusCycler from '@ckeditor/ckeditor5-ui/src/focuscycler';
+import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';
+import SymbolGridView from '@ckeditor/ckeditor5-ui/src/symbolgrid/symbolgridview';
+
+// TODO: Keyboard navigation does not work.
+
+/**
+ * @extends module:ui/view~View
+ */
+export default class SpecialCharactersTableView extends View {
+	/**
+	 * Creates a view to be inserted as a child of {@link module:ui/dropdown/dropdownview~DropdownView}.
+	 *
+	 * @param {module:utils/locale~Locale} [locale] The localization services instance.
+	 * @param {Object} config The configuration object.
+	 * @param {Array.<module:special-characters/specialcharacters~SpecialCharacterDefinition>} config.symbolDefinitions An array with
+	 * definitions of special characters to be displayed in the table.
+	 * @param {Number} config.columns The number of columns in the color grid.
+	 */
+	constructor( locale, { symbolDefinitions = [], columns } ) {
+		super( locale );
+
+		/**
+		 * A collection of the children of the table.
+		 *
+		 * @readonly
+		 * @member {module:ui/viewcollection~ViewCollection}
+		 */
+		this.items = this.createCollection();
+
+		/**
+		 * Tracks information about the DOM focus in the list.
+		 *
+		 * @readonly
+		 * @member {module:utils/focustracker~FocusTracker}
+		 */
+		this.focusTracker = new FocusTracker();
+
+		/**
+		 * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
+		 *
+		 * @readonly
+		 * @member {module:utils/keystrokehandler~KeystrokeHandler}
+		 */
+		this.keystrokes = new KeystrokeHandler();
+
+		/**
+		 * The number of columns in the special characters grid.
+		 *
+		 * @type {Number}
+		 */
+		this.columns = columns;
+
+		/**
+		 * An array with definitions of special characters to be displayed in the table.
+		 *
+		 * @member {Array.<module:special-characters/specialcharacters~SpecialCharacterDefinition>}
+		 */
+		this.symbolDefinitions = symbolDefinitions;
+
+		/**
+		 * Preserves the reference to {@link module:ui/symbolgrid/symbolgrid~SymbolGridView} used to create
+		 * the default (static) symbol set.
+		 *
+		 * @readonly
+		 * @member {module:ui/symbolgrid/symbolgrid~SymbolGridView}
+		 */
+		this.symbolGridView = this._createSymbolGridView();
+
+		/**
+		 * Helps cycling over focusable {@link #items} in the list.
+		 *
+		 * @readonly
+		 * @protected
+		 * @member {module:ui/focuscycler~FocusCycler}
+		 */
+		this._focusCycler = new FocusCycler( {
+			focusables: this.items,
+			focusTracker: this.focusTracker,
+			keystrokeHandler: this.keystrokes,
+			actions: {
+				// Navigate list items backwards using the Arrow Up key.
+				focusPrevious: 'arrowup',
+
+				// Navigate list items forwards using the Arrow Down key.
+				focusNext: 'arrowdown',
+			}
+		} );
+
+		this.setTemplate( {
+			tag: 'div',
+			attributes: {
+				class: [
+					'ck',
+					'ck-grid-table'
+				]
+			},
+			children: this.items
+		} );
+
+		this.items.add( this.symbolGridView );
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	render() {
+		super.render();
+
+		// Items added before rendering should be known to the #focusTracker.
+		for ( const item of this.items ) {
+			this.focusTracker.add( item.element );
+		}
+
+		// Start listening for the keystrokes coming from #element.
+		this.keystrokes.listenTo( this.element );
+	}
+
+	/**
+	 * Focuses the first focusable element in {@link #items}.
+	 */
+	focus() {
+		this._focusCycler.focusFirst();
+	}
+
+	/**
+	 * Focuses the last focusable element in {@link #items}.
+	 */
+	focusLast() {
+		this._focusCycler.focusLast();
+	}
+
+	/**
+	 * Creates a static symbol table grid based on the editor configuration.
+	 *
+	 * @private
+	 * @returns {module:ui/symbolgrid/symbolgrid~SymbolGridView}
+	 */
+	_createSymbolGridView() {
+		const symbolGrid = new SymbolGridView( this.locale, {
+			symbolDefinitions: this.symbolDefinitions,
+			columns: this.columns
+		} );
+
+		symbolGrid.delegate( 'execute' ).to( this );
+
+		return symbolGrid;
+	}
+}