| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- /**
- * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
- */
- /**
- * @module special-characters/specialcharacters
- */
- import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
- import Typing from '@ckeditor/ckeditor5-typing/src/typing';
- import { createDropdown } from '@ckeditor/ckeditor5-ui/src/dropdown/utils';
- import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
- import SpecialCharactersNavigationView from './ui/specialcharactersnavigationview';
- import CharacterGridView from './ui/charactergridview';
- import CharacterInfoView from './ui/characterinfoview';
- import specialCharactersIcon from '../theme/icons/specialcharacters.svg';
- import '../theme/specialcharacters.css';
- const ALL_SPECIAL_CHARACTERS_GROUP = 'All';
- /**
- * The special characters feature.
- *
- * Introduces the `'specialCharacters'` dropdown.
- *
- * @extends module:core/plugin~Plugin
- */
- export default class SpecialCharacters extends Plugin {
- /**
- * @inheritDoc
- */
- static get requires() {
- return [ Typing ];
- }
- /**
- * @inheritDoc
- */
- static get pluginName() {
- return 'SpecialCharacters';
- }
- /**
- * @inheritDoc
- */
- constructor( editor ) {
- super( editor );
- /**
- * Registered characters. A pair of a character name and its symbol.
- *
- * @private
- * @member {Map.<String, String>} #_characters
- */
- this._characters = new Map();
- /**
- * Registered groups. Each group contains a collection with symbol names.
- *
- * @private
- * @member {Map.<String, Set.<String>>} #_groups
- */
- this._groups = new Map();
- }
- /**
- * @inheritDoc
- */
- init() {
- const editor = this.editor;
- const t = editor.t;
- const inputCommand = editor.commands.get( 'input' );
- // Add the `specialCharacters` dropdown button to feature components.
- editor.ui.componentFactory.add( 'specialCharacters', locale => {
- const dropdownView = createDropdown( locale );
- let dropdownPanelContent;
- dropdownView.buttonView.set( {
- label: t( 'Special characters' ),
- icon: specialCharactersIcon,
- tooltip: true
- } );
- dropdownView.bind( 'isEnabled' ).to( inputCommand );
- // Insert a special character when a tile was clicked.
- dropdownView.on( 'execute', ( evt, data ) => {
- editor.execute( 'input', { text: data.character } );
- editor.editing.view.focus();
- } );
- dropdownView.on( 'change:isOpen', () => {
- if ( !dropdownPanelContent ) {
- dropdownPanelContent = this._createDropdownPanelContent( locale, dropdownView );
- dropdownView.panelView.children.add( dropdownPanelContent.navigationView );
- dropdownView.panelView.children.add( dropdownPanelContent.gridView );
- dropdownView.panelView.children.add( dropdownPanelContent.infoView );
- }
- dropdownPanelContent.infoView.set( {
- character: null,
- name: null
- } );
- } );
- return dropdownView;
- } );
- }
- /**
- * Adds a collection of special characters to specified group. A title of a special character must be unique.
- *
- * **Note:** The "All" category name is reserved by the plugin and cannot be used as a new name for special
- * characters category.
- *
- * @param {String} groupName
- * @param {Array.<module:special-characters/specialcharacters~SpecialCharacterDefinition>} items
- */
- addItems( groupName, items ) {
- if ( groupName === ALL_SPECIAL_CHARACTERS_GROUP ) {
- /**
- * The name "All" for special category group cannot be used because it's a special category which displays all available
- * special characters.
- *
- * @error special-character-invalid-group-name
- */
- throw new CKEditorError(
- `special-character-invalid-group-name: The name "${ ALL_SPECIAL_CHARACTERS_GROUP }" is reserved and cannot be used.`
- );
- }
- const group = this._getGroup( groupName );
- for ( const item of items ) {
- group.add( item.title );
- this._characters.set( item.title, item.character );
- }
- }
- /**
- * Returns iterator of special characters groups.
- *
- * @returns {Iterable.<String>}
- */
- getGroups() {
- return this._groups.keys();
- }
- /**
- * Returns a collection of special characters symbol names (titles).
- *
- * @param {String} groupName
- * @returns {Set.<String>|undefined}
- */
- getCharactersForGroup( groupName ) {
- if ( groupName === ALL_SPECIAL_CHARACTERS_GROUP ) {
- return new Set( this._characters.keys() );
- }
- return this._groups.get( groupName );
- }
- /**
- * Returns a symbol of the special character for specified name. If the special character couldn't be found, `undefined` is returned.
- *
- * @param {String} title A title of the special character.
- * @returns {String|undefined}
- */
- getCharacter( title ) {
- return this._characters.get( title );
- }
- /**
- * Returns a group of special characters. If the group with the specified name does not exist, it will be created.
- *
- * @private
- * @param {String} groupName A name of group to create.
- */
- _getGroup( groupName ) {
- if ( !this._groups.has( groupName ) ) {
- this._groups.set( groupName, new Set() );
- }
- return this._groups.get( groupName );
- }
- /**
- * Updates the symbol grid depending on the currently selected character group.
- *
- * @private
- * @param {String} currentGroupName
- * @param {module:special-characters/ui/charactergridview~CharacterGridView} gridView
- */
- _updateGrid( currentGroupName, gridView ) {
- // Updating the grid starts with removing all tiles belonging to the old group.
- gridView.tiles.clear();
- const characterTitles = this.getCharactersForGroup( currentGroupName );
- for ( const title of characterTitles ) {
- const character = this.getCharacter( title );
- gridView.tiles.add( gridView.createTile( character, title ) );
- }
- }
- /**
- * Initializes the dropdown, used for lazy loading.
- *
- * @private
- * @param {module:utils/locale~Locale} locale
- * @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView
- * @returns {Object} Returns an object with `navigationView`, `gridView` and `infoView` properties, containing UI parts.
- */
- _createDropdownPanelContent( locale, dropdownView ) {
- const specialCharsGroups = [ ...this.getGroups() ];
- // Add a special group that shows all available special characters.
- specialCharsGroups.unshift( ALL_SPECIAL_CHARACTERS_GROUP );
- const navigationView = new SpecialCharactersNavigationView( locale, specialCharsGroups );
- const gridView = new CharacterGridView( locale );
- const infoView = new CharacterInfoView( locale );
- gridView.delegate( 'execute' ).to( dropdownView );
- gridView.on( 'tileHover', ( evt, data ) => {
- infoView.set( data );
- } );
- // Update the grid of special characters when a user changed the character group.
- navigationView.on( 'execute', () => {
- this._updateGrid( navigationView.currentGroupName, gridView );
- } );
- // Set the initial content of the special characters grid.
- this._updateGrid( navigationView.currentGroupName, gridView );
- return { navigationView, gridView, infoView };
- }
- }
- /**
- * @typedef {Object} module:special-characters/specialcharacters~SpecialCharacterDefinition
- *
- * @property {String} title A unique name of the character (e.g. "greek small letter epsilon").
- * @property {String} character A human-readable character displayed as label (e.g. "ε").
- */
|