componentfactory.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /**
  2. * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  4. */
  5. /**
  6. * @module ui/componentfactory
  7. */
  8. import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
  9. /**
  10. * A helper class implementing the UI component ({@link module:ui/view~View view}) factory.
  11. *
  12. * It allows functions producing specific UI components to be registered under their unique names
  13. * in the factory. A registered component can be then instantiated by providing its name.
  14. * Note that names are case insensitive.
  15. *
  16. * // The editor provides localization tools for the factory.
  17. * const factory = new ComponentFactory( editor );
  18. *
  19. * factory.add( 'foo', locale => new FooView( locale ) );
  20. * factory.add( 'bar', locale => new BarView( locale ) );
  21. *
  22. * // An instance of FooView.
  23. * const fooInstance = factory.create( 'foo' );
  24. *
  25. * // Names are case insensitive so this is also allowed:
  26. * const barInstance = factory.create( 'Bar' );
  27. *
  28. * The {@link module:core/editor/editor~Editor#locale editor locale} is passed to the factory
  29. * function when {@link module:ui/componentfactory~ComponentFactory#create} is called.
  30. */
  31. export default class ComponentFactory {
  32. /**
  33. * Creates an instance of the factory.
  34. *
  35. * @constructor
  36. * @param {module:core/editor/editor~Editor} editor The editor instance.
  37. */
  38. constructor( editor ) {
  39. /**
  40. * The editor instance that the factory belongs to.
  41. *
  42. * @readonly
  43. * @member {module:core/editor/editor~Editor}
  44. */
  45. this.editor = editor;
  46. /**
  47. * Registered component factories.
  48. *
  49. * @private
  50. * @member {Map}
  51. */
  52. this._components = new Map();
  53. }
  54. /**
  55. * Returns an iterator of registered component names. Names are returned in lower case.
  56. *
  57. * @returns {Iterable.<String>}
  58. */
  59. * names() {
  60. for ( const value of this._components.values() ) {
  61. yield value.originalName;
  62. }
  63. }
  64. /**
  65. * Registers a component factory function that will be used by the
  66. * {@link #create create} method and called with the
  67. * {@link module:core/editor/editor~Editor#locale editor locale} as an argument,
  68. * allowing localization of the {@link module:ui/view~View view}.
  69. *
  70. * @param {String} name The name of the component.
  71. * @param {Function} callback The callback that returns the component.
  72. */
  73. add( name, callback ) {
  74. this._components.set( getNormalized( name ), { callback, originalName: name } );
  75. }
  76. /**
  77. * Creates an instance of a component registered in the factory under a specific name.
  78. *
  79. * When called, the {@link module:core/editor/editor~Editor#locale editor locale} is passed to
  80. * the previously {@link #add added} factory function, allowing localization of the
  81. * {@link module:ui/view~View view}.
  82. *
  83. * @param {String} name The name of the component.
  84. * @returns {module:ui/view~View} The instantiated component view.
  85. */
  86. create( name ) {
  87. if ( !this.has( name ) ) {
  88. /**
  89. * The required component is not registered in the component factory. Please make sure
  90. * the provided name is correct and the component has been correctly
  91. * {@link #add added} to the factory.
  92. *
  93. * @error componentfactory-item-missing
  94. * @param {String} name The name of the missing component.
  95. */
  96. throw new CKEditorError(
  97. 'componentfactory-item-missing',
  98. this,
  99. { name }
  100. );
  101. }
  102. return this._components.get( getNormalized( name ) ).callback( this.editor.locale );
  103. }
  104. /**
  105. * Checks if a component of a given name is registered in the factory.
  106. *
  107. * @param {String} name The name of the component.
  108. * @returns {Boolean}
  109. */
  110. has( name ) {
  111. return this._components.has( getNormalized( name ) );
  112. }
  113. }
  114. //
  115. // Ensures that the component name used as the key in the internal map is in lower case.
  116. //
  117. // @private
  118. // @param {String} name
  119. // @returns {String}
  120. function getNormalized( name ) {
  121. return String( name ).toLowerCase();
  122. }