jstd-web/node_modules/diagram-js/lib/command/CommandInterceptor.js

147 lines
3.6 KiB
JavaScript

import {
forEach,
isFunction,
isArray,
isNumber,
isObject
} from 'min-dash';
/**
* @typedef {import('../core/EventBus').default} EventBus
* @typedef {import(./CommandInterceptor).HandlerFunction} HandlerFunction
* @typedef {import(./CommandInterceptor).ComposeHandlerFunction} ComposeHandlerFunction
*/
var DEFAULT_PRIORITY = 1000;
/**
* A utility that can be used to plug into the command execution for
* extension and/or validation.
*
* @class
* @constructor
*
* @param {EventBus} eventBus
*
* @example
*
* import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
*
* class CommandLogger extends CommandInterceptor {
* constructor(eventBus) {
* super(eventBus);
*
* this.preExecute('shape.create', (event) => {
* console.log('commandStack.shape-create.preExecute', event);
* });
* }
*/
export default function CommandInterceptor(eventBus) {
/**
* @type {EventBus}
*/
this._eventBus = eventBus;
}
CommandInterceptor.$inject = [ 'eventBus' ];
function unwrapEvent(fn, that) {
return function(event) {
return fn.call(that || null, event.context, event.command, event);
};
}
/**
* Intercept a command during one of the phases.
*
* @param {string|string[]} [events] One or more commands to intercept.
* @param {string} [hook] Phase during which to intercept command.
* @param {number} [priority] Priority with which command will be intercepted.
* @param {ComposeHandlerFunction|HandlerFunction} handlerFn Callback.
* @param {boolean} [unwrap] Whether the event should be unwrapped.
* @param {*} [that] `this` value the callback will be called with.
*/
CommandInterceptor.prototype.on = function(events, hook, priority, handlerFn, unwrap, that) {
if (isFunction(hook) || isNumber(hook)) {
that = unwrap;
unwrap = handlerFn;
handlerFn = priority;
priority = hook;
hook = null;
}
if (isFunction(priority)) {
that = unwrap;
unwrap = handlerFn;
handlerFn = priority;
priority = DEFAULT_PRIORITY;
}
if (isObject(unwrap)) {
that = unwrap;
unwrap = false;
}
if (!isFunction(handlerFn)) {
throw new Error('handlerFn must be a function');
}
if (!isArray(events)) {
events = [ events ];
}
var eventBus = this._eventBus;
forEach(events, function(event) {
// concat commandStack(.event)?(.hook)?
var fullEvent = [ 'commandStack', event, hook ].filter(function(e) { return e; }).join('.');
eventBus.on(fullEvent, priority, unwrap ? unwrapEvent(handlerFn, that) : handlerFn, that);
});
};
var hooks = [
'canExecute',
'preExecute',
'preExecuted',
'execute',
'executed',
'postExecute',
'postExecuted',
'revert',
'reverted'
];
/*
* Add prototype methods for each phase of command execution (e.g. execute,
* revert).
*/
forEach(hooks, function(hook) {
/**
* Add prototype method for a specific phase of command execution.
*
* @param {string|string[]} [events] One or more commands to intercept.
* @param {number} [priority] Priority with which command will be intercepted.
* @param {ComposeHandlerFunction|HandlerFunction} handlerFn Callback.
* @param {boolean} [unwrap] Whether the event should be unwrapped.
* @param {*} [that] `this` value the callback will be called with.
*/
CommandInterceptor.prototype[hook] = function(events, priority, handlerFn, unwrap, that) {
if (isFunction(events) || isNumber(events)) {
that = unwrap;
unwrap = handlerFn;
handlerFn = priority;
priority = events;
events = null;
}
this.on(events, hook, priority, handlerFn, unwrap, that);
};
});