(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.BpmnJS = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o\n\n \n \n \n \n \n \n \n \n \n \n"; // function createNewDiagram() { // openDiagram(newDiagramXML); // } // function openDiagram(xml) { // renderer.importXML(xml, function(err) { // if (err) { // container // .removeClass('with-diagram') // .addClass('with-error'); // container.find('.error pre').text(err.message); // console.error(err); // } else { // container // .removeClass('with-error') // .addClass('with-diagram'); // } // }); // } // function saveSVG(done) { // renderer.saveSVG(done); // } // function saveDiagram(done) { // renderer.saveXML({ format: true }, function(err, xml) { // done(err, xml); // }); // } BpmnJSPropertiesPanel.prototype.createNewDiagram = function(){ this.openDiagram(newDiagramXML, this); }; BpmnJSPropertiesPanel.prototype.openDiagram = function(xml, self){ if(self){ }else{ self = this; } self.renderer.importXML(xml, function(err) { if (err) { self.options.container .removeClass('with-diagram') .addClass('with-error'); self.options.container.find('.error pre').text(err.message); console.error(err); } else { self.options.container .removeClass('with-error') .addClass('with-diagram'); } }); }; BpmnJSPropertiesPanel.prototype.saveDiagram = function(done){ this.renderer.saveXML({ format: true }, function(err, xml) { done(err, xml); }); }; BpmnJSPropertiesPanel.prototype.registerFileDrop = function(container, callback){ var self = this; function handleFileSelect(e) { e.stopPropagation(); e.preventDefault(); var files = e.dataTransfer.files; var file = files[0]; var reader = new FileReader(); reader.onload = function(e) { var xml = e.target.result; callback(xml, self); }; reader.readAsText(file); } function handleDragOver(e) { e.stopPropagation(); e.preventDefault(); e.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. } container.get(0).addEventListener('dragover', handleDragOver, false); container.get(0).addEventListener('drop', handleFileSelect, false); }; module.exports = BpmnJSPropertiesPanel; //global.BpmnJSPropertiesPanel = BpmnJSPropertiesPanel; // function registerFileDrop(container, callback) { // function handleFileSelect(e) { // e.stopPropagation(); // e.preventDefault(); // var files = e.dataTransfer.files; // var file = files[0]; // var reader = new FileReader(); // reader.onload = function(e) { // var xml = e.target.result; // callback(xml); // }; // reader.readAsText(file); // } // function handleDragOver(e) { // e.stopPropagation(); // e.preventDefault(); // e.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. // } // container.get(0).addEventListener('dragover', handleDragOver, false); // container.get(0).addEventListener('drop', handleFileSelect, false); // } ////// file drag / drop /////////////////////// // // check file api availability // if (!window.FileList || !window.FileReader) { // window.alert( // 'Looks like you use an older browser that does not support drag and drop. ' + // 'Try using Chrome, Firefox or the Internet Explorer > 10.'); // } else { // registerFileDrop(container, openDiagram); // } // bootstrap diagram functions /* $(document).on('ready', function() { $('#js-create-diagram').click(function(e) { e.stopPropagation(); e.preventDefault(); createNewDiagram(); }); var downloadLink = $('#js-download-diagram'); var downloadSvgLink = $('#js-download-svg'); $('.buttons a').click(function(e) { if (!$(this).is('.active')) { e.preventDefault(); e.stopPropagation(); } }); function setEncoded(link, name, data) { var encodedData = encodeURIComponent(data); if (data) { link.addClass('active').attr({ 'href': 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData, 'download': name }); } else { link.removeClass('active'); } } var _ = require('lodash'); var exportArtifacts = _.debounce(function() { saveSVG(function(err, svg) { setEncoded(downloadSvgLink, 'diagram.svg', err ? null : svg); }); saveDiagram(function(err, xml) { setEncoded(downloadLink, 'diagram.bpmn', err ? null : xml); }); }, 500); renderer.on('commandStack.changed', exportArtifacts); }); */ },{"bpmn-js-properties-panel/lib":17,"bpmn-js-properties-panel/lib/provider/camunda":21,"bpmn-js-properties-panel/lib/provider/camunda/camunda-moddle":20,"bpmn-js/lib/Modeler":49}],2:[function(require,module,exports){ 'use strict'; var DEFAULT_PRIORITY = 1000; /** * A component that decides upon the visibility / editable * state of properties in the properties panel. * * Implementors must subclass this component and override * {@link PropertiesActivator#isEntryVisible} and * {@link PropertiesActivator#isPropertyEditable} to provide * custom behavior. * * @param {EventBus} eventBus * @param {Number} [priority] at which priority to hook into the activation */ function PropertiesActivator(eventBus, priority) { var self = this; priority = priority || DEFAULT_PRIORITY; eventBus.on('propertiesPanel.isEntryVisible', priority, function(e) { return self.isEntryVisible(e.entry, e.element); }); eventBus.on('propertiesPanel.isPropertyEditable', priority, function(e) { return self.isPropertyEditable(e.entry, e.propertyName, e.element); }); } PropertiesActivator.$inject = [ 'eventBus' ]; module.exports = PropertiesActivator; /** * Should the given entry be visible for the specified element. * * @param {EntryDescriptor} entry * @param {ModdleElement} element * * @return {Boolean} */ PropertiesActivator.prototype.isEntryVisible = function(entry, element) { return true; }; /** * Should the given property be editable for the specified element * * @param {EntryDescriptor} entry * @param {String} propertyName * @param {ModdleElement} element * * @return {Boolean} */ PropertiesActivator.prototype.isPropertyEditable = function(entry, propertyName, element) { return true; }; },{}],3:[function(require,module,exports){ 'use strict'; var domify = require('min-dom/lib/domify'), domQuery = require('min-dom/lib/query'), domRemove = require('min-dom/lib/remove'), domClasses = require('min-dom/lib/classes'), domClosest = require('min-dom/lib/closest'), domAttr = require('min-dom/lib/attr'), domDelegate = require('min-dom/lib/delegate'); var is = require('bpmn-js/lib/util/ModelUtil').is; var forEach = require('lodash/collection/forEach'), assign = require('lodash/object/assign'); function isToggle(node) { return node.type === 'checkbox' || node.type === 'radio'; } function getPropertyPlaceholders(node) { return domQuery.all('input[name], textarea[name], [data-value]', node); } function getFormControls(node) { return domQuery.all('input[name], textarea[name], select[name]', node); } /** * Extract input values from entry node * * @param {DOMElement} entryNode * @return {Object} */ function getFormControlValues(entryNode) { var values = {}; var controlNodes = getFormControls(entryNode); forEach(controlNodes, function(controlNode) { var value = controlNode.value; var name = domAttr(controlNode, 'name'); // take toggle state into account for // radio / checkboxes if (isToggle(controlNode)) { if (controlNode.checked) { if (!domAttr(controlNode, 'value')) { value = true; } else { value = controlNode.value; } } else { value = null; } } if (value !== null) { // prevents values to be written to xml as empty string values[name] = (value != '') ? value : undefined; } }); return values; } /** * A properties panel implementation. * * To use it provide a `propertiesProvider` component that knows * about which properties to display. * * Properties edit state / visibility can be intercepted * via a custom {@link PropertiesActivator}. * * @param {Object} config * @param {EventBus} eventBus * @param {Modeling} modeling * @param {PropertiesProvider} propertiesProvider * @param {ElementRegistry} elementRegistry * @param commandStack */ function PropertiesPanel(config, eventBus, modeling, propertiesProvider, elementRegistry, commandStack) { this._eventBus = eventBus; this._modeling = modeling; this._commandStack = commandStack; this._propertiesProvider = propertiesProvider; this._elementRegistry = elementRegistry; this._init(config); } PropertiesPanel.$inject = [ 'config.propertiesPanel', 'eventBus', 'modeling', 'propertiesProvider', 'elementRegistry', 'commandStack' ]; module.exports = PropertiesPanel; PropertiesPanel.prototype._init = function(config) { var eventBus = this._eventBus; var self = this; eventBus.on('diagram.init', function() { self.registerCmdHandlers(); }); eventBus.on('selection.changed', function(e) { var newElement = e.newSelection[0]; self.update(newElement); }); eventBus.on('elements.changed', function(e) { var current = self._current; var element = current && current.element; if (element) { if (e.elements.indexOf(element) !== -1) { self.update(element); } } }); eventBus.on('diagram.destroy', function() { self.detach(); }); var panelNode = this._container = domify('
'); panelNode.querySelector('.panel-toggle').addEventListener('click', function () { domClasses(panelNode).toggle('panel-closed'); }); this._bindListeners(this._container); if (config && config.parent) { this.attachTo(config.parent); } }; PropertiesPanel.prototype.registerCmdHandlers = function() { var self = this; forEach(self.getCmdHandlers(), function(handler, id) { self._commandStack.registerHandler(id, handler); }); }; PropertiesPanel.prototype.getCmdHandlers = function() { return { 'properties-panel.update-businessobject': require('./cmd/UpdateBusinessObjectHandler'), 'properties-panel.create-and-reference': require('./cmd/CreateAndReferenceHandler'), 'properties-panel.create-businessobject-list': require('./cmd/CreateBusinessObjectListHandler'), 'properties-panel.update-businessobject-list': require('./cmd/UpdateBusinessObjectListHandler') }; }; PropertiesPanel.prototype.attachTo = function(parentNode) { // ensure we detach from the // previous, old parent this.detach(); // unwrap jQuery if provided if (parentNode.get) { parentNode = parentNode.get(0); } if (typeof parentNode === 'string') { parentNode = domQuery(parentNode); } var container = this._container; parentNode.appendChild(container); this._emit('attach'); }; PropertiesPanel.prototype.detach = function() { var container = this._container, parentNode = container.parentNode; if (!parentNode) { return; } this._emit('detach'); parentNode.removeChild(container); }; PropertiesPanel.prototype.update = function(element) { var current = this._current; // no actual selection change var needsCreate = true; if (current) { if (current.element === element) { // reuse existing panel needsCreate = false; } else if(typeof element === 'undefined') { // remove old panel domRemove(current.panel); // use RootElement of BPMN diagram to generate properties panel if no element is selected // and the process is no collaboration this._elementRegistry.forEach(function(rootElement) { if(is(rootElement, 'bpmn:Process')) { element = rootElement; needsCreate = true; } }); } else { // remove old panel domRemove(current.panel); } } if (needsCreate) { this._current = this._create(element); } if (this._current) { this._updateActivation(this._current); } this._emit('update'); }; PropertiesPanel.prototype._emit = function(event) { this._eventBus.fire('propertiesPanel.' + event, { panel: this, current: this._current }); }; PropertiesPanel.prototype._bindListeners = function(container) { var self = this; domDelegate.bind(container, '[data-entry]', 'input', function onInput(event) { var node = event.delegateTarget, entryId = domAttr(node, 'data-entry'), entry = self.getEntry(entryId); var actionId = domAttr(event.target, 'data-input'); if(!!actionId) { self.executeAction(entry, node, actionId, event); } var values = getFormControlValues(node); self.validate(entry, values); self.updateShow(entry, node); }); domDelegate.bind(container, '[data-entry]', 'change', function onChange(event) { var node = event.delegateTarget, entryId = domAttr(node, 'data-entry'), entry = self.getEntry(entryId); var values = getFormControlValues(node); if (self.validate(entry, values)) { self.applyChanges(entry, values, node); } self.updateShow(entry, node); }); domDelegate.bind(container, '[data-keypress]', 'keypress', function onKeyPress(event) { // triggers on all inputs var inputNode = event.delegateTarget; var entryNode = domClosest(inputNode, '[data-entry]'); var actionId = domAttr(inputNode, 'data-keypress'), entryId = domAttr(entryNode, 'data-entry'); var entry = self.getEntry(entryId); var isEntryDirty = self.executeAction(entry, entryNode, actionId, event); if(!!isEntryDirty) { var values = getFormControlValues(entryNode); if (self.validate(entry, values)) { self.applyChanges(entry, values); } } self.updateShow(entry, entryNode); }); domDelegate.bind(container, '[data-keydown]', 'keydown', function onKeyDown(event) { // triggers on all inputs var inputNode = event.delegateTarget; var entryNode = domClosest(inputNode, '[data-entry]'); var actionId = domAttr(inputNode, 'data-keydown'), entryId = domAttr(entryNode, 'data-entry'); var entry = self.getEntry(entryId); var isEntryDirty = self.executeAction(entry, entryNode, actionId, event); if(!!isEntryDirty) { var values = getFormControlValues(entryNode); if (self.validate(entry, values)) { self.applyChanges(entry, values); } } self.updateShow(entry, entryNode); }); domDelegate.bind(container, '[data-action]', 'click', function onClick(event) { // triggers on all inputs var inputNode = event.delegateTarget; var entryNode = domClosest(inputNode, '[data-entry]'); var actionId = domAttr(inputNode, 'data-action'), entryId = domAttr(entryNode, 'data-entry'); var entry = self.getEntry(entryId); var isEntryDirty = self.executeAction(entry, entryNode, actionId, event); if(!!isEntryDirty) { var values = getFormControlValues(entryNode); if (self.validate(entry, values)) { self.applyChanges(entry, values); } } self.updateShow(entry, entryNode); }); domDelegate.bind(container, '[data-mousedown]', 'mousedown', function onMousedown(event) { // triggers on all inputs var inputNode = event.delegateTarget; var entryNode = domClosest(inputNode, '[data-entry]'); var eventHandlerId = domAttr(inputNode, 'data-mousedown'), entryId = domAttr(entryNode, 'data-entry'); var entry = self.getEntry(entryId); var isEntryDirty = self.executeAction(entry, entryNode, eventHandlerId, event); if(!!isEntryDirty) { var values = getFormControlValues(entryNode); if (self.validate(entry, values)) { self.applyChanges(entry, values); } } self.updateShow(entry, entryNode); }); domDelegate.bind(container, '[data-focus]', 'focus', function onFocus(event) { // triggers on all inputs var inputNode = event.delegateTarget; var entryNode = domClosest(inputNode, '[data-entry]'); var eventHandlerId = domAttr(inputNode, 'data-focus'), entryId = domAttr(entryNode, 'data-entry'); var entry = self.getEntry(entryId); var isEntryDirty = self.executeAction(entry, entryNode, eventHandlerId, event); if(!!isEntryDirty) { var values = getFormControlValues(entryNode); if (self.validate(entry, values)) { self.applyChanges(entry, values); } } self.updateShow(entry, entryNode); }, true); domDelegate.bind(container, '[data-blur]', 'blur', function onBlur(event) { // triggers on all inputs var inputNode = event.delegateTarget; var entryNode = domClosest(inputNode, '[data-entry]'); var eventHandlerId = domAttr(inputNode, 'data-blur'), entryId = domAttr(entryNode, 'data-entry'); var entry = self.getEntry(entryId); var isEntryDirty = self.executeAction(entry, entryNode, eventHandlerId, event); if(!!isEntryDirty) { var values = getFormControlValues(entryNode); if (self.validate(entry, values)) { self.applyChanges(entry, values); } } self.updateShow(entry, entryNode); }, true); }; PropertiesPanel.prototype.updateShow = function(entry, node) { var current = this._current; if (!current) { return; } var showNodes = domQuery.all('[data-show]', node) || []; forEach(showNodes, function(showNode) { var expr = domAttr(showNode, 'data-show'); if(expr in entry) { var shouldShow = entry[expr](current.element, node, showNode) || false; var hasClass = domClasses(showNode).has('djs-properties-hide'); if(shouldShow) { if(hasClass) { domClasses(showNode).remove('djs-properties-hide'); } } else { domClasses(showNode).add('djs-properties-hide'); } } }); }; PropertiesPanel.prototype.executeAction = function(entry, entryNode, actionId, event) { var current = this._current; if (!current) { return; } if (actionId in entry) { return entry[actionId](current.element, entryNode, event); } }; PropertiesPanel.prototype.applyChanges = function(entry, values, containerElement) { var element = this._current.element; var actualChanges = entry.set(element, values, containerElement); // if the entry does not change the element itself but needs to perform a custom cmd if(!!actualChanges.cmd) { var cmd = actualChanges.cmd; this._commandStack.execute(cmd, actualChanges.context || {element : element}); } else { this._modeling.updateProperties(element, actualChanges); } }; PropertiesPanel.prototype.validate = function(entry, values) { var current = this._current; var validationErrors; if (entry.validate) { validationErrors = entry.validate(current.element, values); } var entryNode = domQuery('[data-entry=' + entry.id + ']', current.panel); var controlNodes = getFormControls(entryNode); var valid = true; forEach(controlNodes, function(controlNode) { var name = domAttr(controlNode, 'name'); var error = validationErrors[name]; if (error) { valid = false; } var errorNode = domQuery('[data-invalid="' + name + '"], [data-invalid=""]', entryNode); if (errorNode) { errorNode.innerText = !error ? '' : (error.message || error); domClasses(errorNode).toggle('invalid', !!error); } // TODO: validate asynchronously? domClasses(controlNode).toggle('invalid', !!error); }); return valid; }; PropertiesPanel.prototype.getEntry = function(id) { return this._current && this._current.entries[id]; }; var flattenDeep = require('lodash/array/flattenDeep'), indexBy = require('lodash/collection/indexBy'), map = require('lodash/collection/map'); PropertiesPanel.prototype._create = function(element) { if (!element) { return null; } var groups = this._propertiesProvider.getGroups(element); var containerNode = this._container; var panelNode = this._createPanel(element, groups); containerNode.appendChild(panelNode); var entries = indexBy(flattenDeep(map(groups, 'entries')), 'id'); return { groups: groups, entries: entries, element: element, panel: panelNode }; }; PropertiesPanel.prototype._updateActivation = function(current) { var self = this; var eventBus = this._eventBus; var element = current.element; function isEntryVisible(entry) { return eventBus.fire('propertiesPanel.isEntryVisible', { entry: entry, element: element }); } function isPropertyEditable(entry, propertyName) { return eventBus.fire('propertiesPanel.isPropertyEditable', { entry: entry, propertyName: propertyName, element: element }); } var panelNode = current.panel; forEach(current.groups, function(group) { var groupVisible = false; var groupNode = domQuery('[data-group=' + group.id + ']', panelNode); forEach(group.entries, function(entry) { var entryNode = domQuery('[data-entry=' + entry.id + ']', groupNode); var entryVisible = isEntryVisible(entry); groupVisible = groupVisible || entryVisible; domClasses(entryNode).toggle('hidden', !entryVisible); var values = 'get' in entry ? entry.get(element, entryNode) : {}; var inputNodes = getPropertyPlaceholders(entryNode); forEach(inputNodes, function(node) { var name, value, editable; // we deal with an input element if ('value' in node) { name = domAttr(node, 'name'); value = values[name]; editable = isPropertyEditable(entry, name); domAttr(node, 'readonly', editable ? null : ''); domAttr(node, 'disabled', editable ? null : ''); if (isToggle(node)) { node.checked = !!(node.value == value || (!domAttr(node, 'value') && value)); } else { // prevents input fields from having the value 'undefined' node.value = (values[name] != undefined) ? values[name] : ''; } } // we deal with some non-editable html element else { name = domAttr(node, 'data-value'); node.textContent = values[name]; } }); // update conditionally visible elements self.updateShow(entry, entryNode); }); domClasses(groupNode).toggle('hidden', !groupVisible); }); }; PropertiesPanel.prototype._createPanel = function(element, groups) { var self = this; var panelNode = domify('
'), headerNode = domify('
' + '
Properties for: ' + element.id + '
' + '' + '
'); panelNode.appendChild(headerNode); forEach(groups, function(group) { if (!group.id) { throw new Error('group must have an id'); } var groupNode = domify('
' + '' + ''+group.label+'' + '
'); groupNode.querySelector('.group-toggle').addEventListener('click', function (evt) { domClasses(groupNode).toggle('group-closed'); evt.preventDefault(); evt.stopPropagation(); }); groupNode.addEventListener('click', function (evt) { if (!evt.defaultPrevented && domClasses(groupNode).has('group-closed')) { domClasses(groupNode).remove('group-closed'); } }); forEach(group.entries, function(entry) { if (!entry.id) { throw new Error('entry must have an id'); } var html = entry.html; if (typeof html === 'string') { html = domify(html); } // unwrap jquery if (html.get) { html = html.get(0); } var entryNode = domify('
'); forEach(entry.cssClasses || [], function (cssClass) { domClasses(entryNode).add(cssClass); }); entryNode.appendChild(html); groupNode.appendChild(entryNode); // update conditionally visible elements self.updateShow(entry, entryNode); }); panelNode.appendChild(groupNode); }); return panelNode; }; },{"./cmd/CreateAndReferenceHandler":4,"./cmd/CreateBusinessObjectListHandler":5,"./cmd/UpdateBusinessObjectHandler":6,"./cmd/UpdateBusinessObjectListHandler":7,"bpmn-js/lib/util/ModelUtil":98,"lodash/array/flattenDeep":290,"lodash/collection/forEach":301,"lodash/collection/indexBy":304,"lodash/collection/map":305,"lodash/object/assign":425,"min-dom/lib/attr":34,"min-dom/lib/classes":35,"min-dom/lib/closest":36,"min-dom/lib/delegate":37,"min-dom/lib/domify":38,"min-dom/lib/query":39,"min-dom/lib/remove":40}],4:[function(require,module,exports){ 'use strict'; var reduce = require('lodash/object/transform'), keys = require('lodash/object/keys'), forEach = require('lodash/collection/forEach'); var elementHelper = require('../helper/ElementHelper'); /** * A handler capable of creating a new element under a provided parent * and updating / creating a reference to it in one atomic action. */ function CreateAndReferenceElementHandler(elementRegistry, bpmnFactory) { this._elementRegistry = elementRegistry; this._bpmnFactory = bpmnFactory; } CreateAndReferenceElementHandler.$inject = [ 'elementRegistry', 'bpmnFactory' ]; module.exports = CreateAndReferenceElementHandler; function ensureNotNull(prop, name) { if(!prop) { throw new Error(name + 'required'); } return prop; } ////// api ///////////////////////////////////////////// /** * Creates a new element under a provided parent and updates / creates a reference to it in * one atomic action. * * @param {Object} context * @param {djs.model.Base} context.element which is the context for the reference * @param {moddle.referencingObject} context.referencingObject the object which creates the reference * @param {String} context.referenceProperty the property of the referencingObject which makes the reference * @param {moddle.newObject} context.newObject the new object to add * @param {moddle.newObjectContainer} context.newObjectContainer the container for the new object * * @return {Array} the updated element */ CreateAndReferenceElementHandler.prototype.execute = function(context) { var referencingObject = ensureNotNull(context.referencingObject, 'referencingObject'), referenceProperty = ensureNotNull(context.referenceProperty, 'referenceProperty'), newObject = ensureNotNull(context.newObject, 'newObject'), newObjectContainer = ensureNotNull(context.newObjectContainer, 'newObjectContainer'), newObjectParent = ensureNotNull(context.newObjectParent, 'newObjectParent'), changed = [ context.element ]; // this will not change any diagram-js elements // create new object var referencedObject = elementHelper.createElement(newObject.type, newObject.properties, newObjectParent, this._bpmnFactory); context.referencedObject = referencedObject; // add to containing list newObjectContainer.push(referencedObject); // adjust reference attribute context.previousReference = referencingObject[referenceProperty]; referencingObject[referenceProperty] = referencedObject; context.changed = changed; // indicate changed on objects affected by the update return changed; }; /** * Reverts the update * * @param {Object} context * * @return {djs.mode.Base} the updated element */ CreateAndReferenceElementHandler.prototype.revert = function(context) { var referencingObject = context.referencingObject, referenceProperty = context.referenceProperty, previousReference = context.previousReference, referencedObject = context.referencedObject, newObjectContainer = context.newObjectContainer; // reset reference referencingObject.set(referenceProperty, previousReference); // remove new element newObjectContainer.splice(newObjectContainer.indexOf(referencedObject), 1); return context.changed; }; },{"../helper/ElementHelper":15,"lodash/collection/forEach":301,"lodash/object/keys":426,"lodash/object/transform":432}],5:[function(require,module,exports){ 'use strict'; var reduce = require('lodash/object/transform'), keys = require('lodash/object/keys'), forEach = require('lodash/collection/forEach'); var elementHelper = require('../helper/ElementHelper'); /** * A handler that implements a BPMN 2.0 property update * for business objects which are not represented in the * diagram. * * This is useful in the context of the properties panel in * order to update child elements of elements visible in * the diagram. * * Example: perform an update of a specific event definition * of an intermediate event. * */ function CreateBusinessObjectListHandler(elementRegistry, bpmnFactory) { this._elementRegistry = elementRegistry; this._bpmnFactory = bpmnFactory; } CreateBusinessObjectListHandler.$inject = [ 'elementRegistry', 'bpmnFactory' ]; module.exports = CreateBusinessObjectListHandler; function ensureNotNull(prop, name) { if(!prop) { throw new Error(name + 'required'); } return prop; } function ensureList(prop, name) { if(!prop || Object.prototype.toString.call(prop) !== '[object Array]' ) { throw new Error(name + ' needs to be a list'); } return prop; } ////// api ///////////////////////////////////////////// /** * Creates a new element under a provided parent and updates / creates a reference to it in * one atomic action. * * @param {Object} context * @param {djs.model.Base} context.element which is the context for the reference * @param {moddle.referencingObject} context.referencingObject the object which creates the reference * @param {String} context.referenceProperty the property of the referencingObject which makes the reference * @param {moddle.newObject} context.newObject the new object to add * @param {moddle.newObjectContainer} context.newObjectContainer the container for the new object * * @return {Array} the updated element */ CreateBusinessObjectListHandler.prototype.execute = function(context) { var currentObject = ensureNotNull(context.currentObject, 'currentObject'), propertyName = ensureNotNull(context.propertyName, 'propertyName'), newObjects = ensureList(context.newObjects, 'newObjects'), changed = [ context.element ]; // this will not change any diagram-js elements var childObjects = []; var self = this; // create new array of business objects forEach(newObjects, function(obj) { var element = elementHelper.createElement(obj.type, obj.properties, currentObject, self._bpmnFactory); childObjects.push(element); }); context.childObject = childObjects; // adjust array reference in the parent business object context.previousChilds = currentObject[propertyName]; currentObject[propertyName] = childObjects; context.changed = changed; // indicate changed on objects affected by the update return changed; }; /** * Reverts the update * * @param {Object} context * * @return {djs.mode.Base} the updated element */ CreateBusinessObjectListHandler.prototype.revert = function(context) { var currentObject = context.currentObject, propertyName = context.propertyName, previousChilds = context.previousChilds; // remove new element currentObject.set(propertyName, previousChilds); return context.changed; }; },{"../helper/ElementHelper":15,"lodash/collection/forEach":301,"lodash/object/keys":426,"lodash/object/transform":432}],6:[function(require,module,exports){ 'use strict'; var reduce = require('lodash/object/transform'), is = require('bpmn-js/lib/util/ModelUtil').is, keys = require('lodash/object/keys'), forEach = require('lodash/collection/forEach'); /** * A handler that implements a BPMN 2.0 property update * for business objects which are not represented in the * diagram. * * This is useful in the context of the properties panel in * order to update child elements of elements visible in * the diagram. * * Example: perform an update of a specific event definition * of an intermediate event. * */ function UpdateBusinessObjectHandler(elementRegistry) { this._elementRegistry = elementRegistry; } UpdateBusinessObjectHandler.$inject = [ 'elementRegistry' ]; module.exports = UpdateBusinessObjectHandler; /** * returns the root element */ function getRoot(businessObject) { var parent = businessObject; while(parent.$parent) { parent = parent.$parent; } return parent; } function getProperties(businessObject, propertyNames) { return reduce(propertyNames, function(result, key) { result[key] = businessObject.get(key); return result; }, {}); } function setProperties(businessObject, properties) { forEach(properties, function(value, key) { businessObject.set(key, value); }); } ////// api ///////////////////////////////////////////// /** * Updates a business object with a list of new properties * * @param {Object} context * @param {djs.model.Base} context.element the element which has a child business object updated * @param {moddle.businessObject} context.businessObject the businessObject to update * @param {Object} context.properties a list of properties to set on the businessObject * * @return {Array} the updated element */ UpdateBusinessObjectHandler.prototype.execute = function(context) { var element = context.element, businessObject = context.businessObject, rootElements = getRoot(businessObject).rootElements, referenceType = context.referenceType, referenceProperty = context.referenceProperty, changed = [ element ]; // this will not change any diagram-js elements if (!element) { throw new Error('element required'); } if(!businessObject) { throw new Error('businessObject required'); } var properties = context.properties, oldProperties = context.oldProperties || getProperties(businessObject, keys(properties)); // check if there the update needs an external element for reference if(typeof referenceType !== 'undefined' && typeof referenceProperty !== 'undefined') { forEach(rootElements, function(rootElement) { if(is(rootElement, referenceType)) { if(rootElement.id === properties[referenceProperty]) { properties[referenceProperty] = rootElement; } } }); } // update properties setProperties(businessObject, properties); // store old values context.oldProperties = oldProperties; context.changed = changed; // indicate changed on objects affected by the update return changed; }; /** * Reverts the update * * @param {Object} context * * @return {djs.mode.Base} the updated element */ UpdateBusinessObjectHandler.prototype.revert = function(context) { var oldProperties = context.oldProperties, businessObject = context.businessObject; // update properties setProperties(businessObject, oldProperties); return context.changed; }; },{"bpmn-js/lib/util/ModelUtil":98,"lodash/collection/forEach":301,"lodash/object/keys":426,"lodash/object/transform":432}],7:[function(require,module,exports){ 'use strict'; var reduce = require('lodash/object/transform'), keys = require('lodash/object/keys'), forEach = require('lodash/collection/forEach'), findIndex = require('lodash/array/findIndex'); var is = require('bpmn-js/lib/util/ModelUtil').is; /** * A handler that implements a BPMN 2.0 property update * for business object lists which are not represented in the * diagram. * * This is useful in the context of the properties panel in * order to update child elements of elements visible in * the diagram. * * Example: perform an update of a specific event definition * of an intermediate event. * */ function CreateBusinessObjectListHandler(elementRegistry, bpmnFactory) { this._elementRegistry = elementRegistry; this._bpmnFactory = bpmnFactory; } CreateBusinessObjectListHandler.$inject = [ 'elementRegistry', 'bpmnFactory' ]; module.exports = CreateBusinessObjectListHandler; function ensureNotNull(prop, name) { if(!prop) { throw new Error(name + 'required'); } return prop; } function ensureList(prop, name) { if(!prop || Object.prototype.toString.call(prop) !== '[object Array]' ) { throw new Error(name + ' needs to be a list'); } return prop; } ////// api ///////////////////////////////////////////// /** * Updates a element under a provided parent. * * @param {Object} context * @param {djs.model.Base} context.element which is the context for the reference * @param {Array} context.updatedObjectList which contains a list of objects * @param {moddle.referencingObject} context.referencingObject the object which creates the reference * @param {String} context.referenceProperty the property of the referencingObject which makes the reference * @param {moddle.newObject} context.newObject the new object to add * @param {moddle.newObjectContainer} context.newObjectContainer the container for the new object * * @return {Array} the updated element */ CreateBusinessObjectListHandler.prototype.execute = function(context) { var currentObject = ensureNotNull(context.currentObject, 'currentObject'), propertyName = ensureNotNull(context.propertyName, 'propertyName'), updatedObjectList = ensureList(context.updatedObjectList, 'updatedObjectList'), changed = [ context.element ]; // this will not change any diagram-js elements var objectList = currentObject[propertyName]; // replace objects forEach(updatedObjectList, function(obj) { var oldObj = obj['old'], // fetch index of the old object index = findIndex(objectList, oldObj); // replace the old object with the new one objectList[index] = obj['new']; }); // adjust array reference in the parent business object context.previousList = currentObject[propertyName]; currentObject[propertyName] = objectList; context.changed = changed; // indicate changed on objects affected by the update return changed; }; /** * Reverts the update * * @param {Object} context * * @return {djs.mode.Base} the updated element */ CreateBusinessObjectListHandler.prototype.revert = function(context) { var currentObject = context.currentObject, propertyName = context.propertyName, previousList = context.previousList; // remove new element currentObject.set(propertyName, previousList); return context.changed; }; },{"bpmn-js/lib/util/ModelUtil":98,"lodash/array/findIndex":288,"lodash/collection/forEach":301,"lodash/object/keys":426,"lodash/object/transform":432}],8:[function(require,module,exports){ 'use strict'; var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject; var checkbox = function(options, defaultParameters) { var resource = defaultParameters, label = options.label || resource.id; resource.html = '' + ''; resource.get = function(element) { var bo = getBusinessObject(element), res = {}; res[options.modelProperty] = bo.get(options.modelProperty); return res; }; resource.set = function(element, values) { var res = {}; res[options.modelProperty] = !!values[options.modelProperty]; return res }; if(typeof options.set === 'function') { resource.set = options.set; } if(typeof options.get === 'function') { resource.get = options.get; } resource.cssClasses = ['checkbox']; return resource; }; module.exports = checkbox; },{"bpmn-js/lib/util/ModelUtil":98}],9:[function(require,module,exports){ 'use strict'; /** * conditional functionality for inputs * * @param element * @param options * @param condition * @returns {*} */ var isConditional = function(element, options, condition) { var defaultConditionName = 'condition-' + element.id; if(!element) { throw new Error('Element must be set.'); } if(typeof options === 'function') { condition = options; options = { name: defaultConditionName }; } if(typeof options !== 'object') { throw new Error('options must be an object') } if(!condition || typeof condition !== 'function') { throw new Error('A condition of type function must be set.'); } var showName = (options.conditionName) ? options.conditionName : defaultConditionName; var wrapperBegin = '
', wrapperEnd = '
'; element.html = wrapperBegin + element.html + wrapperEnd; element[showName] = condition; return element; }; module.exports = isConditional; },{}],10:[function(require,module,exports){ 'use strict'; var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, is = require('bpmn-js/lib/util/ModelUtil').is, forEach = require('lodash/collection/forEach'); // condition var isConditional = require('./ConditionalEntryFactory'); // input entities var textInputField = require('./TextInputEntryFactory'), checkboxField = require('./CheckboxEntryFactory'), referenceComboboxField = require('./SelectReferenceComboboxFactory'), selectBoxField = require('./SelectEntryFactory'), textAreaField = require('./TextAreaEntryFactory'); // helpers //////////////////////////////////////// /** * returns the root element */ function getRoot(businessObject) { var parent = businessObject; while(parent.$parent) { parent = parent.$parent; } return parent; } /** * filters all elements in the list which have a given type. * removes a new list */ function filterElementsByType(objectList, type) { var list = objectList || []; var result = []; forEach(list, function(obj) { if(is(obj, type)) { result.push(obj); } }); return result; } function findRootElementsByType(businessObject, referencedType) { var root = getRoot(businessObject); return filterElementsByType(root.rootElements, referencedType); } function removeAllChildren(domElement) { while(!!domElement.firstChild) { domElement.removeChild(domElement.firstChild); } } function ensureNotNull(prop) { if(!prop) { throw new Error(prop + ' must be set.') } return prop; } /** * sets the default parameters which are needed to create an entry * * @param options * @returns {{id: *, description: (*|string), get: (*|Function), set: (*|Function), validate: (*|Function), html: string}} */ var setDefaultParameters = function ( options ) { // default method to fetch the current value of the input field var defaultGet = function (element) { var bo = getBusinessObject(element), res = {}, prop = ensureNotNull(options.modelProperty); res[prop] = bo.get(prop); return res; }; // default method to set a new value to the input field var defaultSet = function (element, values) { var res = {}, prop = ensureNotNull(options.modelProperty); res[prop] = values[prop]; return res; }; // default validation method var defaultValidate = function () { return {}; }; return { id : options.id, description : ( options.description || '' ), get : ( options.get || defaultGet ), set : ( options.set || defaultSet ), validate : ( options.validate || defaultValidate ), html: '' }; }; function EntryFactory() { } /** * Generates an text input entry object for a property panel. * options are: * - id: id of the entry - String * * - description: description of the property - String * * - label: label for the input field - String * * - set: setter method - Function * * - get: getter method - Function * * - validate: validation mehtod - Function * * - modelProperty: name of the model property - String * * - buttonAction: Object which contains the following properties: - Object * ---- name: name of the [data-action] callback - String * ---- method: callback function for [data-action] - Function * * - buttonShow: Object which contains the following properties: - Object * ---- name: name of the [data-show] callback - String * ---- method: callback function for [data-show] - Function * * @param options * @returns the propertyPanel entry resource object */ EntryFactory.textField = function(options) { return textInputField(options, setDefaultParameters(options)); }; /** * Generates a checkbox input entry object for a property panel. * options are: * - id: id of the entry - String * * - description: description of the property - String * * - label: label for the input field - String * * - set: setter method - Function * * - get: getter method - Function * * - validate: validation mehtod - Function * * - modelProperty: name of the model property - String * * @param options * @returns the propertyPanel entry resource object */ EntryFactory.checkbox = function(options) { return checkboxField(options, setDefaultParameters(options)); }; EntryFactory.referenceCombobox = function(options) { return referenceComboboxField(options, setDefaultParameters(options), getRoot, findRootElementsByType, removeAllChildren); }; EntryFactory.textArea = function(options) { return textAreaField(options, setDefaultParameters(options)); }; EntryFactory.selectBox = function(options) { return selectBoxField(options, setDefaultParameters(options)); }; EntryFactory.isConditional = isConditional; module.exports = EntryFactory; },{"./CheckboxEntryFactory":8,"./ConditionalEntryFactory":9,"./SelectEntryFactory":11,"./SelectReferenceComboboxFactory":12,"./TextAreaEntryFactory":13,"./TextInputEntryFactory":14,"bpmn-js/lib/util/ModelUtil":98,"lodash/collection/forEach":301}],11:[function(require,module,exports){ 'use strict'; var forEach = require('lodash/collection/forEach'), reduce = require('lodash/object/transform'), domQuery = require('min-dom/lib/query'), domAttr = require('min-dom/lib/attr'), getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject; var isList = function(list) { return !(!list || Object.prototype.toString.call(list) !== '[object Array]'); }; var addEmptyParameter = function(list) { return list.concat([{ name: '', value: '' }]); }; var selectbox = function(options, defaultParameters) { var resource = defaultParameters, label = options.label || resource.id, selectOptions = (isList(options.selectOptions)) ? addEmptyParameter(options.selectOptions) : [ { name: '', value: '' }], modelProperty = options.modelProperty; resource.html = '' + ''; resource.get = function(element, propertyName) { var businessObject = getBusinessObject(element), boValue = businessObject.get(modelProperty) || '', elementFields = domQuery.all('select#camunda-' + resource.id + ' > option', propertyName); forEach(elementFields, function(field) { if(field.value === boValue) { domAttr(field, 'selected', 'selected'); } else { domAttr(field, 'selected', null); } }); }; resource.cssClasses = ['dropdown']; return resource; }; module.exports = selectbox; },{"bpmn-js/lib/util/ModelUtil":98,"lodash/collection/forEach":301,"lodash/object/transform":432,"min-dom/lib/attr":34,"min-dom/lib/query":39}],12:[function(require,module,exports){ 'use strict'; var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, is = require('bpmn-js/lib/util/ModelUtil').is, domQuery = require('min-dom/lib/query'), domClasses = require('min-dom/lib/classes'), domAttr = require('min-dom/lib/attr'), domify = require('min-dom/lib/domify'), forEach = require('lodash/collection/forEach'), indexBy = require('lodash/collection/indexBy'); var popup = require('./../popup')(); var combobox = function(options, defaultParameters, getRoot, findRootElementsByType, removeAllChildren) { var resource = defaultParameters, label = options.label || resource.id, businessObject = options.businessObject, referencedType = options.referencedType, referenceTypeName = options.referencedType.substr(5), referenceProperty = options.referenceProperty, referencedObjectToString = options.referencedObjectToString || function(obj) { return obj.name + ' (id='+obj.id+')'; }; if(!businessObject) throw new Error('businessObject is required'); if(!referencedType) throw new Error('referencedType is required'); if(!referenceProperty) throw new Error('referenceProperty is required'); resource.html = '
' + '' + '
' + '' + '' + '' + '' + '' + '
' + '
' + '
    ' + '
    ' + 'No ' + referenceTypeName + ' defined. Type to create a new ' + referenceTypeName + '.' + '
    ' + '
    '+ '
    '; var optionTemplate = '
  • '; resource.businessObject = options.businessObject; resource.optionsVisible = false; resource.selectedOption = {}; resource.optionsModel = []; resource.get = function() { // load available messages: var values = {}, currentModel = businessObject[referenceProperty], currentModelValue = (currentModel) ? currentModel.id : undefined; resource.refreshOptionsModel(); resource.optionsVisible = false; values[referenceProperty] = resource.selectOptionById(currentModelValue); return values; }; resource.selectOptionById = function(id) { var selectedOption = indexBy(resource.optionsModel, 'value')[id]; resource.selectedOption = selectedOption; return selectedOption ? selectedOption.label : ''; }; resource.refreshOptionsModel = function() { var model = []; var referableObjects = findRootElementsByType(businessObject, referencedType); forEach(referableObjects, function(obj) { model.push({ label: referencedObjectToString(obj), value: obj.id, name: obj.name }); }); resource.optionsModel = model; }; resource.set = function(element, values) { var providedValue = values[referenceProperty]; if(!resource.selectedOption && providedValue && providedValue.length > 0) { // create and reference new element return { cmd: 'properties-panel.create-and-reference', context: { element: element, referencingObject: businessObject, referenceProperty: referenceProperty, newObject: { type: referencedType, properties: { name: providedValue } }, newObjectContainer: getRoot(businessObject).rootElements, newObjectParent: getRoot(businessObject) } }; } else { // update or clear reference on business object var changes = {}; changes[referenceProperty] = ( resource.selectedOption ) ? resource.selectedOption.value : undefined; return { cmd:'properties-panel.update-businessobject', context: { element: element, businessObject: businessObject, referenceType: referencedType, referenceProperty: referenceProperty, properties: changes } }; } }; resource.canClear = function(el, node) { var currentValue = domQuery('input', node).value; return currentValue && currentValue.length > 0; }; resource.clear = function(el, node) { var input = domQuery('input', node); input.value = ''; // trigger a change if the user clears the selected option. // In that case the reference needs to be cleared var changed = resource.selectedOption; resource.selectedOption = null; return changed; }; resource.isOptionsAvailable = function() { return resource.optionsModel.length > 0; }; resource.isNoOptionsAvailable = function() { return !resource.isOptionsAvailable(); }; resource.canShowOptions = function() { return !resource.optionsVisible; }; resource.toggleOptions = function(el, node, evt) { if(!resource.optionsVisible) { resource.showOptions(el, node, evt); } else { resource.hideOptions(el, node, evt); } }; resource.showOptions = function (el, node) { resource.optionsVisible = true; resource.updateOptionsDropDown(node, domQuery('input', node)); domClasses(node).add('open'); }; resource.hideOptions = function(el, node) { resource.optionsVisible = false; domClasses(node).remove('open'); }; resource.canCreateNew = function(el, entry) { var value = domQuery('input', entry).value; return !resource.selectedOption && value && value.length > 0; }; resource.createNew = function() { resource.selectedOption = undefined; return true; }; resource.popUp = function (el, node) { // var cloned = domQuery('.options', node); // if (cloned) { // popup.body.appendChild(cloned); // } popup.header.textContent = label; popup.open(); }; resource.optionsUpdateOnKeyPress = function(el, entry, evt) { // if the user changes the input, reset if(resource.selectedOption && evt.charCode) { evt.target.value = ''; resource.selectedOption = null; } resource.optionsVisible = true; resource.updateOptionsDropDown(entry); }; resource.optionsUpdateOnKeyDown = function(el, entry, evt) { // clear on backspace if(resource.selectedOption && evt.keyCode === 8) { evt.target.value = ''; resource.selectedOption = null; } resource.optionsVisible = true; resource.updateOptionsDropDown(entry); }; resource.updateOptionsDropDown = function(entry) { // update options var optionsEl = domQuery('ul', entry); removeAllChildren(optionsEl); if(resource.optionsModel.length > 0) { forEach(resource.optionsModel, function(option) { var optionDomElement = domify(optionTemplate); optionDomElement.textContent = option.label; domAttr(optionDomElement, 'data-option-id', option.value); optionsEl.appendChild(optionDomElement); }); } }; resource.preventInputBlur = function(el, entry, evt) { // prevent the input from being blurred evt.preventDefault(); }; resource.selectOption = function(el, entry, evt) { var target = evt.target, optionId = domAttr(target, 'data-option-id'); if(!optionId) { return; } // select option and set label to input field domQuery('input', entry).value = resource.selectOptionById(optionId); return true; }; resource.cssClasses = ['combobox']; return resource; }; module.exports = combobox; },{"./../popup":18,"bpmn-js/lib/util/ModelUtil":98,"lodash/collection/forEach":301,"lodash/collection/indexBy":304,"min-dom/lib/attr":34,"min-dom/lib/classes":35,"min-dom/lib/domify":38,"min-dom/lib/query":39}],13:[function(require,module,exports){ 'use strict'; var domQuery = require('min-dom/lib/query'); var textArea = function(options, defaultParameters) { // Default action for the button next to the input-field var defaultButtonAction = function (element, inputNode) { var input = domQuery('textarea[name='+options.modelProperty+']', inputNode); input.value = ''; return true; }; // default method to determine if the button should be visible var defaultButtonShow = function (element, inputNode) { var input = domQuery('textarea[name='+options.modelProperty+']', inputNode); return input.value !== ''; }; var resource = defaultParameters, label = options.label || resource.id, buttonLabel = ( options.buttonLabel || 'X' ), actionName = ( typeof options.buttonAction != 'undefined' ) ? options.buttonAction.name : 'clear', actionMethod = ( typeof options.buttonAction != 'undefined' ) ? options.buttonAction.method : defaultButtonAction, showName = ( typeof options.buttonShow != 'undefined' ) ? options.buttonShow.name : 'canClear', showMethod = ( typeof options.buttonShow != 'undefined' ) ? options.buttonShow.method : defaultButtonShow; resource.html = '' + '
    ' + '' + '' + '
    '; resource[actionName] = actionMethod; resource[showName] = showMethod; resource.cssClasses = ['textarea']; return resource; }; module.exports = textArea; },{"min-dom/lib/query":39}],14:[function(require,module,exports){ 'use strict'; var domQuery = require('min-dom/lib/query'); var textField = function(options, defaultParameters) { // Default action for the button next to the input-field var defaultButtonAction = function (element, inputNode) { var input = domQuery('input[name='+options.modelProperty+']', inputNode); input.value = ''; return true; }; // default method to determine if the button should be visible var defaultButtonShow = function (element, inputNode) { var input = domQuery('input[name='+options.modelProperty+']', inputNode); return input.value !== ''; }; var resource = defaultParameters, label = options.label || resource.id, buttonLabel = ( options.buttonLabel || 'X' ), actionName = ( typeof options.buttonAction != 'undefined' ) ? options.buttonAction.name : 'clear', actionMethod = ( typeof options.buttonAction != 'undefined' ) ? options.buttonAction.method : defaultButtonAction, showName = ( typeof options.buttonShow != 'undefined' ) ? options.buttonShow.name : 'canClear', showMethod = ( typeof options.buttonShow != 'undefined' ) ? options.buttonShow.method : defaultButtonShow; resource.html = '' + '
    ' + '' + '' + '
    '; resource[actionName] = actionMethod; resource[showName] = showMethod; resource.cssClasses = ['textfield']; return resource; }; module.exports = textField; },{"min-dom/lib/query":39}],15:[function(require,module,exports){ 'use strict'; var forEach = require('lodash/collection/forEach'), remove = require('lodash/array/remove'); var is = require('bpmn-js/lib/util/ModelUtil').is; var ElementHelper = {}; module.exports = ElementHelper; /** * Creates a new element and set the parent to it * * @param {String} elementType of the new element * @param {Object} properties of the new element in key-value pairs * @param {moddle.object} parent of the new element * @param {BpmnFactory} factory which creates the new element * @returns {djs.model.Base} element which is created */ ElementHelper.createElement = function(elementType, properties, parent, factory) { var element = factory.create(elementType, properties); element.$parent = parent; return element }; /** * * Removes an element * * @param {Object} options * @param options.businessObject * @param {String} options.propertyName * @param {String} options.elementType * @param {Object} options.value * @param {String} options.value.name * @param {String|Boolean} options.value.value */ ElementHelper.removeElement = function(options) { var businessObject = options.businessObject, propertyName = options.propertyName, elementType = options.elementType, value = options.value, hasValue = typeof value === 'object'; if(!businessObject) throw new Error('businessObject is required'); if(!propertyName) throw new Error('propertyName is required'); if(!elementType) throw new Error('elementType is required'); if(value) { if(!value.name) throw new Error('value.name is required'); if(!value.value) throw new Error('value.value is required'); } var removingObject = businessObject.get(propertyName); if(Object.prototype.toString.call(removingObject) === '[object Array]') { remove(removingObject, function(obj) { // TODO: Waiting for https://github.com/bpmn-io/moddle-xml/issues/8 to remove the typeof check var isElement = (typeof obj.$instanceOf === 'function' && is(obj, elementType)); if(isElement) { return (hasValue) ? obj[value.name] === value.value : true; } else { return false; } }); businessObject.set(propertyName, removingObject); } if(typeof removingObject === 'string' || typeof removingObject === 'boolean') { businessObject.set(propertyName, undefined); } return businessObject; }; /** * * @param element * @param businessObject * @param propertyName * @param listOfNewObjects */ ElementHelper.createListCreateContext = function(element, businessObject, propertyName, listOfNewObjects) { return { cmd: 'properties-panel.create-businessobject-list', context: { element: element, currentObject: businessObject, propertyName: propertyName, newObjects: listOfNewObjects } } }; /** * * @param {djs.model.Base} element which should be updated * @param {moddle.object} businessObject which should be updated * @param {String} propertyName of the property which should be updated * @param {Array} listOfUpdatedElements containing all elements which should be updated * @param {moddle.Object} listOfUpdatedElements.old element which should be replaced * @param {moddle.Object} listOfUpdatedElements.new element which should replace the old one * @returns {{cmd: string, context: {element: *, currentObject: *, propertyName: *, updatedObjectList: *}}} */ ElementHelper.createListUpdateContext = function(element, businessObject, propertyName, listOfUpdatedElements) { return { cmd: 'properties-panel.update-businessobject-list', context: { element: element, currentObject: businessObject, propertyName: propertyName, updatedObjectList: listOfUpdatedElements } }; }; /** * Create the context for an update of a businessObject * @param {djs.model.Base} element which should be updated * @param {moddle.Object} businessObject which should be updated * @param {String} propertyName of the property which should be updated * @param {Array} listOfNewElements which should be inserted * @returns {{cmd: string, context: {element: *, businessObject: *, properties: {values: *}}}} */ ElementHelper.createElementUpdateContext = function(element, businessObject, propertyName, listOfNewElements) { var properties = {}; if(typeof listOfNewElements === 'string' || typeof listOfNewElements === 'boolean') { properties[propertyName] = listOfNewElements; } if(Object.prototype.toString.call(listOfNewElements) === '[object Array]') { var property = businessObject.get(propertyName); forEach(listOfNewElements, function(newElement) { property.push(newElement); }); properties[propertyName] = property; } if(typeof listOfNewElements === 'undefined') { if(typeof propertyName === 'object') { properties = propertyName; } else if(typeof propertyName === 'string') { properties[propertyName] = listOfNewElements; } else { throw new Error('When listOfNewElements is undefined you need to provide an [Object] for propertyName'); } } return { cmd: 'properties-panel.update-businessobject', context: { element: element, businessObject: businessObject, properties: properties } } }; },{"bpmn-js/lib/util/ModelUtil":98,"lodash/array/remove":292,"lodash/collection/forEach":301}],16:[function(require,module,exports){ 'use strict'; var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, is = require('bpmn-js/lib/util/ModelUtil').is, forEach = require('lodash/collection/forEach'); var EventDefinitionHelper = {}; module.exports = EventDefinitionHelper; EventDefinitionHelper.getEventDefinition = function(element, eventType) { var bo = getBusinessObject(element), eventDefinition = null; if(bo.eventDefinitions) { forEach(bo.eventDefinitions, function(event) { if(is(event, eventType)) { eventDefinition = event; } }); } return eventDefinition; }; EventDefinitionHelper.getTimerEventDefinition = function(element) { return this.getEventDefinition(element, 'bpmn:TimerEventDefinition'); }; EventDefinitionHelper.getMessageEventDefinition = function(element) { return this.getEventDefinition(element, 'bpmn:MessageEventDefinition'); }; EventDefinitionHelper.getSignalEventDefinition = function(element) { return this.getEventDefinition(element, 'bpmn:SignalEventDefinition'); }; EventDefinitionHelper.getErrorEventDefinition = function(element) { return this.getEventDefinition(element, 'bpmn:ErrorEventDefinition'); }; },{"bpmn-js/lib/util/ModelUtil":98,"lodash/collection/forEach":301}],17:[function(require,module,exports){ module.exports = { __init__: [ 'propertiesPanel' ], propertiesPanel: [ 'type', require('./PropertiesPanel') ] }; },{"./PropertiesPanel":3}],18:[function(require,module,exports){ 'use strict'; var domQuery = require('min-dom/lib/query'), domClasses = require('min-dom/lib/classes'), domify = require('min-dom/lib/domify'), bind = require('lodash/function/bind'); function Popup(options) { options = options || {}; this.template = options.template || this.template; var el = this.el = domify(this.template); this.header = domQuery('.popup-header', el); this.body = domQuery('.popup-body', el); this.footer = domQuery('.popup-footer', el); document.body.appendChild(el); this._attachEvents(); } Popup.prototype.template = '
    ' + '
    ' + '' + '
    '; Popup.prototype._attachEvents = function () { var self = this; var events = this.events; var el = this.el; Object.keys(events).forEach(function (instruction) { var cb = bind(self[events[instruction]], self); var parts = instruction.split(' '); var evtName = parts.shift(); var target = parts.length ? parts.shift() : false; target = target ? domQuery(target, el) : el; if (!target) { return; } target.addEventListener(evtName, cb); }); }; Popup.prototype._detachEvents = function () { var self = this; var events = this.events; var el = this.el; Object.keys(events).forEach(function (instruction) { var cb = bind(self[events[instruction]], self); var parts = instruction.split(' '); var evtName = parts.shift(); var target = parts.length ? parts.shift() : false; target = target ? domQuery(target, el) : el; if (!target) { return; } target.removeEventListener(evtName, cb); }); }; Popup.prototype.events = { // 'keydown:esc': '_handleClose', 'click .underlay': '_handleClose', 'click .popup-close': '_handleClose' }; Popup.prototype._handleClose = function (evt) { this.close(); }; Popup.prototype.open = function (content) { domClasses(this.el).add('open'); }; Popup.prototype.close = function () { domClasses(this.el).remove('open'); }; Popup.prototype.remove = function () { this._detachEvents(); if (document.body.contains(this.el)) { document.body.removeChild(this.el); } }; var popup; module.exports = function () { if (!popup) { popup = new Popup(); } return popup; }; },{"lodash/function/bind":311,"min-dom/lib/classes":35,"min-dom/lib/domify":38,"min-dom/lib/query":39}],19:[function(require,module,exports){ 'use strict'; var inherits = require('inherits'); var PropertiesActivator = require('../../PropertiesActivator'); var serviceTaskDelegateProps = require('./parts/ServiceTaskDelegateProps'), userTaskProps = require('./parts/UserTaskProps'), asynchronousContinuationProps = require('./parts/AsynchronousContinuationProps'), processProps = require('./parts/ProcessProps'), eventProps = require('./parts/EventProps'), linkProps = require('./parts/LinkProps'), callActivityProps = require('./parts/CallActivityProps'), documentationProps = require('./parts/DocumentationProps'), multiInstanceProps = require('./parts/MultiInstanceLoopProps'), sequenceFlowProps = require('./parts/SequenceFlowProps'), jobRetryTimeCycle = require('./parts/JobRetryTimeCycle'); function DefaultPropertiesProvider(eventBus, bpmnFactory) { PropertiesActivator.call(this, eventBus); this.getGroups = function(element) { var generalGroup = { id: 'general', label: 'General', entries: [] }; processProps(generalGroup, element); serviceTaskDelegateProps(generalGroup, element); multiInstanceProps(generalGroup, element, bpmnFactory); userTaskProps(generalGroup, element); linkProps(generalGroup, element); callActivityProps(generalGroup, element); eventProps(generalGroup, element); sequenceFlowProps(generalGroup, element, bpmnFactory); var asyncGroup = { id : 'asyncGroup', label: 'Asynchronous Continuations', entries : [] }; asynchronousContinuationProps(asyncGroup, element); jobRetryTimeCycle(asyncGroup, element, bpmnFactory); var documentationGroup = { id: 'documentation', label: 'Documentation', entries: [] }; documentationProps(documentationGroup, element); return[ generalGroup, asyncGroup, documentationGroup ]; }; } inherits(DefaultPropertiesProvider, PropertiesActivator); module.exports = DefaultPropertiesProvider; },{"../../PropertiesActivator":2,"./parts/AsynchronousContinuationProps":22,"./parts/CallActivityProps":23,"./parts/DocumentationProps":24,"./parts/EventProps":25,"./parts/JobRetryTimeCycle":26,"./parts/LinkProps":27,"./parts/MultiInstanceLoopProps":28,"./parts/ProcessProps":29,"./parts/SequenceFlowProps":30,"./parts/ServiceTaskDelegateProps":31,"./parts/UserTaskProps":32,"inherits":33}],20:[function(require,module,exports){ module.exports={ "name": "Camunda", "uri": "http://camunda.org/bpmn", "prefix": "activiti", "xml": { "tagAlias": "lowerCase" }, "associations": [], "types": [ { "name": "AsyncCapable", "isAbstract": true, "extends": [ "bpmn:Activity", "bpmn:Gateway", "bpmn:Event" ], "properties": [ { "name": "asyncBefore", "isAttr": true, "type": "Boolean", "default": false }, { "name": "asyncAfter", "isAttr": true, "type": "Boolean", "default": false }, { "name": "exclusive", "isAttr": true, "type": "Boolean", "default": true } ] }, { "name": "Assignable", "extends": [ "bpmn:UserTask" ], "properties": [ { "name": "assignee", "isAttr": true, "type": "String" }, { "name": "formKey", "isAttr": true, "type": "String" }, { "name": "candidateUsers", "isAttr": true, "type": "String" }, { "name": "candidateGroups", "isAttr": true, "type": "String" }, { "name": "dueDate", "isAttr": true, "type": "String" }, { "name": "followUpDate", "isAttr": true, "type": "String" }, { "name": "priority", "isAttr": true, "type": "Integer" } ] }, { "name": "Calling", "extends": [ "bpmn:CallActivity" ], "properties": [ { "name": "calledElementBinding", "isAttr": true, "type": "String" }, { "name": "calledElementVersion", "isAttr": true, "type": "Integer" } ] }, { "name": "ServiceTaskLike", "extends": [ "bpmn:ServiceTask", "bpmn:BusinessRuleTask", "bpmn:SendTask", "bpmn:MessageEventDefinition" ], "properties": [ { "name": "expression", "isAttr": true, "type": "String" }, { "name": "class", "isAttr": true, "type": "String" }, { "name": "delegateExpression", "isAttr": true, "type": "String" } ] }, // { "name": "ExtensionElementsLike", "extends": [ "bpmn:ExtensionElements" ], "properties": [ { "name":"executionListener", "type":"ExecutionListener", "isMany":true }, { "name":"taskListener", "type":"TaskListener", "isMany":true } ] }, { "name":"ExecutionListener", "properties": [ { "name": "expression", "type": "String", "isAttr":true }, { "name": "delegateExpression", "type": "String", "isAttr":true }, { "name": "event", "type": "String", "isAttr":true } ] }, { "name":"TaskListener", "properties": [ { "name": "expression", "type": "String", "isAttr":true }, { "name": "delegateExpression", "type": "String", "isAttr":true }, { "name": "class", "type": "String", "isAttr":true }, { "name": "event", "type": "String", "isAttr":true } ] }, // { "name": "Connector", "superClass": [ "Element" ], "properties": [ { "name": "inputOutput", "type": "InputOutput" }, { "name": "connectorId", "type": "String" } ] }, { "name": "InputOutput", "superClass": [ "Element" ], "properties": [ { "name": "inputOutput", "type": "InputOutput" }, { "name": "connectorId", "type": "String" }, { "name": "inputParameters", "isMany": true, "type": "InputParameter" }, { "name": "outputParameters", "isMany": true, "type": "OutputParameter" } ] }, { "name": "InputOutputParameter", "properties": [ { "name": "name", "isAttr": true, "type": "String" }, { "name": "value", "isBody": true, "type": "String" }, { "name": "definition", "type": "InputOutputParameterDefinition" } ] }, { "name": "InputOutputParameterDefinition", "isAbstract": true }, { "name": "List", "superClass": [ "InputOutputParameterDefinition" ], "properties": [ { "name": "items", "isMany": true, "type": "InputOutputParameterDefinition" } ] }, { "name": "Map", "superClass": [ "InputOutputParameterDefinition" ], "properties": [ { "name": "entries", "isMany": true, "type": "Entry" } ] }, { "name": "Entry", "properties": [ { "name": "key", "isAttr": true, "type": "String" }, { "name": "value", "type": "InputOutputParameterDefinition" } ] }, { "name": "Value", "superClass": [ "InputOutputParameterDefinition" ], "properties": [ { "name": "value", "isBody": true, "type": "String" } ] }, { "name": "Script", "superClass": [ "InputOutputParameterDefinition" ], "properties": [ { "name": "scriptLanguage", "isAttr": true, "type": "String" }, { "name": "source", "isBody": true, "type": "String" } ] }, { "name": "InputParameter", "superClass": [ "InputOutputParameter" ] }, { "name": "OutputParameter", "superClass": [ "InputOutputParameter" ] }, { "name": "Collectable", "isAbstract": true, "extends": [ "bpmn:MultiInstanceLoopCharacteristics" ], "superClass": [ "activiti:AsyncCapable" ], "properties": [ { "name": "collection", "isAttr": true, "type": "String" }, { "name": "completionCondition", "type": "bpmn:CompletionCondition", "redefines": "bpmn:MultiInstanceLoopCharacteristics#completionCondition", } ] }, { "name": "FailedJobRetryTimeCycle", "superClass": [ "Element" ], "properties": [ { "name": "body", "isBody": true, "type": "String" } ] } ], "emumerations": [ ] } },{}],21:[function(require,module,exports){ module.exports = { __init__: [ 'propertiesProvider' ], propertiesProvider: [ 'type', require('./CamundaPropertiesProvider') ] }; },{"./CamundaPropertiesProvider":19}],22:[function(require,module,exports){ 'use strict'; var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, is = require('bpmn-js/lib/util/ModelUtil').is, domQuery = require('min-dom/lib/query'), entryFactory = require('../../../factory/EntryFactory'), forEach = require('lodash/collection/forEach'), elementHelper = require('../../../helper/ElementHelper'); module.exports = function(group, element) { if (is(element, 'activiti:AsyncCapable')) { var asyncAfterButton, asyncBeforeButton; // AsyncBefore group.entries.push(entryFactory.checkbox({ id: 'asyncBefore', description: '', label: 'Asynchronous Before', modelProperty: 'asyncBefore', get: function(element, node) { var bo = getBusinessObject(element); // save the current state of the input field asyncBeforeButton = domQuery('input[name=asyncBefore]', node); return { asyncBefore: bo.get('asyncBefore')}; }, set: function(element, values) { var res = { asyncBefore: !!values['asyncBefore'] }; if(!asyncAfterButton.checked && !values['asyncBefore']) { res.exclusive = true; var bo = getBusinessObject(element); if(bo.get('extensionElements')) { res.extensionElements = elementHelper.removeElement({ businessObject: bo.get('extensionElements'), propertyName: 'values', elementType: 'camunda:FailedJobRetryTimeCycle' }); } } return res; } })); // AsyncAfter group.entries.push(entryFactory.checkbox({ id: 'asyncAfter', description: '', label: 'Asynchronous After', modelProperty: 'asyncAfter', get: function(element, node) { var bo = getBusinessObject(element); // save the current state of the input field asyncAfterButton = domQuery('input[name=asyncAfter]', node); return { asyncAfter: bo.get('asyncAfter')}; }, set: function(element, values) { var res = { asyncAfter: !!values['asyncAfter'] }; if(!asyncBeforeButton.checked && !values['asyncAfter']) { res.exclusive = true; var bo = getBusinessObject(element); if(bo.get('extensionElements')) { res.extensionElements = elementHelper.removeElement({ businessObject: bo.get('extensionElements'), propertyName: 'values', elementType: 'camunda:FailedJobRetryTimeCycle' }); } } return res; } })); // exclusive group.entries.push( entryFactory.isConditional(entryFactory.checkbox({ id: 'exclusive', description: '', label: 'Exclusive', modelProperty: 'exclusive' }), function(element, node) { var asyncBeforeChecked = domQuery('input[name=asyncBefore]', node.parentElement).checked, asyncAfterChecked = domQuery('input[name=asyncAfter]', node.parentElement).checked; return asyncAfterChecked || asyncBeforeChecked })); } }; },{"../../../factory/EntryFactory":10,"../../../helper/ElementHelper":15,"bpmn-js/lib/util/ModelUtil":98,"lodash/collection/forEach":301,"min-dom/lib/query":39}],23:[function(require,module,exports){ 'use strict'; var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, is = require('bpmn-js/lib/util/ModelUtil').is, domQuery = require('min-dom/lib/query'), entryFactory = require('../../../factory/EntryFactory'); module.exports = function(group, element) { if (is(element, 'activiti:Calling')) { // called element group.entries.push(entryFactory.textField({ id: 'calledElement', description: '', label: 'Called Element', modelProperty: 'calledElement' })); // called element binding group.entries.push(entryFactory.selectBox({ id: 'calledElementBinding', description: '', label: 'Called Element Binding', modelProperty: 'calledElementBinding', selectOptions: [ { name: 'latest', value: 'latest' }, { name: 'deployment', value: 'deployment' }, { name: 'version', value: 'version' } ], set: function(element, values) { var res = {}; res.calledElementBinding = values['calledElementBinding']; if(res.calledElementBinding !== 'version') { res.calledElementVersion = undefined; } return res; } })); group.entries.push(entryFactory.isConditional(entryFactory.textField({ id: 'calledElementVersion', description: '', label: 'Called Element Version', modelProperty: 'calledElementVersion' }), function(element, node) { var elementBinding = domQuery('select > option:checked', node.parentElement), input = domQuery('input', node); if(elementBinding === null) { elementBinding = domQuery('select > option[selected=selected]', node.parentElement); } return elementBinding.value === 'version' } )) } }; },{"../../../factory/EntryFactory":10,"bpmn-js/lib/util/ModelUtil":98,"min-dom/lib/query":39}],24:[function(require,module,exports){ 'use strict'; var is = require('bpmn-js/lib/util/ModelUtil').is, entryFactory = require('../../../factory/EntryFactory'), getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, elementHelper = require('../../../helper/ElementHelper'), forEach = require('lodash/collection/forEach'); module.exports = function(group) { // Documentation var entry = entryFactory.textArea({ id: 'documentation', description: '', label: 'Documentation', modelProperty: 'documentation' }); entry.set = function(element, values) { var businessObject = getBusinessObject(element), property = { text: values.documentation}, newObjectList = []; if(typeof values.documentation !== 'undefined' && values.documentation !== '') { newObjectList.push({ type: 'bpmn:Documentation', properties: property }) } return elementHelper.createListCreateContext(element, businessObject, 'documentation', newObjectList); }; entry.get = function(element) { var businessObject = getBusinessObject(element), documentations = businessObject.get('documentation'), text = (documentations.length > 0) ? documentations[0].text : ''; return { documentation: text }; }; group.entries.push(entry); }; },{"../../../factory/EntryFactory":10,"../../../helper/ElementHelper":15,"bpmn-js/lib/util/ModelUtil":98,"lodash/collection/forEach":301}],25:[function(require,module,exports){ 'use strict'; var is = require('bpmn-js/lib/util/ModelUtil').is, getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, eventDefinitionHelper = require('../../../helper/EventDefinitionHelper'), entryFactory = require('../../../factory/EntryFactory'); var forEach = require('lodash/collection/forEach'); module.exports = function(group, element) { var events = [ 'bpmn:StartEvent', 'bpmn:EndEvent', 'bpmn:IntermediateThrowEvent', 'bpmn:BoundaryEvent', 'bpmn:IntermediateCatchEvent' ]; // Message and Signal Event Definition forEach(events, function(event) { if(is(element, event)) { var messageEventDefinition = eventDefinitionHelper.getMessageEventDefinition(element), signalEventDefinition = eventDefinitionHelper.getSignalEventDefinition(element); if(messageEventDefinition) { group.entries.push(entryFactory.referenceCombobox({ id: 'selectMessage', description: '', label: 'Message Definition', businessObject: messageEventDefinition, referencedType: 'bpmn:Message', referenceProperty: 'messageRef' })); } if(signalEventDefinition) { group.entries.push(entryFactory.referenceCombobox({ id: 'selectSignal', description: '', label: 'Signal Definition', businessObject: signalEventDefinition, referencedType: 'bpmn:Signal', referenceProperty: 'signalRef' })); } } }); // Special Case: Receive Task if(is(element, 'bpmn:ReceiveTask')) { group.entries.push(entryFactory.referenceCombobox({ id: 'selectMessage-ReceiveTask', description: '', label: 'Message Definition', businessObject: getBusinessObject(element), referencedType: 'bpmn:Message', referenceProperty: 'messageRef' })) } // Error Event Definition var errorEvents = [ 'bpmn:StartEvent', 'bpmn:BoundaryEvent', 'bpmn:EndEvent' ]; forEach(errorEvents, function(event) { if(is(element, event)) { var errorEventDefinition = eventDefinitionHelper.getErrorEventDefinition(element); if(errorEventDefinition) { group.entries.push(entryFactory.referenceCombobox({ id: 'selectError', description: '', label: 'Error Definition', businessObject: errorEventDefinition, referencedType: 'bpmn:Error', referenceProperty: 'errorRef', referencedObjectToString: function(obj) { var code = (obj.errorCode) ? obj.errorCode : ''; return obj.name + ' (id=' + obj.id + ';errorCode=' + code + ')'; } })) } } }) }; },{"../../../factory/EntryFactory":10,"../../../helper/EventDefinitionHelper":16,"bpmn-js/lib/util/ModelUtil":98,"lodash/collection/forEach":301}],26:[function(require,module,exports){ 'use strict'; var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, is = require('bpmn-js/lib/util/ModelUtil').is, domQuery = require('min-dom/lib/query'), forEach = require('lodash/collection/forEach'), entryFactory = require('../../../factory/EntryFactory'), eventDefinitionHelper = require('../../../helper/EventDefinitionHelper'), elementHelper = require('../../../helper/ElementHelper'); module.exports = function(group, element, bpmnFactory) { if (is(element, 'camunda:AsyncCapable')) { var entry = { id: 'jobRetryTimerCycle', description: 'Retry interval in ISO 8601 format (e.g. "R3/PT10M" for "3 cycles, every 10 minutes")', label: 'Retry Time Cycle', modelProperty: 'jobRetryTimeCycle', get: function (element) { var businessObject = getBusinessObject(element).get('extensionElements'); var val = ''; if(businessObject) { forEach(businessObject.get('values'), function (value) { // TODO: Wating for https://github.com/bpmn-io/moddle-xml/issues/8 to remove the typeof check if (typeof value.$instanceOf === 'function' && is(value, 'camunda:FailedJobRetryTimeCycle')) { val = value.get('body'); } }); } return {jobRetryTimeCycle: val}; }, set: function (element, values) { var businessObject = getBusinessObject(element), isNotEmpty = typeof values.jobRetryTimeCycle !== 'undefined' && values.jobRetryTimeCycle != ''; var extensionElements = businessObject.get('extensionElements'), jobRetryTimerElement = undefined, isExtensionElementNew = false, isJobElementNew = false; // create the extensionElements field if it does not exist if (!extensionElements) { extensionElements = elementHelper.createElement('bpmn:ExtensionElements', {values: []}, businessObject, bpmnFactory); isExtensionElementNew = true; } // Set job retry timer value if there is one already // TODO: Waiting for https://github.com/bpmn-io/moddle-xml/issues/8 to remove the typeof check var extensionValues = extensionElements.get('values'); forEach(extensionValues, function (value) { if (typeof value.$instanceOf === 'function' && is(value, 'camunda:FailedJobRetryTimeCycle')) { jobRetryTimerElement = value; } }); // create job retry timer if it not exists if (!jobRetryTimerElement && isNotEmpty) { jobRetryTimerElement = elementHelper.createElement( 'activiti:FailedJobRetryTimeCycle', {body: values['jobRetryTimeCycle']}, extensionElements, bpmnFactory ); isJobElementNew = true; } var updatedElements = []; if(isNotEmpty) { // create full new element set if (isExtensionElementNew && isJobElementNew) { extensionElements.get('values').push(jobRetryTimerElement); return {extensionElements: extensionElements}; } if (isJobElementNew) { return elementHelper.createElementUpdateContext(element, extensionElements, 'values', [jobRetryTimerElement]); } var oldJob = jobRetryTimerElement; jobRetryTimerElement.body = values['jobRetryTimeCycle']; updatedElements.push({ old: oldJob, new: jobRetryTimerElement }); return elementHelper.createListUpdateContext(element, extensionElements, 'values', updatedElements); } else { // removing if(extensionValues.length > 1) { return { extensionElements: elementHelper.removeElement({ businessObject: extensionElements, propertyName: 'values', elementType: 'activiti:FailedJobRetryTimeCycle' }) } } else { return { extensionElements: undefined }; } } } }; var condition = function(element, node) { var asyncBeforeChecked = domQuery('input[name=asyncBefore]', node.parentElement).checked, asyncAfterChecked = domQuery('input[name=asyncAfter]', node.parentElement).checked, oneIsChecked = (asyncBeforeChecked || asyncAfterChecked); if (is(element, 'bpmn:BoundaryEvent')) { var eventDefinitions = eventDefinitionHelper.getTimerEventDefinition(element); if (eventDefinitions) return true; } return oneIsChecked }; group.entries.push(entryFactory.isConditional(entryFactory.textField(entry), condition)); } }; },{"../../../factory/EntryFactory":10,"../../../helper/ElementHelper":15,"../../../helper/EventDefinitionHelper":16,"bpmn-js/lib/util/ModelUtil":98,"lodash/collection/forEach":301,"min-dom/lib/query":39}],27:[function(require,module,exports){ 'use strict'; var is = require('bpmn-js/lib/util/ModelUtil').is, getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, entryFactory = require('../../../factory/EntryFactory'), elementHelper = require('../../../helper/ElementHelper'); var forEach = require('lodash/collection/forEach'); function getLinkEventDefinition(element) { var bo = getBusinessObject(element); var linkEventDefinition = null; if(bo.eventDefinitions) { forEach(bo.eventDefinitions, function(eventDefinition) { if(is(eventDefinition, 'bpmn:LinkEventDefinition')) { linkEventDefinition = eventDefinition; } }); } return linkEventDefinition; } module.exports = function(group, element) { var linkEvents = [ 'bpmn:IntermediateThrowEvent', 'bpmn:IntermediateCatchEvent' ]; forEach(linkEvents, function(event) { if(is(element, event)) { var linkEventDefinition = getLinkEventDefinition(element); if(linkEventDefinition) { var entry = entryFactory.textField({ id: 'link-event', description: '', label: 'Link Name', modelProperty: 'link-name' }); entry.get = function () { return { 'link-name': linkEventDefinition.get('name')}; }; entry.set = function (element, values) { return elementHelper.createElementUpdateContext(element, linkEventDefinition, 'name', values['link-name']); }; group.entries.push(entry); } } }); }; },{"../../../factory/EntryFactory":10,"../../../helper/ElementHelper":15,"bpmn-js/lib/util/ModelUtil":98,"lodash/collection/forEach":301}],28:[function(require,module,exports){ 'use strict'; var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, is = require('bpmn-js/lib/util/ModelUtil').is, domQuery = require('min-dom/lib/query'), entryFactory = require('../../../factory/EntryFactory'), elementHelper = require('../../../helper/ElementHelper'); var forEach = require('lodash/collection/forEach'); module.exports = function(group, element, bpmnFactory) { var businessObject = getBusinessObject(element), asyncAfterButton, asyncBeforeButton; if(is(businessObject.loopCharacteristics, 'activiti:Collectable')) { var modifyBusinessObject = function(element, property, values) { var businessObject = getBusinessObject(element).get('loopCharacteristics'); // create new entry (or overwriting old one) var entry = {}; if(values[property] !== '' && values[property] !== undefined) { entry[property] = elementHelper .createElement('bpmn:FormalExpression', {body: values[property]}, businessObject, bpmnFactory); } else { // removes the element entry[property] = undefined; } return elementHelper.createElementUpdateContext(element, businessObject, entry); }; var get = function(element, property) { var loopCharacteristics = businessObject.get('loopCharacteristics'), entity = loopCharacteristics.get(property), res = {}; if(entity) res[property] = entity.body; return res; }; // loopCardinality group.entries.push(entryFactory.textField({ id: 'loopCardinality', description: '', label: 'Loop Cardinality', modelProperty: 'loopCardinality', set: function(element, values) { return modifyBusinessObject(element, 'loopCardinality', values); }, get: function(element) { return get(element, 'loopCardinality') } })); // completition Condition group.entries.push(entryFactory.textField({ id: 'completionCondition', description: '', label: 'Completion Condition', modelProperty: 'completionCondition', set: function(element, values) { return modifyBusinessObject(element, 'completionCondition', values); }, get: function(element) { return get(element, 'completionCondition') } })); // camunda:collection group.entries.push(entryFactory.textField({ id: 'collection', description: '', label: 'Collection', modelProperty: 'collection', set: function(element, values) { var businessObject = getBusinessObject(element).get('loopCharacteristics'); return elementHelper.createElementUpdateContext(element, businessObject, 'collection', values['collection']); }, get: function(element) { var bo = getBusinessObject(element).get('loopCharacteristics'); return { collection: bo.get('collection')} } })); // AsyncBefore group.entries.push(entryFactory.checkbox({ id: 'loopAsyncBefore', description: '', label: 'Multi Instance Asynchronous Before', modelProperty: 'loopAsyncBefore', get: function(element, node) { asyncBeforeButton = domQuery('input[name=loopAsyncBefore]', node); var bo = getBusinessObject(element).get('loopCharacteristics'); return { loopAsyncBefore: bo.get('asyncBefore')} }, set: function(element, values) { var businessObject = getBusinessObject(element).get('loopCharacteristics'); var properties = {}; properties.asyncBefore = !!values.loopAsyncBefore; if(!asyncAfterButton.checked && !values.loopAsyncBefore) { properties.exclusive = true; } return elementHelper.createElementUpdateContext(element, businessObject, properties); } })); // AsyncAfter group.entries.push(entryFactory.checkbox({ id: 'loopAsyncAfter', description: '', label: 'Multi Instance Asynchronous After', modelProperty: 'loopAsyncAfter', get: function(element, node) { asyncAfterButton = domQuery('input[name=loopAsyncAfter]', node); var bo = getBusinessObject(element).get('loopCharacteristics'); return { loopAsyncAfter: bo.get('asyncAfter')} }, set: function(element, values) { var businessObject = getBusinessObject(element).get('loopCharacteristics'); var properties = {}; properties.asyncAfter = !!values.loopAsyncAfter; if(!asyncBeforeButton.checked && !values.loopAsyncAfter) { properties.exclusive = true; } return elementHelper.createElementUpdateContext(element, businessObject, properties); } })); group.entries.push( entryFactory.isConditional(entryFactory.checkbox({ id: 'loopExclusive', description: '', label: 'Multi Instance Exclusive', modelProperty: 'loopExclusive', get: function(element) { var bo = getBusinessObject(element).get('loopCharacteristics'); return { loopExclusive: bo.get('exclusive')} }, set: function(element, values) { var businessObject = getBusinessObject(element).get('loopCharacteristics'); return elementHelper.createElementUpdateContext(element, businessObject, 'exclusive', !!values['loopExclusive']); } }), function(element, node) { var asyncBeforeChecked = domQuery('input[name=loopAsyncBefore]', node.parentElement).checked, asyncAfterChecked = domQuery('input[name=loopAsyncAfter]', node.parentElement).checked; return asyncAfterChecked || asyncBeforeChecked })); } }; },{"../../../factory/EntryFactory":10,"../../../helper/ElementHelper":15,"bpmn-js/lib/util/ModelUtil":98,"lodash/collection/forEach":301,"min-dom/lib/query":39}],29:[function(require,module,exports){ 'use strict'; var is = require('bpmn-js/lib/util/ModelUtil').is, entryFactory = require('../../../factory/EntryFactory'), getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, domQuery = require('min-dom/lib/query'), elementHelper = require('../../../helper/ElementHelper'); function modifyBusinessObject(element, property, values) { var businessObject = getBusinessObject(element).get('processRef'); return elementHelper.createElementUpdateContext(element, businessObject, property, values[property]); } function getModifiedBusinessObject(element, property) { var bo = getBusinessObject(element).get('processRef'), res = {}; res[property] = bo.get(property); return res; } module.exports = function(group, element) { if (is(element, 'bpmn:Process') || is(element, 'bpmn:Participant')) { // name var label = (is(element, 'bpmn:Participant')) ? 'Process Name' : 'Name'; var nameEntry = entryFactory.textField({ id: 'name', description: '', label: label, modelProperty: 'name' }); // in participants we have to change the default behavior of set and get if(is(element, 'bpmn:Participant')) { nameEntry.get = function (element) { return getModifiedBusinessObject(element, 'name'); }; nameEntry.set = function (element, values) { return modifyBusinessObject(element, 'name', values); }; } group.entries.push(nameEntry); // isExecutable var executableEntry = entryFactory.checkbox({ id: 'isExecutable', description: 'Defines if a process is executable by a process engine', label: 'Executable', modelProperty: 'isExecutable' }); // in participants we have to change the default behavior of set and get if(is(element, 'bpmn:Participant')) { executableEntry.get = function (element) { return getModifiedBusinessObject(element, 'isExecutable'); }; executableEntry.set = function (element, values) { return modifyBusinessObject(element, 'isExecutable', values); }; } group.entries.push(executableEntry); } }; },{"../../../factory/EntryFactory":10,"../../../helper/ElementHelper":15,"bpmn-js/lib/util/ModelUtil":98,"min-dom/lib/query":39}],30:[function(require,module,exports){ 'use strict'; var is = require('bpmn-js/lib/util/ModelUtil').is, getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, entryFactory = require('../../../factory/EntryFactory'), elementHelper = require('../../../helper/ElementHelper'); var forEach = require('lodash/collection/forEach'); module.exports = function(group, element, bpmnFactory) { if(is(element,'bpmn:SequenceFlow')){ var businessObject = getBusinessObject(element); var modifyBusinessObject = function(element, property, values) { // create new entry (or overwriting old one) var entry = {}; if(values[property] !== '' && values[property] !== undefined) { entry[property] = elementHelper .createElement('FormalExpression', {body: values[property]}, businessObject, bpmnFactory); } else { // removes the element entry[property] = undefined; } return elementHelper.createElementUpdateContext(element, businessObject, entry); }; var get = function(element, property) { var entity = businessObject.get('conditionExpression'), res = {}; if(entity) res[property] = entity.body; return res; }; group.entries.push(entryFactory.textField({ id: 'conditionExpression', description: '', label: 'conditionExpression', modelProperty: 'conditionExpression', set: function(element, values) { return modifyBusinessObject(element, 'conditionExpression', values); }, get: function(element) { return get(element, 'conditionExpression') } })); } }; },{"../../../factory/EntryFactory":10,"../../../helper/ElementHelper":15,"bpmn-js/lib/util/ModelUtil":98,"lodash/collection/forEach":301}],31:[function(require,module,exports){ 'use strict'; var is = require('bpmn-js/lib/util/ModelUtil').is, getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, domQuery = require('min-dom/lib/query'); module.exports = function(group, element) { if(is(element, 'activiti:ServiceTaskLike')) { group.entries.push( { 'id': 'class', 'description': 'References a Java class with the JavaDelegate-Interface', label: 'Delegate Method', 'html': '' + '
    ' + '' + '' + '
    '+ '
      ' + '
    • ' + '' + '' + '
    • ' + '
    • ' + '' + '' + '
    • ' + '
    • ' + '' + '' + '
    • ' + '
    ', 'get': function (element, propertyName) { // read values from xml: var bo = getBusinessObject(element), boExpression = bo.get('activiti:expression'), boDelegate = bo.get('activiti:delegateExpression'), boClass = bo.get('activiti:class'); var delegateValue = undefined, delegateResolutionValue = undefined; if(!!boExpression) { delegateValue = boExpression; delegateResolutionValue = 'expression'; } else if(!!boDelegate) { delegateValue = boDelegate; delegateResolutionValue = 'delegateExpression'; } else if(!!boClass) { delegateValue = boClass; delegateResolutionValue = 'class'; } return { delegate: delegateValue, delegateResolution: delegateResolutionValue }; }, 'set': function (element, values, containerElement) { var delegateResolutionValue = values.delegateResolution; var delegateValue = values.delegate; var update = { "activiti:expression": undefined, "activiti:delegateExpression": undefined, "activiti:class": undefined }; if(!!delegateResolutionValue) { update['activiti:'+delegateResolutionValue] = delegateValue; } return update; }, validate: function(element, values) { var delegateResolutionValue = values.delegateResolution; var delegateValue = values.delegate; var validationResult = {}; if(!delegateValue && !!delegateResolutionValue) { validationResult.delegate = "Value must provide a value."; } if(!!delegateValue && !delegateResolutionValue) { validationResult.delegateResolution = "Must select a radio button"; } return validationResult; }, clear: function(element, inputNode) { // clear text input domQuery('input[name=delegate]', inputNode).value=''; // clear radio button selection var checkedRadio = domQuery('input[name=delegateResolution]:checked', inputNode); if(!!checkedRadio) { checkedRadio.checked = false; } return true; }, canClear: function(element, inputNode) { var input = domQuery('input[name=delegate]', inputNode); var radioButton = domQuery('input[name=delegateResolution]:checked', inputNode); return input.value !== '' || !!radioButton; }, cssClasses: ['textfield'] } ); } }; },{"bpmn-js/lib/util/ModelUtil":98,"min-dom/lib/query":39}],32:[function(require,module,exports){ 'use strict'; var is = require('bpmn-js/lib/util/ModelUtil').is, getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject, entryFactory = require('../../../factory/EntryFactory'); module.exports = function(group, element) { if(is(element, 'activiti:Assignable')) { // Assignee group.entries.push(entryFactory.textField({ id : 'assignee', description : 'Assignee of the User Task', label : 'Assignee', modelProperty : 'assignee' })); // Form Key group.entries.push(entryFactory.textField({ id : 'formKey', description : 'URI to the form for this User Task', label : 'Form Key', modelProperty : 'formKey' })); // Candidate Users group.entries.push(entryFactory.textField({ id : 'candidateUsers', description : 'A list of candidates for this User Task', label : 'Candidate Users', modelProperty : 'candidateUsers' })); // Candidate Groups group.entries.push(entryFactory.textField({ id : 'candidateGroups', description : 'A list of candidate groups for this User Task', label : 'Candidate Groups', modelProperty : 'candidateGroups' })); // Due Date group.entries.push(entryFactory.textField({ id : 'dueDate', description : 'The due date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)', label : 'Due Date', modelProperty : 'dueDate' })); // FollowUp Date group.entries.push(entryFactory.textField({ id : 'followUpDate', description : 'The follow up date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)', label : 'Follow Up Date', modelProperty : 'followUpDate' })); // priority group.entries.push(entryFactory.textField({ id : 'priority', description : 'Priority of this User Task', label : 'Priority', modelProperty : 'priority' })); /* group.entries.push( { 'id': 'class', 'description': 'References a Java class with the JavaDelegate-Interface', label: 'Delegate Method', 'html': '' + '
    ' + '' + '' + '
    '+ '
      ' + '
    • ' + '' + '' + '
    • ' + '
    • ' + '' + '' + '
    • ' + '
    • ' + '' + '' + '
    • ' + '
    ', 'get': function (element, propertyName) { var bo = getBusinessObject(element), boExtension = bo.get('extensionElements'); if(boExtension){ var taskListener = boExtension.get('activiti:taskListener'); }else{ } // read values from xml: var bo = getBusinessObject(element).get('extensionElements'), boExpression = bo.get('activiti:expression'), boDelegate = bo.get('activiti:delegateExpression'), boClass = bo.get('activiti:class'); var delegateValue = undefined, delegateResolutionValue = undefined; if(!!boExpression) { delegateValue = boExpression; delegateResolutionValue = 'expression'; } else if(!!boDelegate) { delegateValue = boDelegate; delegateResolutionValue = 'delegateExpression'; } else if(!!boClass) { delegateValue = boClass; delegateResolutionValue = 'class'; } return { delegate: delegateValue, delegateResolution: delegateResolutionValue }; }, 'set': function (element, values, containerElement) { var delegateResolutionValue = values.delegateResolution; var delegateValue = values.delegate; var update = { "activiti:expression": undefined, "activiti:delegateExpression": undefined, "activiti:class": undefined }; if(!!delegateResolutionValue) { update['activiti:'+delegateResolutionValue] = delegateValue; } return update; }, validate: function(element, values) { var delegateResolutionValue = values.delegateResolution; var delegateValue = values.delegate; var validationResult = {}; if(!delegateValue && !!delegateResolutionValue) { validationResult.delegate = "Value must provide a value."; } if(!!delegateValue && !delegateResolutionValue) { validationResult.delegateResolution = "Must select a radio button"; } return validationResult; }, clear: function(element, inputNode) { // clear text input domQuery('input[name=delegate]', inputNode).value=''; // clear radio button selection var checkedRadio = domQuery('input[name=delegateResolution]:checked', inputNode); if(!!checkedRadio) { checkedRadio.checked = false; } return true; }, canClear: function(element, inputNode) { var input = domQuery('input[name=delegate]', inputNode); var radioButton = domQuery('input[name=delegateResolution]:checked', inputNode); return input.value !== '' || !!radioButton; }, cssClasses: ['textfield'] } );*/ } }; },{"../../../factory/EntryFactory":10,"bpmn-js/lib/util/ModelUtil":98}],33:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { ctor.super_ = superCtor ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); }; } else { // old school shim for old browsers module.exports = function inherits(ctor, superCtor) { ctor.super_ = superCtor var TempCtor = function () {} TempCtor.prototype = superCtor.prototype ctor.prototype = new TempCtor() ctor.prototype.constructor = ctor } } },{}],34:[function(require,module,exports){ /** * Set attribute `name` to `val`, or get attr `name`. * * @param {Element} el * @param {String} name * @param {String} [val] * @api public */ module.exports = function(el, name, val) { // get if (arguments.length == 2) { return el.getAttribute(name); } // remove if (val === null) { return el.removeAttribute(name); } // set el.setAttribute(name, val); return el; }; },{}],35:[function(require,module,exports){ module.exports = require('component-classes'); },{"component-classes":41}],36:[function(require,module,exports){ module.exports = require('component-closest'); },{"component-closest":43}],37:[function(require,module,exports){ module.exports = require('component-delegate'); },{"component-delegate":44}],38:[function(require,module,exports){ module.exports = require('domify'); },{"domify":48}],39:[function(require,module,exports){ module.exports = require('component-query'); },{"component-query":47}],40:[function(require,module,exports){ module.exports = function(el) { el.parentNode && el.parentNode.removeChild(el); }; },{}],41:[function(require,module,exports){ /** * Module dependencies. */ var index = require('indexof'); /** * Whitespace regexp. */ var re = /\s+/; /** * toString reference. */ var toString = Object.prototype.toString; /** * Wrap `el` in a `ClassList`. * * @param {Element} el * @return {ClassList} * @api public */ module.exports = function(el){ return new ClassList(el); }; /** * Initialize a new ClassList for `el`. * * @param {Element} el * @api private */ function ClassList(el) { if (!el || !el.nodeType) { throw new Error('A DOM element reference is required'); } this.el = el; this.list = el.classList; } /** * Add class `name` if not already present. * * @param {String} name * @return {ClassList} * @api public */ ClassList.prototype.add = function(name){ // classList if (this.list) { this.list.add(name); return this; } // fallback var arr = this.array(); var i = index(arr, name); if (!~i) arr.push(name); this.el.className = arr.join(' '); return this; }; /** * Remove class `name` when present, or * pass a regular expression to remove * any which match. * * @param {String|RegExp} name * @return {ClassList} * @api public */ ClassList.prototype.remove = function(name){ if ('[object RegExp]' == toString.call(name)) { return this.removeMatching(name); } // classList if (this.list) { this.list.remove(name); return this; } // fallback var arr = this.array(); var i = index(arr, name); if (~i) arr.splice(i, 1); this.el.className = arr.join(' '); return this; }; /** * Remove all classes matching `re`. * * @param {RegExp} re * @return {ClassList} * @api private */ ClassList.prototype.removeMatching = function(re){ var arr = this.array(); for (var i = 0; i < arr.length; i++) { if (re.test(arr[i])) { this.remove(arr[i]); } } return this; }; /** * Toggle class `name`, can force state via `force`. * * For browsers that support classList, but do not support `force` yet, * the mistake will be detected and corrected. * * @param {String} name * @param {Boolean} force * @return {ClassList} * @api public */ ClassList.prototype.toggle = function(name, force){ // classList if (this.list) { if ("undefined" !== typeof force) { if (force !== this.list.toggle(name, force)) { this.list.toggle(name); // toggle again to correct } } else { this.list.toggle(name); } return this; } // fallback if ("undefined" !== typeof force) { if (!force) { this.remove(name); } else { this.add(name); } } else { if (this.has(name)) { this.remove(name); } else { this.add(name); } } return this; }; /** * Return an array of classes. * * @return {Array} * @api public */ ClassList.prototype.array = function(){ var className = this.el.getAttribute('class') || ''; var str = className.replace(/^\s+|\s+$/g, ''); var arr = str.split(re); if ('' === arr[0]) arr.shift(); return arr; }; /** * Check if class `name` is present. * * @param {String} name * @return {ClassList} * @api public */ ClassList.prototype.has = ClassList.prototype.contains = function(name){ return this.list ? this.list.contains(name) : !! ~index(this.array(), name); }; },{"indexof":42}],42:[function(require,module,exports){ module.exports = function(arr, obj){ if (arr.indexOf) return arr.indexOf(obj); for (var i = 0; i < arr.length; ++i) { if (arr[i] === obj) return i; } return -1; }; },{}],43:[function(require,module,exports){ var matches = require('matches-selector') module.exports = function (element, selector, checkYoSelf, root) { element = checkYoSelf ? {parentNode: element} : element root = root || document // Make sure `element !== document` and `element != null` // otherwise we get an illegal invocation while ((element = element.parentNode) && element !== document) { if (matches(element, selector)) return element // After `matches` on the edge case that // the selector matches the root // (when the root is not the document) if (element === root) return } } },{"matches-selector":46}],44:[function(require,module,exports){ /** * Module dependencies. */ var closest = require('closest') , event = require('event'); /** * Delegate event `type` to `selector` * and invoke `fn(e)`. A callback function * is returned which may be passed to `.unbind()`. * * @param {Element} el * @param {String} selector * @param {String} type * @param {Function} fn * @param {Boolean} capture * @return {Function} * @api public */ exports.bind = function(el, selector, type, fn, capture){ return event.bind(el, type, function(e){ var target = e.target || e.srcElement; e.delegateTarget = closest(target, selector, true, el); if (e.delegateTarget) fn.call(el, e); }, capture); }; /** * Unbind event `type`'s callback `fn`. * * @param {Element} el * @param {String} type * @param {Function} fn * @param {Boolean} capture * @api public */ exports.unbind = function(el, type, fn, capture){ event.unbind(el, type, fn, capture); }; },{"closest":43,"event":45}],45:[function(require,module,exports){ var bind = window.addEventListener ? 'addEventListener' : 'attachEvent', unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent', prefix = bind !== 'addEventListener' ? 'on' : ''; /** * Bind `el` event `type` to `fn`. * * @param {Element} el * @param {String} type * @param {Function} fn * @param {Boolean} capture * @return {Function} * @api public */ exports.bind = function(el, type, fn, capture){ el[bind](prefix + type, fn, capture || false); return fn; }; /** * Unbind `el` event `type`'s callback `fn`. * * @param {Element} el * @param {String} type * @param {Function} fn * @param {Boolean} capture * @return {Function} * @api public */ exports.unbind = function(el, type, fn, capture){ el[unbind](prefix + type, fn, capture || false); return fn; }; },{}],46:[function(require,module,exports){ /** * Module dependencies. */ var query = require('query'); /** * Element prototype. */ var proto = Element.prototype; /** * Vendor function. */ var vendor = proto.matches || proto.webkitMatchesSelector || proto.mozMatchesSelector || proto.msMatchesSelector || proto.oMatchesSelector; /** * Expose `match()`. */ module.exports = match; /** * Match `el` to `selector`. * * @param {Element} el * @param {String} selector * @return {Boolean} * @api public */ function match(el, selector) { if (!el || el.nodeType !== 1) return false; if (vendor) return vendor.call(el, selector); var nodes = query.all(selector, el.parentNode); for (var i = 0; i < nodes.length; ++i) { if (nodes[i] == el) return true; } return false; } },{"query":47}],47:[function(require,module,exports){ function one(selector, el) { return el.querySelector(selector); } exports = module.exports = function(selector, el){ el = el || document; return one(selector, el); }; exports.all = function(selector, el){ el = el || document; return el.querySelectorAll(selector); }; exports.engine = function(obj){ if (!obj.one) throw new Error('.one callback required'); if (!obj.all) throw new Error('.all callback required'); one = obj.one; exports.all = obj.all; return exports; }; },{}],48:[function(require,module,exports){ /** * Expose `parse`. */ module.exports = parse; /** * Tests for browser support. */ var innerHTMLBug = false; var bugTestDiv; if (typeof document !== 'undefined') { bugTestDiv = document.createElement('div'); // Setup bugTestDiv.innerHTML = '
    a'; // Make sure that link elements get serialized correctly by innerHTML // This requires a wrapper element in IE innerHTMLBug = !bugTestDiv.getElementsByTagName('link').length; bugTestDiv = undefined; } /** * Wrap map from jquery. */ var map = { legend: [1, '
    ', '
    '], tr: [2, '', '
    '], col: [2, '', '
    '], // for script/link/style tags to work in IE6-8, you have to wrap // in a div with a non-whitespace character in front, ha! _default: innerHTMLBug ? [1, 'X
    ', '
    '] : [0, '', ''] }; map.td = map.th = [3, '', '
    ']; map.option = map.optgroup = [1, '']; map.thead = map.tbody = map.colgroup = map.caption = map.tfoot = [1, '', '
    ']; map.polyline = map.ellipse = map.polygon = map.circle = map.text = map.line = map.path = map.rect = map.g = [1, '','']; /** * Parse `html` and return a DOM Node instance, which could be a TextNode, * HTML DOM Node of some kind (
    for example), or a DocumentFragment * instance, depending on the contents of the `html` string. * * @param {String} html - HTML string to "domify" * @param {Document} doc - The `document` instance to create the Node for * @return {DOMNode} the TextNode, DOM Node, or DocumentFragment instance * @api private */ function parse(html, doc) { if ('string' != typeof html) throw new TypeError('String expected'); // default to the global `document` object if (!doc) doc = document; // tag name var m = /<([\w:]+)/.exec(html); if (!m) return doc.createTextNode(html); html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace var tag = m[1]; // body support if (tag == 'body') { var el = doc.createElement('html'); el.innerHTML = html; return el.removeChild(el.lastChild); } // wrap map var wrap = map[tag] || map._default; var depth = wrap[0]; var prefix = wrap[1]; var suffix = wrap[2]; var el = doc.createElement('div'); el.innerHTML = prefix + html + suffix; while (depth--) el = el.lastChild; // one element if (el.firstChild == el.lastChild) { return el.removeChild(el.firstChild); } // several elements var fragment = doc.createDocumentFragment(); while (el.firstChild) { fragment.appendChild(el.removeChild(el.firstChild)); } return fragment; } },{}],49:[function(require,module,exports){ 'use strict'; var inherits = require('inherits'); var IdSupport = require('bpmn-moddle/lib/id-support'), Ids = require('ids'); var Viewer = require('./Viewer'); var initialDiagram = '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + ''; /** * A modeler for BPMN 2.0 diagrams. * * * ## Extending the Modeler * * In order to extend the viewer pass extension modules to bootstrap via the * `additionalModules` option. An extension module is an object that exposes * named services. * * The following example depicts the integration of a simple * logging component that integrates with interaction events: * * * ```javascript * * // logging component * function InteractionLogger(eventBus) { * eventBus.on('element.hover', function(event) { * console.log() * }) * } * * InteractionLogger.$inject = [ 'eventBus' ]; // minification save * * // extension module * var extensionModule = { * __init__: [ 'interactionLogger' ], * interactionLogger: [ 'type', InteractionLogger ] * }; * * // extend the viewer * var bpmnModeler = new Modeler({ additionalModules: [ extensionModule ] }); * bpmnModeler.importXML(...); * ``` * * * ## Customizing / Replacing Components * * You can replace individual diagram components by redefining them in override modules. * This works for all components, including those defined in the core. * * Pass in override modules via the `options.additionalModules` flag like this: * * ```javascript * function CustomContextPadProvider(contextPad) { * * contextPad.registerProvider(this); * * this.getContextPadEntries = function(element) { * // no entries, effectively disable the context pad * return {}; * }; * } * * CustomContextPadProvider.$inject = [ 'contextPad' ]; * * var overrideModule = { * contextPadProvider: [ 'type', CustomContextPadProvider ] * }; * * var bpmnModeler = new Modeler({ additionalModules: [ overrideModule ]}); * ``` * * @param {Object} [options] configuration options to pass to the viewer * @param {DOMElement} [options.container] the container to render the viewer in, defaults to body. * @param {String|Number} [options.width] the width of the viewer * @param {String|Number} [options.height] the height of the viewer * @param {Object} [options.moddleExtensions] extension packages to provide * @param {Array} [options.modules] a list of modules to override the default modules * @param {Array} [options.additionalModules] a list of modules to use with the default modules */ function Modeler(options) { Viewer.call(this, options); } inherits(Modeler, Viewer); Modeler.prototype.createDiagram = function(done) { return this.importXML(initialDiagram, done); }; Modeler.prototype.createModdle = function() { var moddle = Viewer.prototype.createModdle.call(this); IdSupport.extend(moddle, new Ids([ 32, 36, 1 ])); return moddle; }; Modeler.prototype._interactionModules = [ // non-modeling components require('./features/label-editing'), require('diagram-js/lib/navigation/zoomscroll'), require('diagram-js/lib/navigation/movecanvas'), require('diagram-js/lib/navigation/touch') ]; Modeler.prototype._modelingModules = [ // modeling components require('diagram-js/lib/features/move'), require('diagram-js/lib/features/bendpoints'), require('diagram-js/lib/features/resize'), require('diagram-js/lib/features/space-tool'), require('diagram-js/lib/features/lasso-tool'), require('./features/keyboard'), require('./features/snapping'), require('./features/modeling'), require('./features/context-pad'), require('./features/palette') ]; // modules the modeler is composed of // // - viewer modules // - interaction modules // - modeling modules Modeler.prototype._modules = [].concat( Modeler.prototype._modules, Modeler.prototype._interactionModules, Modeler.prototype._modelingModules); module.exports = Modeler; },{"./Viewer":50,"./features/context-pad":56,"./features/keyboard":58,"./features/label-editing":62,"./features/modeling":80,"./features/palette":84,"./features/snapping":90,"bpmn-moddle/lib/id-support":101,"diagram-js/lib/features/bendpoints":157,"diagram-js/lib/features/lasso-tool":175,"diagram-js/lib/features/move":200,"diagram-js/lib/features/resize":213,"diagram-js/lib/features/space-tool":227,"diagram-js/lib/navigation/movecanvas":239,"diagram-js/lib/navigation/touch":240,"diagram-js/lib/navigation/zoomscroll":243,"ids":124,"inherits":126}],50:[function(require,module,exports){ 'use strict'; var assign = require('lodash/object/assign'), omit = require('lodash/object/omit'), isString = require('lodash/lang/isString'), isNumber = require('lodash/lang/isNumber'); var domify = require('min-dom/lib/domify'), domQuery = require('min-dom/lib/query'), domRemove = require('min-dom/lib/remove'); var Diagram = require('diagram-js'), BpmnModdle = require('bpmn-moddle'); var Importer = require('./import/Importer'); function initListeners(diagram, listeners) { var events = diagram.get('eventBus'); listeners.forEach(function(l) { events.on(l.event, l.handler); }); } function checkValidationError(err) { // check if we can help the user by indicating wrong BPMN 2.0 xml // (in case he or the exporting tool did not get that right) var pattern = /unparsable content <([^>]+)> detected([\s\S]*)$/; var match = pattern.exec(err.message); if (match) { err.message = 'unparsable content <' + match[1] + '> detected; ' + 'this may indicate an invalid BPMN 2.0 diagram file' + match[2]; } return err; } var DEFAULT_OPTIONS = { width: '100%', height: '100%', position: 'relative', container: 'body' }; /** * Ensure the passed argument is a proper unit (defaulting to px) */ function ensureUnit(val) { return val + (isNumber(val) ? 'px' : ''); } /** * A viewer for BPMN 2.0 diagrams. * * Have a look at {@link NavigatedViewer} or {@link Modeler} for bundles that include * additional features. * * * ## Extending the Viewer * * In order to extend the viewer pass extension modules to bootstrap via the * `additionalModules` option. An extension module is an object that exposes * named services. * * The following example depicts the integration of a simple * logging component that integrates with interaction events: * * * ```javascript * * // logging component * function InteractionLogger(eventBus) { * eventBus.on('element.hover', function(event) { * console.log() * }) * } * * InteractionLogger.$inject = [ 'eventBus' ]; // minification save * * // extension module * var extensionModule = { * __init__: [ 'interactionLogger' ], * interactionLogger: [ 'type', InteractionLogger ] * }; * * // extend the viewer * var bpmnViewer = new Viewer({ additionalModules: [ extensionModule ] }); * bpmnViewer.importXML(...); * ``` * * @param {Object} [options] configuration options to pass to the viewer * @param {DOMElement} [options.container] the container to render the viewer in, defaults to body. * @param {String|Number} [options.width] the width of the viewer * @param {String|Number} [options.height] the height of the viewer * @param {Object} [options.moddleExtensions] extension packages to provide * @param {Array} [options.modules] a list of modules to override the default modules * @param {Array} [options.additionalModules] a list of modules to use with the default modules */ function Viewer(options) { this.options = options = assign({}, DEFAULT_OPTIONS, options || {}); var parent = options.container; // support jquery element // unwrap it if passed if (parent.get) { parent = parent.get(0); } // support selector if (isString(parent)) { parent = domQuery(parent); } var container = this.container = domify('
    '); parent.appendChild(container); assign(container.style, { width: ensureUnit(options.width), height: ensureUnit(options.height), position: options.position }); /** * The code in the area * must not be changed, see http://bpmn.io/license for more information * * */ /* jshint -W101 */ // inlined ../resources/bpmnjs.png var logoData = 'iVBORw0KGgoAAAANSUhEUgAAADQAAAA0CAMAAADypuvZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADBQTFRFiMte9PrwldFwfcZPqtqN0+zEyOe1XLgjvuKncsJAZ70y6fXh3vDT////UrQV////G2zN+AAAABB0Uk5T////////////////////AOAjXRkAAAHDSURBVHjavJZJkoUgDEBJmAX8979tM8u3E6x20VlYJfFFMoL4vBDxATxZcakIOJTWSmxvKWVIkJ8jHvlRv1F2LFrVISCZI+tCtQx+XfewgVTfyY3plPiQEAzI3zWy+kR6NBhFBYeBuscJLOUuA2WVLpCjVIaFzrNQZArxAZKUQm6gsj37L9Cb7dnIBUKxENaaMJQqMpDXvSL+ktxdGRm2IsKgJGGPg7atwUG5CcFUEuSv+CwQqizTrvDTNXdMU2bMiDWZd8d7QIySWVRsb2vBBioxOFt4OinPBapL+neAb5KL5IJ8szOza2/DYoipUCx+CjO0Bpsv0V6mktNZ+k8rlABlWG0FrOpKYVo8DT3dBeLEjUBAj7moDogVii7nSS9QzZnFcOVBp1g2PyBQ3Vr5aIapN91VJy33HTJLC1iX2FY6F8gRdaAeIEfVONgtFCzZTmoLEdOjBDfsIOA6128gw3eu1shAajdZNAORxuQDJN5A5PbEG6gNIu24QJD5iNyRMZIr6bsHbCtCU/OaOaSvgkUyDMdDa1BXGf5HJ1To+/Ym6mCKT02Y+/Sa126ZKyd3jxhzpc1r8zVL6YM1Qy/kR4ABAFJ6iQUnivhAAAAAAElFTkSuQmCC'; /* jshint +W101 */ var linkMarkup = '' + '' + ''; container.appendChild(domify(linkMarkup)); /* */ } Viewer.prototype.importXML = function(xml, done) { var self = this; this.moddle = this.createModdle(); this.moddle.fromXML(xml, 'bpmn:Definitions', function(err, definitions, context) { if (err) { err = checkValidationError(err); return done(err); } var parseWarnings = context.warnings; self.importDefinitions(definitions, function(err, importWarnings) { if (err) { return done(err); } done(null, parseWarnings.concat(importWarnings || [])); }); }); }; Viewer.prototype.saveXML = function(options, done) { if (!done) { done = options; options = {}; } var definitions = this.definitions; if (!definitions) { return done(new Error('no definitions loaded')); } this.moddle.toXML(definitions, options, done); }; Viewer.prototype.createModdle = function() { return new BpmnModdle(this.options.moddleExtensions); }; Viewer.prototype.saveSVG = function(options, done) { if (!done) { done = options; options = {}; } var canvas = this.get('canvas'); var contentNode = canvas.getDefaultLayer(), defsNode = canvas._svg.select('defs'); var contents = contentNode.innerSVG(), defs = (defsNode && defsNode.outerSVG()) || ''; var bbox = contentNode.getBBox(); var svg = '\n' + '\n' + '\n' + '' + defs + contents + ''; done(null, svg); }; Viewer.prototype.get = function(name) { if (!this.diagram) { throw new Error('no diagram loaded'); } return this.diagram.get(name); }; Viewer.prototype.invoke = function(fn) { if (!this.diagram) { throw new Error('no diagram loaded'); } return this.diagram.invoke(fn); }; Viewer.prototype.importDefinitions = function(definitions, done) { // use try/catch to not swallow synchronous exceptions // that may be raised during model parsing try { if (this.diagram) { this.clear(); } this.definitions = definitions; var diagram = this.diagram = this._createDiagram(this.options); this._init(diagram); Importer.importBpmnDiagram(diagram, definitions, done); } catch (e) { done(e); } }; Viewer.prototype._init = function(diagram) { initListeners(diagram, this.__listeners || []); }; Viewer.prototype._createDiagram = function(options) { var modules = [].concat(options.modules || this.getModules(), options.additionalModules || []); // add self as an available service modules.unshift({ bpmnjs: [ 'value', this ], moddle: [ 'value', this.moddle ] }); options = omit(options, 'additionalModules'); options = assign(options, { canvas: { container: this.container }, modules: modules }); return new Diagram(options); }; Viewer.prototype.getModules = function() { return this._modules; }; /** * Remove all drawn elements from the viewer. * * After calling this method the viewer can still * be reused for opening another diagram. */ Viewer.prototype.clear = function() { var diagram = this.diagram; if (diagram) { diagram.destroy(); } }; /** * Destroy the viewer instance and remove all its remainders * from the document tree. */ Viewer.prototype.destroy = function() { // clear underlying diagram this.clear(); // remove container domRemove(this.container); }; /** * Register an event listener on the viewer * * @param {String} event * @param {Function} handler */ Viewer.prototype.on = function(event, handler) { var diagram = this.diagram, listeners = this.__listeners = this.__listeners || []; listeners.push({ event: event, handler: handler }); if (diagram) { diagram.get('eventBus').on(event, handler); } }; // modules the viewer is composed of Viewer.prototype._modules = [ require('./core'), require('diagram-js/lib/features/selection'), require('diagram-js/lib/features/overlays') ]; module.exports = Viewer; },{"./core":51,"./import/Importer":93,"bpmn-moddle":99,"diagram-js":137,"diagram-js/lib/features/overlays":204,"diagram-js/lib/features/selection":220,"lodash/lang/isNumber":419,"lodash/lang/isString":422,"lodash/object/assign":425,"lodash/object/omit":429,"min-dom/lib/domify":127,"min-dom/lib/query":129,"min-dom/lib/remove":130}],51:[function(require,module,exports){ module.exports = { __depends__: [ require('../draw'), require('../import') ] }; },{"../draw":54,"../import":95}],52:[function(require,module,exports){ 'use strict'; var inherits = require('inherits'), isArray = require('lodash/lang/isArray'), isObject = require('lodash/lang/isObject'), assign = require('lodash/object/assign'), forEach = require('lodash/collection/forEach'), every = require('lodash/collection/every'), includes = require('lodash/collection/includes'), some = require('lodash/collection/some'); var DefaultRenderer = require('diagram-js/lib/draw/Renderer'), TextUtil = require('diagram-js/lib/util/Text'), DiUtil = require('../util/DiUtil'); var createLine = DefaultRenderer.createLine; function BpmnRenderer(events, styles, pathMap) { DefaultRenderer.call(this, styles); var TASK_BORDER_RADIUS = 10; var INNER_OUTER_DIST = 3; var LABEL_STYLE = { fontFamily: 'Arial, sans-serif', fontSize: '12px' }; var textUtil = new TextUtil({ style: LABEL_STYLE, size: { width: 100 } }); var markers = {}; function addMarker(id, element) { markers[id] = element; } function marker(id) { return markers[id]; } function initMarkers(svg) { function createMarker(id, options) { var attrs = assign({ fill: 'black', strokeWidth: 1, strokeLinecap: 'round', strokeDasharray: 'none' }, options.attrs); var ref = options.ref || { x: 0, y: 0 }; var scale = options.scale || 1; // fix for safari / chrome / firefox bug not correctly // resetting stroke dash array if (attrs.strokeDasharray === 'none') { attrs.strokeDasharray = [10000, 1]; } var marker = options.element .attr(attrs) .marker(0, 0, 20, 20, ref.x, ref.y) .attr({ markerWidth: 20 * scale, markerHeight: 20 * scale }); return addMarker(id, marker); } createMarker('sequenceflow-end', { element: svg.path('M 1 5 L 11 10 L 1 15 Z'), ref: { x: 11, y: 10 }, scale: 0.5 }); createMarker('messageflow-start', { element: svg.circle(6, 6, 3.5), attrs: { fill: 'white', stroke: 'black' }, ref: { x: 6, y: 6 } }); createMarker('messageflow-end', { element: svg.path('m 1 5 l 0 -3 l 7 3 l -7 3 z'), attrs: { fill: 'white', stroke: 'black', strokeLinecap: 'butt' }, ref: { x: 8.5, y: 5 } }); createMarker('data-association-end', { element: svg.path('M 1 5 L 11 10 L 1 15'), attrs: { fill: 'white', stroke: 'black' }, ref: { x: 11, y: 10 }, scale: 0.5 }); createMarker('conditional-flow-marker', { element: svg.path('M 0 10 L 8 6 L 16 10 L 8 14 Z'), attrs: { fill: 'white', stroke: 'black' }, ref: { x: -1, y: 10 }, scale: 0.5 }); createMarker('conditional-default-flow-marker', { element: svg.path('M 1 4 L 5 16'), attrs: { stroke: 'black' }, ref: { x: -5, y: 10 }, scale: 0.5 }); } function computeStyle(custom, traits, defaultStyles) { if (!isArray(traits)) { defaultStyles = traits; traits = []; } return styles.style(traits || [], assign(defaultStyles, custom || {})); } function drawCircle(p, width, height, offset, attrs) { if (isObject(offset)) { attrs = offset; offset = 0; } offset = offset || 0; attrs = computeStyle(attrs, { stroke: 'black', strokeWidth: 2, fill: 'white' }); var cx = width / 2, cy = height / 2; return p.circle(cx, cy, Math.round((width + height) / 4 - offset)).attr(attrs); } function drawRect(p, width, height, r, offset, attrs) { if (isObject(offset)) { attrs = offset; offset = 0; } offset = offset || 0; attrs = computeStyle(attrs, { stroke: 'black', strokeWidth: 2, fill: 'white' }); return p.rect(offset, offset, width - offset * 2, height - offset * 2, r).attr(attrs); } function drawDiamond(p, width, height, attrs) { var x_2 = width / 2; var y_2 = height / 2; var points = [x_2, 0, width, y_2, x_2, height, 0, y_2 ]; attrs = computeStyle(attrs, { stroke: 'black', strokeWidth: 2, fill: 'white' }); return p.polygon(points).attr(attrs); } function drawLine(p, waypoints, attrs) { attrs = computeStyle(attrs, [ 'no-fill' ], { stroke: 'black', strokeWidth: 2, fill: 'none' }); return createLine(waypoints, attrs).appendTo(p); } function drawPath(p, d, attrs) { attrs = computeStyle(attrs, [ 'no-fill' ], { strokeWidth: 2, stroke: 'black' }); return p.path(d).attr(attrs); } function as(type) { return function(p, element) { return handlers[type](p, element); }; } function renderer(type) { return handlers[type]; } function renderEventContent(element, p) { var event = getSemantic(element); var isThrowing = isThrowEvent(event); if (isTypedEvent(event, 'bpmn:MessageEventDefinition')) { return renderer('bpmn:MessageEventDefinition')(p, element, isThrowing); } if (isTypedEvent(event, 'bpmn:TimerEventDefinition')) { return renderer('bpmn:TimerEventDefinition')(p, element, isThrowing); } if (isTypedEvent(event, 'bpmn:ConditionalEventDefinition')) { return renderer('bpmn:ConditionalEventDefinition')(p, element); } if (isTypedEvent(event, 'bpmn:SignalEventDefinition')) { return renderer('bpmn:SignalEventDefinition')(p, element, isThrowing); } if (isTypedEvent(event, 'bpmn:CancelEventDefinition') && isTypedEvent(event, 'bpmn:TerminateEventDefinition', { parallelMultiple: false })) { return renderer('bpmn:MultipleEventDefinition')(p, element, isThrowing); } if (isTypedEvent(event, 'bpmn:CancelEventDefinition') && isTypedEvent(event, 'bpmn:TerminateEventDefinition', { parallelMultiple: true })) { return renderer('bpmn:ParallelMultipleEventDefinition')(p, element, isThrowing); } if (isTypedEvent(event, 'bpmn:EscalationEventDefinition')) { return renderer('bpmn:EscalationEventDefinition')(p, element, isThrowing); } if (isTypedEvent(event, 'bpmn:LinkEventDefinition')) { return renderer('bpmn:LinkEventDefinition')(p, element, isThrowing); } if (isTypedEvent(event, 'bpmn:ErrorEventDefinition')) { return renderer('bpmn:ErrorEventDefinition')(p, element, isThrowing); } if (isTypedEvent(event, 'bpmn:CancelEventDefinition')) { return renderer('bpmn:CancelEventDefinition')(p, element, isThrowing); } if (isTypedEvent(event, 'bpmn:CompensateEventDefinition')) { return renderer('bpmn:CompensateEventDefinition')(p, element, isThrowing); } if (isTypedEvent(event, 'bpmn:TerminateEventDefinition')) { return renderer('bpmn:TerminateEventDefinition')(p, element, isThrowing); } return null; } function renderLabel(p, label, options) { return textUtil.createText(p, label || '', options).addClass('djs-label'); } function renderEmbeddedLabel(p, element, align) { var semantic = getSemantic(element); return renderLabel(p, semantic.name, { box: element, align: align, padding: 5 }); } function renderExternalLabel(p, element, align) { var semantic = getSemantic(element); if (!semantic.name) { element.hidden = true; } return renderLabel(p, semantic.name, { box: element, align: align, style: { fontSize: '11px' } }); } function renderLaneLabel(p, text, element) { var textBox = renderLabel(p, text, { box: { height: 30, width: element.height }, align: 'center-middle' }); var top = -1 * element.height; textBox.transform( 'rotate(270) ' + 'translate(' + top + ',' + 0 + ')' ); } function createPathFromConnection(connection) { var waypoints = connection.waypoints; var pathData = 'm ' + waypoints[0].x + ',' + waypoints[0].y; for (var i = 1; i < waypoints.length; i++) { pathData += 'L' + waypoints[i].x + ',' + waypoints[i].y + ' '; } return pathData; } var handlers = { 'bpmn:Event': function(p, element, attrs) { return drawCircle(p, element.width, element.height, attrs); }, 'bpmn:StartEvent': function(p, element) { var attrs = {}; var semantic = getSemantic(element); if (!semantic.isInterrupting) { attrs = { strokeDasharray: '6', strokeLinecap: 'round' }; } var circle = renderer('bpmn:Event')(p, element, attrs); renderEventContent(element, p); return circle; }, 'bpmn:MessageEventDefinition': function(p, element, isThrowing) { var pathData = pathMap.getScaledPath('EVENT_MESSAGE', { xScaleFactor: 0.9, yScaleFactor: 0.9, containerWidth: element.width, containerHeight: element.height, position: { mx: 0.235, my: 0.315 } }); var fill = isThrowing ? 'black' : 'white'; var stroke = isThrowing ? 'white' : 'black'; var messagePath = drawPath(p, pathData, { strokeWidth: 1, fill: fill, stroke: stroke }); return messagePath; }, 'bpmn:TimerEventDefinition': function(p, element) { var circle = drawCircle(p, element.width, element.height, 0.2 * element.height, { strokeWidth: 2 }); var pathData = pathMap.getScaledPath('EVENT_TIMER_WH', { xScaleFactor: 0.75, yScaleFactor: 0.75, containerWidth: element.width, containerHeight: element.height, position: { mx: 0.5, my: 0.5 } }); drawPath(p, pathData, { strokeWidth: 2, strokeLinecap: 'square' }); for(var i = 0;i < 12;i++) { var linePathData = pathMap.getScaledPath('EVENT_TIMER_LINE', { xScaleFactor: 0.75, yScaleFactor: 0.75, containerWidth: element.width, containerHeight: element.height, position: { mx: 0.5, my: 0.5 } }); var width = element.width / 2; var height = element.height / 2; drawPath(p, linePathData, { strokeWidth: 1, strokeLinecap: 'square', transform: 'rotate(' + (i * 30) + ',' + height + ',' + width + ')' }); } return circle; }, 'bpmn:EscalationEventDefinition': function(p, event, isThrowing) { var pathData = pathMap.getScaledPath('EVENT_ESCALATION', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: event.width, containerHeight: event.height, position: { mx: 0.5, my: 0.555 } }); var fill = isThrowing ? 'black' : 'none'; return drawPath(p, pathData, { strokeWidth: 1, fill: fill }); }, 'bpmn:ConditionalEventDefinition': function(p, event) { var pathData = pathMap.getScaledPath('EVENT_CONDITIONAL', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: event.width, containerHeight: event.height, position: { mx: 0.5, my: 0.222 } }); return drawPath(p, pathData, { strokeWidth: 1 }); }, 'bpmn:LinkEventDefinition': function(p, event, isThrowing) { var pathData = pathMap.getScaledPath('EVENT_LINK', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: event.width, containerHeight: event.height, position: { mx: 0.57, my: 0.263 } }); var fill = isThrowing ? 'black' : 'none'; return drawPath(p, pathData, { strokeWidth: 1, fill: fill }); }, 'bpmn:ErrorEventDefinition': function(p, event, isThrowing) { var pathData = pathMap.getScaledPath('EVENT_ERROR', { xScaleFactor: 1.1, yScaleFactor: 1.1, containerWidth: event.width, containerHeight: event.height, position: { mx: 0.2, my: 0.722 } }); var fill = isThrowing ? 'black' : 'none'; return drawPath(p, pathData, { strokeWidth: 1, fill: fill }); }, 'bpmn:CancelEventDefinition': function(p, event, isThrowing) { var pathData = pathMap.getScaledPath('EVENT_CANCEL_45', { xScaleFactor: 1.0, yScaleFactor: 1.0, containerWidth: event.width, containerHeight: event.height, position: { mx: 0.638, my: -0.055 } }); var fill = isThrowing ? 'black' : 'none'; return drawPath(p, pathData, { strokeWidth: 1, fill: fill }).transform('rotate(45)'); }, 'bpmn:CompensateEventDefinition': function(p, event, isThrowing) { var pathData = pathMap.getScaledPath('EVENT_COMPENSATION', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: event.width, containerHeight: event.height, position: { mx: 0.201, my: 0.472 } }); var fill = isThrowing ? 'black' : 'none'; return drawPath(p, pathData, { strokeWidth: 1, fill: fill }); }, 'bpmn:SignalEventDefinition': function(p, event, isThrowing) { var pathData = pathMap.getScaledPath('EVENT_SIGNAL', { xScaleFactor: 0.9, yScaleFactor: 0.9, containerWidth: event.width, containerHeight: event.height, position: { mx: 0.5, my: 0.2 } }); var fill = isThrowing ? 'black' : 'none'; return drawPath(p, pathData, { strokeWidth: 1, fill: fill }); }, 'bpmn:MultipleEventDefinition': function(p, event, isThrowing) { var pathData = pathMap.getScaledPath('EVENT_MULTIPLE', { xScaleFactor: 1.1, yScaleFactor: 1.1, containerWidth: event.width, containerHeight: event.height, position: { mx: 0.222, my: 0.36 } }); var fill = isThrowing ? 'black' : 'none'; return drawPath(p, pathData, { strokeWidth: 1, fill: fill }); }, 'bpmn:ParallelMultipleEventDefinition': function(p, event) { var pathData = pathMap.getScaledPath('EVENT_PARALLEL_MULTIPLE', { xScaleFactor: 1.2, yScaleFactor: 1.2, containerWidth: event.width, containerHeight: event.height, position: { mx: 0.458, my: 0.194 } }); return drawPath(p, pathData, { strokeWidth: 1 }); }, 'bpmn:EndEvent': function(p, element) { var circle = renderer('bpmn:Event')(p, element, { strokeWidth: 4 }); renderEventContent(element, p, true); return circle; }, 'bpmn:TerminateEventDefinition': function(p, element) { var circle = drawCircle(p, element.width, element.height, 8, { strokeWidth: 4, fill: 'black' }); return circle; }, 'bpmn:IntermediateEvent': function(p, element) { var outer = renderer('bpmn:Event')(p, element, { strokeWidth: 1 }); /* inner */ drawCircle(p, element.width, element.height, INNER_OUTER_DIST, { strokeWidth: 1, fill: 'none' }); renderEventContent(element, p); return outer; }, 'bpmn:IntermediateCatchEvent': as('bpmn:IntermediateEvent'), 'bpmn:IntermediateThrowEvent': as('bpmn:IntermediateEvent'), 'bpmn:Activity': function(p, element, attrs) { return drawRect(p, element.width, element.height, TASK_BORDER_RADIUS, attrs); }, 'bpmn:Task': function(p, element, attrs) { var rect = renderer('bpmn:Activity')(p, element, attrs); renderEmbeddedLabel(p, element, 'center-middle'); attachTaskMarkers(p, element); return rect; }, 'bpmn:ServiceTask': function(p, element) { var task = renderer('bpmn:Task')(p, element); var pathDataBG = pathMap.getScaledPath('TASK_TYPE_SERVICE', { abspos: { x: 12, y: 18 } }); /* service bg */ drawPath(p, pathDataBG, { strokeWidth: 1, fill: 'none' }); var fillPathData = pathMap.getScaledPath('TASK_TYPE_SERVICE_FILL', { abspos: { x: 17.2, y: 18 } }); /* service fill */ drawPath(p, fillPathData, { strokeWidth: 0, stroke: 'none', fill: 'white' }); var pathData = pathMap.getScaledPath('TASK_TYPE_SERVICE', { abspos: { x: 17, y: 22 } }); /* service */ drawPath(p, pathData, { strokeWidth: 1, fill: 'white' }); return task; }, 'bpmn:UserTask': function(p, element) { var task = renderer('bpmn:Task')(p, element); var x = 15; var y = 12; var pathData = pathMap.getScaledPath('TASK_TYPE_USER_1', { abspos: { x: x, y: y } }); /* user path */ drawPath(p, pathData, { strokeWidth: 0.5, fill: 'none' }); var pathData2 = pathMap.getScaledPath('TASK_TYPE_USER_2', { abspos: { x: x, y: y } }); /* user2 path */ drawPath(p, pathData2, { strokeWidth: 0.5, fill: 'none' }); var pathData3 = pathMap.getScaledPath('TASK_TYPE_USER_3', { abspos: { x: x, y: y } }); /* user3 path */ drawPath(p, pathData3, { strokeWidth: 0.5, fill: 'black' }); return task; }, 'bpmn:ManualTask': function(p, element) { var task = renderer('bpmn:Task')(p, element); var pathData = pathMap.getScaledPath('TASK_TYPE_MANUAL', { abspos: { x: 17, y: 15 } }); /* manual path */ drawPath(p, pathData, { strokeWidth: 0.25, fill: 'white', stroke: 'black' }); return task; }, 'bpmn:SendTask': function(p, element) { var task = renderer('bpmn:Task')(p, element); var pathData = pathMap.getScaledPath('TASK_TYPE_SEND', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: 21, containerHeight: 14, position: { mx: 0.285, my: 0.357 } }); /* send path */ drawPath(p, pathData, { strokeWidth: 1, fill: 'black', stroke: 'white' }); return task; }, 'bpmn:ReceiveTask' : function(p, element) { var semantic = getSemantic(element); var task = renderer('bpmn:Task')(p, element); var pathData; if (semantic.instantiate) { drawCircle(p, 28, 28, 20 * 0.22, { strokeWidth: 1 }); pathData = pathMap.getScaledPath('TASK_TYPE_INSTANTIATING_SEND', { abspos: { x: 7.77, y: 9.52 } }); } else { pathData = pathMap.getScaledPath('TASK_TYPE_SEND', { xScaleFactor: 0.9, yScaleFactor: 0.9, containerWidth: 21, containerHeight: 14, position: { mx: 0.3, my: 0.4 } }); } /* receive path */ drawPath(p, pathData, { strokeWidth: 1 }); return task; }, 'bpmn:ScriptTask': function(p, element) { var task = renderer('bpmn:Task')(p, element); var pathData = pathMap.getScaledPath('TASK_TYPE_SCRIPT', { abspos: { x: 15, y: 20 } }); /* script path */ drawPath(p, pathData, { strokeWidth: 1 }); return task; }, 'bpmn:BusinessRuleTask': function(p, element) { var task = renderer('bpmn:Task')(p, element); var headerPathData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_HEADER', { abspos: { x: 8, y: 8 } }); var businessHeaderPath = drawPath(p, headerPathData); businessHeaderPath.attr({ strokeWidth: 1, fill: 'AAA' }); var headerData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_MAIN', { abspos: { x: 8, y: 8 } }); var businessPath = drawPath(p, headerData); businessPath.attr({ strokeWidth: 1 }); return task; }, 'bpmn:SubProcess': function(p, element, attrs) { var rect = renderer('bpmn:Activity')(p, element, attrs); var semantic = getSemantic(element); var expanded = DiUtil.isExpanded(semantic); var isEventSubProcess = !!semantic.triggeredByEvent; if (isEventSubProcess) { rect.attr({ strokeDasharray: '1,2' }); } renderEmbeddedLabel(p, element, expanded ? 'center-top' : 'center-middle'); if (expanded) { attachTaskMarkers(p, element); } else { attachTaskMarkers(p, element, ['SubProcessMarker']); } return rect; }, 'bpmn:AdHocSubProcess': function(p, element) { return renderer('bpmn:SubProcess')(p, element); }, 'bpmn:Transaction': function(p, element) { var outer = renderer('bpmn:SubProcess')(p, element); var innerAttrs = styles.style([ 'no-fill', 'no-events' ]); /* inner path */ drawRect(p, element.width, element.height, TASK_BORDER_RADIUS - 2, INNER_OUTER_DIST, innerAttrs); return outer; }, 'bpmn:CallActivity': function(p, element) { return renderer('bpmn:Task')(p, element, { strokeWidth: 5 }); }, 'bpmn:Participant': function(p, element) { var lane = renderer('bpmn:Lane')(p, element, { fill: 'White' }); var expandedPool = DiUtil.isExpanded(element); if (expandedPool) { drawLine(p, [ { x: 30, y: 0 }, { x: 30, y: element.height } ]); var text = getSemantic(element).name; renderLaneLabel(p, text, element); } else { // Collapsed pool draw text inline var text2 = getSemantic(element).name; renderLabel(p, text2, { box: element, align: 'center-middle' }); } var participantMultiplicity = !!(getSemantic(element).participantMultiplicity); if(participantMultiplicity) { renderer('ParticipantMultiplicityMarker')(p, element); } return lane; }, 'bpmn:Lane': function(p, element, attrs) { var rect = drawRect(p, element.width, element.height, 0, attrs || { fill: 'none' }); var semantic = getSemantic(element); if (semantic.$type === 'bpmn:Lane') { var text = semantic.name; renderLaneLabel(p, text, element); } return rect; }, 'bpmn:InclusiveGateway': function(p, element) { var diamond = drawDiamond(p, element.width, element.height); /* circle path */ drawCircle(p, element.width, element.height, element.height * 0.24, { strokeWidth: 2.5, fill: 'none' }); return diamond; }, 'bpmn:ExclusiveGateway': function(p, element) { var diamond = drawDiamond(p, element.width, element.height); var pathData = pathMap.getScaledPath('GATEWAY_EXCLUSIVE', { xScaleFactor: 0.4, yScaleFactor: 0.4, containerWidth: element.width, containerHeight: element.height, position: { mx: 0.32, my: 0.3 } }); if (!!(getDi(element).isMarkerVisible)) { drawPath(p, pathData, { strokeWidth: 1, fill: 'black' }); } return diamond; }, 'bpmn:ComplexGateway': function(p, element) { var diamond = drawDiamond(p, element.width, element.height); var pathData = pathMap.getScaledPath('GATEWAY_COMPLEX', { xScaleFactor: 0.5, yScaleFactor:0.5, containerWidth: element.width, containerHeight: element.height, position: { mx: 0.46, my: 0.26 } }); /* complex path */ drawPath(p, pathData, { strokeWidth: 1, fill: 'black' }); return diamond; }, 'bpmn:ParallelGateway': function(p, element) { var diamond = drawDiamond(p, element.width, element.height); var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', { xScaleFactor: 0.6, yScaleFactor:0.6, containerWidth: element.width, containerHeight: element.height, position: { mx: 0.46, my: 0.2 } }); /* parallel path */ drawPath(p, pathData, { strokeWidth: 1, fill: 'black' }); return diamond; }, 'bpmn:EventBasedGateway': function(p, element) { var semantic = getSemantic(element); var diamond = drawDiamond(p, element.width, element.height); /* outer circle path */ drawCircle(p, element.width, element.height, element.height * 0.20, { strokeWidth: 1, fill: 'none' }); var type = semantic.eventGatewayType; var instantiate = !!semantic.instantiate; function drawEvent() { var pathData = pathMap.getScaledPath('GATEWAY_EVENT_BASED', { xScaleFactor: 0.18, yScaleFactor: 0.18, containerWidth: element.width, containerHeight: element.height, position: { mx: 0.36, my: 0.44 } }); /* event path */ drawPath(p, pathData, { strokeWidth: 2, fill: 'none' }); } if (type === 'Parallel') { var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', { xScaleFactor: 0.4, yScaleFactor:0.4, containerWidth: element.width, containerHeight: element.height, position: { mx: 0.474, my: 0.296 } }); var parallelPath = drawPath(p, pathData); parallelPath.attr({ strokeWidth: 1, fill: 'none' }); } else if (type === 'Exclusive') { if (!instantiate) { var innerCircle = drawCircle(p, element.width, element.height, element.height * 0.26); innerCircle.attr({ strokeWidth: 1, fill: 'none' }); } drawEvent(); } return diamond; }, 'bpmn:Gateway': function(p, element) { return drawDiamond(p, element.width, element.height); }, 'bpmn:SequenceFlow': function(p, element) { var pathData = createPathFromConnection(element); var path = drawPath(p, pathData, { strokeLinejoin: 'round', markerEnd: marker('sequenceflow-end') }); var sequenceFlow = getSemantic(element); var source = element.source.businessObject; // conditional flow marker if (sequenceFlow.conditionExpression && source.$instanceOf('bpmn:Task')) { path.attr({ markerStart: marker('conditional-flow-marker') }); } // default marker if (source.default && source.$instanceOf('bpmn:Gateway') && source.default === sequenceFlow) { path.attr({ markerStart: marker('conditional-default-flow-marker') }); } return path; }, 'bpmn:Association': function(p, element, attrs) { attrs = assign({ strokeDasharray: '1,6', strokeLinecap: 'round', strokeLinejoin: 'round' }, attrs || {}); // TODO(nre): style according to directed state return drawLine(p, element.waypoints, attrs); }, 'bpmn:DataInputAssociation': function(p, element) { return renderer('bpmn:Association')(p, element, { markerEnd: marker('data-association-end') }); }, 'bpmn:DataOutputAssociation': function(p, element) { return renderer('bpmn:Association')(p, element, { markerEnd: marker('data-association-end') }); }, 'bpmn:MessageFlow': function(p, element) { var semantic = getSemantic(element), di = getDi(element); var pathData = createPathFromConnection(element); var path = drawPath(p, pathData, { markerEnd: marker('messageflow-end'), markerStart: marker('messageflow-start'), strokeDasharray: '10, 12', strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: '1.5px' }); if (semantic.messageRef) { var midPoint = path.getPointAtLength(path.getTotalLength() / 2); var markerPathData = pathMap.getScaledPath('MESSAGE_FLOW_MARKER', { abspos: { x: midPoint.x, y: midPoint.y } }); var messageAttrs = { strokeWidth: 1 }; if (di.messageVisibleKind === 'initiating') { messageAttrs.fill = 'white'; messageAttrs.stroke = 'black'; } else { messageAttrs.fill = '#888'; messageAttrs.stroke = 'white'; } drawPath(p, markerPathData, messageAttrs); } return path; }, 'bpmn:DataObject': function(p, element) { var pathData = pathMap.getScaledPath('DATA_OBJECT_PATH', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: element.width, containerHeight: element.height, position: { mx: 0.474, my: 0.296 } }); var elementObject = drawPath(p, pathData, { fill: 'white' }); var semantic = getSemantic(element); if (isCollection(semantic)) { renderDataItemCollection(p, element); } return elementObject; }, 'bpmn:DataObjectReference': as('bpmn:DataObject'), 'bpmn:DataInput': function(p, element) { var arrowPathData = pathMap.getRawPath('DATA_ARROW'); // page var elementObject = renderer('bpmn:DataObject')(p, element); /* input arrow path */ drawPath(p, arrowPathData, { strokeWidth: 1 }); return elementObject; }, 'bpmn:DataOutput': function(p, element) { var arrowPathData = pathMap.getRawPath('DATA_ARROW'); // page var elementObject = renderer('bpmn:DataObject')(p, element); /* output arrow path */ drawPath(p, arrowPathData, { strokeWidth: 1, fill: 'black' }); return elementObject; }, 'bpmn:DataStoreReference': function(p, element) { var DATA_STORE_PATH = pathMap.getScaledPath('DATA_STORE', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: element.width, containerHeight: element.height, position: { mx: 0, my: 0.133 } }); var elementStore = drawPath(p, DATA_STORE_PATH, { strokeWidth: 2, fill: 'white' }); return elementStore; }, 'bpmn:BoundaryEvent': function(p, element) { var semantic = getSemantic(element), cancel = semantic.cancelActivity; var attrs = { strokeWidth: 1 }; if (!cancel) { attrs.strokeDasharray = '6'; attrs.strokeLinecap = 'round'; } var outer = renderer('bpmn:Event')(p, element, attrs); /* inner path */ drawCircle(p, element.width, element.height, INNER_OUTER_DIST, assign(attrs, { fill: 'none' })); renderEventContent(element, p); return outer; }, 'bpmn:Group': function(p, element) { return drawRect(p, element.width, element.height, TASK_BORDER_RADIUS, { strokeWidth: 1, strokeDasharray: '8,3,1,3', fill: 'none', pointerEvents: 'none' }); }, 'label': function(p, element) { return renderExternalLabel(p, element, ''); }, 'bpmn:TextAnnotation': function(p, element) { var style = { 'fill': 'none', 'stroke': 'none' }; var textElement = drawRect(p, element.width, element.height, 0, 0, style); var textPathData = pathMap.getScaledPath('TEXT_ANNOTATION', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: element.width, containerHeight: element.height, position: { mx: 0.0, my: 0.0 } }); drawPath(p, textPathData); var text = getSemantic(element).text || ''; renderLabel(p, text, { box: element, align: 'left-middle', padding: 5 }); return textElement; }, 'ParticipantMultiplicityMarker': function(p, element) { var subProcessPath = pathMap.getScaledPath('MARKER_PARALLEL', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: element.width, containerHeight: element.height, position: { mx: ((element.width / 2) / element.width), my: (element.height - 15) / element.height } }); drawPath(p, subProcessPath); }, 'SubProcessMarker': function(p, element) { var markerRect = drawRect(p, 14, 14, 0, { strokeWidth: 1 }); // Process marker is placed in the middle of the box // therefore fixed values can be used here markerRect.transform('translate(' + (element.width / 2 - 7.5) + ',' + (element.height - 20) + ')'); var subProcessPath = pathMap.getScaledPath('MARKER_SUB_PROCESS', { xScaleFactor: 1.5, yScaleFactor: 1.5, containerWidth: element.width, containerHeight: element.height, position: { mx: (element.width / 2 - 7.5) / element.width, my: (element.height - 20) / element.height } }); drawPath(p, subProcessPath); }, 'ParallelMarker': function(p, element, position) { var subProcessPath = pathMap.getScaledPath('MARKER_PARALLEL', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: element.width, containerHeight: element.height, position: { mx: ((element.width / 2 + position.parallel) / element.width), my: (element.height - 20) / element.height } }); drawPath(p, subProcessPath); }, 'SequentialMarker': function(p, element, position) { var sequentialPath = pathMap.getScaledPath('MARKER_SEQUENTIAL', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: element.width, containerHeight: element.height, position: { mx: ((element.width / 2 + position.seq) / element.width), my: (element.height - 19) / element.height } }); drawPath(p, sequentialPath); }, 'CompensationMarker': function(p, element, position) { var compensationPath = pathMap.getScaledPath('MARKER_COMPENSATION', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: element.width, containerHeight: element.height, position: { mx: ((element.width / 2 + position.compensation) / element.width), my: (element.height - 13) / element.height } }); drawPath(p, compensationPath, { strokeWidth: 1 }); }, 'LoopMarker': function(p, element, position) { var loopPath = pathMap.getScaledPath('MARKER_LOOP', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: element.width, containerHeight: element.height, position: { mx: ((element.width / 2 + position.loop) / element.width), my: (element.height - 7) / element.height } }); drawPath(p, loopPath, { strokeWidth: 1, fill: 'none', strokeLinecap: 'round', strokeMiterlimit: 0.5 }); }, 'AdhocMarker': function(p, element, position) { var loopPath = pathMap.getScaledPath('MARKER_ADHOC', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: element.width, containerHeight: element.height, position: { mx: ((element.width / 2 + position.adhoc) / element.width), my: (element.height - 15) / element.height } }); drawPath(p, loopPath, { strokeWidth: 1, fill: 'black' }); } }; function attachTaskMarkers(p, element, taskMarkers) { var obj = getSemantic(element); var subprocess = includes(taskMarkers, 'SubProcessMarker'); var position; if (subprocess) { position = { seq: -21, parallel: -22, compensation: -42, loop: -18, adhoc: 10 }; } else { position = { seq: -3, parallel: -6, compensation: -27, loop: 0, adhoc: 10 }; } forEach(taskMarkers, function(marker) { renderer(marker)(p, element, position); }); if (obj.$type === 'bpmn:AdHocSubProcess') { renderer('AdhocMarker')(p, element, position); } if (obj.loopCharacteristics && obj.loopCharacteristics.isSequential === undefined) { renderer('LoopMarker')(p, element, position); return; } if (obj.loopCharacteristics && obj.loopCharacteristics.isSequential !== undefined && !obj.loopCharacteristics.isSequential) { renderer('ParallelMarker')(p, element, position); } if (obj.loopCharacteristics && !!obj.loopCharacteristics.isSequential) { renderer('SequentialMarker')(p, element, position); } if (!!obj.isForCompensation) { renderer('CompensationMarker')(p, element, position); } } function drawShape(parent, element) { var type = element.type; var h = handlers[type]; /* jshint -W040 */ if (!h) { return DefaultRenderer.prototype.drawShape.apply(this, [ parent, element ]); } else { return h(parent, element); } } function drawConnection(parent, element) { var type = element.type; var h = handlers[type]; /* jshint -W040 */ if (!h) { return DefaultRenderer.prototype.drawConnection.apply(this, [ parent, element ]); } else { return h(parent, element); } } function renderDataItemCollection(p, element) { var yPosition = (element.height - 16) / element.height; var pathData = pathMap.getScaledPath('DATA_OBJECT_COLLECTION_PATH', { xScaleFactor: 1, yScaleFactor: 1, containerWidth: element.width, containerHeight: element.height, position: { mx: 0.451, my: yPosition } }); /* collection path */ drawPath(p, pathData, { strokeWidth: 2 }); } function isCollection(element, filter) { return element.isCollection || (element.elementObjectRef && element.elementObjectRef.isCollection); } function getDi(element) { return element.businessObject.di; } function getSemantic(element) { return element.businessObject; } /** * Checks if eventDefinition of the given element matches with semantic type. * * @return {boolean} true if element is of the given semantic type */ function isTypedEvent(event, eventDefinitionType, filter) { function matches(definition, filter) { return every(filter, function(val, key) { // we want a == conversion here, to be able to catch // undefined == false and friends /* jshint -W116 */ return definition[key] == val; }); } return some(event.eventDefinitions, function(definition) { return definition.$type === eventDefinitionType && matches(event, filter); }); } function isThrowEvent(event) { return (event.$type === 'bpmn:IntermediateThrowEvent') || (event.$type === 'bpmn:EndEvent'); } /////// cropping path customizations ///////////////////////// function componentsToPath(elements) { return elements.join(',').replace(/,?([A-z]),?/g, '$1'); } function getCirclePath(shape) { var cx = shape.x + shape.width / 2, cy = shape.y + shape.height / 2, radius = shape.width / 2; var circlePath = [ ['M', cx, cy], ['m', 0, -radius], ['a', radius, radius, 0, 1, 1, 0, 2 * radius], ['a', radius, radius, 0, 1, 1, 0, -2 * radius], ['z'] ]; return componentsToPath(circlePath); } function getRoundRectPath(shape) { var radius = TASK_BORDER_RADIUS, x = shape.x, y = shape.y, width = shape.width, height = shape.height; var roundRectPath = [ ['M', x + radius, y], ['l', width - radius * 2, 0], ['a', radius, radius, 0, 0, 1, radius, radius], ['l', 0, height - radius * 2], ['a', radius, radius, 0, 0, 1, -radius, radius], ['l', radius * 2 - width, 0], ['a', radius, radius, 0, 0, 1, -radius, -radius], ['l', 0, radius * 2 - height], ['a', radius, radius, 0, 0, 1, radius, -radius], ['z'] ]; return componentsToPath(roundRectPath); } function getDiamondPath(shape) { var width = shape.width, height = shape.height, x = shape.x, y = shape.y, halfWidth = width / 2, halfHeight = height / 2; var diamondPath = [ ['M', x + halfWidth, y], ['l', halfWidth, halfHeight], ['l', -halfWidth, halfHeight], ['l', -halfWidth, -halfHeight], ['z'] ]; return componentsToPath(diamondPath); } function getRectPath(shape) { var x = shape.x, y = shape.y, width = shape.width, height = shape.height; var rectPath = [ ['M', x, y], ['l', width, 0], ['l', 0, height], ['l', -width, 0], ['z'] ]; return componentsToPath(rectPath); } function getShapePath(element) { var obj = getSemantic(element); if (obj.$instanceOf('bpmn:Event')) { return getCirclePath(element); } if (obj.$instanceOf('bpmn:Activity')) { return getRoundRectPath(element); } if (obj.$instanceOf('bpmn:Gateway')) { return getDiamondPath(element); } return getRectPath(element); } // hook onto canvas init event to initialize // connection start/end markers on svg events.on('canvas.init', function(event) { initMarkers(event.svg); }); this.drawShape = drawShape; this.drawConnection = drawConnection; this.getShapePath = getShapePath; } inherits(BpmnRenderer, DefaultRenderer); BpmnRenderer.$inject = [ 'eventBus', 'styles', 'pathMap' ]; module.exports = BpmnRenderer; },{"../util/DiUtil":96,"diagram-js/lib/draw/Renderer":148,"diagram-js/lib/util/Text":257,"inherits":126,"lodash/collection/every":298,"lodash/collection/forEach":301,"lodash/collection/includes":303,"lodash/collection/some":308,"lodash/lang/isArray":416,"lodash/lang/isObject":420,"lodash/object/assign":425}],53:[function(require,module,exports){ 'use strict'; var Snap = require('diagram-js/vendor/snapsvg'); /** * Map containing SVG paths needed by BpmnRenderer. */ function PathMap() { /** * Contains a map of path elements * *

    Path definition

    * A parameterized path is defined like this: *
       * 'GATEWAY_PARALLEL': {
       *   d: 'm {mx},{my} {e.x0},0 0,{e.x1} {e.x1},0 0,{e.y0} -{e.x1},0 0,{e.y1} ' +
              '-{e.x0},0 0,-{e.y1} -{e.x1},0 0,-{e.y0} {e.x1},0 z',
       *   height: 17.5,
       *   width:  17.5,
       *   heightElements: [2.5, 7.5],
       *   widthElements: [2.5, 7.5]
       * }
       * 
    *

    It's important to specify a correct height and width for the path as the scaling * is based on the ratio between the specified height and width in this object and the * height and width that is set as scale target (Note x,y coordinates will be scaled with * individual ratios).

    *

    The 'heightElements' and 'widthElements' array must contain the values that will be scaled. * The scaling is based on the computed ratios. * Coordinates on the y axis should be in the heightElement's array, they will be scaled using * the computed ratio coefficient. * In the parameterized path the scaled values can be accessed through the 'e' object in {} brackets. *

      *
    • The values for the y axis can be accessed in the path string using {e.y0}, {e.y1}, ....
    • *
    • The values for the x axis can be accessed in the path string using {e.x0}, {e.x1}, ....
    • *
    * The numbers x0, x1 respectively y0, y1, ... map to the corresponding array index. *

    */ this.pathMap = { 'EVENT_MESSAGE': { d: 'm {mx},{my} l 0,{e.y1} l {e.x1},0 l 0,-{e.y1} z l {e.x0},{e.y0} l {e.x0},-{e.y0}', height: 36, width: 36, heightElements: [6, 14], widthElements: [10.5, 21] }, 'EVENT_SIGNAL': { d: 'M {mx},{my} l {e.x0},{e.y0} l -{e.x1},0 Z', height: 36, width: 36, heightElements: [18], widthElements: [10, 20] }, 'EVENT_ESCALATION': { d: 'm {mx},{my} c -{e.x1},{e.y0} -{e.x3},{e.y1} -{e.x5},{e.y4} {e.x1},-{e.y3} {e.x3},-{e.y5} {e.x5},-{e.y6} ' + '{e.x0},{e.y3} {e.x2},{e.y5} {e.x4},{e.y6} -{e.x0},-{e.y0} -{e.x2},-{e.y1} -{e.x4},-{e.y4} z', height: 36, width: 36, heightElements: [2.382, 4.764, 4.926, 6.589333, 7.146, 13.178667, 19.768], widthElements: [2.463, 2.808, 4.926, 5.616, 7.389, 8.424] }, 'EVENT_CONDITIONAL': { d: 'M {e.x0},{e.y0} l {e.x1},0 l 0,{e.y2} l -{e.x1},0 Z ' + 'M {e.x2},{e.y3} l {e.x0},0 ' + 'M {e.x2},{e.y4} l {e.x0},0 ' + 'M {e.x2},{e.y5} l {e.x0},0 ' + 'M {e.x2},{e.y6} l {e.x0},0 ' + 'M {e.x2},{e.y7} l {e.x0},0 ' + 'M {e.x2},{e.y8} l {e.x0},0 ', height: 36, width: 36, heightElements: [8.5, 14.5, 18, 11.5, 14.5, 17.5, 20.5, 23.5, 26.5], widthElements: [10.5, 14.5, 12.5] }, 'EVENT_LINK': { d: 'm {mx},{my} 0,{e.y0} -{e.x1},0 0,{e.y1} {e.x1},0 0,{e.y0} {e.x0},-{e.y2} -{e.x0},-{e.y2} z', height: 36, width: 36, heightElements: [4.4375, 6.75, 7.8125], widthElements: [9.84375, 13.5] }, 'EVENT_ERROR': { d: 'm {mx},{my} {e.x0},-{e.y0} {e.x1},-{e.y1} {e.x2},{e.y2} {e.x3},-{e.y3} -{e.x4},{e.y4} -{e.x5},-{e.y5} z', height: 36, width: 36, heightElements: [0.023, 8.737, 8.151, 16.564, 10.591, 8.714], widthElements: [0.085, 6.672, 6.97, 4.273, 5.337, 6.636] }, 'EVENT_CANCEL_45': { d: 'm {mx},{my} -{e.x1},0 0,{e.x0} {e.x1},0 0,{e.y1} {e.x0},0 ' + '0,-{e.y1} {e.x1},0 0,-{e.y0} -{e.x1},0 0,-{e.y1} -{e.x0},0 z', height: 36, width: 36, heightElements: [4.75, 8.5], widthElements: [4.75, 8.5] }, 'EVENT_COMPENSATION': { d: 'm {mx},{my} {e.x0},-{e.y0} 0,{e.y1} z m {e.x0},0 {e.x0},-{e.y0} 0,{e.y1} z', height: 36, width: 36, heightElements: [5, 10], widthElements: [10] }, 'EVENT_TIMER_WH': { d: 'M {mx},{my} l {e.x0},-{e.y0} m -{e.x0},{e.y0} l {e.x1},{e.y1} ', height: 36, width: 36, heightElements: [10, 2], widthElements: [3, 7] }, 'EVENT_TIMER_LINE': { d: 'M {mx},{my} ' + 'm {e.x0},{e.y0} l -{e.x1},{e.y1} ', height: 36, width: 36, heightElements: [10, 3], widthElements: [0, 0] }, 'EVENT_MULTIPLE': { d:'m {mx},{my} {e.x1},-{e.y0} {e.x1},{e.y0} -{e.x0},{e.y1} -{e.x2},0 z', height: 36, width: 36, heightElements: [6.28099, 12.56199], widthElements: [3.1405, 9.42149, 12.56198] }, 'EVENT_PARALLEL_MULTIPLE': { d:'m {mx},{my} {e.x0},0 0,{e.y1} {e.x1},0 0,{e.y0} -{e.x1},0 0,{e.y1} ' + '-{e.x0},0 0,-{e.y1} -{e.x1},0 0,-{e.y0} {e.x1},0 z', height: 36, width: 36, heightElements: [2.56228, 7.68683], widthElements: [2.56228, 7.68683] }, 'GATEWAY_EXCLUSIVE': { d:'m {mx},{my} {e.x0},{e.y0} {e.x1},{e.y0} {e.x2},0 {e.x4},{e.y2} ' + '{e.x4},{e.y1} {e.x2},0 {e.x1},{e.y3} {e.x0},{e.y3} ' + '{e.x3},0 {e.x5},{e.y1} {e.x5},{e.y2} {e.x3},0 z', height: 17.5, width: 17.5, heightElements: [8.5, 6.5312, -6.5312, -8.5], widthElements: [6.5, -6.5, 3, -3, 5, -5] }, 'GATEWAY_PARALLEL': { d:'m {mx},{my} 0,{e.y1} -{e.x1},0 0,{e.y0} {e.x1},0 0,{e.y1} {e.x0},0 ' + '0,-{e.y1} {e.x1},0 0,-{e.y0} -{e.x1},0 0,-{e.y1} -{e.x0},0 z', height: 30, width: 30, heightElements: [5, 12.5], widthElements: [5, 12.5] }, 'GATEWAY_EVENT_BASED': { d:'m {mx},{my} {e.x0},{e.y0} {e.x0},{e.y1} {e.x1},{e.y2} {e.x2},0 z', height: 11, width: 11, heightElements: [-6, 6, 12, -12], widthElements: [9, -3, -12] }, 'GATEWAY_COMPLEX': { d:'m {mx},{my} 0,{e.y0} -{e.x0},-{e.y1} -{e.x1},{e.y2} {e.x0},{e.y1} -{e.x2},0 0,{e.y3} ' + '{e.x2},0 -{e.x0},{e.y1} l {e.x1},{e.y2} {e.x0},-{e.y1} 0,{e.y0} {e.x3},0 0,-{e.y0} {e.x0},{e.y1} ' + '{e.x1},-{e.y2} -{e.x0},-{e.y1} {e.x2},0 0,-{e.y3} -{e.x2},0 {e.x0},-{e.y1} -{e.x1},-{e.y2} ' + '-{e.x0},{e.y1} 0,-{e.y0} -{e.x3},0 z', height: 17.125, width: 17.125, heightElements: [4.875, 3.4375, 2.125, 3], widthElements: [3.4375, 2.125, 4.875, 3] }, 'DATA_OBJECT_PATH': { d:'m 0,0 {e.x1},0 {e.x0},{e.y0} 0,{e.y1} -{e.x2},0 0,-{e.y2} {e.x1},0 0,{e.y0} {e.x0},0', height: 61, width: 51, heightElements: [10, 50, 60], widthElements: [10, 40, 50, 60] }, 'DATA_OBJECT_COLLECTION_PATH': { d:'m {mx}, {my} ' + 'm 0 15 l 0 -15 ' + 'm 4 15 l 0 -15 ' + 'm 4 15 l 0 -15 ', height: 61, width: 51, heightElements: [12], widthElements: [1, 6, 12, 15] }, 'DATA_ARROW': { d:'m 5,9 9,0 0,-3 5,5 -5,5 0,-3 -9,0 z', height: 61, width: 51, heightElements: [], widthElements: [] }, 'DATA_STORE': { d:'m {mx},{my} ' + 'l 0,{e.y2} ' + 'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0 ' + 'l 0,-{e.y2} ' + 'c -{e.x0},-{e.y1} -{e.x1},-{e.y1} -{e.x2},0' + 'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0 ' + 'm -{e.x2},{e.y0}' + 'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0' + 'm -{e.x2},{e.y0}' + 'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0', height: 61, width: 61, heightElements: [7, 10, 45], widthElements: [2, 58, 60] }, 'TEXT_ANNOTATION': { d: 'm {mx}, {my} m 10,0 l -10,0 l 0,{e.y0} l 10,0', height: 30, width: 10, heightElements: [30], widthElements: [10] }, 'MARKER_SUB_PROCESS': { d: 'm{mx},{my} m 7,2 l 0,10 m -5,-5 l 10,0', height: 10, width: 10, heightElements: [], widthElements: [] }, 'MARKER_PARALLEL': { d: 'm{mx},{my} m 3,2 l 0,10 m 3,-10 l 0,10 m 3,-10 l 0,10', height: 10, width: 10, heightElements: [], widthElements: [] }, 'MARKER_SEQUENTIAL': { d: 'm{mx},{my} m 0,3 l 10,0 m -10,3 l 10,0 m -10,3 l 10,0', height: 10, width: 10, heightElements: [], widthElements: [] }, 'MARKER_COMPENSATION': { d: 'm {mx},{my} 8,-5 0,10 z m 9,0 8,-5 0,10 z', height: 10, width: 21, heightElements: [], widthElements: [] }, 'MARKER_LOOP': { d: 'm {mx},{my} c 3.526979,0 6.386161,-2.829858 6.386161,-6.320661 0,-3.490806 -2.859182,-6.320661 ' + '-6.386161,-6.320661 -3.526978,0 -6.38616,2.829855 -6.38616,6.320661 0,1.745402 ' + '0.714797,3.325567 1.870463,4.469381 0.577834,0.571908 1.265885,1.034728 2.029916,1.35457 ' + 'l -0.718163,-3.909793 m 0.718163,3.909793 -3.885211,0.802902', height: 13.9, width: 13.7, heightElements: [], widthElements: [] }, 'MARKER_ADHOC': { d: 'm {mx},{my} m 0.84461,2.64411 c 1.05533,-1.23780996 2.64337,-2.07882 4.29653,-1.97997996 2.05163,0.0805 ' + '3.85579,1.15803 5.76082,1.79107 1.06385,0.34139996 2.24454,0.1438 3.18759,-0.43767 0.61743,-0.33642 ' + '1.2775,-0.64078 1.7542,-1.17511 0,0.56023 0,1.12046 0,1.6807 -0.98706,0.96237996 -2.29792,1.62393996 ' + '-3.6918,1.66181996 -1.24459,0.0927 -2.46671,-0.2491 -3.59505,-0.74812 -1.35789,-0.55965 ' + '-2.75133,-1.33436996 -4.27027,-1.18121996 -1.37741,0.14601 -2.41842,1.13685996 -3.44288,1.96782996 z', height: 4, width: 15, heightElements: [], widthElements: [] }, 'TASK_TYPE_SEND': { d: 'm {mx},{my} l 0,{e.y1} l {e.x1},0 l 0,-{e.y1} z l {e.x0},{e.y0} l {e.x0},-{e.y0}', height: 14, width: 21, heightElements: [6, 14], widthElements: [10.5, 21] }, 'TASK_TYPE_SCRIPT': { d: 'm {mx},{my} c 9.966553,-6.27276 -8.000926,-7.91932 2.968968,-14.938 l -8.802728,0 ' + 'c -10.969894,7.01868 6.997585,8.66524 -2.968967,14.938 z ' + 'm -7,-12 l 5,0 ' + 'm -4.5,3 l 4.5,0 ' + 'm -3,3 l 5,0' + 'm -4,3 l 5,0', height: 15, width: 12.6, heightElements: [6, 14], widthElements: [10.5, 21] }, 'TASK_TYPE_USER_1': { d: 'm {mx},{my} c 0.909,-0.845 1.594,-2.049 1.594,-3.385 0,-2.554 -1.805,-4.62199999 ' + '-4.357,-4.62199999 -2.55199998,0 -4.28799998,2.06799999 -4.28799998,4.62199999 0,1.348 ' + '0.974,2.562 1.89599998,3.405 -0.52899998,0.187 -5.669,2.097 -5.794,4.7560005 v 6.718 ' + 'h 17 v -6.718 c 0,-2.2980005 -5.5279996,-4.5950005 -6.0509996,-4.7760005 z' + 'm -8,6 l 0,5.5 m 11,0 l 0,-5' }, 'TASK_TYPE_USER_2': { d: 'm {mx},{my} m 2.162,1.009 c 0,2.4470005 -2.158,4.4310005 -4.821,4.4310005 ' + '-2.66499998,0 -4.822,-1.981 -4.822,-4.4310005 ' }, 'TASK_TYPE_USER_3': { d: 'm {mx},{my} m -6.9,-3.80 c 0,0 2.25099998,-2.358 4.27399998,-1.177 2.024,1.181 4.221,1.537 ' + '4.124,0.965 -0.098,-0.57 -0.117,-3.79099999 -4.191,-4.13599999 -3.57499998,0.001 ' + '-4.20799998,3.36699999 -4.20699998,4.34799999 z' }, 'TASK_TYPE_MANUAL': { d: 'm {mx},{my} c 0.234,-0.01 5.604,0.008 8.029,0.004 0.808,0 1.271,-0.172 1.417,-0.752 0.227,-0.898 ' + '-0.334,-1.314 -1.338,-1.316 -2.467,-0.01 -7.886,-0.004 -8.108,-0.004 -0.014,-0.079 0.016,-0.533 0,-0.61 ' + '0.195,-0.042 8.507,0.006 9.616,0.002 0.877,-0.007 1.35,-0.438 1.353,-1.208 0.003,-0.768 -0.479,-1.09 ' + '-1.35,-1.091 -2.968,-0.002 -9.619,-0.013 -9.619,-0.013 v -0.591 c 0,0 5.052,-0.016 7.225,-0.016 ' + '0.888,-0.002 1.354,-0.416 1.351,-1.193 -0.006,-0.761 -0.492,-1.196 -1.361,-1.196 -3.473,-0.005 ' + '-10.86,-0.003 -11.0829995,-0.003 -0.022,-0.047 -0.045,-0.094 -0.069,-0.139 0.3939995,-0.319 ' + '2.0409995,-1.626 2.4149995,-2.017 0.469,-0.4870005 0.519,-1.1650005 0.162,-1.6040005 -0.414,-0.511 ' + '-0.973,-0.5 -1.48,-0.236 -1.4609995,0.764 -6.5999995,3.6430005 -7.7329995,4.2710005 -0.9,0.499 ' + '-1.516,1.253 -1.882,2.19 -0.37000002,0.95 -0.17,2.01 -0.166,2.979 0.004,0.718 -0.27300002,1.345 ' + '-0.055,2.063 0.629,2.087 2.425,3.312 4.859,3.318 4.6179995,0.014 9.2379995,-0.139 13.8569995,-0.158 ' + '0.755,-0.004 1.171,-0.301 1.182,-1.033 0.012,-0.754 -0.423,-0.969 -1.183,-0.973 -1.778,-0.01 ' + '-5.824,-0.004 -6.04,-0.004 10e-4,-0.084 0.003,-0.586 10e-4,-0.67 z' }, 'TASK_TYPE_INSTANTIATING_SEND': { d: 'm {mx},{my} l 0,8.4 l 12.6,0 l 0,-8.4 z l 6.3,3.6 l 6.3,-3.6' }, 'TASK_TYPE_SERVICE': { d: 'm {mx},{my} v -1.71335 c 0.352326,-0.0705 0.703932,-0.17838 1.047628,-0.32133 ' + '0.344416,-0.14465 0.665822,-0.32133 0.966377,-0.52145 l 1.19431,1.18005 1.567487,-1.57688 ' + '-1.195028,-1.18014 c 0.403376,-0.61394 0.683079,-1.29908 0.825447,-2.01824 l 1.622133,-0.01 ' + 'v -2.2196 l -1.636514,0.01 c -0.07333,-0.35153 -0.178319,-0.70024 -0.323564,-1.04372 ' + '-0.145244,-0.34406 -0.321407,-0.6644 -0.522735,-0.96217 l 1.131035,-1.13631 -1.583305,-1.56293 ' + '-1.129598,1.13589 c -0.614052,-0.40108 -1.302883,-0.68093 -2.022633,-0.82247 l 0.0093,-1.61852 ' + 'h -2.241173 l 0.0042,1.63124 c -0.353763,0.0736 -0.705369,0.17977 -1.049785,0.32371 -0.344415,0.14437 ' + '-0.665102,0.32092 -0.9635006,0.52046 l -1.1698628,-1.15823 -1.5667691,1.5792 1.1684265,1.15669 ' + 'c -0.4026573,0.61283 -0.68308,1.29797 -0.8247287,2.01713 l -1.6588041,0.003 v 2.22174 ' + 'l 1.6724648,-0.006 c 0.073327,0.35077 0.1797598,0.70243 0.3242851,1.04472 0.1452428,0.34448 ' + '0.3214064,0.6644 0.5227339,0.96066 l -1.1993431,1.19723 1.5840256,1.56011 1.1964668,-1.19348 ' + 'c 0.6140517,0.40346 1.3028827,0.68232 2.0233517,0.82331 l 7.19e-4,1.69892 h 2.226848 z ' + 'm 0.221462,-3.9957 c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' + '0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' + '0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z' }, 'TASK_TYPE_SERVICE_FILL': { d: 'm {mx},{my} c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' + '0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' + '0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z' }, 'TASK_TYPE_BUSINESS_RULE_HEADER': { d: 'm {mx},{my} 0,4 20,0 0,-4 z' }, 'TASK_TYPE_BUSINESS_RULE_MAIN': { d: 'm {mx},{my} 0,12 20,0 0,-12 z' + 'm 0,8 l 20,0 ' + 'm -13,-4 l 0,8' }, 'MESSAGE_FLOW_MARKER': { d: 'm {mx},{my} m -10.5 ,-7 l 0,14 l 21,0 l 0,-14 z l 10.5,6 l 10.5,-6' } }; this.getRawPath = function getRawPath(pathId) { return this.pathMap[pathId].d; }; /** * Scales the path to the given height and width. *

    Use case

    *

    Use case is to scale the content of elements (event, gateways) based * on the element bounding box's size. *

    *

    Why not transform

    *

    Scaling a path with transform() will also scale the stroke and IE does not support * the option 'non-scaling-stroke' to prevent this. * Also there are use cases where only some parts of a path should be * scaled.

    * * @param {String} pathId The ID of the path. * @param {Object} param

    * Example param object scales the path to 60% size of the container (data.width, data.height). *

       *   {
       *     xScaleFactor: 0.6,
       *     yScaleFactor:0.6,
       *     containerWidth: data.width,
       *     containerHeight: data.height,
       *     position: {
       *       mx: 0.46,
       *       my: 0.2,
       *     }
       *   }
       *   
    *
      *
    • targetpathwidth = xScaleFactor * containerWidth
    • *
    • targetpathheight = yScaleFactor * containerHeight
    • *
    • Position is used to set the starting coordinate of the path. M is computed: *
        *
      • position.x * containerWidth
      • *
      • position.y * containerHeight
      • *
      * Center of the container
       position: {
         *       mx: 0.5,
         *       my: 0.5,
         *     }
      * Upper left corner of the container *
       position: {
         *       mx: 0.0,
         *       my: 0.0,
         *     }
      *
    • *
    *

    * */ this.getScaledPath = function getScaledPath(pathId, param) { var rawPath = this.pathMap[pathId]; // positioning // compute the start point of the path var mx, my; if(!!param.abspos) { mx = param.abspos.x; my = param.abspos.y; } else { mx = param.containerWidth * param.position.mx; my = param.containerHeight * param.position.my; } var coordinates = {}; //map for the scaled coordinates if(param.position) { // path var heightRatio = (param.containerHeight / rawPath.height) * param.yScaleFactor; var widthRatio = (param.containerWidth / rawPath.width) * param.xScaleFactor; //Apply height ratio for (var heightIndex = 0; heightIndex < rawPath.heightElements.length; heightIndex++) { coordinates['y' + heightIndex] = rawPath.heightElements[heightIndex] * heightRatio; } //Apply width ratio for (var widthIndex = 0; widthIndex < rawPath.widthElements.length; widthIndex++) { coordinates['x' + widthIndex] = rawPath.widthElements[widthIndex] * widthRatio; } } //Apply value to raw path var path = Snap.format( rawPath.d, { mx: mx, my: my, e: coordinates } ); return path; }; } module.exports = PathMap; },{"diagram-js/vendor/snapsvg":287}],54:[function(require,module,exports){ module.exports = { renderer: [ 'type', require('./BpmnRenderer') ], pathMap: [ 'type', require('./PathMap') ] }; },{"./BpmnRenderer":52,"./PathMap":53}],55:[function(require,module,exports){ 'use strict'; var assign = require('lodash/object/assign'), forEach = require('lodash/collection/forEach'), is = require('../../util/ModelUtil').is; /** * A provider for BPMN 2.0 elements context pad */ function ContextPadProvider(contextPad, modeling, elementFactory, connect, create, bpmnReplace, canvas) { contextPad.registerProvider(this); this._contextPad = contextPad; this._modeling = modeling; this._elementFactory = elementFactory; this._connect = connect; this._create = create; this._bpmnReplace = bpmnReplace; this._canvas = canvas; } ContextPadProvider.$inject = [ 'contextPad', 'modeling', 'elementFactory', 'connect', 'create', 'bpmnReplace', 'canvas' ]; ContextPadProvider.prototype.getContextPadEntries = function(element) { var contextPad = this._contextPad, modeling = this._modeling, elementFactory = this._elementFactory, connect = this._connect, create = this._create, bpmnReplace = this._bpmnReplace, canvas = this._canvas; var actions = {}; if (element.type === 'label') { return actions; } var bpmnElement = element.businessObject; function startConnect(event, element, autoActivate) { connect.start(event, element, autoActivate); } function removeElement(e) { if (element.waypoints) { modeling.removeConnection(element); } else { modeling.removeShape(element); } } function getReplaceMenuPosition(element) { var Y_OFFSET = 5; var diagramContainer = canvas.getContainer(), pad = contextPad.getPad(element).html; var diagramRect = diagramContainer.getBoundingClientRect(), padRect = pad.getBoundingClientRect(); var top = padRect.top - diagramRect.top; var left = padRect.left - diagramRect.left; var pos = { x: left, y: top + padRect.height + Y_OFFSET }; return pos; } function appendAction(type, className, options) { function appendListener(event, element) { var shape = elementFactory.createShape(assign({ type: type }, options)); create.start(event, shape, element); } var shortType = type.replace(/^bpmn\:/, ''); return { group: 'model', className: className, title: 'Append ' + shortType, action: { dragstart: appendListener, click: appendListener } }; } if (is(bpmnElement, 'bpmn:FlowNode')) { if (!is(bpmnElement, 'bpmn:EndEvent') && !is(bpmnElement, 'bpmn:EventBasedGateway') && !isEventType(bpmnElement, 'bpmn:IntermediateThrowEvent', 'bpmn:LinkEventDefinition')) { assign(actions, { 'append.end-event': appendAction('bpmn:EndEvent', 'icon-end-event-none'), 'append.gateway': appendAction('bpmn:ExclusiveGateway', 'icon-gateway-xor'), 'append.append-task': appendAction('bpmn:Task', 'icon-task'), 'append.intermediate-event': appendAction('bpmn:IntermediateThrowEvent', 'icon-intermediate-event-none') }); } if (is(bpmnElement, 'bpmn:EventBasedGateway')) { assign(actions, { 'append.receive-task': appendAction('bpmn:ReceiveTask', 'icon-receive-task'), 'append.message-intermediate-event': appendAction('bpmn:IntermediateCatchEvent', 'icon-intermediate-event-catch-message', { _eventDefinitionType: 'bpmn:MessageEventDefinition'}), 'append.timer-intermediate-event': appendAction('bpmn:IntermediateCatchEvent', 'icon-intermediate-event-catch-timer', { _eventDefinitionType: 'bpmn:TimerEventDefinition'}), 'append.condtion-intermediate-event': appendAction('bpmn:IntermediateCatchEvent', 'icon-intermediate-event-catch-condition', { _eventDefinitionType: 'bpmn:ConditionalEventDefinition'}), 'append.signal-intermediate-event': appendAction('bpmn:IntermediateCatchEvent', 'icon-intermediate-event-catch-signal', { _eventDefinitionType: 'bpmn:SignalEventDefinition'}) }); } // Replace menu entry assign(actions, { 'replace': { group: 'edit', className: 'icon-screw-wrench', title: 'Change type', action: { click: function(event, element) { bpmnReplace.openChooser(getReplaceMenuPosition(element), element); } } } }); } if (is(bpmnElement, 'bpmn:FlowNode') || is(bpmnElement, 'bpmn:InteractionNode')) { assign(actions, { 'append.text-annotation': appendAction('bpmn:TextAnnotation', 'icon-text-annotation'), 'connect': { group: 'connect', className: 'icon-connection-multi', title: 'Connect using Sequence/MessageFlow', action: { click: startConnect, dragstart: startConnect } } }); } // Delete Element Entry assign(actions, { 'delete': { group: 'edit', className: 'icon-trash', title: 'Remove', action: { click: removeElement, dragstart: removeElement } } }); return actions; }; function isEventType(eventBo, type, definition) { var isType = eventBo.$instanceOf(type); var isDefinition = false; var definitions = eventBo.eventDefinitions || []; forEach(definitions, function(def) { if (def.$type === definition) { isDefinition = true; } }); return isType && isDefinition; } module.exports = ContextPadProvider; },{"../../util/ModelUtil":98,"lodash/collection/forEach":301,"lodash/object/assign":425}],56:[function(require,module,exports){ module.exports = { __depends__: [ require('diagram-js-direct-editing'), require('diagram-js/lib/features/context-pad'), require('diagram-js/lib/features/selection'), require('diagram-js/lib/features/connect'), require('diagram-js/lib/features/create'), require('../replace') ], __init__: [ 'contextPadProvider' ], contextPadProvider: [ 'type', require('./ContextPadProvider') ] }; },{"../replace":87,"./ContextPadProvider":55,"diagram-js-direct-editing":121,"diagram-js/lib/features/connect":161,"diagram-js/lib/features/context-pad":163,"diagram-js/lib/features/create":165,"diagram-js/lib/features/selection":220}],57:[function(require,module,exports){ 'use strict'; function BpmnKeyBindings( keyboard, spaceTool, lassoTool, directEditing, selection, canvas, elementRegistry) { keyboard.addListener(function(key, modifiers) { // ctrl + a -> select all elements if (key === 65 && keyboard.isCmd(modifiers)) { // select all elements except for the invisible // root element var rootElement = canvas.getRootElement(); var elements = elementRegistry.filter(function(element) { return element != rootElement; }); selection.select(elements); return true; } if (keyboard.hasModifier(modifiers)) { return; } // s -> activate space tool if (key === 83) { spaceTool.activateSelection(); return true; } // l -> activate lasso tool if (key === 76) { lassoTool.activateSelection(); return true; } var currentSelection = selection.get(); // e -> activate direct editing if (key === 69) { if (currentSelection.length) { directEditing.activate(currentSelection[0]); } return true; } }); } BpmnKeyBindings.$inject = [ 'keyboard', 'spaceTool', 'lassoTool', 'directEditing', 'selection', 'canvas', 'elementRegistry' ]; module.exports = BpmnKeyBindings; },{}],58:[function(require,module,exports){ module.exports = { __depends__: [ require('diagram-js/lib/features/keyboard') ], __init__: [ 'bpmnKeyBindings' ], bpmnKeyBindings: [ 'type', require('./BpmnKeyBindings') ] }; },{"./BpmnKeyBindings":57,"diagram-js/lib/features/keyboard":171}],59:[function(require,module,exports){ 'use strict'; var UpdateLabelHandler = require('./cmd/UpdateLabelHandler'); var LabelUtil = require('./LabelUtil'); var is = require('../../util/ModelUtil').is, isExpanded = require('../../util/DiUtil').isExpanded; var MIN_BOUNDS = { width: 150, height: 50 }; function LabelEditingProvider(eventBus, canvas, directEditing, commandStack, injector) { directEditing.registerProvider(this); commandStack.registerHandler('element.updateLabel', UpdateLabelHandler); // listen to dblclick on non-root elements eventBus.on('element.dblclick', function(event) { directEditing.activate(event.element); }); // complete on followup canvas operation eventBus.on([ 'element.mousedown', 'drag.activate', 'canvas.viewbox.changed' ], function(event) { directEditing.complete(); }); // cancel on command stack changes eventBus.on([ 'commandStack.changed' ], function() { directEditing.cancel(); }); // activate direct editing for activities and text annotations if ('ontouchstart' in document.documentElement) { // we deactivate automatic label editing on mobile devices // as it breaks the user interaction workflow // TODO(nre): we should temporarily focus the edited element here // and release the focused viewport after the direct edit operation is finished } else { eventBus.on('create.end', 500, function(e) { var element = e.shape, canExecute = e.context.canExecute; if (!canExecute) { return; } if (is(element, 'bpmn:Task') || is(element, 'bpmn:TextAnnotation') || (is(element, 'bpmn:SubProcess') && !isExpanded(element))) { directEditing.activate(element); } }); } this._canvas = canvas; this._commandStack = commandStack; } LabelEditingProvider.$inject = [ 'eventBus', 'canvas', 'directEditing', 'commandStack', 'injector' ]; module.exports = LabelEditingProvider; LabelEditingProvider.prototype.activate = function(element) { var text = LabelUtil.getLabel(element); if (text === undefined) { return; } var bbox = this.getEditingBBox(element); // adjust for expanded pools AND lanes if ((is(element, 'bpmn:Participant') && isExpanded(element)) || is(element, 'bpmn:Lane')) { bbox.width = MIN_BOUNDS.width; bbox.height = MIN_BOUNDS.height; bbox.x = bbox.x + 10 - bbox.width / 2; bbox.y = bbox.mid.y - bbox.height / 2; } // adjust for expanded sub processes if (is(element, 'bpmn:SubProcess') && isExpanded(element)) { bbox.height = MIN_BOUNDS.height; bbox.x = bbox.mid.x - bbox.width / 2; bbox.y = bbox.y + 10 - bbox.height / 2; } return { bounds: bbox, text: text }; }; LabelEditingProvider.prototype.getEditingBBox = function(element, maxBounds) { var target = element.label || element; var bbox = this._canvas.getAbsoluteBBox(target); var mid = { x: bbox.x + bbox.width / 2, y: bbox.y + bbox.height / 2 }; // external label if (target.labelTarget) { bbox.width = Math.max(bbox.width, MIN_BOUNDS.width); bbox.height = Math.max(bbox.height, MIN_BOUNDS.height); bbox.x = mid.x - bbox.width / 2; } bbox.mid = mid; return bbox; }; LabelEditingProvider.prototype.update = function(element, newLabel) { this._commandStack.execute('element.updateLabel', { element: element, newLabel: newLabel }); }; },{"../../util/DiUtil":96,"../../util/ModelUtil":98,"./LabelUtil":60,"./cmd/UpdateLabelHandler":61}],60:[function(require,module,exports){ 'use strict'; function getLabelAttr(semantic) { if (semantic.$instanceOf('bpmn:FlowElement') || semantic.$instanceOf('bpmn:Participant') || semantic.$instanceOf('bpmn:Lane') || semantic.$instanceOf('bpmn:SequenceFlow') || semantic.$instanceOf('bpmn:MessageFlow')) { return 'name'; } if (semantic.$instanceOf('bpmn:TextAnnotation')) { return 'text'; } } module.exports.getLabel = function(element) { var semantic = element.businessObject, attr = getLabelAttr(semantic); if (attr) { return semantic[attr] || ''; } }; module.exports.setLabel = function(element, text) { var semantic = element.businessObject, attr = getLabelAttr(semantic); if (attr) { semantic[attr] = text; } var label = element.label || element; // show label label.hidden = false; return label; }; },{}],61:[function(require,module,exports){ 'use strict'; var LabelUtil = require('../LabelUtil'); /** * A handler that updates the text of a BPMN element. * * @param {EventBus} eventBus */ function UpdateTextHandler(eventBus) { function setText(element, text) { var label = LabelUtil.setLabel(element, text); eventBus.fire('element.changed', { element: label }); } function execute(ctx) { ctx.oldLabel = LabelUtil.getLabel(ctx.element); return setText(ctx.element, ctx.newLabel); } function revert(ctx) { return setText(ctx.element, ctx.oldLabel); } function canExecute(ctx) { return true; } // API this.execute = execute; this.revert = revert; this.canExecute = canExecute; } UpdateTextHandler.$inject = [ 'eventBus' ]; module.exports = UpdateTextHandler; },{"../LabelUtil":60}],62:[function(require,module,exports){ module.exports = { __depends__: [ require('diagram-js/lib/command'), require('diagram-js/lib/features/change-support'), require('diagram-js-direct-editing') ], __init__: [ 'labelEditingProvider' ], labelEditingProvider: [ 'type', require('./LabelEditingProvider') ] }; },{"./LabelEditingProvider":59,"diagram-js-direct-editing":121,"diagram-js/lib/command":141,"diagram-js/lib/features/change-support":159}],63:[function(require,module,exports){ 'use strict'; var map = require('lodash/collection/map'), assign = require('lodash/object/assign'), pick = require('lodash/object/pick'); function BpmnFactory(moddle) { this._model = moddle; } BpmnFactory.$inject = [ 'moddle' ]; BpmnFactory.prototype._needsId = function(element) { return element.$instanceOf('bpmn:RootElement') || element.$instanceOf('bpmn:FlowElement') || element.$instanceOf('bpmn:MessageFlow') || element.$instanceOf('bpmn:Artifact') || element.$instanceOf('bpmn:Participant') || element.$instanceOf('bpmn:Process') || element.$instanceOf('bpmn:Collaboration') || element.$instanceOf('bpmndi:BPMNShape') || element.$instanceOf('bpmndi:BPMNEdge') || element.$instanceOf('bpmndi:BPMNDiagram') || element.$instanceOf('bpmndi:BPMNPlane'); }; BpmnFactory.prototype._ensureId = function(element) { // generate semantic ids for elements // bpmn:SequenceFlow -> SequenceFlow_ID var prefix = (element.$type || '').replace(/^[^:]*:/g, '') + '_'; if (!element.id && this._needsId(element)) { element.id = this._model.ids.nextPrefixed(prefix, element); } }; BpmnFactory.prototype.create = function(type, attrs) { var element = this._model.create(type, attrs || {}); this._ensureId(element); return element; }; BpmnFactory.prototype.createDiLabel = function() { return this.create('bpmndi:BPMNLabel', { bounds: this.createDiBounds() }); }; BpmnFactory.prototype.createDiShape = function(semantic, bounds, attrs) { return this.create('bpmndi:BPMNShape', assign({ bpmnElement: semantic, bounds: this.createDiBounds(bounds) }, attrs)); }; BpmnFactory.prototype.createDiBounds = function(bounds) { return this.create('dc:Bounds', bounds); }; BpmnFactory.prototype.createDiWaypoints = function(waypoints) { return map(waypoints, function(pos) { return this.createDiWaypoint(pos); }, this); }; BpmnFactory.prototype.createDiWaypoint = function(point) { return this.create('dc:Point', pick(point, [ 'x', 'y' ])); }; BpmnFactory.prototype.createDiEdge = function(semantic, waypoints, attrs) { return this.create('bpmndi:BPMNEdge', assign({ bpmnElement: semantic }, attrs)); }; BpmnFactory.prototype.createDiPlane = function(semantic) { return this.create('bpmndi:BPMNPlane', { bpmnElement: semantic }); }; module.exports = BpmnFactory; },{"lodash/collection/map":305,"lodash/object/assign":425,"lodash/object/pick":431}],64:[function(require,module,exports){ 'use strict'; var assign = require('lodash/object/assign'), inherits = require('inherits'); var LabelUtil = require('../../util/LabelUtil'); var hasExternalLabel = LabelUtil.hasExternalLabel, getExternalLabelMid = LabelUtil.getExternalLabelMid; var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); function LabelSupport(eventBus, modeling, bpmnFactory) { CommandInterceptor.call(this, eventBus); // create external labels on shape creation this.postExecute([ 'shape.create', 'connection.create' ], function(e) { var context = e.context; var element = context.shape || context.connection, businessObject = element.businessObject; var position; if (hasExternalLabel(businessObject)) { position = getExternalLabelMid(element); modeling.createLabel(element, position, { id: businessObject.id + '_label', businessObject: businessObject }); } }); // update di information on label movement and creation this.executed([ 'label.create', 'shape.moved' ], function(e) { var element = e.context.shape, businessObject = element.businessObject, di = businessObject.di; // we want to trigger on real labels only if (!element.labelTarget) { return; } if (!di.label) { di.label = bpmnFactory.create('bpmndi:BPMNLabel', { bounds: bpmnFactory.create('dc:Bounds') }); } assign(di.label.bounds, { x: element.x, y: element.y, width: element.width, height: element.height }); }); } inherits(LabelSupport, CommandInterceptor); LabelSupport.$inject = [ 'eventBus', 'modeling', 'bpmnFactory' ]; module.exports = LabelSupport; },{"../../util/LabelUtil":97,"diagram-js/lib/command/CommandInterceptor":139,"inherits":126,"lodash/object/assign":425}],65:[function(require,module,exports){ 'use strict'; var inherits = require('inherits'); var assign = require('lodash/object/assign'); var BaseLayouter = require('diagram-js/lib/layout/BaseLayouter'), ManhattanLayout = require('diagram-js/lib/layout/ManhattanLayout'); var LayoutUtil = require('diagram-js/lib/layout/LayoutUtil'); var getMid = LayoutUtil.getMid, getOrientation = LayoutUtil.getOrientation; var is = require('../../util/ModelUtil').is; function BpmnLayouter() {} inherits(BpmnLayouter, BaseLayouter); module.exports = BpmnLayouter; BpmnLayouter.prototype.layoutConnection = function(connection, layoutHints) { var source = connection.source, target = connection.target, waypoints = connection.waypoints, start, end; var manhattanOptions, updatedWaypoints; start = getConnectionDocking(waypoints, 0, source); end = getConnectionDocking(waypoints, waypoints && waypoints.length - 1, target); // TODO (nre): support vertical modeling // and invert preferredLayouts accordingly // manhattan layout sequence / message flows if (is(connection, 'bpmn:MessageFlow')) { manhattanOptions = { preferredLayouts: [ 'straight', 'v:v' ] }; } else // layout all connection between flow elements h:h, // // except for // // (1) outgoing of BoundaryEvents -> layout h:v or v:h based on attach orientation // (2) incoming / outgoing of Gateway -> v:h (outgoing), h:v (incoming) // if (is(connection, 'bpmn:SequenceFlow')) { // make sure boundary event connections do // not look ugly =:> if (is(source, 'bpmn:BoundaryEvent')) { var orientation = getAttachOrientation(source); if (/left|right/.test(orientation)) { manhattanOptions = { preferredLayouts: [ 'h:v' ] }; } else if (/top|bottom/.test(orientation)) { manhattanOptions = { preferredLayouts: [ 'v:h' ] }; } } else if (is(source, 'bpmn:Gateway')) { manhattanOptions = { preferredLayouts: [ 'v:h' ] }; } else if (is(target, 'bpmn:Gateway')) { manhattanOptions = { preferredLayouts: [ 'h:v' ] }; } // apply horizontal love <3 else { manhattanOptions = { preferredLayouts: [ 'h:h' ] }; } } if (manhattanOptions) { manhattanOptions = assign(manhattanOptions, layoutHints); updatedWaypoints = ManhattanLayout.repairConnection( source, target, start, end, waypoints, manhattanOptions); } return updatedWaypoints || [ start, end ]; }; function getAttachOrientation(attachedElement) { var hostElement = attachedElement.host, padding = -10; return getOrientation(getMid(attachedElement), hostElement, padding); } function getConnectionDocking(waypoints, idx, shape) { var point = waypoints && waypoints[idx]; return point ? (point.original || point) : getMid(shape); } },{"../../util/ModelUtil":98,"diagram-js/lib/layout/BaseLayouter":233,"diagram-js/lib/layout/LayoutUtil":235,"diagram-js/lib/layout/ManhattanLayout":236,"inherits":126,"lodash/object/assign":425}],66:[function(require,module,exports){ 'use strict'; var assign = require('lodash/object/assign'), forEach = require('lodash/collection/forEach'), inherits = require('inherits'); var Collections = require('diagram-js/lib/util/Collections'), Model = require('diagram-js/lib/model'); var getBusinessObject = require('../../util/ModelUtil').getBusinessObject, is = require('../../util/ModelUtil').is; var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); /** * A handler responsible for updating the underlying BPMN 2.0 XML + DI * once changes on the diagram happen */ function BpmnUpdater(eventBus, bpmnFactory, connectionDocking) { CommandInterceptor.call(this, eventBus); this._bpmnFactory = bpmnFactory; var self = this; ////// connection cropping ///////////////////////// // crop connection ends during create/update function cropConnection(e) { var context = e.context, connection; if (!context.cropped) { connection = context.connection; connection.waypoints = connectionDocking.getCroppedWaypoints(connection); context.cropped = true; } } this.executed([ 'connection.layout', 'connection.create', 'connection.reconnectEnd', 'connection.reconnectStart' ], cropConnection); this.reverted([ 'connection.layout' ], function(e) { delete e.context.cropped; }); ////// BPMN + DI update ///////////////////////// // update parent function updateParent(e) { self.updateParent(e.context.shape || e.context.connection); } this.executed([ 'shape.move', 'shape.create', 'shape.delete', 'connection.create', 'connection.move', 'connection.delete' ], updateParent); this.reverted([ 'shape.move', 'shape.create', 'shape.delete', 'connection.create', 'connection.move', 'connection.delete' ], updateParent); /* * ## Updating Parent * * When morphing a Process into a Collaboration or vice-versa, * make sure that both the *semantic* and *di* parent of each element * is updated. * */ function updateRoot(event) { var context = event.context, oldRoot = context.oldRoot, children = oldRoot.children; forEach(children, function(child) { self.updateParent(child); }); } this.executed([ 'canvas.updateRoot' ], updateRoot); this.reverted([ 'canvas.updateRoot' ], updateRoot); // update bounds function updateBounds(e) { self.updateBounds(e.context.shape); } this.executed([ 'shape.move', 'shape.create', 'shape.resize' ], updateBounds); this.reverted([ 'shape.move', 'shape.create', 'shape.resize' ], updateBounds); // attach / detach connection function updateConnection(e) { self.updateConnection(e.context.connection); } this.executed([ 'connection.create', 'connection.move', 'connection.delete', 'connection.reconnectEnd', 'connection.reconnectStart' ], updateConnection); this.reverted([ 'connection.create', 'connection.move', 'connection.delete', 'connection.reconnectEnd', 'connection.reconnectStart' ], updateConnection); // update waypoints function updateConnectionWaypoints(e) { self.updateConnectionWaypoints(e.context.connection); } this.executed([ 'connection.layout', 'connection.move', 'connection.updateWaypoints', 'connection.reconnectEnd', 'connection.reconnectStart' ], updateConnectionWaypoints); this.reverted([ 'connection.layout', 'connection.move', 'connection.updateWaypoints', 'connection.reconnectEnd', 'connection.reconnectStart' ], updateConnectionWaypoints); // update attachments function updateAttachment(e) { self.updateAttachment(e.context); } this.executed([ 'shape.attach' ], updateAttachment); this.reverted([ 'shape.attach' ], updateAttachment); } inherits(BpmnUpdater, CommandInterceptor); module.exports = BpmnUpdater; BpmnUpdater.$inject = [ 'eventBus', 'bpmnFactory', 'connectionDocking']; /////// implementation ////////////////////////////////// BpmnUpdater.prototype.updateAttachment = function(context) { var shape = context.shape, businessObject = shape.businessObject, host = shape.host; businessObject.attachedToRef = host && host.businessObject; }; BpmnUpdater.prototype.updateParent = function(element) { // do not update BPMN 2.0 label parent if (element instanceof Model.Label) { return; } var parentShape = element.parent; var businessObject = element.businessObject, parentBusinessObject = parentShape && parentShape.businessObject, parentDi = parentBusinessObject && parentBusinessObject.di; this.updateSemanticParent(businessObject, parentBusinessObject); this.updateDiParent(businessObject.di, parentDi); }; BpmnUpdater.prototype.updateBounds = function(shape) { var di = shape.businessObject.di; var bounds = (shape instanceof Model.Label) ? this._getLabel(di).bounds : di.bounds; assign(bounds, { x: shape.x, y: shape.y, width: shape.width, height: shape.height }); }; BpmnUpdater.prototype.updateDiParent = function(di, parentDi) { if (parentDi && !is(parentDi, 'bpmndi:BPMNPlane')) { parentDi = parentDi.$parent; } if (di.$parent === parentDi) { return; } var planeElements = (parentDi || di.$parent).get('planeElement'); if (parentDi) { planeElements.push(di); di.$parent = parentDi; } else { Collections.remove(planeElements, di); di.$parent = null; } }; function getDefinitions(element) { while (element && !is(element, 'bpmn:Definitions')) { element = element.$parent; } return element; } BpmnUpdater.prototype.updateSemanticParent = function(businessObject, newParent) { var containment; if (businessObject.$parent === newParent) { return; } if (is(businessObject, 'bpmn:FlowElement')) { if (newParent && is(newParent, 'bpmn:Participant')) { newParent = newParent.processRef; } containment = 'flowElements'; } else if (is(businessObject, 'bpmn:Artifact')) { while (newParent && !is(newParent, 'bpmn:Process') && !is(newParent, 'bpmn:SubProcess') && !is(newParent, 'bpmn:Collaboration')) { if (is(newParent, 'bpmn:Participant')) { newParent = newParent.processRef; break; } else { newParent = newParent.$parent; } } containment = 'artifacts'; } else if (is(businessObject, 'bpmn:MessageFlow')) { containment = 'messageFlows'; } else if (is(businessObject, 'bpmn:Participant')) { containment = 'participants'; // make sure the participants process is properly attached / detached // from the XML document var process = businessObject.processRef, definitions; if (process) { definitions = getDefinitions(businessObject.$parent || newParent); if (businessObject.$parent) { Collections.remove(definitions.get('rootElements'), process); process.$parent = null; } if (newParent) { Collections.add(definitions.get('rootElements'), process); process.$parent = definitions; } } } if (!containment) { throw new Error('no parent for ', businessObject, newParent); } var children; if (businessObject.$parent) { // remove from old parent children = businessObject.$parent.get(containment); Collections.remove(children, businessObject); } if (!newParent) { businessObject.$parent = null; } else { // add to new parent children = newParent.get(containment); children.push(businessObject); businessObject.$parent = newParent; } }; BpmnUpdater.prototype.updateConnectionWaypoints = function(connection) { connection.businessObject.di.set('waypoint', this._bpmnFactory.createDiWaypoints(connection.waypoints)); }; BpmnUpdater.prototype.updateConnection = function(connection) { var businessObject = getBusinessObject(connection), newSource = getBusinessObject(connection.source), newTarget = getBusinessObject(connection.target); var inverseSet = is(businessObject, 'bpmn:SequenceFlow'); if (businessObject.sourceRef !== newSource) { if (inverseSet) { Collections.remove(businessObject.sourceRef && businessObject.sourceRef.get('outgoing'), businessObject); if (newSource && newSource.get('outgoing')) { newSource.get('outgoing').push(businessObject); } } businessObject.sourceRef = newSource; } if (businessObject.targetRef !== newTarget) { if (inverseSet) { Collections.remove(businessObject.targetRef && businessObject.targetRef.get('incoming'), businessObject); if (newTarget && newTarget.get('incoming')) { newTarget.get('incoming').push(businessObject); } } businessObject.targetRef = newTarget; } businessObject.di.set('waypoint', this._bpmnFactory.createDiWaypoints(connection.waypoints)); }; /////// helpers ///////////////////////////////////////// BpmnUpdater.prototype._getLabel = function(di) { if (!di.label) { di.label = this._bpmnFactory.createDiLabel(); } return di.label; }; },{"../../util/ModelUtil":98,"diagram-js/lib/command/CommandInterceptor":139,"diagram-js/lib/model":237,"diagram-js/lib/util/Collections":245,"inherits":126,"lodash/collection/forEach":301,"lodash/object/assign":425}],67:[function(require,module,exports){ 'use strict'; var assign = require('lodash/object/assign'), inherits = require('inherits'); var BaseElementFactory = require('diagram-js/lib/core/ElementFactory'), LabelUtil = require('../../util/LabelUtil'); /** * A bpmn-aware factory for diagram-js shapes */ function ElementFactory(bpmnFactory, moddle) { BaseElementFactory.call(this); this._bpmnFactory = bpmnFactory; this._moddle = moddle; } inherits(ElementFactory, BaseElementFactory); ElementFactory.$inject = [ 'bpmnFactory', 'moddle' ]; module.exports = ElementFactory; ElementFactory.prototype.baseCreate = BaseElementFactory.prototype.create; ElementFactory.prototype.create = function(elementType, attrs) { // no special magic for labels, // we assume their businessObjects have already been created // and wired via attrs if (elementType === 'label') { return this.baseCreate(elementType, assign({ type: 'label' }, LabelUtil.DEFAULT_LABEL_SIZE, attrs)); } attrs = attrs || {}; var businessObject = attrs.businessObject, size; if (!businessObject) { if (!attrs.type) { throw new Error('no shape type specified'); } businessObject = this._bpmnFactory.create(attrs.type); } if (!businessObject.di) { if (elementType === 'root') { businessObject.di = this._bpmnFactory.createDiPlane(businessObject, [], { id: businessObject.id + '_di' }); } else if (elementType === 'connection') { businessObject.di = this._bpmnFactory.createDiEdge(businessObject, [], { id: businessObject.id + '_di' }); } else { businessObject.di = this._bpmnFactory.createDiShape(businessObject, {}, { id: businessObject.id + '_di' }); } } if (!!attrs.isExpanded) { businessObject.di.isExpanded = attrs.isExpanded; } if (businessObject.$instanceOf('bpmn:ExclusiveGateway')) { businessObject.di.isMarkerVisible = true; } if (attrs._eventDefinitionType) { var eventDefinitions = businessObject.get('eventDefinitions') || [], newEventDefinition = this._moddle.create(attrs._eventDefinitionType); eventDefinitions.push(newEventDefinition); businessObject.eventDefinitions = eventDefinitions; } size = this._getDefaultSize(businessObject); attrs = assign({ businessObject: businessObject, id: businessObject.id }, size, attrs); return this.baseCreate(elementType, attrs); }; ElementFactory.prototype._getDefaultSize = function(semantic) { if (semantic.$instanceOf('bpmn:SubProcess')) { var isExpanded = semantic.di.isExpanded === true; if (isExpanded) { return { width: 350, height: 200 }; } else { return { width: 100, height: 80 }; } } if (semantic.$instanceOf('bpmn:Task')) { return { width: 100, height: 80 }; } if (semantic.$instanceOf('bpmn:Gateway')) { return { width: 50, height: 50 }; } if (semantic.$instanceOf('bpmn:Event')) { return { width: 36, height: 36 }; } if (semantic.$instanceOf('bpmn:Participant')) { return { width: 600, height: 250 }; } return { width: 100, height: 80 }; }; ElementFactory.prototype.createParticipantShape = function(collapsed) { var participantShape = this.createShape({ type: 'bpmn:Participant' }); if (!collapsed) { participantShape.businessObject.processRef = this._bpmnFactory.create('bpmn:Process'); } return participantShape; }; },{"../../util/LabelUtil":97,"diagram-js/lib/core/ElementFactory":143,"inherits":126,"lodash/object/assign":425}],68:[function(require,module,exports){ 'use strict'; var inherits = require('inherits'); var BaseModeling = require('diagram-js/lib/features/modeling/Modeling'); var UpdatePropertiesHandler = require('./cmd/UpdatePropertiesHandler'), UpdateCanvasRootHandler = require('./cmd/UpdateCanvasRootHandler'); /** * BPMN 2.0 modeling features activator * * @param {EventBus} eventBus * @param {ElementFactory} elementFactory * @param {CommandStack} commandStack * @param {BpmnRules} bpmnRules */ function Modeling(eventBus, elementFactory, commandStack, bpmnRules) { BaseModeling.call(this, eventBus, elementFactory, commandStack); this._bpmnRules = bpmnRules; } inherits(Modeling, BaseModeling); Modeling.$inject = [ 'eventBus', 'elementFactory', 'commandStack', 'bpmnRules' ]; module.exports = Modeling; Modeling.prototype.getHandlers = function() { var handlers = BaseModeling.prototype.getHandlers.call(this); handlers['element.updateProperties'] = UpdatePropertiesHandler; handlers['canvas.updateRoot'] = UpdateCanvasRootHandler; return handlers; }; Modeling.prototype.updateLabel = function(element, newLabel) { this._commandStack.execute('element.updateLabel', { element: element, newLabel: newLabel }); }; var getSharedParent = require('./ModelingUtil').getSharedParent; Modeling.prototype.connect = function(source, target, attrs) { var bpmnRules = this._bpmnRules; if (!attrs) { if (bpmnRules.canConnectMessageFlow(source, target)) { attrs = { type: 'bpmn:MessageFlow' }; } else if (bpmnRules.canConnectSequenceFlow(source, target)) { attrs = { type: 'bpmn:SequenceFlow' }; } else { attrs = { type: 'bpmn:Association' }; } } return this.createConnection(source, target, attrs, getSharedParent(source, target)); }; Modeling.prototype.updateProperties = function(element, properties) { this._commandStack.execute('element.updateProperties', { element: element, properties: properties }); }; /** * Transform the current diagram into a collaboration. * * @return {djs.model.Root} the new root element */ Modeling.prototype.makeCollaboration = function() { var collaborationElement = this._create('root', { type: 'bpmn:Collaboration' }); var context = { newRoot: collaborationElement }; this._commandStack.execute('canvas.updateRoot', context); return collaborationElement; }; /** * Transform the current diagram into a process. * * @return {djs.model.Root} the new root element */ Modeling.prototype.makeProcess = function() { var processElement = this._create('root', { type: 'bpmn:Process' }); var context = { newRoot: processElement }; this._commandStack.execute('canvas.updateRoot', context); }; },{"./ModelingUtil":69,"./cmd/UpdateCanvasRootHandler":78,"./cmd/UpdatePropertiesHandler":79,"diagram-js/lib/features/modeling/Modeling":176,"inherits":126}],69:[function(require,module,exports){ 'use strict'; var find = require('lodash/collection/find'); function getParents(element) { var parents = []; while (element) { element = element.parent; if (element) { parents.push(element); } } return parents; } module.exports.getParents = getParents; function getSharedParent(a, b) { var parentsA = getParents(a), parentsB = getParents(b); return find(parentsA, function(parent) { return parentsB.indexOf(parent) !== -1; }); } module.exports.getSharedParent = getSharedParent; },{"lodash/collection/find":300}],70:[function(require,module,exports){ 'use strict'; var inherits = require('inherits'); var is = require('../../../util/ModelUtil').is; var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); function AppendBehavior(eventBus, elementFactory, bpmnRules) { CommandInterceptor.call(this, eventBus); // assign correct shape position unless already set this.preExecute('shape.append', function(context) { var source = context.source, shape = context.shape; if (!context.position) { if (is(shape, 'bpmn:TextAnnotation')) { context.position = { x: source.x + source.width / 2 + 75, y: source.y - (50) - shape.height / 2 }; } else { context.position = { x: source.x + source.width + 80 + shape.width / 2, y: source.y + source.height / 2 }; } } }, true); } AppendBehavior.$inject = [ 'eventBus', 'elementFactory', 'bpmnRules' ]; inherits(AppendBehavior, CommandInterceptor); module.exports = AppendBehavior; },{"../../../util/ModelUtil":98,"diagram-js/lib/command/CommandInterceptor":139,"inherits":126}],71:[function(require,module,exports){ 'use strict'; var inherits = require('inherits'); var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); var is = require('../../../util/ModelUtil').is; /** * BPMN specific create boundary event behavior */ function CreateBoundaryEventBehavior(eventBus, modeling, elementFactory, bpmnFactory) { CommandInterceptor.call(this, eventBus); /** * replace intermediate event with boundary event when * attaching it to a shape */ this.preExecute('shape.create', function(context) { var shape = context.shape, host = context.host, businessObject, boundaryEvent; var attrs = { cancelActivity: true }; if (host && is(shape, 'bpmn:IntermediateThrowEvent')) { attrs.attachedToRef = host.businessObject; businessObject = bpmnFactory.create('bpmn:BoundaryEvent', attrs); boundaryEvent = { type: 'bpmn:BoundaryEvent', businessObject: businessObject }; context.shape = elementFactory.createShape(boundaryEvent); } }, true); } CreateBoundaryEventBehavior.$inject = [ 'eventBus', 'modeling', 'elementFactory', 'bpmnFactory' ]; inherits(CreateBoundaryEventBehavior, CommandInterceptor); module.exports = CreateBoundaryEventBehavior; },{"../../../util/ModelUtil":98,"diagram-js/lib/command/CommandInterceptor":139,"inherits":126}],72:[function(require,module,exports){ 'use strict'; var inherits = require('inherits'); var assign = require('lodash/object/assign'); var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); var getApproxIntersection = require('diagram-js/lib/util/LineIntersection').getApproxIntersection; function copy(obj) { return assign({}, obj); } function CreateOnFlowBehavior(eventBus, bpmnRules, modeling) { CommandInterceptor.call(this, eventBus); /** * Reconnect start / end of a connection after * dropping an element on a flow. */ this.preExecute('shape.create', function(context) { var parent = context.parent, shape = context.shape; if (bpmnRules.canInsert(shape, parent)) { context.targetFlow = parent; context.parent = parent.parent; } }, true); this.postExecute('shape.create', function(context) { var shape = context.shape, targetFlow = context.targetFlow, position = context.position, source, target, reconnected, intersection, waypoints, waypointsBefore, waypointsAfter, dockingPoint; if (targetFlow) { waypoints = targetFlow.waypoints; intersection = getApproxIntersection(waypoints, position); if (intersection) { waypointsBefore = waypoints.slice(0, intersection.index); waypointsAfter = waypoints.slice(intersection.index + (intersection.bendpoint ? 1 : 0)); dockingPoint = intersection.bendpoint ? waypoints[intersection.index] : position; waypointsBefore.push(copy(dockingPoint)); waypointsAfter.unshift(copy(dockingPoint)); } source = targetFlow.source; target = targetFlow.target; if (bpmnRules.canConnect(source, shape, targetFlow)) { // reconnect source -> inserted shape modeling.reconnectEnd(targetFlow, shape, waypointsBefore || copy(position)); reconnected = true; } if (bpmnRules.canConnect(shape, target, targetFlow)) { if (!reconnected) { // reconnect inserted shape -> end modeling.reconnectStart(targetFlow, shape, waypointsAfter || copy(position)); } else { modeling.connect(shape, target, { type: targetFlow.type, waypoints: waypointsAfter }); } } } }, true); } inherits(CreateOnFlowBehavior, CommandInterceptor); CreateOnFlowBehavior.$inject = [ 'eventBus', 'bpmnRules', 'modeling' ]; module.exports = CreateOnFlowBehavior; },{"diagram-js/lib/command/CommandInterceptor":139,"diagram-js/lib/util/LineIntersection":252,"inherits":126,"lodash/object/assign":425}],73:[function(require,module,exports){ 'use strict'; var inherits = require('inherits'); var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); var is = require('../../../util/ModelUtil').is; /** * BPMN specific create participant behavior */ function CreateParticipantBehavior(eventBus, modeling, elementFactory, bpmnFactory) { CommandInterceptor.call(this, eventBus); /** * morph process into collaboration before adding * participant onto collaboration */ this.preExecute('shape.create', function(context) { var parent = context.parent, shape = context.shape, position = context.position; if (is(parent, 'bpmn:Process') && is(shape, 'bpmn:Participant')) { // this is going to detach the process root // and set the returned collaboration element // as the new root element var collaborationElement = modeling.makeCollaboration(); // monkey patch the create context // so that the participant is being dropped // onto the new collaboration root instead context.position = position; context.parent = collaborationElement; context.processRoot = parent; } }, true); this.execute('shape.create', function(context) { var processRoot = context.processRoot, shape = context.shape; if (processRoot) { context.oldProcessRef = shape.businessObject.processRef; // assign the participant processRef shape.businessObject.processRef = processRoot.businessObject; } }, true); this.revert('shape.create', function(context) { var processRoot = context.processRoot, shape = context.shape; if (processRoot) { // assign the participant processRef shape.businessObject.processRef = context.oldProcessRef; } }, true); this.postExecute('shape.create', function(context) { var processRoot = context.processRoot, shape = context.shape; if (processRoot) { // process root is already detached at this point var processChildren = processRoot.children.slice(); modeling.moveShapes(processChildren, { x: 0, y: 0 }, shape); } }, true); } CreateParticipantBehavior.$inject = [ 'eventBus', 'modeling', 'elementFactory', 'bpmnFactory' ]; inherits(CreateParticipantBehavior, CommandInterceptor); module.exports = CreateParticipantBehavior; },{"../../../util/ModelUtil":98,"diagram-js/lib/command/CommandInterceptor":139,"inherits":126}],74:[function(require,module,exports){ 'use strict'; var is = require('../../../util/ModelUtil').is; function ModelingFeedback(eventBus, tooltips) { function showError(position, message) { tooltips.add({ position: { x: position.x + 5, y: position.y + 5 }, type: 'error', timeout: 2000, html: '
    ' + message + '
    ' }); } eventBus.on([ 'shape.move.rejected', 'create.rejected' ], function(event) { var context = event.context, shape = context.shape, target = context.target; if (is(target, 'bpmn:Collaboration') && is(shape, 'bpmn:FlowNode')) { showError(event, 'flow elements must be children of pools/participants'); } }); } ModelingFeedback.$inject = [ 'eventBus', 'tooltips' ]; module.exports = ModelingFeedback; },{"../../../util/ModelUtil":98}],75:[function(require,module,exports){ 'use strict'; var inherits = require('inherits'); var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); var is = require('../../../util/ModelUtil').is; /** * BPMN specific remove behavior */ function RemoveBehavior(eventBus, modeling) { CommandInterceptor.call(this, eventBus); /** * morph collaboration diagram into process diagram * after the last participant has been removed */ this.preExecute('shape.delete', function(context) { var shape = context.shape, parent = shape.parent; // activate the behavior if the shape to be removed // is a participant if (is(shape, 'bpmn:Participant')) { context.collaborationRoot = parent; } }, true); this.postExecute('shape.delete', function(context) { var collaborationRoot = context.collaborationRoot; if (collaborationRoot && !collaborationRoot.businessObject.participants.length) { // replace empty collaboration with process diagram modeling.makeProcess(); } }, true); } RemoveBehavior.$inject = [ 'eventBus', 'modeling' ]; inherits(RemoveBehavior, CommandInterceptor); module.exports = RemoveBehavior; },{"../../../util/ModelUtil":98,"diagram-js/lib/command/CommandInterceptor":139,"inherits":126}],76:[function(require,module,exports){ 'use strict'; var forEach = require('lodash/collection/forEach'), inherits = require('inherits'); var CommandInterceptor = require('diagram-js/lib/command/CommandInterceptor'); var is = require('../../../util/ModelUtil').is, getSharedParent = require('../ModelingUtil').getSharedParent; function ReplaceConnectionBehavior(eventBus, modeling, bpmnRules) { CommandInterceptor.call(this, eventBus); function replaceConnection(connection) { var source = connection.source, target = connection.target; var replacementType, remove; /** * Check if incoming or outgoing connections * can stay or could be substituted with an * appropriate replacement. * * This holds true for SequenceFlow <> MessageFlow. */ if (is(connection, 'bpmn:SequenceFlow')) { if (!bpmnRules.canConnectSequenceFlow(source, target)) { remove = true; } if (bpmnRules.canConnectMessageFlow(source, target)) { replacementType = 'bpmn:MessageFlow'; } } // transform message flows into sequence flows, if possible if (is(connection, 'bpmn:MessageFlow')) { if (!bpmnRules.canConnectMessageFlow(source, target)) { remove = true; } if (bpmnRules.canConnectSequenceFlow(source, target)) { replacementType = 'bpmn:SequenceFlow'; } } if (is(connection, 'bpmn:Association') && !bpmnRules.canConnectAssociation(source, target)) { remove = true; } // remove invalid connection if (remove) { modeling.removeConnection(connection); } // replace SequenceFlow <> MessageFlow if (replacementType) { modeling.createConnection(source, target, { type: replacementType, waypoints: connection.waypoints.slice() }, getSharedParent(source, target)); } } this.postExecuted('shapes.move', function(context) { var closure = context.closure, allConnections = closure.allConnections; forEach(allConnections, replaceConnection); }, true); this.postExecuted([ 'connection.reconnectStart', 'connection.reconnectEnd' ], function(event){ var connection = event.context.connection; replaceConnection(connection); }); } inherits(ReplaceConnectionBehavior, CommandInterceptor); ReplaceConnectionBehavior.$inject = [ 'eventBus', 'modeling', 'bpmnRules' ]; module.exports = ReplaceConnectionBehavior; },{"../../../util/ModelUtil":98,"../ModelingUtil":69,"diagram-js/lib/command/CommandInterceptor":139,"inherits":126,"lodash/collection/forEach":301}],77:[function(require,module,exports){ module.exports = { __init__: [ 'appendBehavior', 'createParticipantBehavior', 'createBoundaryEventBehavior', 'createOnFlowBehavior', 'replaceConnectionBehavior', 'removeBehavior', 'modelingFeedback' ], appendBehavior: [ 'type', require('./AppendBehavior') ], createParticipantBehavior: [ 'type', require('./CreateParticipantBehavior') ], createBoundaryEventBehavior: [ 'type', require('./CreateBoundaryEventBehavior') ], createOnFlowBehavior: [ 'type', require('./CreateOnFlowBehavior') ], replaceConnectionBehavior: [ 'type', require('./ReplaceConnectionBehavior') ], removeBehavior: [ 'type', require('./RemoveBehavior') ], modelingFeedback: [ 'type', require('./ModelingFeedback') ] }; },{"./AppendBehavior":70,"./CreateBoundaryEventBehavior":71,"./CreateOnFlowBehavior":72,"./CreateParticipantBehavior":73,"./ModelingFeedback":74,"./RemoveBehavior":75,"./ReplaceConnectionBehavior":76}],78:[function(require,module,exports){ 'use strict'; var Collections = require('diagram-js/lib/util/Collections'); function UpdateCanvasRootHandler(canvas, modeling) { this._canvas = canvas; this._modeling = modeling; } UpdateCanvasRootHandler.$inject = [ 'canvas', 'modeling' ]; module.exports = UpdateCanvasRootHandler; UpdateCanvasRootHandler.prototype.execute = function(context) { var canvas = this._canvas; var newRoot = context.newRoot, newRootBusinessObject = newRoot.businessObject, oldRoot = canvas.getRootElement(), oldRootBusinessObject = oldRoot.businessObject, bpmnDefinitions = oldRootBusinessObject.$parent, diPlane = oldRootBusinessObject.di; // (1) replace process old <> new root canvas.setRootElement(newRoot, true); // (2) update root elements Collections.add(bpmnDefinitions.rootElements, newRootBusinessObject); newRootBusinessObject.$parent = bpmnDefinitions; Collections.remove(bpmnDefinitions.rootElements, oldRootBusinessObject); oldRootBusinessObject.$parent = null; // (3) wire di oldRootBusinessObject.di = null; diPlane.bpmnElement = newRootBusinessObject; newRootBusinessObject.di = diPlane; context.oldRoot = oldRoot; }; UpdateCanvasRootHandler.prototype.revert = function(context) { var canvas = this._canvas; var newRoot = context.newRoot, newRootBusinessObject = newRoot.businessObject, oldRoot = context.oldRoot, oldRootBusinessObject = oldRoot.businessObject, bpmnDefinitions = newRootBusinessObject.$parent, diPlane = newRootBusinessObject.di; // (1) replace process old <> new root canvas.setRootElement(oldRoot, true); // (2) update root elements Collections.remove(bpmnDefinitions.rootElements, newRootBusinessObject); newRootBusinessObject.$parent = null; Collections.add(bpmnDefinitions.rootElements, oldRootBusinessObject); oldRootBusinessObject.$parent = bpmnDefinitions; // (3) wire di newRootBusinessObject.di = null; diPlane.bpmnElement = oldRootBusinessObject; oldRootBusinessObject.di = diPlane; }; },{"diagram-js/lib/util/Collections":245}],79:[function(require,module,exports){ 'use strict'; var reduce = require('lodash/object/transform'), keys = require('lodash/object/keys'), forEach = require('lodash/collection/forEach'); var DEFAULT_FLOW = 'default', NAME = 'name', ID = 'id'; /** * A handler that implements a BPMN 2.0 property update. * * This should be used to set simple properties on elements with * an underlying BPMN business object. * * Use respective diagram-js provided handlers if you would * like to perform automated modeling. */ function UpdatePropertiesHandler(elementRegistry) { this._elementRegistry = elementRegistry; } UpdatePropertiesHandler.$inject = [ 'elementRegistry' ]; module.exports = UpdatePropertiesHandler; function getProperties(businessObject, propertyNames) { return reduce(propertyNames, function(result, key) { result[key] = businessObject.get(key); return result; }, {}); } function setProperties(businessObject, properties) { forEach(properties, function(value, key) { businessObject.set(key, value); }); } ////// api ///////////////////////////////////////////// /** * Updates a BPMN element with a list of new properties * * @param {Object} context * @param {djs.model.Base} context.element the element to update * @param {Object} context.properties a list of properties to set on the element's * businessObject (the BPMN model element) * * @return {Array} the updated element */ UpdatePropertiesHandler.prototype.execute = function(context) { var element = context.element, changed = [ element ]; if (!element) { throw new Error('element required'); } var elementRegistry = this._elementRegistry; var businessObject = element.businessObject, properties = context.properties, oldProperties = context.oldProperties || getProperties(businessObject, keys(properties)); if (ID in properties) { elementRegistry.updateId(element, properties[ID]); } // correctly indicate visual changes on default flow updates if (DEFAULT_FLOW in properties) { if (properties[DEFAULT_FLOW]) { changed.push(elementRegistry.get(properties[DEFAULT_FLOW].id)); } if (businessObject[DEFAULT_FLOW]) { changed.push(elementRegistry.get(businessObject[DEFAULT_FLOW].id)); } } if (NAME in properties && element.label) { changed.push(element.label); } // update properties setProperties(businessObject, properties); // store old values context.oldProperties = oldProperties; context.changed = changed; // indicate changed on objects affected by the update return changed; }; /** * Reverts the update on a BPMN elements properties. * * @param {Object} context * * @return {djs.mode.Base} the updated element */ UpdatePropertiesHandler.prototype.revert = function(context) { var element = context.element, oldProperties = context.oldProperties, businessObject = element.businessObject, elementRegistry = this._elementRegistry; // update properties setProperties(businessObject, oldProperties); if (ID in oldProperties) { elementRegistry.updateId(element, oldProperties[ID]); } return context.changed; }; },{"lodash/collection/forEach":301,"lodash/object/keys":426,"lodash/object/transform":432}],80:[function(require,module,exports){ module.exports = { __init__: [ 'modeling', 'bpmnUpdater', 'bpmnLabelSupport' ], __depends__: [ require('../label-editing'), require('./rules'), require('./behavior'), require('diagram-js/lib/command'), require('diagram-js/lib/features/tooltips'), require('diagram-js/lib/features/label-support'), require('diagram-js/lib/features/attach-support'), require('diagram-js/lib/features/selection'), require('diagram-js/lib/features/change-support') ], bpmnFactory: [ 'type', require('./BpmnFactory') ], bpmnUpdater: [ 'type', require('./BpmnUpdater') ], elementFactory: [ 'type', require('./ElementFactory') ], modeling: [ 'type', require('./Modeling') ], bpmnLabelSupport: [ 'type', require('./BpmnLabelSupport') ], layouter: [ 'type', require('./BpmnLayouter') ], connectionDocking: [ 'type', require('diagram-js/lib/layout/CroppingConnectionDocking') ] }; },{"../label-editing":62,"./BpmnFactory":63,"./BpmnLabelSupport":64,"./BpmnLayouter":65,"./BpmnUpdater":66,"./ElementFactory":67,"./Modeling":68,"./behavior":77,"./rules":82,"diagram-js/lib/command":141,"diagram-js/lib/features/attach-support":152,"diagram-js/lib/features/change-support":159,"diagram-js/lib/features/label-support":173,"diagram-js/lib/features/selection":220,"diagram-js/lib/features/tooltips":229,"diagram-js/lib/layout/CroppingConnectionDocking":234}],81:[function(require,module,exports){ 'use strict'; var groupBy = require('lodash/collection/groupBy'), size = require('lodash/collection/size'), find = require('lodash/collection/find'), any = require('lodash/collection/any'), inherits = require('inherits'); var getParents = require('../ModelingUtil').getParents, is = require('../../../util/ModelUtil').is, getBusinessObject = require('../../../util/ModelUtil').getBusinessObject, isExpanded = require('../../../util/DiUtil').isExpanded; var RuleProvider = require('diagram-js/lib/features/rules/RuleProvider'); var isBoundaryAttachment = require('../../snapping/BpmnSnappingUtil').getBoundaryAttachment; /** * BPMN specific modeling rule */ function BpmnRules(eventBus) { RuleProvider.call(this, eventBus); } inherits(BpmnRules, RuleProvider); BpmnRules.$inject = [ 'eventBus' ]; module.exports = BpmnRules; BpmnRules.prototype.init = function() { this.addRule('connection.create', function(context) { var source = context.source, target = context.target; return canConnect(source, target); }); this.addRule('connection.reconnectStart', function(context) { var connection = context.connection, source = context.hover || context.source, target = connection.target; return canConnect(source, target, connection); }); this.addRule('connection.reconnectEnd', function(context) { var connection = context.connection, source = connection.source, target = context.hover || context.target; return canConnect(source, target, connection); }); this.addRule('connection.updateWaypoints', function(context) { // OK! but visually ignore return null; }); this.addRule('shape.resize', function(context) { var shape = context.shape, newBounds = context.newBounds; return canResize(shape, newBounds); }); this.addRule('shapes.move', function(context) { var target = context.target, shapes = context.shapes, position = context.position; return canAttach(shapes, target, null, position) || canMove(shapes, target, position); }); this.addRule([ 'shape.create', 'shape.append' ], function(context) { var target = context.target, shape = context.shape, source = context.source, position = context.position; return canAttach([ shape ], target, source, position) || canCreate(shape, target, source, position); }); }; BpmnRules.prototype.canConnectMessageFlow = canConnectMessageFlow; BpmnRules.prototype.canConnectSequenceFlow = canConnectSequenceFlow; BpmnRules.prototype.canConnectAssociation = canConnectAssociation; BpmnRules.prototype.canMove = canMove; BpmnRules.prototype.canAttach = canAttach; BpmnRules.prototype.canDrop = canDrop; BpmnRules.prototype.canInsert = canInsert; BpmnRules.prototype.canCreate = canCreate; BpmnRules.prototype.canConnect = canConnect; BpmnRules.prototype.canResize = canResize; /** * Utility functions for rule checking */ function nonExistantOrLabel(element) { return !element || isLabel(element); } function isSame(a, b) { return a === b; } function getOrganizationalParent(element) { var bo = getBusinessObject(element); while (bo && !is(bo, 'bpmn:Process')) { if (is(bo, 'bpmn:Participant')) { return bo.processRef || bo; } bo = bo.$parent; } return bo; } function isSameOrganization(a, b) { var parentA = getOrganizationalParent(a), parentB = getOrganizationalParent(b); return parentA === parentB; } function isMessageFlowSource(element) { return is(element, 'bpmn:InteractionNode') && ( !is(element, 'bpmn:Event') || ( is(element, 'bpmn:ThrowEvent') && hasEventDefinitionOrNone(element, 'bpmn:MessageEventDefinition') ) ); } function isMessageFlowTarget(element) { return is(element, 'bpmn:InteractionNode') && ( !is(element, 'bpmn:Event') || ( is(element, 'bpmn:CatchEvent') && hasEventDefinitionOrNone(element, 'bpmn:MessageEventDefinition') ) ); } function getScopeParent(element) { var bo = getBusinessObject(element); if (is(bo, 'bpmn:Participant')) { return null; } while (bo) { bo = bo.$parent; if (is(bo, 'bpmn:FlowElementsContainer')) { return bo; } } return bo; } function isSameScope(a, b) { var scopeParentA = getScopeParent(a), scopeParentB = getScopeParent(b); return scopeParentA && (scopeParentA === scopeParentB); } function hasEventDefinition(element, eventDefinition) { var bo = getBusinessObject(element); return !!find(bo.eventDefinitions || [], function(definition) { return is(definition, eventDefinition); }); } function hasEventDefinitionOrNone(element, eventDefinition) { var bo = getBusinessObject(element); return (bo.eventDefinitions || []).every(function(definition) { return is(definition, eventDefinition); }); } function isSequenceFlowSource(element) { return is(element, 'bpmn:FlowNode') && !is(element, 'bpmn:EndEvent') && !(is(element, 'bpmn:IntermediateThrowEvent') && hasEventDefinition(element, 'bpmn:LinkEventDefinition') ); } function isSequenceFlowTarget(element) { return is(element, 'bpmn:FlowNode') && !is(element, 'bpmn:StartEvent') && !is(element, 'bpmn:BoundaryEvent') && !(is(element, 'bpmn:IntermediateCatchEvent') && hasEventDefinition(element, 'bpmn:LinkEventDefinition')); } function isEventBasedTarget(element) { return is(element, 'bpmn:ReceiveTask') || ( is(element, 'bpmn:IntermediateCatchEvent') && ( hasEventDefinition(element, 'bpmn:MessageEventDefinition') || hasEventDefinition(element, 'bpmn:TimerEventDefinition') || hasEventDefinition(element, 'bpmn:ConditionalEventDefinition') || hasEventDefinition(element, 'bpmn:SignalEventDefinition') ) ); } function isLabel(element) { return element.labelTarget; } function isConnection(element) { return element.waypoints; } function isParent(possibleParent, element) { var allParents = getParents(element); return allParents.indexOf(possibleParent) !== -1; } function canConnect(source, target, connection) { if (nonExistantOrLabel(source) || nonExistantOrLabel(target)) { return null; } // See https://github.com/bpmn-io/bpmn-js/issues/178 // as a workround we disallow connections with same // target and source element. // This rule must be removed if a auto layout for this // connections is implemented. if (isSame(source, target)) { return false; } if (canConnectMessageFlow(source, target) || canConnectSequenceFlow(source, target)) { return true; } if (is(connection, 'bpmn:Association')) { return canConnectAssociation(source, target); } return false; } /** * Can an element be dropped into the target element * * @return {Boolean} */ function canDrop(element, target) { // can move labels everywhere if (isLabel(element) && !isConnection(target)) { return true; } // allow to create new participants on // on existing collaboration and process diagrams if (is(element, 'bpmn:Participant')) { return is(target, 'bpmn:Process') || is(target, 'bpmn:Collaboration'); } if (is(element, 'bpmn:BoundaryEvent')) { return false; } // drop flow elements onto flow element containers // and participants if (is(element, 'bpmn:FlowElement')) { if (is(target, 'bpmn:FlowElementsContainer')) { return isExpanded(target) !== false; } return is(target, 'bpmn:Participant'); } if (is(element, 'bpmn:Artifact')) { return is(target, 'bpmn:Collaboration') || is(target, 'bpmn:Participant') || is(target, 'bpmn:Process'); } if (is(element, 'bpmn:MessageFlow')) { return is(target, 'bpmn:Collaboration'); } return false; } function isBoundaryEvent(element) { return !isLabel(element) && is(element, 'bpmn:BoundaryEvent'); } /** * We treat IntermediateThrowEvents as boundary events during create, * this must be reflected in the rules. */ function isBoundaryCandidate(element) { return isBoundaryEvent(element) || (is(element, 'bpmn:IntermediateThrowEvent') && !element.parent); } function canAttach(elements, target, source, position) { // disallow appending as boundary event if (source) { return false; } // only (re-)attach one element at a time if (elements.length !== 1) { return false; } var element = elements[0]; // do not attach labels if (isLabel(element)) { return false; } // only handle boundary events if (!isBoundaryCandidate(element)) { return false; } // allow default move operation if (!target) { return true; } // only allow drop on activities if (!is(target, 'bpmn:Activity')) { return false; } // only attach to subprocess border if (position && !isBoundaryAttachment(position, target)) { return false; } return 'attach'; } function canMove(elements, target) { // only move if they have the same parent if (!haveSameParent(elements)) { return false; } // do not move selection containing boundary events if (any(elements, isBoundaryEvent)) { return false; } // allow default move check to start move operation if (!target) { return true; } return elements.every(function(element) { return canDrop(element, target); }); } function canCreate(shape, target, source, position) { if (!target) { return false; } if (isLabel(target)) { return null; } if (isSame(source, target)) { return false; } // ensure we do not drop the element // into source if (source && isParent(source, target)) { return false; } return canDrop(shape, target, position) || canInsert(shape, target, position); } function canResize(shape, newBounds) { if (is(shape, 'bpmn:SubProcess')) { return (!!isExpanded(shape)) && ( !newBounds || (newBounds.width >= 100 && newBounds.height >= 80) ); } if (is(shape, 'bpmn:Participant')) { return !newBounds || (newBounds.width >= 100 && newBounds.height >= 80); } if (is(shape, 'bpmn:TextAnnotation')) { return true; } return false; } function canConnectAssociation(source, target) { // do not connect connections if (isConnection(source) || isConnection(target)) { return false; } // connect if different parent return !isParent(target, source) && !isParent(source, target); } function canConnectMessageFlow(source, target) { return isMessageFlowSource(source) && isMessageFlowTarget(target) && !isSameOrganization(source, target); } function canConnectSequenceFlow(source, target) { return isSequenceFlowSource(source) && isSequenceFlowTarget(target) && isSameScope(source, target) && !(is(source, 'bpmn:EventBasedGateway') && !isEventBasedTarget(target)); } function canInsert(shape, flow, position) { // return true if we can drop on the // underlying flow parent // // at this point we are not really able to talk // about connection rules (yet) return ( is(flow, 'bpmn:SequenceFlow') || is(flow, 'bpmn:MessageFlow') ) && is(shape, 'bpmn:FlowNode') && !is(shape, 'bpmn:BoundaryEvent') && canDrop(shape, flow.parent, position); } function haveSameParent(elements) { return size(groupBy(elements, function(e) { return e.parent && e.parent.id; })) === 1; } },{"../../../util/DiUtil":96,"../../../util/ModelUtil":98,"../../snapping/BpmnSnappingUtil":89,"../ModelingUtil":69,"diagram-js/lib/features/rules/RuleProvider":214,"inherits":126,"lodash/collection/any":297,"lodash/collection/find":300,"lodash/collection/groupBy":302,"lodash/collection/size":307}],82:[function(require,module,exports){ module.exports = { __depends__: [ require('diagram-js/lib/features/rules') ], __init__: [ 'bpmnRules' ], bpmnRules: [ 'type', require('./BpmnRules') ] }; },{"./BpmnRules":81,"diagram-js/lib/features/rules":216}],83:[function(require,module,exports){ 'use strict'; var assign = require('lodash/object/assign'); /** * A palette provider for BPMN 2.0 elements. */ function PaletteProvider(palette, create, elementFactory, spaceTool, lassoTool) { this._create = create; this._elementFactory = elementFactory; this._spaceTool = spaceTool; this._lassoTool = lassoTool; palette.registerProvider(this); } module.exports = PaletteProvider; PaletteProvider.$inject = [ 'palette', 'create', 'elementFactory', 'spaceTool', 'lassoTool' ]; PaletteProvider.prototype.getPaletteEntries = function(element) { var actions = {}, create = this._create, elementFactory = this._elementFactory, spaceTool = this._spaceTool, lassoTool = this._lassoTool; function createAction(type, group, className, title, options) { function createListener(event) { var shape = elementFactory.createShape(assign({ type: type }, options)); if (options) { shape.businessObject.di.isExpanded = options.isExpanded; } create.start(event, shape); } var shortType = type.replace(/^bpmn\:/, ''); return { group: group, className: className, title: title || 'Create ' + shortType, action: { dragstart: createListener, click: createListener } }; } function createParticipant(event, collapsed) { create.start(event, elementFactory.createParticipantShape(collapsed)); } assign(actions, { 'lasso-tool': { group: 'tools', className: 'icon-lasso-tool', title: 'Activate the lasso tool', action: { click: function(event) { lassoTool.activateSelection(event); } } }, 'space-tool': { group: 'tools', className: 'icon-space-tool', title: 'Activate the create/remove space tool', action: { click: function(event) { spaceTool.activateSelection(event); } } }, 'tool-separator': { group: 'tools', separator: true }, 'create.start-event': createAction( 'bpmn:StartEvent', 'event', 'icon-start-event-none' ), 'create.intermediate-event': createAction( 'bpmn:IntermediateThrowEvent', 'event', 'icon-intermediate-event-none' ), 'create.end-event': createAction( 'bpmn:EndEvent', 'event', 'icon-end-event-none' ), 'create.exclusive-gateway': createAction( 'bpmn:ExclusiveGateway', 'gateway', 'icon-gateway-xor' ), 'create.task': createAction( 'bpmn:Task', 'activity', 'icon-task' ), 'create.subprocess-expanded': createAction( 'bpmn:SubProcess', 'activity', 'icon-subprocess-expanded', 'Create expanded SubProcess', { isExpanded: true } ), 'create.participant-expanded': { group: 'collaboration', className: 'icon-participant', title: 'Create Pool/Participant', action: { dragstart: createParticipant, click: createParticipant } } }); return actions; }; },{"lodash/object/assign":425}],84:[function(require,module,exports){ module.exports = { __depends__: [ require('diagram-js/lib/features/palette'), require('diagram-js/lib/features/create'), require('diagram-js/lib/features/space-tool'), require('diagram-js/lib/features/lasso-tool') ], __init__: [ 'paletteProvider' ], paletteProvider: [ 'type', require('./PaletteProvider') ] }; },{"./PaletteProvider":83,"diagram-js/lib/features/create":165,"diagram-js/lib/features/lasso-tool":175,"diagram-js/lib/features/palette":206,"diagram-js/lib/features/space-tool":227}],85:[function(require,module,exports){ 'use strict'; var forEach = require('lodash/collection/forEach'), filter = require('lodash/collection/filter'), pick = require('lodash/object/pick'), assign = require('lodash/object/assign'); var REPLACE_OPTIONS = require ('./ReplaceOptions'); var startEventReplace = REPLACE_OPTIONS.START_EVENT, intermediateEventReplace = REPLACE_OPTIONS.INTERMEDIATE_EVENT, endEventReplace = REPLACE_OPTIONS.END_EVENT, gatewayReplace = REPLACE_OPTIONS.GATEWAY, taskReplace = REPLACE_OPTIONS.TASK, subProcessExpandedReplace = REPLACE_OPTIONS.SUBPROCESS_EXPANDED, transactionReplace = REPLACE_OPTIONS.TRANSACTION, boundaryEventReplace = REPLACE_OPTIONS.BOUNDARY_EVENT; var is = require('../../util/ModelUtil').is, getBusinessObject = require('../../util/ModelUtil').getBusinessObject, isExpanded = require('../../util/DiUtil').isExpanded; var CUSTOM_PROPERTIES = [ 'cancelActivity', 'instantiate', 'eventGatewayType' ]; /** * A replace menu provider that gives users the controls to choose * and replace BPMN elements with each other. * * @param {BpmnFactory} bpmnFactory * @param {Moddle} moddle * @param {PopupMenu} popupMenu * @param {Replace} replace */ function BpmnReplace(bpmnFactory, moddle, popupMenu, replace, selection, modeling, eventBus) { var self = this, currentElement; /** * Prepares a new business object for the replacement element * and triggers the replace operation. * * @param {djs.model.Base} element * @param {Object} target * @return {djs.model.Base} the newly created element */ function replaceElement(element, target) { var type = target.type, oldBusinessObject = element.businessObject, businessObject = bpmnFactory.create(type); var newElement = { type: type, businessObject: businessObject }; // initialize custom BPMN extensions if (target.eventDefinition) { var eventDefinitions = businessObject.get('eventDefinitions'), eventDefinition = moddle.create(target.eventDefinition); eventDefinitions.push(eventDefinition); } // initialize special properties defined in target definition assign(businessObject, pick(target, CUSTOM_PROPERTIES)); // copy size (for activities only) if (is(oldBusinessObject, 'bpmn:Activity')) { // TODO: need also to respect min/max Size newElement.width = element.width; newElement.height = element.height; } if (is(oldBusinessObject, 'bpmn:SubProcess')) { newElement.isExpanded = isExpanded(oldBusinessObject); } // TODO: copy other elligable properties from old business object businessObject.name = oldBusinessObject.name; businessObject.loopCharacteristics = oldBusinessObject.loopCharacteristics; newElement = replace.replaceElement(element, newElement); selection.select(newElement); return newElement; } function toggleLoopEntry(event, entry) { var loopEntries = self.getLoopEntries(currentElement); var loopCharacteristics; if (entry.active) { loopCharacteristics = undefined; } else { forEach(loopEntries, function(action) { var options = action.options; if (entry.id === action.id) { loopCharacteristics = moddle.create(options.loopCharacteristics); if (options.isSequential) { loopCharacteristics.isSequential = options.isSequential; } } }); } modeling.updateProperties(currentElement, { loopCharacteristics: loopCharacteristics }); } function getLoopEntries(element) { currentElement = element; var businessObject = getBusinessObject(element), loopCharacteristics = businessObject.loopCharacteristics; var isSequential, isLoop, isParallel; if (loopCharacteristics) { isSequential = loopCharacteristics.isSequential; isLoop = loopCharacteristics.isSequential === undefined; isParallel = loopCharacteristics.isSequential !== undefined && !loopCharacteristics.isSequential; } var loopEntries = [ { id: 'toggle-parallel-mi', className: 'icon-parallel-mi-marker', active: isParallel, action: toggleLoopEntry, options: { loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics', isSequential: false } }, { id: 'toggle-sequential-mi', className: 'icon-sequential-mi-marker', active: isSequential, action: toggleLoopEntry, options: { loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics', isSequential: true } }, { id: 'toggle-loop', className: 'icon-loop-marker', active: isLoop, action: toggleLoopEntry, options: { loopCharacteristics: 'bpmn:StandardLoopCharacteristics' } } ]; return loopEntries; } function getAdHocEntry(element) { var businessObject = getBusinessObject(element); var isAdHoc = is(businessObject, 'bpmn:AdHocSubProcess'); var adHocEntry = { id: 'toggle-adhoc', className: 'icon-ad-hoc-marker', active: isAdHoc, action: function(event, entry) { if (isAdHoc) { return replaceElement(element, { type: 'bpmn:SubProcess' }); } else { return replaceElement(element, { type: 'bpmn:AdHocSubProcess' }); } } }; return adHocEntry; } function getReplaceOptions(element) { var menuEntries = []; var businessObject = element.businessObject; if (is(businessObject, 'bpmn:StartEvent')) { addEntries(startEventReplace, filterEvents); } else if (is(businessObject, 'bpmn:IntermediateCatchEvent') || is(businessObject, 'bpmn:IntermediateThrowEvent')) { addEntries(intermediateEventReplace, filterEvents); } else if (is(businessObject, 'bpmn:EndEvent')) { addEntries(endEventReplace, filterEvents); } else if (is(businessObject, 'bpmn:Gateway')) { addEntries(gatewayReplace, function(entry) { return entry.target.type !== businessObject.$type; }); } else if (is(businessObject, 'bpmn:Transaction')) { addEntries(transactionReplace, filterEvents); } else if (is(businessObject, 'bpmn:SubProcess') && isExpanded(businessObject)) { addEntries(subProcessExpandedReplace, filterEvents); } else if (is(businessObject, 'bpmn:AdHocSubProcess') && !isExpanded(businessObject)) { addEntries(taskReplace, function(entry) { return entry.target.type !== 'bpmn:SubProcess'; }); } else if (is(businessObject, 'bpmn:BoundaryEvent')) { addEntries(boundaryEventReplace, filterEvents); } else if (is(businessObject, 'bpmn:FlowNode')) { addEntries(taskReplace, function(entry) { return entry.target.type !== businessObject.$type; }); } function filterEvents(entry) { var target = entry.target; var eventDefinition = businessObject.eventDefinitions && businessObject.eventDefinitions[0].$type, cancelActivity; if (businessObject.$type === 'bpmn:BoundaryEvent') { cancelActivity = target.cancelActivity !== false; } var isEventDefinitionEqual = target.eventDefinition == eventDefinition, isEventTypeEqual = businessObject.$type == target.type, isInterruptingEqual = businessObject.cancelActivity == cancelActivity; return ((!isEventDefinitionEqual && isEventTypeEqual) || !isEventTypeEqual) || !(isEventDefinitionEqual && isEventTypeEqual && isInterruptingEqual); } function addEntries(entries, filterFun) { // Filter selected type from the array var filteredEntries = filter(entries, filterFun); // Add entries to replace menu forEach(filteredEntries, function(definition) { var entry = addMenuEntry(definition); menuEntries.push(entry); }); } function addMenuEntry(definition) { return { label: definition.label, className: definition.className, id: definition.actionName, action: function() { return replaceElement(element, definition.target); } }; } return menuEntries; } /** * [function description] * @param {Object} position * @param {Object} element */ this.openChooser = function(position, element) { var entries = this.getReplaceOptions(element), headerEntries = []; if (is(element, 'bpmn:Activity')) { headerEntries = headerEntries.concat(this.getLoopEntries(element)); } if (is(element, 'bpmn:SubProcess') && !is(element, 'bpmn:Transaction')) { headerEntries.push(this.getAdHocEntry(element)); } popupMenu.open({ className: 'replace-menu', element: element, position: position, headerEntries: headerEntries, entries: entries }); }; this.getReplaceOptions = getReplaceOptions; this.getLoopEntries = getLoopEntries; this.getAdHocEntry = getAdHocEntry; this.replaceElement = replaceElement; } BpmnReplace.$inject = [ 'bpmnFactory', 'moddle', 'popupMenu', 'replace', 'selection', 'modeling', 'eventBus' ]; module.exports = BpmnReplace; },{"../../util/DiUtil":96,"../../util/ModelUtil":98,"./ReplaceOptions":86,"lodash/collection/filter":299,"lodash/collection/forEach":301,"lodash/object/assign":425,"lodash/object/pick":431}],86:[function(require,module,exports){ 'use strict'; module.exports.START_EVENT = [ { label: 'Start Event', actionName: 'replace-with-none-start', className: 'icon-start-event-none', target: { type: 'bpmn:StartEvent' } }, { label: 'Intermediate Throw Event', actionName: 'replace-with-none-intermediate-throwing', className: 'icon-intermediate-event-none', target: { type: 'bpmn:IntermediateThrowEvent' } }, { label: 'End Event', actionName: 'replace-with-none-end', className: 'icon-end-event-none', target: { type: 'bpmn:EndEvent' } }, { label: 'Message Start Event', actionName: 'replace-with-message-start', className: 'icon-start-event-message', target: { type: 'bpmn:StartEvent', eventDefinition: 'bpmn:MessageEventDefinition' } }, { label: 'Timer Start Event', actionName: 'replace-with-timer-start', className: 'icon-start-event-timer', target: { type: 'bpmn:StartEvent', eventDefinition: 'bpmn:TimerEventDefinition' } }, { label: 'Conditional Start Event', actionName: 'replace-with-conditional-start', className: 'icon-start-event-condition', target: { type: 'bpmn:StartEvent', eventDefinition: 'bpmn:ConditionalEventDefinition' } }, { label: 'Signal Start Event', actionName: 'replace-with-signal-start', className: 'icon-start-event-signal', target: { type: 'bpmn:StartEvent', eventDefinition: 'bpmn:SignalEventDefinition' } } ]; module.exports.INTERMEDIATE_EVENT = [ { label: 'Start Event', actionName: 'replace-with-none-start', className: 'icon-start-event-none', target: { type: 'bpmn:StartEvent' } }, { label: 'Intermediate Throw Event', actionName: 'replace-with-none-intermediate-throw', className: 'icon-intermediate-event-none', target: { type: 'bpmn:IntermediateThrowEvent' } }, { label: 'End Event', actionName: 'replace-with-none-end', className: 'icon-end-event-none', target: { type: 'bpmn:EndEvent' } }, { label: 'Message Intermediate Catch Event', actionName: 'replace-with-message-intermediate-catch', className: 'icon-intermediate-event-catch-message', target: { type: 'bpmn:IntermediateCatchEvent', eventDefinition: 'bpmn:MessageEventDefinition' } }, { label: 'Message Intermediate Throw Event', actionName: 'replace-with-message-intermediate-throw', className: 'icon-intermediate-event-throw-message', target: { type: 'bpmn:IntermediateThrowEvent', eventDefinition: 'bpmn:MessageEventDefinition' } }, { label: 'Timer Intermediate Catch Event', actionName: 'replace-with-timer-intermediate-catch', className: 'icon-intermediate-event-catch-timer', target: { type: 'bpmn:IntermediateCatchEvent', eventDefinition: 'bpmn:TimerEventDefinition' } }, { label: 'Escalation Intermediate Catch Event', actionName: 'replace-with-escalation-intermediate-catch', className: 'icon-intermediate-event-catch-escalation', target: { type: 'bpmn:IntermediateCatchEvent', eventDefinition: 'bpmn:EscalationEventDefinition' } }, { label: 'Conditional Intermediate Catch Event', actionName: 'replace-with-conditional-intermediate-catch', className: 'icon-intermediate-event-catch-condition', target: { type: 'bpmn:IntermediateCatchEvent', eventDefinition: 'bpmn:ConditionalEventDefinition' } }, { label: 'Link Intermediate Catch Event', actionName: 'replace-with-link-intermediate-catch', className: 'icon-intermediate-event-catch-link', target: { type: 'bpmn:IntermediateCatchEvent', eventDefinition: 'bpmn:LinkEventDefinition' } }, { label: 'Link Intermediate Throw Event', actionName: 'replace-with-link-intermediate-throw', className: 'icon-intermediate-event-throw-link', target: { type: 'bpmn:IntermediateThrowEvent', eventDefinition: 'bpmn:LinkEventDefinition' } }, { label: 'Compensation Intermediate Throw Event', actionName: 'replace-with-compensation-intermediate-throw', className: 'icon-intermediate-event-throw-compensation', target: { type: 'bpmn:IntermediateThrowEvent', eventDefinition: 'bpmn:CompensateEventDefinition' } }, { label: 'Signal Intermediate Catch Event', actionName: 'replace-with-signal-intermediate-catch', className: 'icon-intermediate-event-catch-signal', target: { type: 'bpmn:IntermediateCatchEvent', eventDefinition: 'bpmn:SignalEventDefinition' } }, { label: 'Signal Intermediate Throw Event', actionName: 'replace-with-signal-intermediate-throw', className: 'icon-intermediate-event-throw-signal', target: { type: 'bpmn:IntermediateThrowEvent', eventDefinition: 'bpmn:SignalEventDefinition' } } ]; module.exports.END_EVENT = [ { label: 'Start Event', actionName: 'replace-with-none-start', className: 'icon-start-event-none', target: { type: 'bpmn:StartEvent' } }, { label: 'Intermediate Throw Event', actionName: 'replace-with-none-intermediate-throw', className: 'icon-intermediate-event-none', target: { type: 'bpmn:IntermediateThrowEvent' } }, { label: 'End Event', actionName: 'replace-with-none-end', className: 'icon-end-event-none', target: { type: 'bpmn:EndEvent' } }, { label: 'Message End Event', actionName: 'replace-with-message-end', className: 'icon-end-event-message', target: { type: 'bpmn:EndEvent', eventDefinition: 'bpmn:MessageEventDefinition' } }, { label: 'Escalation End Event', actionName: 'replace-with-escalation-end', className: 'icon-end-event-escalation', target: { type: 'bpmn:EndEvent', eventDefinition: 'bpmn:EscalationEventDefinition' } }, { label: 'Error End Event', actionName: 'replace-with-error-end', className: 'icon-end-event-error', target: { type: 'bpmn:EndEvent', eventDefinition: 'bpmn:ErrorEventDefinition' } }, { label: 'Cancel End Event', actionName: 'replace-with-cancel-end', className: 'icon-end-event-cancel', target: { type: 'bpmn:EndEvent', eventDefinition: 'bpmn:CancelEventDefinition' } }, { label: 'Compensation End Event', actionName: 'replace-with-compensation-end', className: 'icon-end-event-compensation', target: { type: 'bpmn:EndEvent', eventDefinition: 'bpmn:CompensateEventDefinition' } }, { label: 'Signal End Event', actionName: 'replace-with-signal-end', className: 'icon-end-event-signal', target: { type: 'bpmn:EndEvent', eventDefinition: 'bpmn:SignalEventDefinition' } }, { label: 'Terminate End Event', actionName: 'replace-with-terminate-end', className: 'icon-end-event-terminate', target: { type: 'bpmn:EndEvent', eventDefinition: 'bpmn:TerminateEventDefinition' } } ]; module.exports.GATEWAY = [ { label: 'Exclusive Gateway', actionName: 'replace-with-exclusive-gateway', className: 'icon-gateway-xor', target: { type: 'bpmn:ExclusiveGateway' } }, { label: 'Parallel Gateway', actionName: 'replace-with-parallel-gateway', className: 'icon-gateway-parallel', target: { type: 'bpmn:ParallelGateway' } }, { label: 'Inclusive Gateway', actionName: 'replace-with-inclusive-gateway', className: 'icon-gateway-or', target: { type: 'bpmn:InclusiveGateway' } }, { label: 'Complex Gateway', actionName: 'replace-with-complex-gateway', className: 'icon-gateway-complex', target: { type: 'bpmn:ComplexGateway' } }, { label: 'Event based Gateway', actionName: 'replace-with-event-based-gateway', className: 'icon-gateway-eventbased', target: { type: 'bpmn:EventBasedGateway', instantiate: false, eventGatewayType: 'Exclusive' } } // Gateways deactivated until https://github.com/bpmn-io/bpmn-js/issues/194 // { // label: 'Event based instantiating Gateway', // actionName: 'replace-with-exclusive-event-based-gateway', // className: 'icon-exclusive-event-based', // target: { // type: 'bpmn:EventBasedGateway' // }, // options: { // businessObject: { instantiate: true, eventGatewayType: 'Exclusive' } // } // }, // { // label: 'Parallel Event based instantiating Gateway', // actionName: 'replace-with-parallel-event-based-instantiate-gateway', // className: 'icon-parallel-event-based-instantiate-gateway', // target: { // type: 'bpmn:EventBasedGateway' // }, // options: { // businessObject: { instantiate: true, eventGatewayType: 'Parallel' } // } // } ]; module.exports.SUBPROCESS_EXPANDED = [ { label: 'Transaction', actionName: 'replace-with-transaction', className: 'icon-transaction', target: { type: 'bpmn:Transaction', isExpanded: true } } ]; module.exports.TRANSACTION = [ { label: 'Sub Process', actionName: 'replace-with-subprocess', className: 'icon-subprocess-expanded', target: { type: 'bpmn:SubProcess' } } ]; module.exports.TASK = [ { label: 'Task', actionName: 'replace-with-task', className: 'icon-task', target: { type: 'bpmn:Task' } }, { label: 'Send Task', actionName: 'replace-with-send-task', className: 'icon-send', target: { type: 'bpmn:SendTask' } }, { label: 'Receive Task', actionName: 'replace-with-receive-task', className: 'icon-receive', target: { type: 'bpmn:ReceiveTask' } }, { label: 'User Task', actionName: 'replace-with-user-task', className: 'icon-user', target: { type: 'bpmn:UserTask' } }, { label: 'Manual Task', actionName: 'replace-with-manual-task', className: 'icon-manual', target: { type: 'bpmn:ManualTask' } }, { label: 'Business Rule Task', actionName: 'replace-with-rule-task', className: 'icon-business-rule', target: { type: 'bpmn:BusinessRuleTask' } }, { label: 'Service Task', actionName: 'replace-with-service-task', className: 'icon-service', target: { type: 'bpmn:ServiceTask' } }, { label: 'Script Task', actionName: 'replace-with-script-task', className: 'icon-script', target: { type: 'bpmn:ScriptTask' } }, { label: 'Call Activity', actionName: 'replace-with-call-activity', className: 'icon-call-activity', target: { type: 'bpmn:CallActivity' } }, { label: 'Sub Process (collapsed)', actionName: 'replace-with-collapsed-subprocess', className: 'icon-subprocess-collapsed', target: { type: 'bpmn:SubProcess', isExpanded: false } } ]; module.exports.BOUNDARY_EVENT = [ { label: 'Message Boundary Event', actionName: 'replace-with-message-boundary', className: 'icon-intermediate-event-catch-message', target: { type: 'bpmn:BoundaryEvent', eventDefinition: 'bpmn:MessageEventDefinition' } }, { label: 'Timer Boundary Event', actionName: 'replace-with-timer-boundary', className: 'icon-intermediate-event-catch-timer', target: { type: 'bpmn:BoundaryEvent', eventDefinition: 'bpmn:TimerEventDefinition' } }, { label: 'Escalation Boundary Event', actionName: 'replace-with-escalation-boundary', className: 'icon-intermediate-event-catch-escalation', target: { type: 'bpmn:BoundaryEvent', eventDefinition: 'bpmn:EscalationEventDefinition' } }, { label: 'Conditional Boundary Event', actionName: 'replace-with-conditional-boundary', className: 'icon-intermediate-event-catch-condition', target: { type: 'bpmn:BoundaryEvent', eventDefinition: 'bpmn:ConditionalEventDefinition' } }, { label: 'Error Boundary Event', actionName: 'replace-with-error-boundary', className: 'icon-intermediate-event-catch-error', target: { type: 'bpmn:BoundaryEvent', eventDefinition: 'bpmn:ErrorEventDefinition' } }, { label: 'Signal Boundary Event', actionName: 'replace-with-signal-boundary', className: 'icon-intermediate-event-catch-signal', target: { type: 'bpmn:BoundaryEvent', eventDefinition: 'bpmn:SignalEventDefinition' } }, { label: 'Message Boundary Event (non-interrupting)', actionName: 'replace-with-non-interrupting-message-boundary', className: 'icon-intermediate-event-catch-non-interrupting-message', target: { type: 'bpmn:BoundaryEvent', eventDefinition: 'bpmn:MessageEventDefinition', cancelActivity: false } }, { label: 'Timer Boundary Event (non-interrupting)', actionName: 'replace-with-non-interrupting-timer-boundary', className: 'icon-intermediate-event-catch-non-interrupting-timer', target: { type: 'bpmn:BoundaryEvent', eventDefinition: 'bpmn:TimerEventDefinition', cancelActivity: false } }, { label: 'Escalation Boundary Event (non-interrupting)', actionName: 'replace-with-non-interrupting-escalation-boundary', className: 'icon-intermediate-event-catch-non-interrupting-escalation', target: { type: 'bpmn:BoundaryEvent', eventDefinition: 'bpmn:EscalationEventDefinition', cancelActivity: false } }, { label: 'Conditional Boundary Event (non-interrupting)', actionName: 'replace-with-non-interrupting-conditional-boundary', className: 'icon-intermediate-event-catch-non-interrupting-condition', target: { type: 'bpmn:BoundaryEvent', eventDefinition: 'bpmn:ConditionalEventDefinition', cancelActivity: false } }, { label: 'Signal Boundary Event (non-interrupting)', actionName: 'replace-with-non-interrupting-signal-boundary', className: 'icon-intermediate-event-catch-non-interrupting-signal', target: { type: 'bpmn:BoundaryEvent', eventDefinition: 'bpmn:SignalEventDefinition', cancelActivity: false } }, ]; },{}],87:[function(require,module,exports){ module.exports = { __depends__: [ require('diagram-js/lib/features/popup-menu'), require('diagram-js/lib/features/replace'), require('diagram-js/lib/features/selection') ], bpmnReplace: [ 'type', require('./BpmnReplace') ] }; },{"./BpmnReplace":85,"diagram-js/lib/features/popup-menu":208,"diagram-js/lib/features/replace":210,"diagram-js/lib/features/selection":220}],88:[function(require,module,exports){ 'use strict'; var inherits = require('inherits'); var forEach = require('lodash/collection/forEach'); var getBoundingBox = require('diagram-js/lib/util/Elements').getBBox; var is = require('../modeling/ModelingUtil').is, isExpanded = require('../../util/DiUtil').isExpanded; var Snapping = require('diagram-js/lib/features/snapping/Snapping'), SnapUtil = require('diagram-js/lib/features/snapping/SnapUtil'); var is = require('../../util/ModelUtil').is; var round = Math.round; var mid = SnapUtil.mid, topLeft = SnapUtil.topLeft, bottomRight = SnapUtil.bottomRight, isSnapped = SnapUtil.isSnapped, setSnapped = SnapUtil.setSnapped, getBoundaryAttachment = require('./BpmnSnappingUtil').getBoundaryAttachment; /** * BPMN specific snapping functionality * * * snap on process elements if a pool is created inside a * process diagram * * @param {EventBus} eventBus * @param {Canvas} canvas */ function BpmnSnapping(eventBus, canvas, bpmnRules) { // instantiate super Snapping.call(this, eventBus, canvas); /** * Drop participant on process <> process elements snapping */ eventBus.on('create.start', function(event) { var context = event.context, shape = context.shape, rootElement = canvas.getRootElement(); // snap participant around existing elements (if any) if (is(shape, 'bpmn:Participant') && is(rootElement, 'bpmn:Process')) { initParticipantSnapping(context, shape, rootElement.children); } }); eventBus.on([ 'create.move', 'create.end' ], 1500, function(event) { var context = event.context, shape = context.shape, participantSnapBox = context.participantSnapBox; if (!isSnapped(event) && participantSnapBox) { snapParticipant(participantSnapBox, shape, event); } }); eventBus.on('shape.move.start', function(event) { var context = event.context, shape = context.shape, rootElement = canvas.getRootElement(); // snap participant around existing elements (if any) if (is(shape, 'bpmn:Participant') && is(rootElement, 'bpmn:Process')) { initParticipantSnapping(context, shape, rootElement.children); } }); function canAttach(shape, target, position) { return bpmnRules.canAttach([ shape ], target, null, position) === 'attach'; } /** * Snap boundary events to elements border */ eventBus.on([ 'create.move', 'create.end' ], 1500, function(event) { var context = event.context, target = context.target, shape = context.shape; if (target && !isSnapped(event) && canAttach(shape, target, event)) { snapBoundaryEvent(event, shape, target); } }); eventBus.on([ 'shape.move.move', 'shape.move.end' ], 1500, function(event) { var context = event.context, target = context.target, shape = context.shape; if (target && !isSnapped(event) && canAttach(shape, target, event)) { snapBoundaryEvent(event, shape, target); } }); eventBus.on('resize.start', 1500, function(event) { var context = event.context, shape = context.shape; if (is(shape, 'bpmn:SubProcess') && isExpanded(shape)) { context.minDimensions = { width: 140, height: 120 }; } if (is(shape, 'bpmn:Participant')) { context.minDimensions = { width: 300, height: 150 }; context.childrenBoxPadding = { left: 50, right: 35 }; } if (is(shape, 'bpmn:TextAnnotation')) { context.minDimensions = { width: 50, height: 50 }; } }); } inherits(BpmnSnapping, Snapping); BpmnSnapping.$inject = [ 'eventBus', 'canvas', 'bpmnRules' ]; module.exports = BpmnSnapping; BpmnSnapping.prototype.initSnap = function(event) { var context = event.context, shape = event.shape, shapeMid, shapeBounds, shapeTopLeft, shapeBottomRight, snapContext; snapContext = Snapping.prototype.initSnap.call(this, event); if (is(shape, 'bpmn:Participant')) { // assign higher priority for outer snaps on participants snapContext.setSnapLocations([ 'top-left', 'bottom-right', 'mid' ]); } if (shape) { shapeMid = mid(shape, event); shapeBounds = { width: shape.width, height: shape.height, x: isNaN(shape.x) ? round(shapeMid.x - shape.width / 2) : shape.x, y: isNaN(shape.y) ? round(shapeMid.y - shape.height / 2) : shape.y, }; shapeTopLeft = topLeft(shapeBounds); shapeBottomRight = bottomRight(shapeBounds); snapContext.setSnapOrigin('top-left', { x: shapeTopLeft.x - event.x, y: shapeTopLeft.y - event.y }); snapContext.setSnapOrigin('bottom-right', { x: shapeBottomRight.x - event.x, y: shapeBottomRight.y - event.y }); forEach(shape.outgoing, function(c) { var docking = c.waypoints[0]; docking = docking.original || docking; snapContext.setSnapOrigin(c.id + '-docking', { x: docking.x - event.x, y: docking.y - event.y }); }); forEach(shape.incoming, function(c) { var docking = c.waypoints[c.waypoints.length - 1]; docking = docking.original || docking; snapContext.setSnapOrigin(c.id + '-docking', { x: docking.x - event.x, y: docking.y - event.y }); }); } var source = context.source; if (source) { snapContext.addDefaultSnap('mid', mid(source)); } }; BpmnSnapping.prototype.addTargetSnaps = function(snapPoints, shape, target) { // use target parent as snap target if (is(shape, 'bpmn:BoundaryEvent')) { target = target.parent; } // add sequence flow parents as snap targets if (is(target, 'bpmn:SequenceFlow')) { this.addTargetSnaps(snapPoints, shape, target.parent); } var siblings = this.getSiblings(shape, target) || []; forEach(siblings, function(s) { snapPoints.add('mid', mid(s)); if (is(s, 'bpmn:Participant')) { snapPoints.add('top-left', topLeft(s)); snapPoints.add('bottom-right', bottomRight(s)); } }); forEach(shape.incoming, function(c) { if (siblings.indexOf(c.source) === -1) { snapPoints.add('mid', mid(c.source)); } var docking = c.waypoints[0]; snapPoints.add(c.id + '-docking', docking.original || docking); }); forEach(shape.outgoing, function(c) { if (siblings.indexOf(c.target) === -1) { snapPoints.add('mid', mid(c.target)); } var docking = c.waypoints[c.waypoints.length - 1]; snapPoints.add(c.id + '-docking', docking.original || docking); }); }; /////// participant snapping ////////////////// function initParticipantSnapping(context, shape, elements) { if (!elements.length) { return; } var snapBox = getBoundingBox(elements.filter(function(e) { return !e.labelTarget && !e.waypoints; })); snapBox.x -= 50; snapBox.y -= 20; snapBox.width += 70; snapBox.height += 40; // adjust shape height to include bounding box shape.width = Math.max(shape.width, snapBox.width); shape.height = Math.max(shape.height, snapBox.height); context.participantSnapBox = snapBox; } function snapParticipant(snapBox, shape, event, offset) { offset = offset || 0; var shapeHalfWidth = shape.width / 2 - offset, shapeHalfHeight = shape.height / 2; var currentTopLeft = { x: event.x - shapeHalfWidth - offset, y: event.y - shapeHalfHeight }; var currentBottomRight = { x: event.x + shapeHalfWidth + offset, y: event.y + shapeHalfHeight }; var snapTopLeft = snapBox, snapBottomRight = bottomRight(snapBox); if (currentTopLeft.x >= snapTopLeft.x) { setSnapped(event, 'x', snapTopLeft.x + offset + shapeHalfWidth); } else if (currentBottomRight.x <= snapBottomRight.x) { setSnapped(event, 'x', snapBottomRight.x - offset - shapeHalfWidth); } if (currentTopLeft.y >= snapTopLeft.y) { setSnapped(event, 'y', snapTopLeft.y + shapeHalfHeight); } else if (currentBottomRight.y <= snapBottomRight.y) { setSnapped(event, 'y', snapBottomRight.y - shapeHalfHeight); } } /////// boundary event snapping ///////////////////////// var LayoutUtil = require('diagram-js/lib/layout/LayoutUtil'); function snapBoundaryEvent(event, shape, target) { var targetTRBL = LayoutUtil.asTRBL(target); var direction = getBoundaryAttachment(event, target); if (/top/.test(direction)) { setSnapped(event, 'y', targetTRBL.top); } else if (/bottom/.test(direction)) { setSnapped(event, 'y', targetTRBL.bottom); } if (/left/.test(direction)) { setSnapped(event, 'x', targetTRBL.left); } else if (/right/.test(direction)) { setSnapped(event, 'x', targetTRBL.right); } } },{"../../util/DiUtil":96,"../../util/ModelUtil":98,"../modeling/ModelingUtil":69,"./BpmnSnappingUtil":89,"diagram-js/lib/features/snapping/SnapUtil":222,"diagram-js/lib/features/snapping/Snapping":223,"diagram-js/lib/layout/LayoutUtil":235,"diagram-js/lib/util/Elements":247,"inherits":126,"lodash/collection/forEach":301}],89:[function(require,module,exports){ 'use strict'; var getOrientation = require('diagram-js/lib/layout/LayoutUtil').getOrientation; module.exports.getBoundaryAttachment = function(position, targetBounds) { var orientation = getOrientation(position, targetBounds, -15); if (orientation !== 'intersect') { return orientation; } else { return null; } }; },{"diagram-js/lib/layout/LayoutUtil":235}],90:[function(require,module,exports){ module.exports = { __init__: [ 'snapping' ], snapping: [ 'type', require('./BpmnSnapping') ] }; },{"./BpmnSnapping":88}],91:[function(require,module,exports){ 'use strict'; var assign = require('lodash/object/assign'), map = require('lodash/collection/map'); var LabelUtil = require('../util/LabelUtil'); var is = require('../util/ModelUtil').is; var hasExternalLabel = LabelUtil.hasExternalLabel, getExternalLabelBounds = LabelUtil.getExternalLabelBounds, isExpanded = require('../util/DiUtil').isExpanded, elementToString = require('./Util').elementToString; function elementData(semantic, attrs) { return assign({ id: semantic.id, type: semantic.$type, businessObject: semantic }, attrs); } function collectWaypoints(waypoints) { return map(waypoints, function(p) { return { x: p.x, y: p.y }; }); } function notYetDrawn(semantic, refSemantic, property) { return new Error( 'element ' + elementToString(refSemantic) + ' referenced by ' + elementToString(semantic) + '#' + property + ' not yet drawn'); } /** * An importer that adds bpmn elements to the canvas * * @param {EventBus} eventBus * @param {Canvas} canvas * @param {ElementFactory} elementFactory * @param {ElementRegistry} elementRegistry */ function BpmnImporter(eventBus, canvas, elementFactory, elementRegistry) { this._eventBus = eventBus; this._canvas = canvas; this._elementFactory = elementFactory; this._elementRegistry = elementRegistry; } BpmnImporter.$inject = [ 'eventBus', 'canvas', 'elementFactory', 'elementRegistry' ]; module.exports = BpmnImporter; /** * Add bpmn element (semantic) to the canvas onto the * specified parent shape. */ BpmnImporter.prototype.add = function(semantic, parentElement) { var di = semantic.di, element; // ROOT ELEMENT // handle the special case that we deal with a // invisible root element (process or collaboration) if (di.$instanceOf('bpmndi:BPMNPlane')) { // add a virtual element (not being drawn) element = this._elementFactory.createRoot(elementData(semantic)); this._canvas.setRootElement(element); } // SHAPE else if (di.$instanceOf('bpmndi:BPMNShape')) { var collapsed = !isExpanded(semantic); var hidden = parentElement && (parentElement.hidden || parentElement.collapsed); var bounds = semantic.di.bounds; element = this._elementFactory.createShape(elementData(semantic, { collapsed: collapsed, hidden: hidden, x: Math.round(bounds.x), y: Math.round(bounds.y), width: Math.round(bounds.width), height: Math.round(bounds.height) })); if (is(semantic, 'bpmn:BoundaryEvent')) { this._attachBoundary(semantic, element); } this._canvas.addShape(element, parentElement); } // CONNECTION else if (di.$instanceOf('bpmndi:BPMNEdge')) { var source = this._getSource(semantic), target = this._getTarget(semantic); element = this._elementFactory.createConnection(elementData(semantic, { source: source, target: target, waypoints: collectWaypoints(semantic.di.waypoint) })); this._canvas.addConnection(element, parentElement); } else { throw new Error('unknown di ' + elementToString(di) + ' for element ' + elementToString(semantic)); } // (optional) LABEL if (hasExternalLabel(semantic)) { this.addLabel(semantic, element); } this._eventBus.fire('bpmnElement.added', { element: element }); return element; }; /** * Attach the boundary element to the given host * * @param {ModdleElement} boundarySemantic * @param {djs.model.Base} boundaryElement */ BpmnImporter.prototype._attachBoundary = function(boundarySemantic, boundaryElement) { var hostSemantic = boundarySemantic.attachedToRef; if (!hostSemantic) { throw new Error('missing ' + elementToString(boundarySemantic) + '#attachedToRef'); } var host = this._elementRegistry.get(hostSemantic.id), attachers = host && host.attachers; if (!host) { throw notYetDrawn(boundarySemantic, hostSemantic, 'attachedToRef'); } // wire element.host <> host.attachers boundaryElement.host = host; if (!attachers) { host.attachers = attachers = []; } if (attachers.indexOf(boundaryElement) === -1) { attachers.push(boundaryElement); } }; /** * add label for an element */ BpmnImporter.prototype.addLabel = function(semantic, element) { var bounds = getExternalLabelBounds(semantic, element); var label = this._elementFactory.createLabel(elementData(semantic, { id: semantic.id + '_label', labelTarget: element, type: 'label', hidden: element.hidden, x: Math.round(bounds.x), y: Math.round(bounds.y), width: Math.round(bounds.width), height: Math.round(bounds.height) })); return this._canvas.addShape(label, element.parent); }; /** * Return the drawn connection end based on the given side. * * @throws {Error} if the end is not yet drawn */ BpmnImporter.prototype._getEnd = function(semantic, side) { var element, refSemantic, type = semantic.$type; refSemantic = semantic[side + 'Ref']; // handle mysterious isMany DataAssociation#sourceRef if (side === 'source' && type === 'bpmn:DataInputAssociation') { refSemantic = refSemantic && refSemantic[0]; } // fix source / target for DataInputAssociation / DataOutputAssociation if (side === 'source' && type === 'bpmn:DataOutputAssociation' || side === 'target' && type === 'bpmn:DataInputAssociation') { refSemantic = semantic.$parent; } element = refSemantic && this._getElement(refSemantic); if (element) { return element; } if (refSemantic) { throw notYetDrawn(semantic, refSemantic, side + 'Ref'); } else { throw new Error(elementToString(semantic) + '#' + side + 'Ref not specified'); } }; BpmnImporter.prototype._getSource = function(semantic) { return this._getEnd(semantic, 'source'); }; BpmnImporter.prototype._getTarget = function(semantic) { return this._getEnd(semantic, 'target'); }; BpmnImporter.prototype._getElement = function(semantic) { return this._elementRegistry.get(semantic.id); }; },{"../util/DiUtil":96,"../util/LabelUtil":97,"../util/ModelUtil":98,"./Util":94,"lodash/collection/map":305,"lodash/object/assign":425}],92:[function(require,module,exports){ 'use strict'; var filter = require('lodash/collection/filter'), find = require('lodash/collection/find'), forEach = require('lodash/collection/forEach'); var Refs = require('object-refs'); var elementToString = require('./Util').elementToString; var diRefs = new Refs({ name: 'bpmnElement', enumerable: true }, { name: 'di' }); /** * Returns true if an element has the given meta-model type * * @param {ModdleElement} element * @param {String} type * * @return {Boolean} */ function is(element, type) { return element.$instanceOf(type); } /** * Find a suitable display candidate for definitions where the DI does not * correctly specify one. */ function findDisplayCandidate(definitions) { return find(definitions.rootElements, function(e) { return is(e, 'bpmn:Process') || is(e, 'bpmn:Collaboration'); }); } function BpmnTreeWalker(handler) { // list of containers already walked var handledProcesses = []; // list of elements to handle deferred to ensure // prerequisites are drawn var deferred = []; ///// Helpers ///////////////////////////////// function contextual(fn, ctx) { return function(e) { fn(e, ctx); }; } function visit(element, ctx) { var gfx = element.gfx; // avoid multiple rendering of elements if (gfx) { throw new Error('already rendered ' + elementToString(element)); } // call handler return handler.element(element, ctx); } function visitRoot(element, diagram) { return handler.root(element, diagram); } function visitIfDi(element, ctx) { try { return element.di && visit(element, ctx); } catch (e) { logError(e.message, { element: element, error: e }); console.error('failed to import ' + elementToString(element)); console.error(e); } } function logError(message, context) { handler.error(message, context); } ////// DI handling //////////////////////////// function registerDi(di) { var bpmnElement = di.bpmnElement; if (bpmnElement) { if (bpmnElement.di) { logError('multiple DI elements defined for ' + elementToString(bpmnElement), { element: bpmnElement }); } else { diRefs.bind(bpmnElement, 'di'); bpmnElement.di = di; } } else { logError('no bpmnElement referenced in ' + elementToString(di), { element: di }); } } function handleDiagram(diagram) { handlePlane(diagram.plane); } function handlePlane(plane) { registerDi(plane); forEach(plane.planeElement, handlePlaneElement); } function handlePlaneElement(planeElement) { registerDi(planeElement); } ////// Semantic handling ////////////////////// function handleDefinitions(definitions, diagram) { // make sure we walk the correct bpmnElement var diagrams = definitions.diagrams; if (diagram && diagrams.indexOf(diagram) === -1) { throw new Error('diagram not part of bpmn:Definitions'); } if (!diagram && diagrams && diagrams.length) { diagram = diagrams[0]; } // no diagram -> nothing to import if (!diagram) { return; } // load DI from selected diagram only handleDiagram(diagram); var plane = diagram.plane; if (!plane) { throw new Error('no plane for ' + elementToString(diagram)); } var rootElement = plane.bpmnElement; // ensure we default to a suitable display candidate (process or collaboration), // even if non is specified in DI if (!rootElement) { rootElement = findDisplayCandidate(definitions); if (!rootElement) { return logError('no process or collaboration present to display'); } else { logError('correcting missing bpmnElement on ' + elementToString(plane) + ' to ' + elementToString(rootElement)); // correct DI on the fly plane.bpmnElement = rootElement; registerDi(plane); } } var ctx = visitRoot(rootElement, plane); if (is(rootElement, 'bpmn:Process')) { handleProcess(rootElement, ctx); } else if (is(rootElement, 'bpmn:Collaboration')) { handleCollaboration(rootElement, ctx); // force drawing of everything not yet drawn that is part of the target DI handleUnhandledProcesses(definitions.rootElements, ctx); } else { throw new Error('unsupported bpmnElement for ' + elementToString(plane) + ' : ' + elementToString(rootElement)); } // handle all deferred elements handleDeferred(deferred); } function handleDeferred(deferred) { forEach(deferred, function(d) { d(); }); } function handleProcess(process, context) { handleFlowElementsContainer(process, context); handleIoSpecification(process.ioSpecification, context); handleArtifacts(process.artifacts, context); // log process handled handledProcesses.push(process); } function handleUnhandledProcesses(rootElements) { // walk through all processes that have not yet been drawn and draw them // if they contain lanes with DI information. // we do this to pass the free-floating lane test cases in the MIWG test suite var processes = filter(rootElements, function(e) { return is(e, 'bpmn:Process') && e.laneSets && handledProcesses.indexOf(e) === -1; }); processes.forEach(contextual(handleProcess)); } function handleMessageFlow(messageFlow, context) { visitIfDi(messageFlow, context); } function handleMessageFlows(messageFlows, context) { forEach(messageFlows, contextual(handleMessageFlow, context)); } function handleDataAssociation(association, context) { visitIfDi(association, context); } function handleDataInput(dataInput, context) { visitIfDi(dataInput, context); } function handleDataOutput(dataOutput, context) { visitIfDi(dataOutput, context); } function handleArtifact(artifact, context) { // bpmn:TextAnnotation // bpmn:Group // bpmn:Association visitIfDi(artifact, context); } function handleArtifacts(artifacts, context) { forEach(artifacts, function(e) { if (is(e, 'bpmn:Association')) { deferred.push(function() { handleArtifact(e, context); }); } else { handleArtifact(e, context); } }); } function handleIoSpecification(ioSpecification, context) { if (!ioSpecification) { return; } forEach(ioSpecification.dataInputs, contextual(handleDataInput, context)); forEach(ioSpecification.dataOutputs, contextual(handleDataOutput, context)); } function handleSubProcess(subProcess, context) { handleFlowElementsContainer(subProcess, context); handleArtifacts(subProcess.artifacts, context); } function handleFlowNode(flowNode, context) { var childCtx = visitIfDi(flowNode, context); if (is(flowNode, 'bpmn:SubProcess')) { handleSubProcess(flowNode, childCtx || context); } } function handleSequenceFlow(sequenceFlow, context) { visitIfDi(sequenceFlow, context); } function handleDataElement(dataObject, context) { visitIfDi(dataObject, context); } function handleBoundaryEvent(dataObject, context) { visitIfDi(dataObject, context); } function handleLane(lane, context) { var newContext = visitIfDi(lane, context); if (lane.childLaneSet) { handleLaneSet(lane.childLaneSet, newContext || context); } else { var filterList = filter(lane.flowNodeRef, function(e) { return e.$type !== 'bpmn:BoundaryEvent'; }); handleFlowElements(filterList, newContext || context); } } function handleLaneSet(laneSet, context) { forEach(laneSet.lanes, contextual(handleLane, context)); } function handleLaneSets(laneSets, context) { forEach(laneSets, contextual(handleLaneSet, context)); } function handleFlowElementsContainer(container, context) { if (container.laneSets) { handleLaneSets(container.laneSets, context); handleNonFlowNodes(container.flowElements); } else { handleFlowElements(container.flowElements, context); } } function handleNonFlowNodes(flowElements, context) { forEach(flowElements, function(e) { if (is(e, 'bpmn:SequenceFlow')) { deferred.push(function() { handleSequenceFlow(e, context); }); } else if (is(e, 'bpmn:BoundaryEvent')) { deferred.unshift(function() { handleBoundaryEvent(e, context); }); } else if (is(e, 'bpmn:DataObject')) { // SKIP (assume correct referencing via DataObjectReference) } else if (is(e, 'bpmn:DataStoreReference')) { handleDataElement(e, context); } else if (is(e, 'bpmn:DataObjectReference')) { handleDataElement(e, context); } }); } function handleFlowElements(flowElements, context) { forEach(flowElements, function(e) { if (is(e, 'bpmn:SequenceFlow')) { deferred.push(function() { handleSequenceFlow(e, context); }); } else if (is(e, 'bpmn:BoundaryEvent')) { deferred.unshift(function() { handleBoundaryEvent(e, context); }); } else if (is(e, 'bpmn:FlowNode')) { handleFlowNode(e, context); if (is(e, 'bpmn:Activity')) { handleIoSpecification(e.ioSpecification, context); // defer handling of associations deferred.push(function() { forEach(e.dataInputAssociations, contextual(handleDataAssociation, context)); forEach(e.dataOutputAssociations, contextual(handleDataAssociation, context)); }); } } else if (is(e, 'bpmn:DataObject')) { // SKIP (assume correct referencing via DataObjectReference) } else if (is(e, 'bpmn:DataStoreReference')) { handleDataElement(e, context); } else if (is(e, 'bpmn:DataObjectReference')) { handleDataElement(e, context); } else { logError( 'unrecognized flowElement ' + elementToString(e) + ' in context ' + (context ? elementToString(context.businessObject) : null), { element: e, context: context }); } }); } function handleParticipant(participant, context) { var newCtx = visitIfDi(participant, context); var process = participant.processRef; if (process) { handleProcess(process, newCtx || context); } } function handleCollaboration(collaboration) { forEach(collaboration.participants, contextual(handleParticipant)); handleArtifacts(collaboration.artifacts); // handle message flows latest in the process deferred.push(function() { handleMessageFlows(collaboration.messageFlows); }); } ///// API //////////////////////////////// return { handleDefinitions: handleDefinitions }; } module.exports = BpmnTreeWalker; },{"./Util":94,"lodash/collection/filter":299,"lodash/collection/find":300,"lodash/collection/forEach":301,"object-refs":134}],93:[function(require,module,exports){ 'use strict'; var BpmnTreeWalker = require('./BpmnTreeWalker'); /** * Import the definitions into a diagram. * * Errors and warnings are reported through the specified callback. * * @param {Diagram} diagram * @param {ModdleElement} definitions * @param {Function} done the callback, invoked with (err, [ warning ]) once the import is done */ function importBpmnDiagram(diagram, definitions, done) { var importer = diagram.get('bpmnImporter'), eventBus = diagram.get('eventBus'); var error, warnings = []; function parse(definitions) { var visitor = { root: function(element) { return importer.add(element); }, element: function(element, parentShape) { return importer.add(element, parentShape); }, error: function(message, context) { warnings.push({ message: message, context: context }); } }; var walker = new BpmnTreeWalker(visitor); // import walker.handleDefinitions(definitions); } eventBus.fire('import.start'); try { parse(definitions); } catch (e) { error = e; } eventBus.fire(error ? 'import.error' : 'import.success', { error: error, warnings: warnings }); done(error, warnings); } module.exports.importBpmnDiagram = importBpmnDiagram; },{"./BpmnTreeWalker":92}],94:[function(require,module,exports){ 'use strict'; module.exports.elementToString = function(e) { if (!e) { return ''; } return '<' + e.$type + (e.id ? ' id="' + e.id : '') + '" />'; }; },{}],95:[function(require,module,exports){ module.exports = { bpmnImporter: [ 'type', require('./BpmnImporter') ] }; },{"./BpmnImporter":91}],96:[function(require,module,exports){ 'use strict'; var is = require('./ModelUtil').is, getBusinessObject = require('./ModelUtil').getBusinessObject; module.exports.isExpanded = function(element) { if (is(element, 'bpmn:CallActivity')) { return false; } if (is(element, 'bpmn:SubProcess')) { return getBusinessObject(element).di.isExpanded; } if (is(element, 'bpmn:Participant')) { return !!getBusinessObject(element).processRef; } return true; }; },{"./ModelUtil":98}],97:[function(require,module,exports){ 'use strict'; var assign = require('lodash/object/assign'); var DEFAULT_LABEL_SIZE = module.exports.DEFAULT_LABEL_SIZE = { width: 90, height: 20 }; /** * Returns true if the given semantic has an external label * * @param {BpmnElement} semantic * @return {Boolean} true if has label */ module.exports.hasExternalLabel = function(semantic) { return semantic.$instanceOf('bpmn:Event') || semantic.$instanceOf('bpmn:Gateway') || semantic.$instanceOf('bpmn:DataStoreReference') || semantic.$instanceOf('bpmn:DataObjectReference') || semantic.$instanceOf('bpmn:SequenceFlow') || semantic.$instanceOf('bpmn:MessageFlow'); }; /** * Get the middle of a number of waypoints * * @param {Array} waypoints * @return {Point} the mid point */ var getWaypointsMid = module.exports.getWaypointsMid = function(waypoints) { var mid = waypoints.length / 2 - 1; var first = waypoints[Math.floor(mid)]; var second = waypoints[Math.ceil(mid + 0.01)]; return { x: first.x + (second.x - first.x) / 2, y: first.y + (second.y - first.y) / 2 }; }; var getExternalLabelMid = module.exports.getExternalLabelMid = function(element) { if (element.waypoints) { return getWaypointsMid(element.waypoints); } else { return { x: element.x + element.width / 2, y: element.y + element.height + DEFAULT_LABEL_SIZE.height / 2 }; } }; /** * Returns the bounds of an elements label, parsed from the elements DI or * generated from its bounds. * * @param {BpmnElement} semantic * @param {djs.model.Base} element */ module.exports.getExternalLabelBounds = function(semantic, element) { var mid, size, bounds, di = semantic.di, label = di.label; if (label && label.bounds) { bounds = label.bounds; size = { width: Math.max(DEFAULT_LABEL_SIZE.width, bounds.width), height: bounds.height }; mid = { x: bounds.x + bounds.width / 2, y: bounds.y + bounds.height / 2 }; } else { mid = getExternalLabelMid(element); size = DEFAULT_LABEL_SIZE; } return assign({ x: mid.x - size.width / 2, y: mid.y - size.height / 2 }, size); }; },{"lodash/object/assign":425}],98:[function(require,module,exports){ 'use strict'; /** * Is an element of the given BPMN type? * * @param {djs.model.Base|ModdleElement} element * @param {String} type * * @return {Boolean} */ function is(element, type) { var bo = getBusinessObject(element); return bo && bo.$instanceOf(type); } module.exports.is = is; /** * Return the business object for a given element. * * @param {djs.model.Base|ModdleElement} element * * @return {ModdleElement} */ function getBusinessObject(element) { return (element && element.businessObject) || element; } module.exports.getBusinessObject = getBusinessObject; },{}],99:[function(require,module,exports){ module.exports = require('./lib/simple'); },{"./lib/simple":102}],100:[function(require,module,exports){ 'use strict'; var isString = require('lodash/lang/isString'), isFunction = require('lodash/lang/isFunction'), assign = require('lodash/object/assign'); var Moddle = require('moddle'), XmlReader = require('moddle-xml/lib/reader'), XmlWriter = require('moddle-xml/lib/writer'); /** * A sub class of {@link Moddle} with support for import and export of BPMN 2.0 xml files. * * @class BpmnModdle * @extends Moddle * * @param {Object|Array} packages to use for instantiating the model * @param {Object} [options] additional options to pass over */ function BpmnModdle(packages, options) { Moddle.call(this, packages, options); } BpmnModdle.prototype = Object.create(Moddle.prototype); module.exports = BpmnModdle; /** * Instantiates a BPMN model tree from a given xml string. * * @param {String} xmlStr * @param {String} [typeName='bpmn:Definitions'] name of the root element * @param {Object} [options] options to pass to the underlying reader * @param {Function} done callback that is invoked with (err, result, parseContext) * once the import completes */ BpmnModdle.prototype.fromXML = function(xmlStr, typeName, options, done) { if (!isString(typeName)) { done = options; options = typeName; typeName = 'bpmn:Definitions'; } if (isFunction(options)) { done = options; options = {}; } var reader = new XmlReader(assign({ model: this, lax: true }, options)); var rootHandler = reader.handler(typeName); reader.fromXML(xmlStr, rootHandler, done); }; /** * Serializes a BPMN 2.0 object tree to XML. * * @param {String} element the root element, typically an instance of `bpmn:Definitions` * @param {Object} [options] to pass to the underlying writer * @param {Function} done callback invoked with (err, xmlStr) once the import completes */ BpmnModdle.prototype.toXML = function(element, options, done) { if (isFunction(options)) { done = options; options = {}; } var writer = new XmlWriter(options); try { var result = writer.toXML(element); done(null, result); } catch (e) { done(e); } }; },{"lodash/lang/isFunction":417,"lodash/lang/isString":422,"lodash/object/assign":425,"moddle":108,"moddle-xml/lib/reader":104,"moddle-xml/lib/writer":105}],101:[function(require,module,exports){ 'use strict'; var ID_PATTERN = /^(.*:)?id$/; /** * Extends the bpmn instance with id support. * * @example * * var moddle, ids; * * require('id-support').extend(moddle, ids); * * moddle.ids.next(); // create a next id * moddle.ids; // ids instance * * // claims id as used * moddle.create('foo:Bar', { id: 'fooobar1' }); * * * @param {Moddle} model * @param {Ids} ids * * @return {Moddle} the extended moddle instance */ module.exports.extend = function(model, ids) { var set = model.properties.set; // do not reinitialize setter // unless it is already initialized if (!model.ids) { model.properties.set = function(target, property, value) { // ensure we log used ids once they are assigned // to model elements if (ID_PATTERN.test(property)) { var assigned = model.ids.assigned(value); if (assigned && assigned !== target) { throw new Error('id <' + value + '> already used'); } model.ids.claim(value, target); } set.call(this, target, property, value); }; } model.ids = ids; return model; }; },{}],102:[function(require,module,exports){ 'use strict'; var assign = require('lodash/object/assign'); var BpmnModdle = require('./bpmn-moddle'); var packages = { bpmn: require('../resources/bpmn/json/bpmn.json'), bpmndi: require('../resources/bpmn/json/bpmndi.json'), dc: require('../resources/bpmn/json/dc.json'), di: require('../resources/bpmn/json/di.json') }; module.exports = function(additionalPackages, options) { return new BpmnModdle(assign({}, packages, additionalPackages), options); }; },{"../resources/bpmn/json/bpmn.json":117,"../resources/bpmn/json/bpmndi.json":118,"../resources/bpmn/json/dc.json":119,"../resources/bpmn/json/di.json":120,"./bpmn-moddle":100,"lodash/object/assign":425}],103:[function(require,module,exports){ 'use strict'; function capitalize(string) { return string.charAt(0).toUpperCase() + string.slice(1); } function lower(string) { return string.charAt(0).toLowerCase() + string.slice(1); } function hasLowerCaseAlias(pkg) { return pkg.xml && pkg.xml.tagAlias === 'lowerCase'; } module.exports.aliasToName = function(alias, pkg) { if (hasLowerCaseAlias(pkg)) { return capitalize(alias); } else { return alias; } }; module.exports.nameToAlias = function(name, pkg) { if (hasLowerCaseAlias(pkg)) { return lower(name); } else { return name; } }; module.exports.DEFAULT_NS_MAP = { 'xsi': 'http://www.w3.org/2001/XMLSchema-instance' }; var XSI_TYPE = module.exports.XSI_TYPE = 'xsi:type'; function serializeFormat(element) { return element.xml && element.xml.serialize; } module.exports.serializeAsType = function(element) { return serializeFormat(element) === XSI_TYPE; }; module.exports.serializeAsProperty = function(element) { return serializeFormat(element) === 'property'; }; },{}],104:[function(require,module,exports){ 'use strict'; var reduce = require('lodash/collection/reduce'), forEach = require('lodash/collection/forEach'), find = require('lodash/collection/find'), assign = require('lodash/object/assign'), defer = require('lodash/function/defer'); var Stack = require('tiny-stack'), SaxParser = require('sax').parser, Moddle = require('moddle'), parseNameNs = require('moddle/lib/ns').parseName, Types = require('moddle/lib/types'), coerceType = Types.coerceType, isSimpleType = Types.isSimple, common = require('./common'), XSI_TYPE = common.XSI_TYPE, XSI_URI = common.DEFAULT_NS_MAP.xsi, serializeAsType = common.serializeAsType, aliasToName = common.aliasToName; function parseNodeAttributes(node) { var nodeAttrs = node.attributes; return reduce(nodeAttrs, function(result, v, k) { var name, ns; if (!v.local) { name = v.prefix; } else { ns = parseNameNs(v.name, v.prefix); name = ns.name; } result[name] = v.value; return result; }, {}); } function normalizeType(node, attr, model) { var nameNs = parseNameNs(attr.value); var uri = node.ns[nameNs.prefix || ''], localName = nameNs.localName, pkg = uri && model.getPackage(uri), typePrefix; if (pkg) { typePrefix = pkg.xml && pkg.xml.typePrefix; if (typePrefix && localName.indexOf(typePrefix) === 0) { localName = localName.slice(typePrefix.length); } attr.value = pkg.prefix + ':' + localName; } } /** * Normalizes namespaces for a node given an optional default namespace and a * number of mappings from uris to default prefixes. * * @param {XmlNode} node * @param {Model} model the model containing all registered namespaces * @param {Uri} defaultNsUri */ function normalizeNamespaces(node, model, defaultNsUri) { var uri, prefix; uri = node.uri || defaultNsUri; if (uri) { var pkg = model.getPackage(uri); if (pkg) { prefix = pkg.prefix; } else { prefix = node.prefix; } node.prefix = prefix; node.uri = uri; } forEach(node.attributes, function(attr) { // normalize xsi:type attributes because the // assigned type may or may not be namespace prefixed if (attr.uri === XSI_URI && attr.local === 'type') { normalizeType(node, attr, model); } normalizeNamespaces(attr, model, null); }); } /** * A parse context. * * @class * * @param {Object} options * @param {ElementHandler} options.parseRoot the root handler for parsing a document * @param {boolean} [options.lax=false] whether or not to ignore invalid elements */ function Context(options) { /** * @property {ElementHandler} parseRoot */ /** * @property {Boolean} lax */ assign(this, options); var elementsById = this.elementsById = {}; var references = this.references = []; var warnings = this.warnings = []; this.addReference = function(reference) { references.push(reference); }; this.addElement = function(id, element) { if (!id || !element) { throw new Error('[xml-reader] id or ctx must not be null'); } elementsById[id] = element; }; this.addWarning = function (w) { warnings.push(w); }; } function BaseHandler() {} BaseHandler.prototype.handleEnd = function() {}; BaseHandler.prototype.handleText = function() {}; BaseHandler.prototype.handleNode = function() {}; /** * A simple pass through handler that does nothing except for * ignoring all input it receives. * * This is used to ignore unknown elements and * attributes. */ function NoopHandler() { } NoopHandler.prototype = new BaseHandler(); NoopHandler.prototype.handleNode = function() { return this; }; function BodyHandler() {} BodyHandler.prototype = new BaseHandler(); BodyHandler.prototype.handleText = function(text) { this.body = (this.body || '') + text; }; function ReferenceHandler(property, context) { this.property = property; this.context = context; } ReferenceHandler.prototype = new BodyHandler(); ReferenceHandler.prototype.handleNode = function(node) { if (this.element) { throw new Error('expected no sub nodes'); } else { this.element = this.createReference(node); } return this; }; ReferenceHandler.prototype.handleEnd = function() { this.element.id = this.body; }; ReferenceHandler.prototype.createReference = function() { return { property: this.property.ns.name, id: '' }; }; function ValueHandler(propertyDesc, element) { this.element = element; this.propertyDesc = propertyDesc; } ValueHandler.prototype = new BodyHandler(); ValueHandler.prototype.handleEnd = function() { var value = this.body, element = this.element, propertyDesc = this.propertyDesc; value = coerceType(propertyDesc.type, value); if (propertyDesc.isMany) { element.get(propertyDesc.name).push(value); } else { element.set(propertyDesc.name, value); } }; function BaseElementHandler() {} BaseElementHandler.prototype = Object.create(BodyHandler.prototype); BaseElementHandler.prototype.handleNode = function(node) { var parser = this, element = this.element, id; if (!element) { element = this.element = this.createElement(node); id = element.id; if (id) { this.context.addElement(id, element); } } else { parser = this.handleChild(node); } return parser; }; /** * @class XMLReader.ElementHandler * */ function ElementHandler(model, type, context) { this.model = model; this.type = model.getType(type); this.context = context; } ElementHandler.prototype = new BaseElementHandler(); ElementHandler.prototype.addReference = function(reference) { this.context.addReference(reference); }; ElementHandler.prototype.handleEnd = function() { var value = this.body, element = this.element, descriptor = element.$descriptor, bodyProperty = descriptor.bodyProperty; if (bodyProperty && value !== undefined) { value = coerceType(bodyProperty.type, value); element.set(bodyProperty.name, value); } }; /** * Create an instance of the model from the given node. * * @param {Element} node the xml node */ ElementHandler.prototype.createElement = function(node) { var attributes = parseNodeAttributes(node), Type = this.type, descriptor = Type.$descriptor, context = this.context, instance = new Type({}); forEach(attributes, function(value, name) { var prop = descriptor.propertiesByName[name]; if (prop && prop.isReference) { context.addReference({ element: instance, property: prop.ns.name, id: value }); } else { if (prop) { value = coerceType(prop.type, value); } instance.set(name, value); } }); return instance; }; ElementHandler.prototype.getPropertyForNode = function(node) { var nameNs = parseNameNs(node.local, node.prefix); var type = this.type, model = this.model, descriptor = type.$descriptor; var propertyName = nameNs.name, property = descriptor.propertiesByName[propertyName], elementTypeName, elementType, typeAnnotation; // search for properties by name first if (property) { if (serializeAsType(property)) { typeAnnotation = node.attributes[XSI_TYPE]; // xsi type is optional, if it does not exists the // default type is assumed if (typeAnnotation) { elementTypeName = typeAnnotation.value; // TODO: extract real name from attribute elementType = model.getType(elementTypeName); return assign({}, property, { effectiveType: elementType.$descriptor.name }); } } // search for properties by name first return property; } var pkg = model.getPackage(nameNs.prefix); if (pkg) { elementTypeName = nameNs.prefix + ':' + aliasToName(nameNs.localName, descriptor.$pkg); elementType = model.getType(elementTypeName); // search for collection members later property = find(descriptor.properties, function(p) { return !p.isVirtual && !p.isReference && !p.isAttribute && elementType.hasType(p.type); }); if (property) { return assign({}, property, { effectiveType: elementType.$descriptor.name }); } } else { // parse unknown element (maybe extension) property = find(descriptor.properties, function(p) { return !p.isReference && !p.isAttribute && p.type === 'Element'; }); if (property) { return property; } } throw new Error('unrecognized element <' + nameNs.name + '>'); }; ElementHandler.prototype.toString = function() { return 'ElementDescriptor[' + this.type.$descriptor.name + ']'; }; ElementHandler.prototype.valueHandler = function(propertyDesc, element) { return new ValueHandler(propertyDesc, element); }; ElementHandler.prototype.referenceHandler = function(propertyDesc) { return new ReferenceHandler(propertyDesc, this.context); }; ElementHandler.prototype.handler = function(type) { if (type === 'Element') { return new GenericElementHandler(this.model, type, this.context); } else { return new ElementHandler(this.model, type, this.context); } }; /** * Handle the child element parsing * * @param {Element} node the xml node */ ElementHandler.prototype.handleChild = function(node) { var propertyDesc, type, element, childHandler; propertyDesc = this.getPropertyForNode(node); element = this.element; type = propertyDesc.effectiveType || propertyDesc.type; if (isSimpleType(type)) { return this.valueHandler(propertyDesc, element); } if (propertyDesc.isReference) { childHandler = this.referenceHandler(propertyDesc).handleNode(node); } else { childHandler = this.handler(type).handleNode(node); } var newElement = childHandler.element; // child handles may decide to skip elements // by not returning anything if (newElement !== undefined) { if (propertyDesc.isMany) { element.get(propertyDesc.name).push(newElement); } else { element.set(propertyDesc.name, newElement); } if (propertyDesc.isReference) { assign(newElement, { element: element }); this.context.addReference(newElement); } else { // establish child -> parent relationship newElement.$parent = element; } } return childHandler; }; function GenericElementHandler(model, type, context) { this.model = model; this.context = context; } GenericElementHandler.prototype = Object.create(BaseElementHandler.prototype); GenericElementHandler.prototype.createElement = function(node) { var name = node.name, prefix = node.prefix, uri = node.ns[prefix], attributes = node.attributes; return this.model.createAny(name, uri, attributes); }; GenericElementHandler.prototype.handleChild = function(node) { var handler = new GenericElementHandler(this.model, 'Element', this.context).handleNode(node), element = this.element; var newElement = handler.element, children; if (newElement !== undefined) { children = element.$children = element.$children || []; children.push(newElement); // establish child -> parent relationship newElement.$parent = element; } return handler; }; GenericElementHandler.prototype.handleText = function(text) { this.body = this.body || '' + text; }; GenericElementHandler.prototype.handleEnd = function() { if (this.body) { this.element.$body = this.body; } }; /** * A reader for a meta-model * * @param {Object} options * @param {Model} options.model used to read xml files * @param {Boolean} options.lax whether to make parse errors warnings */ function XMLReader(options) { if (options instanceof Moddle) { options = { model: options }; } assign(this, { lax: false }, options); } XMLReader.prototype.fromXML = function(xml, rootHandler, done) { var model = this.model, lax = this.lax, context = new Context({ parseRoot: rootHandler }); var parser = new SaxParser(true, { xmlns: true, trim: true }), stack = new Stack(); rootHandler.context = context; // push root handler stack.push(rootHandler); function resolveReferences() { var elementsById = context.elementsById; var references = context.references; var i, r; for (i = 0; !!(r = references[i]); i++) { var element = r.element; var reference = elementsById[r.id]; var property = element.$descriptor.propertiesByName[r.property]; if (!reference) { context.addWarning({ message: 'unresolved reference <' + r.id + '>', element: r.element, property: r.property, value: r.id }); } if (property.isMany) { var collection = element.get(property.name), idx = collection.indexOf(r); if (!reference) { // remove unresolvable reference collection.splice(idx, 1); } else { // update reference collection[idx] = reference; } } else { element.set(property.name, reference); } } } function handleClose(tagName) { stack.pop().handleEnd(); } function handleOpen(node) { var handler = stack.peek(); normalizeNamespaces(node, model); try { stack.push(handler.handleNode(node)); } catch (e) { var line = this.line, column = this.column; var message = 'unparsable content <' + node.name + '> detected\n\t' + 'line: ' + line + '\n\t' + 'column: ' + column + '\n\t' + 'nested error: ' + e.message; if (lax) { context.addWarning({ message: message, error: e }); console.warn('could not parse node'); console.warn(e); stack.push(new NoopHandler()); } else { console.error('could not parse document'); console.error(e); throw new Error(message); } } } function handleText(text) { stack.peek().handleText(text); } parser.onopentag = handleOpen; parser.oncdata = parser.ontext = handleText; parser.onclosetag = handleClose; parser.onend = resolveReferences; // deferred parse XML to make loading really ascnchronous // this ensures the execution environment (node or browser) // is kept responsive and that certain optimization strategies // can kick in defer(function() { var error; try { parser.write(xml).close(); } catch (e) { error = e; } done(error, error ? undefined : rootHandler.element, context); }); }; XMLReader.prototype.handler = function(name) { return new ElementHandler(this.model, name); }; module.exports = XMLReader; module.exports.ElementHandler = ElementHandler; },{"./common":103,"lodash/collection/find":300,"lodash/collection/forEach":301,"lodash/collection/reduce":306,"lodash/function/defer":313,"lodash/object/assign":425,"moddle":108,"moddle/lib/ns":113,"moddle/lib/types":116,"sax":106,"tiny-stack":107}],105:[function(require,module,exports){ 'use strict'; var map = require('lodash/collection/map'), forEach = require('lodash/collection/forEach'), isString = require('lodash/lang/isString'), filter = require('lodash/collection/filter'), assign = require('lodash/object/assign'); var Types = require('moddle/lib/types'), parseNameNs = require('moddle/lib/ns').parseName, common = require('./common'), nameToAlias = common.nameToAlias, serializeAsType = common.serializeAsType, serializeAsProperty = common.serializeAsProperty; var XML_PREAMBLE = '\n', ESCAPE_CHARS = /(<|>|'|"|&|\n\r|\n)/g, DEFAULT_NS_MAP = common.DEFAULT_NS_MAP, XSI_TYPE = common.XSI_TYPE; function nsName(ns) { if (isString(ns)) { return ns; } else { return (ns.prefix ? ns.prefix + ':' : '') + ns.localName; } } function getElementNs(ns, descriptor) { if (descriptor.isGeneric) { return descriptor.name; } else { return assign({ localName: nameToAlias(descriptor.ns.localName, descriptor.$pkg) }, ns); } } function getPropertyNs(ns, descriptor) { return assign({ localName: descriptor.ns.localName }, ns); } function getSerializableProperties(element) { var descriptor = element.$descriptor; return filter(descriptor.properties, function(p) { var name = p.name; // do not serialize defaults if (!element.hasOwnProperty(name)) { return false; } var value = element[name]; // do not serialize default equals if (value === p.default) { return false; } return p.isMany ? value.length : true; }); } var ESCAPE_MAP = { '\n': '10', '\n\r': '10', '"': '34', '\'': '39', '<': '60', '>': '62', '&': '38' }; /** * Escape a string attribute to not contain any bad values (line breaks, '"', ...) * * @param {String} str the string to escape * @return {String} the escaped string */ function escapeAttr(str) { // ensure we are handling strings here str = isString(str) ? str : '' + str; return str.replace(ESCAPE_CHARS, function(str) { return '&#' + ESCAPE_MAP[str] + ';'; }); } function filterAttributes(props) { return filter(props, function(p) { return p.isAttr; }); } function filterContained(props) { return filter(props, function(p) { return !p.isAttr; }); } function ReferenceSerializer(parent, ns) { this.ns = ns; } ReferenceSerializer.prototype.build = function(element) { this.element = element; return this; }; ReferenceSerializer.prototype.serializeTo = function(writer) { writer .appendIndent() .append('<' + nsName(this.ns) + '>' + this.element.id + '') .appendNewLine(); }; function BodySerializer() {} BodySerializer.prototype.serializeValue = BodySerializer.prototype.serializeTo = function(writer) { var escape = this.escape; if (escape) { writer.append(''); } }; BodySerializer.prototype.build = function(prop, value) { this.value = value; if (prop.type === 'String' && ESCAPE_CHARS.test(value)) { this.escape = true; } return this; }; function ValueSerializer(ns) { this.ns = ns; } ValueSerializer.prototype = new BodySerializer(); ValueSerializer.prototype.serializeTo = function(writer) { writer .appendIndent() .append('<' + nsName(this.ns) + '>'); this.serializeValue(writer); writer .append( '') .appendNewLine(); }; function ElementSerializer(parent, ns) { this.body = []; this.attrs = []; this.parent = parent; this.ns = ns; } ElementSerializer.prototype.build = function(element) { this.element = element; var otherAttrs = this.parseNsAttributes(element); if (!this.ns) { this.ns = this.nsTagName(element.$descriptor); } if (element.$descriptor.isGeneric) { this.parseGeneric(element); } else { var properties = getSerializableProperties(element); this.parseAttributes(filterAttributes(properties)); this.parseContainments(filterContained(properties)); this.parseGenericAttributes(element, otherAttrs); } return this; }; ElementSerializer.prototype.nsTagName = function(descriptor) { var effectiveNs = this.logNamespaceUsed(descriptor.ns); return getElementNs(effectiveNs, descriptor); }; ElementSerializer.prototype.nsPropertyTagName = function(descriptor) { var effectiveNs = this.logNamespaceUsed(descriptor.ns); return getPropertyNs(effectiveNs, descriptor); }; ElementSerializer.prototype.isLocalNs = function(ns) { return ns.uri === this.ns.uri; }; ElementSerializer.prototype.nsAttributeName = function(element) { var ns; if (isString(element)) { ns = parseNameNs(element); } else if (element.ns) { ns = element.ns; } var effectiveNs = this.logNamespaceUsed(ns); // strip prefix if same namespace like parent if (this.isLocalNs(effectiveNs)) { return { localName: ns.localName }; } else { return assign({ localName: ns.localName }, effectiveNs); } }; ElementSerializer.prototype.parseGeneric = function(element) { var self = this, body = this.body, attrs = this.attrs; forEach(element, function(val, key) { if (key === '$body') { body.push(new BodySerializer().build({ type: 'String' }, val)); } else if (key === '$children') { forEach(val, function(child) { body.push(new ElementSerializer(self).build(child)); }); } else if (key.indexOf('$') !== 0) { attrs.push({ name: key, value: escapeAttr(val) }); } }); }; /** * Parse namespaces and return a list of left over generic attributes * * @param {Object} element * @return {Array} */ ElementSerializer.prototype.parseNsAttributes = function(element) { var self = this; var genericAttrs = element.$attrs; var attributes = []; // parse namespace attributes first // and log them. push non namespace attributes to a list // and process them later forEach(genericAttrs, function(value, name) { var nameNs = parseNameNs(name); if (nameNs.prefix === 'xmlns') { self.logNamespace({ prefix: nameNs.localName, uri: value }); } else if (!nameNs.prefix && nameNs.localName === 'xmlns') { self.logNamespace({ uri: value }); } else { attributes.push({ name: name, value: value }); } }); return attributes; }; ElementSerializer.prototype.parseGenericAttributes = function(element, attributes) { var self = this; forEach(attributes, function(attr) { // do not serialize xsi:type attribute // it is set manually based on the actual implementation type if (attr.name === XSI_TYPE) { return; } try { self.addAttribute(self.nsAttributeName(attr.name), attr.value); } catch (e) { console.warn('[writer] missing namespace information for ', attr.name, '=', attr.value, 'on', element, e); } }); }; ElementSerializer.prototype.parseContainments = function(properties) { var self = this, body = this.body, element = this.element; forEach(properties, function(p) { var value = element.get(p.name), isReference = p.isReference, isMany = p.isMany; var ns = self.nsPropertyTagName(p); if (!isMany) { value = [ value ]; } if (p.isBody) { body.push(new BodySerializer().build(p, value[0])); } else if (Types.isSimple(p.type)) { forEach(value, function(v) { body.push(new ValueSerializer(ns).build(p, v)); }); } else if (isReference) { forEach(value, function(v) { body.push(new ReferenceSerializer(self, ns).build(v)); }); } else { // allow serialization via type // rather than element name var asType = serializeAsType(p), asProperty = serializeAsProperty(p); forEach(value, function(v) { var serializer; if (asType) { serializer = new TypeSerializer(self, ns); } else if (asProperty) { serializer = new ElementSerializer(self, ns); } else { serializer = new ElementSerializer(self); } body.push(serializer.build(v)); }); } }); }; ElementSerializer.prototype.getNamespaces = function() { if (!this.parent) { if (!this.namespaces) { this.namespaces = { prefixMap: {}, uriMap: {}, used: {} }; } } else { this.namespaces = this.parent.getNamespaces(); } return this.namespaces; }; ElementSerializer.prototype.logNamespace = function(ns) { var namespaces = this.getNamespaces(); var existing = namespaces.uriMap[ns.uri]; if (!existing) { namespaces.uriMap[ns.uri] = ns; } namespaces.prefixMap[ns.prefix] = ns.uri; return ns; }; ElementSerializer.prototype.logNamespaceUsed = function(ns) { var element = this.element, model = element.$model, namespaces = this.getNamespaces(); // ns may be // // * prefix only // * prefix:uri var prefix = ns.prefix; var uri = ns.uri || DEFAULT_NS_MAP[prefix] || namespaces.prefixMap[prefix] || (model ? (model.getPackage(prefix) || {}).uri : null); if (!uri) { throw new Error('no namespace uri given for prefix <' + ns.prefix + '>'); } ns = namespaces.uriMap[uri]; if (!ns) { ns = this.logNamespace({ prefix: prefix, uri: uri }); } if (!namespaces.used[ns.uri]) { namespaces.used[ns.uri] = ns; } return ns; }; ElementSerializer.prototype.parseAttributes = function(properties) { var self = this, element = this.element; forEach(properties, function(p) { self.logNamespaceUsed(p.ns); var value = element.get(p.name); if (p.isReference) { value = value.id; } self.addAttribute(self.nsAttributeName(p), value); }); }; ElementSerializer.prototype.addAttribute = function(name, value) { var attrs = this.attrs; if (isString(value)) { value = escapeAttr(value); } attrs.push({ name: name, value: value }); }; ElementSerializer.prototype.serializeAttributes = function(writer) { var attrs = this.attrs, root = !this.parent, namespaces = this.namespaces; function collectNsAttrs() { return map(namespaces.used, function(ns) { var name = 'xmlns' + (ns.prefix ? ':' + ns.prefix : ''); return { name: name, value: ns.uri }; }); } if (root) { attrs = collectNsAttrs().concat(attrs); } forEach(attrs, function(a) { writer .append(' ') .append(nsName(a.name)).append('="').append(a.value).append('"'); }); }; ElementSerializer.prototype.serializeTo = function(writer) { var hasBody = this.body.length, indent = !(this.body.length === 1 && this.body[0] instanceof BodySerializer); writer .appendIndent() .append('<' + nsName(this.ns)); this.serializeAttributes(writer); writer.append(hasBody ? '>' : ' />'); if (hasBody) { if (indent) { writer .appendNewLine() .indent(); } forEach(this.body, function(b) { b.serializeTo(writer); }); if (indent) { writer .unindent() .appendIndent(); } writer.append(''); } writer.appendNewLine(); }; /** * A serializer for types that handles serialization of data types */ function TypeSerializer(parent, ns) { ElementSerializer.call(this, parent, ns); } TypeSerializer.prototype = new ElementSerializer(); TypeSerializer.prototype.build = function(element) { var descriptor = element.$descriptor; this.element = element; this.typeNs = this.nsTagName(descriptor); // add xsi:type attribute to represent the elements // actual type var typeNs = this.typeNs, pkg = element.$model.getPackage(typeNs.uri), typePrefix = (pkg.xml && pkg.xml.typePrefix) || ''; this.addAttribute(this.nsAttributeName(XSI_TYPE), (typeNs.prefix ? typeNs.prefix + ':' : '') + typePrefix + descriptor.ns.localName); // do the usual stuff return ElementSerializer.prototype.build.call(this, element); }; TypeSerializer.prototype.isLocalNs = function(ns) { return ns.uri === this.typeNs.uri; }; function SavingWriter() { this.value = ''; this.write = function(str) { this.value += str; }; } function FormatingWriter(out, format) { var indent = ['']; this.append = function(str) { out.write(str); return this; }; this.appendNewLine = function() { if (format) { out.write('\n'); } return this; }; this.appendIndent = function() { if (format) { out.write(indent.join(' ')); } return this; }; this.indent = function() { indent.push(''); return this; }; this.unindent = function() { indent.pop(); return this; }; } /** * A writer for meta-model backed document trees * * @param {Object} options output options to pass into the writer */ function XMLWriter(options) { options = assign({ format: false, preamble: true }, options || {}); function toXML(tree, writer) { var internalWriter = writer || new SavingWriter(); var formatingWriter = new FormatingWriter(internalWriter, options.format); if (options.preamble) { formatingWriter.append(XML_PREAMBLE); } new ElementSerializer().build(tree).serializeTo(formatingWriter); if (!writer) { return internalWriter.value; } } return { toXML: toXML }; } module.exports = XMLWriter; },{"./common":103,"lodash/collection/filter":299,"lodash/collection/forEach":301,"lodash/collection/map":305,"lodash/lang/isString":422,"lodash/object/assign":425,"moddle/lib/ns":113,"moddle/lib/types":116}],106:[function(require,module,exports){ (function (Buffer){ // wrapper for non-node envs ;(function (sax) { sax.parser = function (strict, opt) { return new SAXParser(strict, opt) } sax.SAXParser = SAXParser sax.SAXStream = SAXStream sax.createStream = createStream // When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns. // When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)), // since that's the earliest that a buffer overrun could occur. This way, checks are // as rare as required, but as often as necessary to ensure never crossing this bound. // Furthermore, buffers are only tested at most once per write(), so passing a very // large string into write() might have undesirable effects, but this is manageable by // the caller, so it is assumed to be safe. Thus, a call to write() may, in the extreme // edge case, result in creating at most one complete copy of the string passed in. // Set to Infinity to have unlimited buffers. sax.MAX_BUFFER_LENGTH = 64 * 1024 var buffers = [ "comment", "sgmlDecl", "textNode", "tagName", "doctype", "procInstName", "procInstBody", "entity", "attribName", "attribValue", "cdata", "script" ] sax.EVENTS = // for discoverability. [ "text" , "processinginstruction" , "sgmldeclaration" , "doctype" , "comment" , "attribute" , "opentag" , "closetag" , "opencdata" , "cdata" , "closecdata" , "error" , "end" , "ready" , "script" , "opennamespace" , "closenamespace" ] function SAXParser (strict, opt) { if (!(this instanceof SAXParser)) return new SAXParser(strict, opt) var parser = this clearBuffers(parser) parser.q = parser.c = "" parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH parser.opt = opt || {} parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags parser.looseCase = parser.opt.lowercase ? "toLowerCase" : "toUpperCase" parser.tags = [] parser.closed = parser.closedRoot = parser.sawRoot = false parser.tag = parser.error = null parser.strict = !!strict parser.noscript = !!(strict || parser.opt.noscript) parser.state = S.BEGIN parser.ENTITIES = Object.create(sax.ENTITIES) parser.attribList = [] // namespaces form a prototype chain. // it always points at the current tag, // which protos to its parent tag. if (parser.opt.xmlns) parser.ns = Object.create(rootNS) // mostly just for error reporting parser.trackPosition = parser.opt.position !== false if (parser.trackPosition) { parser.position = parser.line = parser.column = 0 } emit(parser, "onready") } if (!Object.create) Object.create = function (o) { function f () { this.__proto__ = o } f.prototype = o return new f } if (!Object.getPrototypeOf) Object.getPrototypeOf = function (o) { return o.__proto__ } if (!Object.keys) Object.keys = function (o) { var a = [] for (var i in o) if (o.hasOwnProperty(i)) a.push(i) return a } function checkBufferLength (parser) { var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10) , maxActual = 0 for (var i = 0, l = buffers.length; i < l; i ++) { var len = parser[buffers[i]].length if (len > maxAllowed) { // Text/cdata nodes can get big, and since they're buffered, // we can get here under normal conditions. // Avoid issues by emitting the text node now, // so at least it won't get any bigger. switch (buffers[i]) { case "textNode": closeText(parser) break case "cdata": emitNode(parser, "oncdata", parser.cdata) parser.cdata = "" break case "script": emitNode(parser, "onscript", parser.script) parser.script = "" break default: error(parser, "Max buffer length exceeded: "+buffers[i]) } } maxActual = Math.max(maxActual, len) } // schedule the next check for the earliest possible buffer overrun. parser.bufferCheckPosition = (sax.MAX_BUFFER_LENGTH - maxActual) + parser.position } function clearBuffers (parser) { for (var i = 0, l = buffers.length; i < l; i ++) { parser[buffers[i]] = "" } } function flushBuffers (parser) { closeText(parser) if (parser.cdata !== "") { emitNode(parser, "oncdata", parser.cdata) parser.cdata = "" } if (parser.script !== "") { emitNode(parser, "onscript", parser.script) parser.script = "" } } SAXParser.prototype = { end: function () { end(this) } , write: write , resume: function () { this.error = null; return this } , close: function () { return this.write(null) } , flush: function () { flushBuffers(this) } } try { var Stream = require("stream").Stream } catch (ex) { var Stream = function () {} } var streamWraps = sax.EVENTS.filter(function (ev) { return ev !== "error" && ev !== "end" }) function createStream (strict, opt) { return new SAXStream(strict, opt) } function SAXStream (strict, opt) { if (!(this instanceof SAXStream)) return new SAXStream(strict, opt) Stream.apply(this) this._parser = new SAXParser(strict, opt) this.writable = true this.readable = true var me = this this._parser.onend = function () { me.emit("end") } this._parser.onerror = function (er) { me.emit("error", er) // if didn't throw, then means error was handled. // go ahead and clear error, so we can write again. me._parser.error = null } this._decoder = null; streamWraps.forEach(function (ev) { Object.defineProperty(me, "on" + ev, { get: function () { return me._parser["on" + ev] }, set: function (h) { if (!h) { me.removeAllListeners(ev) return me._parser["on"+ev] = h } me.on(ev, h) }, enumerable: true, configurable: false }) }) } SAXStream.prototype = Object.create(Stream.prototype, { constructor: { value: SAXStream } }) SAXStream.prototype.write = function (data) { if (typeof Buffer === 'function' && typeof Buffer.isBuffer === 'function' && Buffer.isBuffer(data)) { if (!this._decoder) { var SD = require('string_decoder').StringDecoder this._decoder = new SD('utf8') } data = this._decoder.write(data); } this._parser.write(data.toString()) this.emit("data", data) return true } SAXStream.prototype.end = function (chunk) { if (chunk && chunk.length) this.write(chunk) this._parser.end() return true } SAXStream.prototype.on = function (ev, handler) { var me = this if (!me._parser["on"+ev] && streamWraps.indexOf(ev) !== -1) { me._parser["on"+ev] = function () { var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments) args.splice(0, 0, ev) me.emit.apply(me, args) } } return Stream.prototype.on.call(me, ev, handler) } // character classes and tokens var whitespace = "\r\n\t " // this really needs to be replaced with character classes. // XML allows all manner of ridiculous numbers and digits. , number = "0124356789" , letter = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" // (Letter | "_" | ":") , quote = "'\"" , entity = number+letter+"#" , attribEnd = whitespace + ">" , CDATA = "[CDATA[" , DOCTYPE = "DOCTYPE" , XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace" , XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/" , rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE } // turn all the string character sets into character class objects. whitespace = charClass(whitespace) number = charClass(number) letter = charClass(letter) // http://www.w3.org/TR/REC-xml/#NT-NameStartChar // This implementation works on strings, a single character at a time // as such, it cannot ever support astral-plane characters (10000-EFFFF) // without a significant breaking change to either this parser, or the // JavaScript language. Implementation of an emoji-capable xml parser // is left as an exercise for the reader. var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/ var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040\.\d-]/ quote = charClass(quote) entity = charClass(entity) attribEnd = charClass(attribEnd) function charClass (str) { return str.split("").reduce(function (s, c) { s[c] = true return s }, {}) } function isRegExp (c) { return Object.prototype.toString.call(c) === '[object RegExp]' } function is (charclass, c) { return isRegExp(charclass) ? !!c.match(charclass) : charclass[c] } function not (charclass, c) { return !is(charclass, c) } var S = 0 sax.STATE = { BEGIN : S++ , TEXT : S++ // general stuff , TEXT_ENTITY : S++ // & and such. , OPEN_WAKA : S++ // < , SGML_DECL : S++ // , SCRIPT : S++ //