CommandInterceptor.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import {
  2. forEach,
  3. isFunction,
  4. isArray,
  5. isNumber,
  6. isObject
  7. } from 'min-dash';
  8. var DEFAULT_PRIORITY = 1000;
  9. /**
  10. * A utility that can be used to plug-in into the command execution for
  11. * extension and/or validation.
  12. *
  13. * @param {EventBus} eventBus
  14. *
  15. * @example
  16. *
  17. * import inherits from 'inherits';
  18. *
  19. * import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
  20. *
  21. * function CommandLogger(eventBus) {
  22. * CommandInterceptor.call(this, eventBus);
  23. *
  24. * this.preExecute(function(event) {
  25. * console.log('command pre-execute', event);
  26. * });
  27. * }
  28. *
  29. * inherits(CommandLogger, CommandInterceptor);
  30. *
  31. */
  32. export default function CommandInterceptor(eventBus) {
  33. this._eventBus = eventBus;
  34. }
  35. CommandInterceptor.$inject = [ 'eventBus' ];
  36. function unwrapEvent(fn, that) {
  37. return function(event) {
  38. return fn.call(that || null, event.context, event.command, event);
  39. };
  40. }
  41. /**
  42. * Register an interceptor for a command execution
  43. *
  44. * @param {String|Array<String>} [events] list of commands to register on
  45. * @param {String} [hook] command hook, i.e. preExecute, executed to listen on
  46. * @param {Number} [priority] the priority on which to hook into the execution
  47. * @param {Function} handlerFn interceptor to be invoked with (event)
  48. * @param {Boolean} unwrap if true, unwrap the event and pass (context, command, event) to the
  49. * listener instead
  50. * @param {Object} [that] Pass context (`this`) to the handler function
  51. */
  52. CommandInterceptor.prototype.on = function(events, hook, priority, handlerFn, unwrap, that) {
  53. if (isFunction(hook) || isNumber(hook)) {
  54. that = unwrap;
  55. unwrap = handlerFn;
  56. handlerFn = priority;
  57. priority = hook;
  58. hook = null;
  59. }
  60. if (isFunction(priority)) {
  61. that = unwrap;
  62. unwrap = handlerFn;
  63. handlerFn = priority;
  64. priority = DEFAULT_PRIORITY;
  65. }
  66. if (isObject(unwrap)) {
  67. that = unwrap;
  68. unwrap = false;
  69. }
  70. if (!isFunction(handlerFn)) {
  71. throw new Error('handlerFn must be a function');
  72. }
  73. if (!isArray(events)) {
  74. events = [ events ];
  75. }
  76. var eventBus = this._eventBus;
  77. forEach(events, function(event) {
  78. // concat commandStack(.event)?(.hook)?
  79. var fullEvent = [ 'commandStack', event, hook ].filter(function(e) { return e; }).join('.');
  80. eventBus.on(fullEvent, priority, unwrap ? unwrapEvent(handlerFn, that) : handlerFn, that);
  81. });
  82. };
  83. var hooks = [
  84. 'canExecute',
  85. 'preExecute',
  86. 'preExecuted',
  87. 'execute',
  88. 'executed',
  89. 'postExecute',
  90. 'postExecuted',
  91. 'revert',
  92. 'reverted'
  93. ];
  94. /*
  95. * Install hook shortcuts
  96. *
  97. * This will generate the CommandInterceptor#(preExecute|...|reverted) methods
  98. * which will in term forward to CommandInterceptor#on.
  99. */
  100. forEach(hooks, function(hook) {
  101. /**
  102. * {canExecute|preExecute|preExecuted|execute|executed|postExecute|postExecuted|revert|reverted}
  103. *
  104. * A named hook for plugging into the command execution
  105. *
  106. * @param {String|Array<String>} [events] list of commands to register on
  107. * @param {Number} [priority] the priority on which to hook into the execution
  108. * @param {Function} handlerFn interceptor to be invoked with (event)
  109. * @param {Boolean} [unwrap=false] if true, unwrap the event and pass (context, command, event) to the
  110. * listener instead
  111. * @param {Object} [that] Pass context (`this`) to the handler function
  112. */
  113. CommandInterceptor.prototype[hook] = function(events, priority, handlerFn, unwrap, that) {
  114. if (isFunction(events) || isNumber(events)) {
  115. that = unwrap;
  116. unwrap = handlerFn;
  117. handlerFn = priority;
  118. priority = events;
  119. events = null;
  120. }
  121. this.on(events, hook, priority, handlerFn, unwrap, that);
  122. };
  123. });