8
0

componentfactory.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /**
  2. * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  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 {Iterator.<String>}
  58. */
  59. * names() {
  60. yield* this._components.keys();
  61. }
  62. /**
  63. * Registers a component factory function that will be used by the
  64. * {@link #create create} method and called with the
  65. * {@link module:core/editor/editor~Editor#locale editor locale} as an argument,
  66. * allowing localization of the {@link module:ui/view~View view}.
  67. *
  68. * @param {String} name The name of the component.
  69. * @param {Function} callback The callback that returns the component.
  70. */
  71. add( name, callback ) {
  72. if ( this.has( name ) ) {
  73. /**
  74. * The item already exists in the component factory.
  75. *
  76. * @error componentfactory-item-exists
  77. * @param {String} name The name of the component.
  78. */
  79. throw new CKEditorError(
  80. 'componentfactory-item-exists: The item already exists in the component factory.', { name }
  81. );
  82. }
  83. this._components.set( getNormalized( name ), callback );
  84. }
  85. /**
  86. * Creates an instance of a component registered in the factory under a specific name.
  87. *
  88. * When called, the {@link module:core/editor/editor~Editor#locale editor locale} is passed to
  89. * the previously {@link #add added} factory function, allowing localization of the
  90. * {@link module:ui/view~View view}.
  91. *
  92. * @param {String} name The name of the component.
  93. * @returns {module:ui/view~View} The instantiated component view.
  94. */
  95. create( name ) {
  96. if ( !this.has( name ) ) {
  97. /**
  98. * The required component is not registered in the component factory. Please make sure
  99. * the provided name is correct and the component has been correctly
  100. * {@link #add added} to the factory.
  101. *
  102. * @error componentfactory-item-missing
  103. * @param {String} name The name of the missing component.
  104. */
  105. throw new CKEditorError(
  106. 'componentfactory-item-missing: The required component is not registered in the factory.', { name }
  107. );
  108. }
  109. return this._components.get( getNormalized( name ) )( this.editor.locale );
  110. }
  111. /**
  112. * Checks if a component of a given name is registered in the factory.
  113. *
  114. * @param {String} name The name of the component.
  115. * @returns {Boolean}
  116. */
  117. has( name ) {
  118. return this._components.has( getNormalized( name ) );
  119. }
  120. }
  121. //
  122. // Ensures that the component name used as the key in the internal map is in lower case.
  123. //
  124. // @private
  125. // @param {String} name
  126. // @returns {String}
  127. function getNormalized( name ) {
  128. return String( name ).toLowerCase();
  129. }