core/plugin-manager.js

  1. /*
  2. * Your installation or use of this SugarCRM file is subject to the applicable
  3. * terms available at
  4. * http://support.sugarcrm.com/Resources/Master_Subscription_Agreements/.
  5. * If you do not agree to all of the applicable terms or do not have the
  6. * authority to bind the entity as an authorized representative, then do not
  7. * install or use this SugarCRM file.
  8. *
  9. * Copyright (C) SugarCRM Inc. All rights reserved.
  10. */
  11. /**
  12. * Plugin manager.
  13. *
  14. * Example:
  15. *
  16. * ```
  17. * const PluginManager = require('core/plugin-manager');
  18. *
  19. * PluginManager.register('fast-click-highlight', ['view', 'field'], {
  20. * color : "red",
  21. * events: {
  22. * 'click .fast-click-highlighted': 'onClickItem'
  23. * },
  24. * onClickItem: function(e) {
  25. * alert(1)
  26. * },
  27. *
  28. * // The onAttach function will be called every time the plugin is
  29. * // attached to a new component. It will be executed from the scope of
  30. * // the component being attached to.
  31. * //Applied after the plugin has been mixed into the component.
  32. * onAttach: function(component, plugin) {
  33. * this.on('render', function(){
  34. * //same as plugin.color and component.$el.css
  35. * this.$el.css('color', this.color);
  36. * });
  37. * }
  38. * });
  39. * ```
  40. *
  41. * If you want to use the current plugin for a view, you have to declare the
  42. * plugin in it:
  43. *
  44. * ```
  45. * const ViewManager = require('view/view-manager');
  46. * var MyView = ViewManager.View.extend({
  47. * initialize: function(options) {},
  48. * plugins: ['fast-click-highlight'],
  49. * ...,
  50. * });
  51. *
  52. * // or
  53. *
  54. * $plugins: [{
  55. * 'fast-click-highlight': {
  56. * events: {
  57. * 'click article' : 'onClickItem'
  58. * }
  59. * }
  60. * }],
  61. *
  62. * onClickItem: function() {
  63. * alert(2);
  64. * }
  65. * ```
  66. *
  67. * If you want to disable a plugin, you have to use the `disabledPlugins`
  68. * property as in the following example:
  69. *
  70. * ```
  71. * var MyView = ViewManager.View.extend({
  72. * initialize: function(options) {},
  73. * disabledPlugins: ['fast-click-highlight'],
  74. * ...,
  75. * });
  76. * ```
  77. * @module Core/PluginManager
  78. */
  79. /**
  80. * Gets a plugin by name.
  81. *
  82. * @param {string} name The plugin name.
  83. * @param {string} type The component type. Can be one of the following:
  84. * 'view', 'layout', 'field', 'model' or 'collection'.
  85. * @return {Object} The desired plugin object.
  86. * @private
  87. */
  88. function get(name, type) {
  89. if (PluginManager.plugins[type] && PluginManager.plugins[type][name]) {
  90. return PluginManager.plugins[type][name];
  91. }
  92. };
  93. /**
  94. * Checks if a plugin is disabled.
  95. *
  96. * @param {View/Component|Data/Bean|Data/BeanCollection} component The
  97. * component.
  98. * @param {string} pluginName The plugin name.
  99. * @return {boolean} `true` if the plugin is disabled; `false` otherwise.
  100. * @private
  101. */
  102. function isPluginDisabled(component, pluginName) {
  103. return !!_.find(component.disabledPlugins, function(name) {
  104. return name === pluginName;
  105. });
  106. };
  107. /**
  108. * @alias module:Core/PluginManager
  109. */
  110. const PluginManager = {
  111. /**
  112. * A hash map containing all registered plugins.
  113. */
  114. plugins: {
  115. view: {},
  116. field: {},
  117. layout: {},
  118. model: {},
  119. collection: {}
  120. },
  121. /**
  122. * Attaches a plugin to a view.
  123. *
  124. * @param {View/Component|Data/Bean|Data/BeanCollection} component The
  125. * component.
  126. * @param {string} type The component type. Can be one of the following:
  127. * 'view', 'layout', 'field', 'model' or 'collection'.
  128. */
  129. attach: function(component, type) {
  130. _.each(component.plugins, function(pluginName) {
  131. var prop = null;
  132. if (_.isObject(pluginName)) {
  133. var n = _.keys(pluginName)[0];
  134. prop = pluginName[n];
  135. pluginName = n;
  136. }
  137. var p = get(pluginName, type);
  138. if (p && !isPluginDisabled(component, pluginName)) {
  139. var events = _.extend({}, (_.isFunction(component.events)) ?
  140. component.events() : component.events, p.events);
  141. _.extend(component, p);
  142. if (prop) {
  143. _.extend(component, prop);
  144. if (prop.events) {
  145. _.extend(events, prop.events);
  146. }
  147. }
  148. component.events = events;
  149. //If a plugin has an onAttach function, call it now so that the plugin can initialize
  150. if (_.isFunction(p.onAttach)) {
  151. p.onAttach.call(component, component, p);
  152. }
  153. }
  154. }, this);
  155. },
  156. /**
  157. * Detaches plugins and calls the `onDetach` method on each one.
  158. *
  159. * @param {View/Component|Data/Bean|Data/BeanCollection} component The
  160. * component.
  161. * @param {string} type The component type. Can be one of the following:
  162. * 'view', 'layout', 'field', 'model' or 'collection'.
  163. */
  164. detach: function(component, type) {
  165. _.each(component.plugins, function(name) {
  166. var plugin = get(name, type);
  167. if (plugin && _.isFunction(plugin.onDetach)) {
  168. plugin.onDetach.call(component, component, plugin);
  169. }
  170. }, this);
  171. },
  172. /**
  173. * Registers a plugin.
  174. *
  175. * @param {string} name The plugin name.
  176. * @param {string|string[]} validTypes The list of component types this
  177. * plugin can be applied to ('view', 'field', 'layout', 'model' and/or
  178. * 'collection').
  179. * @param {Object} plugin The plugin object.
  180. */
  181. register: function(name, validTypes, plugin) {
  182. if (!_.isArray(validTypes)) {
  183. validTypes = [validTypes];
  184. }
  185. _.each(validTypes , function(type) {
  186. this.plugins[type] = this.plugins[type] || {};
  187. this.plugins[type][name] = plugin;
  188. }, this);
  189. },
  190. _isPluginDisabled: function(component, pluginName) {
  191. if (!SUGAR.App.config.sidecarCompatMode) {
  192. SUGAR.App.logger.error('Core.pluginManager#_isPluginDisabled is a private method that you are not allowed ' +
  193. 'to access. Please use only the public API.');
  194. return;
  195. }
  196. SUGAR.App.logger.warn('Core.pluginManager#_isPluginDisabled is a private method that you should not access. ' +
  197. 'You will NOT be allowed to access it in the next release. Please update your code to rely on the public ' +
  198. 'API only.');
  199. return isPluginDisabled(component, pluginName);
  200. },
  201. _get: function(name, type) {
  202. if (!SUGAR.App.config.sidecarCompatMode) {
  203. SUGAR.App.logger.error('Core.pluginManager#_get is a private method that you are not allowed ' +
  204. 'to access. Please use only the public API.');
  205. return;
  206. }
  207. SUGAR.App.logger.warn('Core.pluginManager#_get is a private method that you should not access. ' +
  208. 'You will NOT be allowed to access it in the next release. Please update your code to rely on the public ' +
  209. 'API only.');
  210. return get(name, type);
  211. }
  212. };
  213. module.exports = PluginManager;
  214. JAVASCRIPT
    Copied!