/*! * bpmn-js - bpmn-modeler v0.14.1 * Copyright 2014, 2015 camunda Services GmbH and other contributors * * Released under the bpmn.io license * http://bpmn.io/license * * Source Code: https://github.com/bpmn-io/bpmn-js * * Date: 2016-03-23 */ (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' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + ''; /** * 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); // hook ID collection into the modeler this.on('import.parse.complete', function(event) { if (!event.error) { this._collectIds(event.definitions, event.context); } }, this); this.on('diagram.destroy', function() { this.moddle.ids.clear(); }, this); } inherits(Modeler, Viewer); module.exports = Modeler; /** * Create a new diagram to start modeling. * * @param {Function} [done] */ Modeler.prototype.createDiagram = function(done) { return this.importXML(initialDiagram, done); }; /** * Create a moddle instance, attaching ids to it. * * @param {Object} options */ Modeler.prototype._createModdle = function(options) { var moddle = Viewer.prototype._createModdle.call(this, options); // attach ids to moddle to be able to track // and validated ids in the BPMN 2.0 XML document // tree moddle.ids = new Ids([ 32, 36, 1 ]); return moddle; }; /** * Collect ids processed during parsing of the * definitions object. * * @param {ModdleElement} definitions * @param {Context} context */ Modeler.prototype._collectIds = function(definitions, context) { var moddle = definitions.$model, ids = moddle.ids, id; // remove references from previous import ids.clear(); for (id in context.elementsById) { ids.claim(id, context.elementsById[id]); } }; Modeler.prototype._interactionModules = [ // non-modeling components _dereq_(16), _dereq_(8), _dereq_(216), _dereq_(212), _dereq_(213) ]; Modeler.prototype._modelingModules = [ // modeling components _dereq_(166), _dereq_(118), _dereq_(182), _dereq_(196), _dereq_(141), _dereq_(133), _dereq_(12), _dereq_(62), _dereq_(43), _dereq_(10), _dereq_(49), _dereq_(54) ]; // 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); },{"10":10,"118":118,"12":12,"133":133,"141":141,"16":16,"166":166,"182":182,"196":196,"2":2,"212":212,"213":213,"216":216,"241":241,"243":243,"43":43,"49":49,"54":54,"62":62,"8":8}],2:[function(_dereq_,module,exports){ /** * The code in the area * must not be changed. * * @see http://bpmn.io/license for more information. */ 'use strict'; var assign = _dereq_(377), omit = _dereq_(381), isString = _dereq_(374), isNumber = _dereq_(371); var domify = _dereq_(394), domQuery = _dereq_(397), domRemove = _dereq_(398); var Diagram = _dereq_(96), BpmnModdle = _dereq_(72); var inherits = _dereq_(243); var Importer = _dereq_(65); 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) { options = assign({}, DEFAULT_OPTIONS, options); this.moddle = this._createModdle(options); this.container = this._createContainer(options); /* */ addProjectLogo(this.container); /* */ this._init(this.container, this.moddle, options); } inherits(Viewer, Diagram); module.exports = Viewer; /** * Parse and render a BPMN 2.0 diagram. * * Once finished the viewer reports back the result to the * provided callback function with (err, warnings). * * ## Life-Cycle Events * * During import the viewer will fire life-cycle events: * * * import.parse.start (about to read model from xml) * * import.parse.complete (model read; may have worked or not) * * import.render.start (graphical import start) * * import.render.complete (graphical import finished) * * import.done (everything done) * * You can use these events to hook into the life-cycle. * * @param {String} xml the BPMN 2.0 xml * @param {Function} [done] invoked with (err, warnings=[]) */ Viewer.prototype.importXML = function(xml, done) { // done is optional done = done || function() {}; var self = this; // hook in pre-parse listeners + // allow xml manipulation xml = this._emit('import.parse.start', { xml: xml }) || xml; this.moddle.fromXML(xml, 'bpmn:Definitions', function(err, definitions, context) { // hook in post parse listeners + // allow definitions manipulation definitions = self._emit('import.parse.complete', { error: err, definitions: definitions, context: context }) || definitions; if (err) { err = checkValidationError(err); self._emit('import.done', { error: err }); return done(err); } var parseWarnings = context.warnings; self.importDefinitions(definitions, function(err, importWarnings) { var allWarnings = [].concat(parseWarnings, importWarnings || []); self._emit('import.done', { error: err, warnings: allWarnings }); done(err, allWarnings); }); }); }; /** * Export the currently displayed BPMN 2.0 diagram as * a BPMN 2.0 XML document. * * @param {Object} [options] export options * @param {Boolean} [options.format=false] output formated XML * @param {Boolean} [options.preamble=true] output preamble * * @param {Function} done invoked with (err, xml) */ 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); }; /** * Export the currently displayed BPMN 2.0 diagram as * an SVG image. * * @param {Object} [options] * @param {Function} done invoked with (err, svgStr) */ 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); }; /** * Get a named diagram service. * * @example * * var elementRegistry = viewer.get('elementRegistry'); * var startEventShape = elementRegistry.get('StartEvent_1'); * * @param {String} name * * @return {Object} diagram service instance * * @method Viewer#get */ /** * Invoke a function in the context of this viewer. * * @example * * viewer.invoke(function(elementRegistry) { * var startEventShape = elementRegistry.get('StartEvent_1'); * }); * * @param {Function} fn to be invoked * * @return {Object} the functions return value * * @method Viewer#invoke */ /** * Remove all drawn elements from the viewer. * * After calling this method the viewer can still * be reused for opening another diagram. * * @method Viewer#clear */ Viewer.prototype.importDefinitions = function(definitions, done) { // use try/catch to not swallow synchronous exceptions // that may be raised during model parsing try { if (this.definitions) { // clear existing rendered diagram this.clear(); } // update definitions this.definitions = definitions; // perform graphical import Importer.importBpmnDiagram(this, definitions, done); } catch (e) { // handle synchronous errors done(e); } }; Viewer.prototype.getModules = function() { return this._modules; }; /** * Destroy the viewer instance and remove all its * remainders from the document tree. */ Viewer.prototype.destroy = function() { // diagram destroy Diagram.prototype.destroy.call(this); // dom detach domRemove(this.container); }; /** * Register an event listener * * Remove a previously added listener via {@link #off(event, callback)}. * * @param {String} event * @param {Number} [priority] * @param {Function} callback * @param {Object} [that] */ Viewer.prototype.on = function(event, priority, callback, target) { return this.get('eventBus').on(event, priority, callback, target); }; /** * De-register an event listener * * @param {String} event * @param {Function} callback */ Viewer.prototype.off = function(event, callback) { this.get('eventBus').off(event, callback); }; Viewer.prototype._init = function(container, moddle, options) { var baseModules = options.modules || this.getModules(), additionalModules = options.additionalModules || [], staticModules = [ { bpmnjs: [ 'value', this ], moddle: [ 'value', moddle ] } ]; var diagramModules = [].concat(staticModules, baseModules, additionalModules); var diagramOptions = assign(omit(options, 'additionalModules'), { canvas: assign({}, options.canvas, { container: container }), modules: diagramModules }); // invoke diagram constructor Diagram.call(this, diagramOptions); }; /** * Emit an event on the underlying {@link EventBus} * * @param {String} type * @param {Object} event * * @return {Object} event processing result (if any) */ Viewer.prototype._emit = function(type, event) { return this.get('eventBus').fire(type, event); }; Viewer.prototype._createContainer = function(options) { var parent = options.container, container; // support jquery element // unwrap it if passed if (parent.get) { parent = parent.get(0); } // support selector if (isString(parent)) { parent = domQuery(parent); } container = domify('
'); assign(container.style, { width: ensureUnit(options.width), height: ensureUnit(options.height), position: options.position }); parent.appendChild(container); return container; }; Viewer.prototype._createModdle = function(options) { var moddleOptions = assign({}, this._moddleExtensions, options.moddleExtensions); return new BpmnModdle(moddleOptions); }; // modules the viewer is composed of Viewer.prototype._modules = [ _dereq_(3), _dereq_(204), _dereq_(189), _dereq_(171) ]; // default moddle extensions the viewer is composed of Viewer.prototype._moddleExtensions = {}; /* */ var PoweredBy = _dereq_(71), domEvent = _dereq_(395); /** * Adds the project logo to the diagram container as * required by the bpmn.io license. * * @see http://bpmn.io/license * * @param {Element} container */ function addProjectLogo(container) { var logoData = PoweredBy.BPMNIO_LOGO; var linkMarkup = '' + '' + ''; var linkElement = domify(linkMarkup); container.appendChild(linkElement); domEvent.bind(linkElement, 'click', function(event) { PoweredBy.open(); event.preventDefault(); }); } /* */ },{"171":171,"189":189,"204":204,"243":243,"3":3,"371":371,"374":374,"377":377,"381":381,"394":394,"395":395,"397":397,"398":398,"65":65,"71":71,"72":72,"96":96}],3:[function(_dereq_,module,exports){ module.exports = { __depends__: [ _dereq_(6), _dereq_(67) ] }; },{"6":6,"67":67}],4:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243), isObject = _dereq_(372), assign = _dereq_(377), forEach = _dereq_(255), every = _dereq_(252), includes = _dereq_(257), some = _dereq_(261); var BaseRenderer = _dereq_(107), TextUtil = _dereq_(232), DiUtil = _dereq_(68); var is = _dereq_(70).is; var RenderUtil = _dereq_(231); var componentsToPath = RenderUtil.componentsToPath, createLine = RenderUtil.createLine; var TASK_BORDER_RADIUS = 10; var INNER_OUTER_DIST = 3; var LABEL_STYLE = { fontFamily: 'Arial, sans-serif', fontSize: '12px' }; function BpmnRenderer(eventBus, styles, pathMap, priority) { BaseRenderer.call(this, eventBus, priority); var textUtil = new TextUtil({ style: LABEL_STYLE, size: { width: 100 } }); var markers = {}; var computeStyle = styles.computeStyle; 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('association-start', { element: svg.path('M 11 5 L 1 10 L 11 15'), attrs: { fill: 'none', stroke: 'black', strokeWidth: 1.5 }, ref: { x: 1, y: 10 }, scale: 0.5 }); createMarker('association-end', { element: svg.path('M 1 5 L 11 10 L 1 15'), attrs: { fill: 'none', stroke: 'black', strokeWidth: 1.5 }, ref: { x: 12, 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 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 drawMarker(type, p, path, attrs) { return drawPath(p, path, assign({ 'data-marker': type }, 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); 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 = this.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.22, my: 0.5 } }); 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) { attrs = assign({ fillOpacity: 0.95 }, attrs); var rect = renderer('bpmn:Activity')(p, element, attrs); var expanded = DiUtil.isExpanded(element); var isEventSubProcess = DiUtil.isEventSubProcess(element); 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:SubProcess')(p, element, { strokeWidth: 5 }); }, 'bpmn:Participant': function(p, element) { var lane = renderer('bpmn:Lane')(p, element, { fillOpacity: 0.95, 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:Activity')) { path.attr({ markerStart: marker('conditional-flow-marker') }); } // default marker if (source.default && (source.$instanceOf('bpmn:Gateway') || source.$instanceOf('bpmn:Activity')) && source.default === sequenceFlow) { path.attr({ markerStart: marker('conditional-default-flow-marker') }); } return path; }, 'bpmn:Association': function(p, element, attrs) { var semantic = getSemantic(element); attrs = assign({ strokeDasharray: '0.5, 5', strokeLinecap: 'round', strokeLinejoin: 'round' }, attrs || {}); if (semantic.associationDirection === 'One' || semantic.associationDirection === 'Both') { attrs.markerEnd = marker('association-end'); } if (semantic.associationDirection === 'Both') { attrs.markerStart = marker('association-start'); } return drawLine(p, element.waypoints, attrs); }, 'bpmn:DataInputAssociation': function(p, element) { return renderer('bpmn:Association')(p, element, { markerEnd: marker('association-end') }); }, 'bpmn:DataOutputAssociation': function(p, element) { return renderer('bpmn:Association')(p, element, { markerEnd: marker('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 markerPath = 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 } }); drawMarker('participant-multiplicity', p, markerPath); }, '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 markerPath = 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 } }); drawMarker('sub-process', p, markerPath); }, 'ParallelMarker': function(p, element, position) { var markerPath = 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 } }); drawMarker('parallel', p, markerPath); }, 'SequentialMarker': function(p, element, position) { var markerPath = 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 } }); drawMarker('sequential', p, markerPath); }, 'CompensationMarker': function(p, element, position) { var markerMath = 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 } }); drawMarker('compensation', p, markerMath, { strokeWidth: 1 }); }, 'LoopMarker': function(p, element, position) { var markerPath = 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 } }); drawMarker('loop', p, markerPath, { strokeWidth: 1, fill: 'none', strokeLinecap: 'round', strokeMiterlimit: 0.5 }); }, 'AdhocMarker': function(p, element, position) { var markerPath = 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 } }); drawMarker('adhoc', p, markerPath, { 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.isForCompensation) { renderer('CompensationMarker')(p, element, position); } if (obj.$type === 'bpmn:AdHocSubProcess') { renderer('AdhocMarker')(p, element, position); } var loopCharacteristics = obj.loopCharacteristics, isSequential = loopCharacteristics && loopCharacteristics.isSequential; if (loopCharacteristics) { if (isSequential === undefined) { renderer('LoopMarker')(p, element, position); } if (isSequential === false) { renderer('ParallelMarker')(p, element, position); } if (isSequential === true) { renderer('SequentialMarker')(p, element, position); } } } 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 }); } // hook onto canvas init event to initialize // connection start/end markers on svg eventBus.on('canvas.init', function(event) { initMarkers(event.svg); }); } inherits(BpmnRenderer, BaseRenderer); BpmnRenderer.$inject = [ 'eventBus', 'styles', 'pathMap' ]; module.exports = BpmnRenderer; BpmnRenderer.prototype.canRender = function(element) { return is(element, 'bpmn:BaseElement'); }; BpmnRenderer.prototype.drawShape = function(visuals, element) { var type = element.type; var h = this.handlers[type]; /* jshint -W040 */ return h(visuals, element); }; BpmnRenderer.prototype.drawConnection = function(visuals, element) { var type = element.type; var h = this.handlers[type]; /* jshint -W040 */ return h(visuals, element); }; BpmnRenderer.prototype.getShapePath = function(element) { if (is(element, 'bpmn:Event')) { return getCirclePath(element); } if (is(element, 'bpmn:Activity')) { return getRoundRectPath(element, TASK_BORDER_RADIUS); } if (is(element, 'bpmn:Gateway')) { return getDiamondPath(element); } return getRectPath(element); }; ///////// helper functions ///////////////////////////// /** * 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'); } function isCollection(element) { return element.isCollection || (element.elementObjectRef && element.elementObjectRef.isCollection); } function getDi(element) { return element.businessObject.di; } function getSemantic(element) { return element.businessObject; } /////// cropping path customizations ///////////////////////// 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, borderRadius) { var x = shape.x, y = shape.y, width = shape.width, height = shape.height; var roundRectPath = [ ['M', x + borderRadius, y], ['l', width - borderRadius * 2, 0], ['a', borderRadius, borderRadius, 0, 0, 1, borderRadius, borderRadius], ['l', 0, height - borderRadius * 2], ['a', borderRadius, borderRadius, 0, 0, 1, -borderRadius, borderRadius], ['l', borderRadius * 2 - width, 0], ['a', borderRadius, borderRadius, 0, 0, 1, -borderRadius, -borderRadius], ['l', 0, borderRadius * 2 - height], ['a', borderRadius, borderRadius, 0, 0, 1, borderRadius, -borderRadius], ['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); } },{"107":107,"231":231,"232":232,"243":243,"252":252,"255":255,"257":257,"261":261,"372":372,"377":377,"68":68,"70":70}],5:[function(_dereq_,module,exports){ 'use strict'; var Snap = _dereq_(240); /** * 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.x1},-{e.y2} {e.x2},-{e.y3} 0,{e.y1} -{e.x2},-{e.y3} z', height: 36, width: 36, heightElements: [6.5, 13, 0.4, 6.1], widthElements: [9, 9.3, 8.7] }, '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} 7,-5 0,10 z m 7.1,-0.3 6.9,-4.7 0,10 -6.9,-4.7 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; },{"240":240}],6:[function(_dereq_,module,exports){ module.exports = { __init__: [ 'bpmnRenderer' ], bpmnRenderer: [ 'type', _dereq_(4) ], pathMap: [ 'type', _dereq_(5) ] }; },{"4":4,"5":5}],7:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var is = _dereq_(70).is, getBoundingBox = _dereq_(221).getBBox; var pick = _dereq_(383), assign = _dereq_(377), forEach = _dereq_(255), values = _dereq_(385), flatten = _dereq_(245), groupBy = _dereq_(256); var CommandInterceptor = _dereq_(98); var OFFSET = { top: 60, bottom: 60, left: 100, right: 100 }; var PADDING = { top: 2, bottom: 2, left: 15, right: 15 }; /** * An auto resize component that takes care of expanding parent participants * and lanes if elements are modeled close to an edge of the parent element. */ function AutoResize(eventBus, canvas, modeling, elementRegistry){ CommandInterceptor.call(this, eventBus); this.postExecuted([ 'shape.create' ], function(event) { var context = event.context, shape = context.shape, parent = context.parent || context.newParent; expand([ shape ], parent); }); this.postExecuted([ 'elements.move' ], function(event) { var context = event.context, elements = flatten(values(context.closure.topLevel)); var expandings = groupBy(elements, function(element){ return element.parent.id; }); forEach(expandings, function(elements, parentId) { expand(elements, parentId); }); }); /** * Returns an object which indicates near which bounding edge(s) * of a target a bounding box is located. * * @param {Object} bbox bounding box object with x, y, width and height properties * @param {Shape} target * @param {Number} padding * * @return {Object} {top, bottom, left, right} * * @example * * // If the bounding box is near the bottom left corner of a target the return object is: * { top: false, bottom: true, left: true, right: false } * */ function isInbounds(bbox, target, padding) { return { top: bbox.y < target.y + padding.top, bottom: bbox.y + bbox.height > target.y + target.height - padding.bottom, left: bbox.x < target.x + padding.left, right: bbox.x + bbox.width > target.x + target.width - padding.right, }; } /** * Expand the target shape if the bounding box of the moved elements is near or on an edge, * considering the position of the bounding box in relation to the parent's edge plus padding. * The amount to expand can be defined for each edge in the OFFSET object. * * @param {Array} elements * @param {Shape|String} target|targetId */ function expand(elements, target) { if (typeof target === 'string') { target = elementRegistry.get(target); } var bbox = getBoundingBox(elements), canExpand = true; if (!is(target, 'bpmn:Participant') && !is(target, 'bpmn:Lane') && !(is(target, 'bpmn:SubProcess'))) { return; } forEach(elements, function(element) { if (is(element, 'bpmn:Lane') || element.labelTarget) { canExpand = false; return; } }); if (!canExpand) { return; } var inbounds = isInbounds(bbox, target, PADDING); var newBounds = pick(target, [ 'x', 'y', 'width', 'height' ]); if (inbounds.top) { var topPosition = bbox.y - OFFSET.top; assign(newBounds, { y: topPosition, height: newBounds.height + newBounds.y - topPosition }); } if (inbounds.bottom) { assign(newBounds, { height: bbox.y + bbox.height + OFFSET.bottom - newBounds.y }); } if (inbounds.left) { var leftPosition = bbox.x - OFFSET.left; assign(newBounds, { x: leftPosition, width: newBounds.width + newBounds.x - leftPosition }); } if (inbounds.right) { assign(newBounds, { width: bbox.x + bbox.width + OFFSET.right - newBounds.x }); } if (is(target, 'bpmn:Participant')) { modeling.resizeLane(target, newBounds); } else { modeling.resizeShape(target, newBounds); } var parent = target.parent; // recursively expand parent elements if (parent) { expand([ target ], parent); } } } AutoResize.$inject = [ 'eventBus', 'canvas', 'modeling', 'elementRegistry' ]; inherits(AutoResize, CommandInterceptor); module.exports = AutoResize; },{"221":221,"243":243,"245":245,"255":255,"256":256,"377":377,"383":383,"385":385,"70":70,"98":98}],8:[function(_dereq_,module,exports){ module.exports = { __init__: [ 'autoResize' ], autoResize: [ 'type', _dereq_(7) ] }; },{"7":7}],9:[function(_dereq_,module,exports){ 'use strict'; var assign = _dereq_(377), forEach = _dereq_(255), isArray = _dereq_(368), is = _dereq_(70).is, isExpanded = _dereq_(68).isExpanded, isAny = _dereq_(45).isAny, getChildLanes = _dereq_(44).getChildLanes, isEventSubProcess = _dereq_(68).isEventSubProcess; /** * A provider for BPMN 2.0 elements context pad */ function ContextPadProvider(contextPad, modeling, elementFactory, connect, create, popupMenu, canvas, rules, translate) { contextPad.registerProvider(this); this._contextPad = contextPad; this._modeling = modeling; this._elementFactory = elementFactory; this._connect = connect; this._create = create; this._popupMenu = popupMenu; this._canvas = canvas; this._rules = rules; this._translate = translate; } ContextPadProvider.$inject = [ 'contextPad', 'modeling', 'elementFactory', 'connect', 'create', 'popupMenu', 'canvas', 'rules', 'translate' ]; module.exports = ContextPadProvider; ContextPadProvider.prototype.getContextPadEntries = function(element) { var contextPad = this._contextPad, modeling = this._modeling, elementFactory = this._elementFactory, connect = this._connect, create = this._create, popupMenu = this._popupMenu, canvas = this._canvas, rules = this._rules, translate = this._translate; var actions = {}; if (element.type === 'label') { return actions; } var businessObject = element.businessObject; function startConnect(event, element, autoActivate) { connect.start(event, element, autoActivate); } function removeElement(e) { modeling.removeElements([ 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; } /** * Create an append action * * @param {String} type * @param {String} className * @param {String} [title] * @param {Object} [options] * * @return {Object} descriptor */ function appendAction(type, className, title, options) { if (typeof title !== 'string') { options = title; title = translate('Append {type}', { type: type.replace(/^bpmn\:/, '') }); } function appendListener(event, element) { var shape = elementFactory.createShape(assign({ type: type }, options)); create.start(event, shape, element); } return { group: 'model', className: className, title: title, action: { dragstart: appendListener, click: appendListener } }; } function splitLaneHandler(count) { return function(event, element) { // actual split modeling.splitLane(element, count); // refresh context pad after split to // get rid of split icons contextPad.open(element, true); }; } if (isAny(businessObject, [ 'bpmn:Lane', 'bpmn:Participant' ]) && isExpanded(businessObject)) { var childLanes = getChildLanes(element); assign(actions, { 'lane-insert-above': { group: 'lane-insert-above', className: 'bpmn-icon-lane-insert-above', title: translate('Add Lane above'), action: { click: function(event, element) { modeling.addLane(element, 'top'); } } } }); if (childLanes.length < 2) { if (element.height >= 120) { assign(actions, { 'lane-divide-two': { group: 'lane-divide', className: 'bpmn-icon-lane-divide-two', title: translate('Divide into two Lanes'), action: { click: splitLaneHandler(2) } } }); } if (element.height >= 180) { assign(actions, { 'lane-divide-three': { group: 'lane-divide', className: 'bpmn-icon-lane-divide-three', title: translate('Divide into three Lanes'), action: { click: splitLaneHandler(3) } } }); } } assign(actions, { 'lane-insert-below': { group: 'lane-insert-below', className: 'bpmn-icon-lane-insert-below', title: translate('Add Lane below'), action: { click: function(event, element) { modeling.addLane(element, 'bottom'); } } } }); } if (is(businessObject, 'bpmn:FlowNode')) { if (is(businessObject, 'bpmn:EventBasedGateway')) { assign(actions, { 'append.receive-task': appendAction('bpmn:ReceiveTask', 'bpmn-icon-receive-task'), 'append.message-intermediate-event': appendAction('bpmn:IntermediateCatchEvent', 'bpmn-icon-intermediate-event-catch-message', { eventDefinitionType: 'bpmn:MessageEventDefinition'}), 'append.timer-intermediate-event': appendAction('bpmn:IntermediateCatchEvent', 'bpmn-icon-intermediate-event-catch-timer', { eventDefinitionType: 'bpmn:TimerEventDefinition'}), 'append.condtion-intermediate-event': appendAction('bpmn:IntermediateCatchEvent', 'bpmn-icon-intermediate-event-catch-condition', { eventDefinitionType: 'bpmn:ConditionalEventDefinition'}), 'append.signal-intermediate-event': appendAction('bpmn:IntermediateCatchEvent', 'bpmn-icon-intermediate-event-catch-signal', { eventDefinitionType: 'bpmn:SignalEventDefinition'}) }); } else if (isEventType(businessObject, 'bpmn:BoundaryEvent', 'bpmn:CompensateEventDefinition')) { assign(actions, { 'append.compensation-activity': appendAction('bpmn:Task', 'bpmn-icon-task', translate('Append compensation activity'), { isForCompensation: true }) }); } else if (!is(businessObject, 'bpmn:EndEvent') && !businessObject.isForCompensation && !isEventType(businessObject, 'bpmn:IntermediateThrowEvent', 'bpmn:LinkEventDefinition') && !isEventSubProcess(businessObject)) { assign(actions, { 'append.end-event': appendAction('bpmn:EndEvent', 'bpmn-icon-end-event-none'), 'append.gateway': appendAction('bpmn:ExclusiveGateway', 'bpmn-icon-gateway-xor'), 'append.append-task': appendAction('bpmn:Task', 'bpmn-icon-task'), 'append.intermediate-event': appendAction('bpmn:IntermediateThrowEvent', 'bpmn-icon-intermediate-event-none') }); } } var replaceMenu; if (popupMenu._providers['bpmn-replace']) { replaceMenu = popupMenu.create('bpmn-replace', element); } if (replaceMenu && !replaceMenu.isEmpty()) { // Replace menu entry assign(actions, { 'replace': { group: 'edit', className: 'bpmn-icon-screw-wrench', title: translate('Change type'), action: { click: function(event, element) { replaceMenu.open(assign(getReplaceMenuPosition(element), { cursor: { x: event.x, y: event.y } }), element); } } } }); } if (isAny(businessObject, [ 'bpmn:FlowNode', 'bpmn:InteractionNode' ]) ) { assign(actions, { 'append.text-annotation': appendAction('bpmn:TextAnnotation', 'bpmn-icon-text-annotation'), 'connect': { group: 'connect', className: 'bpmn-icon-connection-multi', title: translate('Connect using ' + (businessObject.isForCompensation ? '' : 'Sequence/MessageFlow or ') + 'Association'), action: { click: startConnect, dragstart: startConnect } } }); } if (isAny(businessObject, [ 'bpmn:DataObjectReference', 'bpmn:DataStoreReference' ])) { assign(actions, { 'connect': { group: 'connect', className: 'bpmn-icon-connection-multi', title: translate('Connect using DataInputAssociation'), action: { click: startConnect, dragstart: startConnect } } }); } // delete element entry, only show if allowed by rules var deleteAllowed = rules.allowed('elements.delete', { elements: [ element ]}); if (isArray(deleteAllowed)) { // was the element returned as a deletion candidate? deleteAllowed = deleteAllowed[0] === element; } if (deleteAllowed) { assign(actions, { 'delete': { group: 'edit', className: 'bpmn-icon-trash', title: translate('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; } },{"255":255,"368":368,"377":377,"44":44,"45":45,"68":68,"70":70}],10:[function(_dereq_,module,exports){ module.exports = { __depends__: [ _dereq_(93), _dereq_(124), _dereq_(189), _dereq_(122), _dereq_(126), _dereq_(51) ], __init__: [ 'contextPadProvider' ], contextPadProvider: [ 'type', _dereq_(9) ] }; },{"122":122,"124":124,"126":126,"189":189,"51":51,"9":9,"93":93}],11:[function(_dereq_,module,exports){ 'use strict'; function BpmnKeyBindings(keyboard, spaceTool, lassoTool, handTool, directEditing, selection, canvas, elementRegistry, editorActions) { var actions = { selectElements: function() { // 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); }, spaceTool: function() { spaceTool.toggle(); }, lassoTool: function() { lassoTool.toggle(); }, handTool: function() { handTool.toggle(); }, directEditing: function() { var currentSelection = selection.get(); if (currentSelection.length) { directEditing.activate(currentSelection[0]); } } }; editorActions.register(actions); keyboard.addListener(function(key, modifiers) { // ctrl + a -> select all elements if (key === 65 && keyboard.isCmd(modifiers)) { editorActions.trigger('selectElements'); return true; } if (keyboard.hasModifier(modifiers)) { return; } // s -> activate space tool if (key === 83) { editorActions.trigger('spaceTool'); return true; } // l -> activate lasso tool if (key === 76) { editorActions.trigger('lassoTool'); return true; } // h -> activate hand tool if (key === 72) { editorActions.trigger('handTool'); return true; } // e -> activate direct editing if (key === 69) { editorActions.trigger('directEditing'); return true; } }); } BpmnKeyBindings.$inject = [ 'keyboard', 'spaceTool', 'lassoTool', 'handTool', 'directEditing', 'selection', 'canvas', 'elementRegistry', 'editorActions' ]; module.exports = BpmnKeyBindings; },{}],12:[function(_dereq_,module,exports){ module.exports = { __depends__: [ _dereq_(137) ], __init__: [ 'bpmnKeyBindings' ], bpmnKeyBindings: [ 'type', _dereq_(11) ] }; },{"11":11,"137":137}],13:[function(_dereq_,module,exports){ 'use strict'; var UpdateLabelHandler = _dereq_(15); var LabelUtil = _dereq_(14); var is = _dereq_(70).is, isExpanded = _dereq_(68).isExpanded; var MIN_BOUNDS = { width: 150, height: 50 }; function LabelEditingProvider(eventBus, canvas, directEditing, commandStack) { 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.init', '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' ]; 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; } // ajust minumum size for task and activities if ((is(element, 'bpmn:Task') || is(element, 'bpmn:Activity') )) { if (bbox.width < 100) { bbox.width = 100; bbox.x = bbox.mid.x - bbox.width / 2; } if (bbox.height < 80) { bbox.height = 80; bbox.y = bbox.mid.y - bbox.height / 2; } } // adjust for expanded sub processes and collapsed pools if ((is(element, 'bpmn:SubProcess') && isExpanded(element)) || (is(element, 'bpmn:Participant') && !isExpanded(element))) { bbox.width = element.width; bbox.height = MIN_BOUNDS.height; bbox.x = bbox.mid.x - element.width / 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 }); }; },{"14":14,"15":15,"68":68,"70":70}],14:[function(_dereq_,module,exports){ 'use strict'; var is = _dereq_(70).is; function getLabelAttr(semantic) { if (is(semantic, 'bpmn:FlowElement') || is(semantic, 'bpmn:Participant') || is(semantic, 'bpmn:Lane') || is(semantic, 'bpmn:SequenceFlow') || is(semantic, 'bpmn:MessageFlow')) { return 'name'; } if (is(semantic, '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, isExternal) { var semantic = element.businessObject, attr = getLabelAttr(semantic); if (attr) { semantic[attr] = text; } // show external label if not empty if (isExternal) { element.hidden = !text; } return element; }; },{"70":70}],15:[function(_dereq_,module,exports){ 'use strict'; var LabelUtil = _dereq_(14); /** * A handler that updates the text of a BPMN element. */ function UpdateLabelHandler() { /** * Set the label and return the changed elements. * * Element parameter can be label itself or connection (i.e. sequence flow). * * @param {djs.model.Base} element * @param {String} text */ function setText(element, text) { // external label if present var label = element.label || element; var labelTarget = element.labelTarget || element; LabelUtil.setLabel(label, text, labelTarget !== label); return [ label, labelTarget ]; } function execute(ctx) { ctx.oldLabel = LabelUtil.getLabel(ctx.element); return setText(ctx.element, ctx.newLabel); } function revert(ctx) { return setText(ctx.element, ctx.oldLabel); } // API this.execute = execute; this.revert = revert; } module.exports = UpdateLabelHandler; },{"14":14}],16:[function(_dereq_,module,exports){ module.exports = { __depends__: [ _dereq_(100), _dereq_(120), _dereq_(93) ], __init__: [ 'labelEditingProvider' ], labelEditingProvider: [ 'type', _dereq_(13) ] }; },{"100":100,"120":120,"13":13,"93":93}],17:[function(_dereq_,module,exports){ 'use strict'; var map = _dereq_(258), assign = _dereq_(377), pick = _dereq_(383); 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:DataAssociation') || element.$instanceOf('bpmn:Artifact') || element.$instanceOf('bpmn:Participant') || element.$instanceOf('bpmn:Lane') || element.$instanceOf('bpmn:Process') || element.$instanceOf('bpmn:Collaboration') || element.$instanceOf('bpmndi:BPMNShape') || element.$instanceOf('bpmndi:BPMNEdge') || element.$instanceOf('bpmndi:BPMNDiagram') || element.$instanceOf('bpmndi:BPMNPlane') || element.$instanceOf('bpmn:Property'); }; 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; },{"258":258,"377":377,"383":383}],18:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var assign = _dereq_(377); var BaseLayouter = _dereq_(206), ManhattanLayout = _dereq_(209); var LayoutUtil = _dereq_(208); var getMid = LayoutUtil.getMid, getOrientation = LayoutUtil.getOrientation; var is = _dereq_(70).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 if (is(connection, 'bpmn:Association') || is(connection, 'bpmn:DataAssociation')) { if (waypoints && !isCompensationAssociation(connection)) { return waypoints; } } // manhattan layout sequence / message flows if (is(connection, 'bpmn:MessageFlow')) { manhattanOptions = { preferredLayouts: [ 'straight', 'v:v' ] }; if (is(target, 'bpmn:Event')) { manhattanOptions = { preferredLayouts: [ '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') || isCompensationAssociation(connection)) { // 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); } function isCompensationAssociation(connection) { var source = connection.source, target = connection.target; return is(target, 'bpmn:Activity') && is(source, 'bpmn:BoundaryEvent') && target.businessObject.isForCompensation; } },{"206":206,"208":208,"209":209,"243":243,"377":377,"70":70}],19:[function(_dereq_,module,exports){ 'use strict'; var assign = _dereq_(377), forEach = _dereq_(255), inherits = _dereq_(243); var Collections = _dereq_(219), Model = _dereq_(210); var getBusinessObject = _dereq_(70).getBusinessObject, is = _dereq_(70).is; var CommandInterceptor = _dereq_(98); /** * A handler responsible for updating the underlying BPMN 2.0 XML + DI * once changes on the diagram happen */ function BpmnUpdater(eventBus, bpmnFactory, connectionDocking, translate) { CommandInterceptor.call(this, eventBus); this._bpmnFactory = bpmnFactory; this._translate = translate; 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) { var context = e.context; self.updateParent(context.shape || context.connection, context.oldParent); } function reverseUpdateParent(e) { var context = e.context; var element = context.shape || context.connection, // oldParent is the (old) new parent, because we are undoing oldParent = context.parent || context.newParent; self.updateParent(element, oldParent); } this.executed([ 'shape.move', 'shape.create', 'shape.delete', 'connection.create', 'connection.move', 'connection.delete' ], ifBpmn(updateParent)); this.reverted([ 'shape.move', 'shape.create', 'shape.delete', 'connection.create', 'connection.move', 'connection.delete' ], ifBpmn(reverseUpdateParent)); /* * ## 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) { var shape = e.context.shape; if (!is(shape, 'bpmn:BaseElement')) { return; } self.updateBounds(shape); } this.executed([ 'shape.move', 'shape.create', 'shape.resize' ], ifBpmn(updateBounds)); this.reverted([ 'shape.move', 'shape.create', 'shape.resize' ], ifBpmn(updateBounds)); // attach / detach connection function updateConnection(e) { self.updateConnection(e.context); } this.executed([ 'connection.create', 'connection.move', 'connection.delete', 'connection.reconnectEnd', 'connection.reconnectStart' ], ifBpmn(updateConnection)); this.reverted([ 'connection.create', 'connection.move', 'connection.delete', 'connection.reconnectEnd', 'connection.reconnectStart' ], ifBpmn(updateConnection)); // update waypoints function updateConnectionWaypoints(e) { self.updateConnectionWaypoints(e.context.connection); } this.executed([ 'connection.layout', 'connection.move', 'connection.updateWaypoints', 'connection.reconnectEnd', 'connection.reconnectStart' ], ifBpmn(updateConnectionWaypoints)); this.reverted([ 'connection.layout', 'connection.move', 'connection.updateWaypoints', 'connection.reconnectEnd', 'connection.reconnectStart' ], ifBpmn(updateConnectionWaypoints)); // update Default & Conditional flows this.executed([ 'connection.reconnectEnd', 'connection.reconnectStart' ], ifBpmn(function(e) { var context = e.context, connection = context.connection, businessObject = getBusinessObject(connection), oldSource = getBusinessObject(context.oldSource), oldTarget = getBusinessObject(context.oldTarget), newSource = getBusinessObject(connection.source), newTarget = getBusinessObject(connection.target); if (oldSource === newSource || oldTarget === newTarget) { return; } // on reconnectStart -> default flow if (oldSource && oldSource.default) { context.default = oldSource.default; oldSource.default = undefined; } // on reconnectEnd -> default flow if ((businessObject.sourceRef && businessObject.sourceRef.default) && !is(newTarget, 'bpmn:Activity')) { context.default = businessObject.sourceRef.default; businessObject.sourceRef.default = undefined; } // on reconnectStart -> condtional flow if ((businessObject.conditionExpression) && is(oldSource, 'bpmn:Activity')) { context.conditionExpression = businessObject.conditionExpression; businessObject.conditionExpression = undefined; } // on reconnectEnd -> condtional flow if ((businessObject.conditionExpression) && !is(newTarget, 'bpmn:Activity')) { context.conditionExpression = businessObject.conditionExpression; businessObject.conditionExpression = undefined; } })); this.reverted([ 'connection.reconnectEnd', 'connection.reconnectStart' ], ifBpmn(function(e) { var context = e.context, connection = context.connection, businessObject = getBusinessObject(connection), newSource = getBusinessObject(connection.source); // default flow if (context.default) { if (is(newSource, 'bpmn:ExclusiveGateway') || is(newSource, 'bpmn:InclusiveGateway') || is(newSource, 'bpmn:Activity')) { newSource.default = context.default; } } // conditional flow if (context.conditionExpression && is(newSource, 'bpmn:Activity')) { businessObject.conditionExpression = context.conditionExpression; } })); // update attachments function updateAttachment(e) { self.updateAttachment(e.context); } this.executed([ 'element.updateAttachment' ], ifBpmn(updateAttachment)); this.reverted([ 'element.updateAttachment' ], ifBpmn(updateAttachment)); } inherits(BpmnUpdater, CommandInterceptor); module.exports = BpmnUpdater; BpmnUpdater.$inject = [ 'eventBus', 'bpmnFactory', 'connectionDocking', 'translate' ]; /////// 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, oldParent) { // 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; if (is(element, 'bpmn:FlowNode')) { this.updateFlowNodeRefs(businessObject, parentBusinessObject, oldParent && oldParent.businessObject); } if (is(element, 'bpmn:DataOutputAssociation')) { if (element.source) { parentBusinessObject = element.source.businessObject; } else { parentBusinessObject = null; } } if (is(element, 'bpmn:DataInputAssociation')) { if (element.target) { parentBusinessObject = element.target.businessObject; } else { parentBusinessObject = null; } } this.updateSemanticParent(businessObject, parentBusinessObject); if (is(element, 'bpmn:DataObjectReference') && businessObject.dataObjectRef) { this.updateSemanticParent(businessObject.dataObjectRef, 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.updateFlowNodeRefs = function(businessObject, newContainment, oldContainment) { if (oldContainment === newContainment) { return; } var oldRefs, newRefs; if (is (oldContainment, 'bpmn:Lane')) { oldRefs = oldContainment.get('flowNodeRef'); Collections.remove(oldRefs, businessObject); } if (is(newContainment, 'bpmn:Lane')) { newRefs = newContainment.get('flowNodeRef'); Collections.add(newRefs, businessObject); } }; 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.getLaneSet = function(container) { var laneSet, laneSets; // bpmn:Lane if (is(container, 'bpmn:Lane')) { laneSet = container.childLaneSet; if (!laneSet) { laneSet = this._bpmnFactory.create('bpmn:LaneSet'); container.childLaneSet = laneSet; laneSet.$parent = container; } return laneSet; } // bpmn:Participant if (is(container, 'bpmn:Participant')) { container = container.processRef; } // bpmn:FlowElementsContainer laneSets = container.get('laneSets'); laneSet = laneSets[0]; if (!laneSet) { laneSet = this._bpmnFactory.create('bpmn:LaneSet'); laneSet.$parent = container; laneSets.push(laneSet); } return laneSet; }; BpmnUpdater.prototype.updateSemanticParent = function(businessObject, newParent) { var containment, translate = this._translate; if (businessObject.$parent === newParent) { return; } if (is(businessObject, 'bpmn:Lane')) { if (newParent) { newParent = this.getLaneSet(newParent); } containment = 'lanes'; } else if (is(businessObject, 'bpmn:FlowElement')) { if (newParent) { if (is(newParent, 'bpmn:Participant')) { newParent = newParent.processRef; } else if (is(newParent, 'bpmn:Lane')) { do { // unwrap Lane -> LaneSet -> (Lane | FlowElementsContainer) newParent = newParent.$parent.$parent; } while(is(newParent, 'bpmn:Lane')); } } 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; } } } else if (is(businessObject, 'bpmn:DataOutputAssociation')) { containment = 'dataOutputAssociations'; } else if (is(businessObject, 'bpmn:DataInputAssociation')) { containment = 'dataInputAssociations'; } if (!containment) { throw new Error(translate( 'no parent for {element} in {parent}', { element: businessObject.id, parent: newParent.id } )); } 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(context) { var connection = context.connection, businessObject = getBusinessObject(connection), newSource = getBusinessObject(connection.source), newTarget = getBusinessObject(connection.target); if (!is(businessObject, 'bpmn:DataAssociation')) { 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; } } else if (is(businessObject, 'bpmn:DataInputAssociation')) { // handle obnoxious isMany sourceRef businessObject.get('sourceRef')[0] = newSource; // targetRef = new parent this.updateSemanticParent(businessObject, newTarget); } else if (is(businessObject, 'bpmn:DataOutputAssociation')) { // sourceRef = new parent this.updateSemanticParent(businessObject, newSource); // targetRef = new target businessObject.targetRef = newTarget; } this.updateConnectionWaypoints(connection); }; /////// helpers ///////////////////////////////////////// BpmnUpdater.prototype._getLabel = function(di) { if (!di.label) { di.label = this._bpmnFactory.createDiLabel(); } return di.label; }; /** * Make sure the event listener is only called * if the touched element is a BPMN element. * * @param {Function} fn * @return {Function} guarded function */ function ifBpmn(fn) { return function(event) { var context = event.context, element = context.shape || context.connection; if (is(element, 'bpmn:BaseElement')) { fn(event); } }; } },{"210":210,"219":219,"243":243,"255":255,"377":377,"70":70,"98":98}],20:[function(_dereq_,module,exports){ 'use strict'; var assign = _dereq_(377), inherits = _dereq_(243); var is = _dereq_(70).is; var isExpanded = _dereq_(68).isExpanded; var BaseElementFactory = _dereq_(102), LabelUtil = _dereq_(69); /** * A bpmn-aware factory for diagram-js shapes */ function ElementFactory(bpmnFactory, moddle, translate) { BaseElementFactory.call(this); this._bpmnFactory = bpmnFactory; this._moddle = moddle; this._translate = translate; } inherits(ElementFactory, BaseElementFactory); ElementFactory.$inject = [ 'bpmnFactory', 'moddle', 'translate' ]; 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)); } return this.createBpmnElement(elementType, attrs); }; ElementFactory.prototype.createBpmnElement = function(elementType, attrs) { var size, translate = this._translate; attrs = attrs || {}; var businessObject = attrs.businessObject; if (!businessObject) { if (!attrs.type) { throw new Error(translate('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.processRef) { businessObject.processRef = attrs.processRef; } if (attrs.isExpanded) { businessObject.di.isExpanded = attrs.isExpanded; } if (is(businessObject, 'bpmn:ExclusiveGateway')) { businessObject.di.isMarkerVisible = true; } if (attrs.isInterrupting === false) { businessObject.isInterrupting = false; } if (attrs.associationDirection) { businessObject.associationDirection = attrs.associationDirection; } var eventDefinitions, newEventDefinition; if (attrs.eventDefinitionType) { eventDefinitions = businessObject.get('eventDefinitions') || []; newEventDefinition = this._moddle.create(attrs.eventDefinitionType); eventDefinitions.push(newEventDefinition); newEventDefinition.$parent = businessObject; businessObject.eventDefinitions = eventDefinitions; } if (attrs.isForCompensation) { businessObject.isForCompensation = true; } size = this._getDefaultSize(businessObject); attrs = assign({ businessObject: businessObject, id: businessObject.id }, size, attrs); return this.baseCreate(elementType, attrs); }; ElementFactory.prototype._getDefaultSize = function(semantic) { if (is(semantic, 'bpmn:SubProcess')) { if (isExpanded(semantic)) { return { width: 350, height: 200 }; } else { return { width: 100, height: 80 }; } } if (is(semantic, 'bpmn:Task')) { return { width: 100, height: 80 }; } if (is(semantic, 'bpmn:Gateway')) { return { width: 50, height: 50 }; } if (is(semantic, 'bpmn:Event')) { return { width: 36, height: 36 }; } if (is(semantic, 'bpmn:Participant')) { if (!isExpanded(semantic)) { return { width: 400, height: 100 }; } else { return { width: 600, height: 250 }; } } if (is(semantic, 'bpmn:Lane')) { return { width: 400, height: 100 }; } if (is(semantic, 'bpmn:DataObjectReference')) { return { width: 36, height: 50 }; } if (is(semantic, 'bpmn:DataStoreReference')) { return { width: 50, height: 50 }; } if (is(semantic, 'bpmn:TextAnnotation')) { return { width: 100, height: 30 }; } return { width: 100, height: 80 }; }; ElementFactory.prototype.createParticipantShape = function(collapsed) { var attrs = { type: 'bpmn:Participant' }; if (!collapsed) { attrs.processRef = this._bpmnFactory.create('bpmn:Process'); } return this.createShape(attrs); }; },{"102":102,"243":243,"377":377,"68":68,"69":69,"70":70}],21:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var BaseModeling = _dereq_(142); var UpdatePropertiesHandler = _dereq_(42), UpdateCanvasRootHandler = _dereq_(40), AddLaneHandler = _dereq_(37), SplitLaneHandler = _dereq_(39), ResizeLaneHandler = _dereq_(38), UpdateFlowNodeRefsHandler = _dereq_(41); /** * 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; handlers['lane.add'] = AddLaneHandler; handlers['lane.resize'] = ResizeLaneHandler; handlers['lane.split'] = SplitLaneHandler; handlers['lane.updateRefs'] = UpdateFlowNodeRefsHandler; return handlers; }; Modeling.prototype.updateLabel = function(element, newLabel) { this._commandStack.execute('element.updateLabel', { element: element, newLabel: newLabel }); }; Modeling.prototype.connect = function(source, target, attrs) { var bpmnRules = this._bpmnRules; if (!attrs) { attrs = bpmnRules.canConnect(source, target) || { type: 'bpmn:Association' }; } return this.createConnection(source, target, attrs, source.parent); }; Modeling.prototype.updateProperties = function(element, properties) { this._commandStack.execute('element.updateProperties', { element: element, properties: properties }); }; Modeling.prototype.resizeLane = function(laneShape, newBounds, balanced) { this._commandStack.execute('lane.resize', { shape: laneShape, newBounds: newBounds, balanced: balanced }); }; Modeling.prototype.addLane = function(targetLaneShape, location) { var context = { shape: targetLaneShape, location: location }; this._commandStack.execute('lane.add', context); return context.newLane; }; Modeling.prototype.splitLane = function(targetLane, count) { this._commandStack.execute('lane.split', { shape: targetLane, count: count }); }; /** * 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; }; Modeling.prototype.updateLaneRefs = function(flowNodeShapes, laneShapes) { this._commandStack.execute('lane.updateRefs', { flowNodeShapes: flowNodeShapes, laneShapes: laneShapes }); }; /** * 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); }; },{"142":142,"243":243,"37":37,"38":38,"39":39,"40":40,"41":41,"42":42}],22:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var is = _dereq_(70).is; var CommandInterceptor = _dereq_(98); 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; },{"243":243,"70":70,"98":98}],23:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var CommandInterceptor = _dereq_(98); var is = _dereq_(70).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; },{"243":243,"70":70,"98":98}],24:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var CommandInterceptor = _dereq_(98); var is = _dereq_(70).is; /** * BPMN specific create data object behavior */ function CreateDataObjectBehavior(eventBus, bpmnFactory, moddle) { CommandInterceptor.call(this, eventBus); this.preExecute('shape.create', function(event) { var context = event.context, shape = context.shape; if (is(shape, 'bpmn:DataObjectReference') && shape.type !== 'label') { // create a DataObject every time a DataObjectReference is created var dataObject = bpmnFactory.create('bpmn:DataObject'); // set the reference to the DataObject shape.businessObject.dataObjectRef = dataObject; } }); } CreateDataObjectBehavior.$inject = [ 'eventBus', 'bpmnFactory', 'moddle' ]; inherits(CreateDataObjectBehavior, CommandInterceptor); module.exports = CreateDataObjectBehavior; },{"243":243,"70":70,"98":98}],25:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var assign = _dereq_(377); var CommandInterceptor = _dereq_(98); var getApproxIntersection = _dereq_(226).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; },{"226":226,"243":243,"377":377,"98":98}],26:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var CommandInterceptor = _dereq_(98); var is = _dereq_(70).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.moveElements(processChildren, { x: 0, y: 0 }, shape); } }, true); } CreateParticipantBehavior.$inject = [ 'eventBus', 'modeling', 'elementFactory', 'bpmnFactory' ]; inherits(CreateParticipantBehavior, CommandInterceptor); module.exports = CreateParticipantBehavior; },{"243":243,"70":70,"98":98}],27:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var CommandInterceptor = _dereq_(98); var Collections = _dereq_(219); var find = _dereq_(254); var is = _dereq_(70).is; var TARGET_REF_PLACEHOLDER_NAME = '__targetRef_placeholder'; /** * This behavior makes sure we always set a fake * DataInputAssociation#targetRef as demanded by the BPMN 2.0 * XSD schema. * * The reference is set to a bpmn:Property{ name: '__targetRef_placeholder' } * which is created on the fly and cleaned up afterwards if not needed * anymore. * * @param {EventBus} eventBus * @param {BpmnFactory} bpmnFactory */ function DataInputAssociationBehavior(eventBus, bpmnFactory) { CommandInterceptor.call(this, eventBus); this.executed([ 'connection.create', 'connection.delete', 'connection.move', 'connection.reconnectEnd' ], ifDataInputAssociation(fixTargetRef)); this.reverted([ 'connection.create', 'connection.delete', 'connection.move', 'connection.reconnectEnd' ], ifDataInputAssociation(fixTargetRef)); function usesTargetRef(element, targetRef, removedConnection) { var inputAssociations = element.get('dataInputAssociations'); return find(inputAssociations, function(association) { return association !== removedConnection && association.targetRef === targetRef; }); } function getTargetRef(element, create) { var properties = element.get('properties'); var targetRefProp = find(properties, function(p) { return p.name === TARGET_REF_PLACEHOLDER_NAME; }); if (!targetRefProp && create) { targetRefProp = bpmnFactory.create('bpmn:Property', { name: TARGET_REF_PLACEHOLDER_NAME }); Collections.add(properties, targetRefProp); } return targetRefProp; } function cleanupTargetRef(element, connection) { var targetRefProp = getTargetRef(element); if (!targetRefProp) { return; } if (!usesTargetRef(element, targetRefProp, connection)) { Collections.remove(element.get('properties'), targetRefProp); } } /** * Make sure targetRef is set to a valid property or * `null` if the connection is detached. * * @param {Event} event */ function fixTargetRef(event) { var context = event.context, connection = context.connection, connectionBo = connection.businessObject, target = connection.target, targetBo = target && target.businessObject, newTarget = context.newTarget, newTargetBo = newTarget && newTarget.businessObject, oldTarget = context.oldTarget || context.target, oldTargetBo = oldTarget && oldTarget.businessObject; var dataAssociation = connection.businessObject, targetRefProp; if (oldTargetBo && oldTargetBo !== targetBo) { cleanupTargetRef(oldTargetBo, connectionBo); } if (newTargetBo && newTargetBo !== targetBo) { cleanupTargetRef(newTargetBo, connectionBo); } if (targetBo) { targetRefProp = getTargetRef(targetBo, true); dataAssociation.targetRef = targetRefProp; } else { dataAssociation.targetRef = null; } } } DataInputAssociationBehavior.$inject = [ 'eventBus', 'bpmnFactory' ]; inherits(DataInputAssociationBehavior, CommandInterceptor); module.exports = DataInputAssociationBehavior; /** * Only call the given function when the event * touches a bpmn:DataInputAssociation. * * @param {Function} fn * @return {Function} */ function ifDataInputAssociation(fn) { return function(event) { var context = event.context, connection = context.connection; if (is(connection, 'bpmn:DataInputAssociation')) { return fn(event); } }; } },{"219":219,"243":243,"254":254,"70":70,"98":98}],28:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var CommandInterceptor = _dereq_(98); var is = _dereq_(70).is; var getChildLanes = _dereq_(44).getChildLanes; var eachElement = _dereq_(221).eachElement; var LOW_PRIORITY = 500; /** * BPMN specific delete lane behavior */ function DeleteLaneBehavior(eventBus, modeling, spaceTool) { CommandInterceptor.call(this, eventBus); function compensateLaneDelete(shape, oldParent) { var siblings = getChildLanes(oldParent); var topAffected = []; var bottomAffected = []; eachElement(siblings, function(element) { if (element.y > shape.y) { bottomAffected.push(element); } else { topAffected.push(element); } return element.children; }); if (!siblings.length) { return; } var offset; if (bottomAffected.length && topAffected.length) { offset = shape.height / 2; } else { offset = shape.height; } var topAdjustments, bottomAdjustments; if (topAffected.length) { topAdjustments = spaceTool.calculateAdjustments( topAffected, 'y', offset, shape.y - 10); spaceTool.makeSpace( topAdjustments.movingShapes, topAdjustments.resizingShapes, { x: 0, y: offset }, 's'); } if (bottomAffected.length) { bottomAdjustments = spaceTool.calculateAdjustments( bottomAffected, 'y', -offset, shape.y + shape.height + 10); spaceTool.makeSpace( bottomAdjustments.movingShapes, bottomAdjustments.resizingShapes, { x: 0, y: -offset }, 'n'); } } /** * Adjust sizes of other lanes after lane deletion */ this.postExecuted('shape.delete', LOW_PRIORITY, function(event) { var context = event.context, hints = context.hints, shape = context.shape, oldParent = context.oldParent; // only compensate lane deletes if (!is(shape, 'bpmn:Lane')) { return; } // compensate root deletes only if (hints && hints.nested) { return; } compensateLaneDelete(shape, oldParent); }); } DeleteLaneBehavior.$inject = [ 'eventBus', 'modeling', 'spaceTool' ]; inherits(DeleteLaneBehavior, CommandInterceptor); module.exports = DeleteLaneBehavior; },{"221":221,"243":243,"44":44,"70":70,"98":98}],29:[function(_dereq_,module,exports){ 'use strict'; var assign = _dereq_(377), inherits = _dereq_(243); var LabelUtil = _dereq_(69), is = _dereq_(70).is; var hasExternalLabel = LabelUtil.hasExternalLabel, getExternalLabelMid = LabelUtil.getExternalLabelMid; var CommandInterceptor = _dereq_(98); /** * A component that makes sure that external labels are added * together with respective elements and properly updated (DI wise) * during move. * * @param {EventBus} eventBus * @param {Modeling} modeling * @param {BpmnFactory} bpmnFactory */ 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', hidden: !businessObject.name, businessObject: businessObject }); } }); // update di information on label creation this.executed([ 'label.create' ], function(e) { var element = e.context.shape, businessObject, di; // we want to trigger on real labels only if (!element.labelTarget) { return; } // we want to trigger on BPMN elements only if (!is(element.labelTarget || element, 'bpmn:BaseElement')) { return; } businessObject = element.businessObject, di = businessObject.di; 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; },{"243":243,"377":377,"69":69,"70":70,"98":98}],30:[function(_dereq_,module,exports){ 'use strict'; var is = _dereq_(70).is; function ModelingFeedback(eventBus, tooltips, translate) { 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, translate('flow elements must be children of pools/participants')); } }); } ModelingFeedback.$inject = [ 'eventBus', 'tooltips', 'translate' ]; module.exports = ModelingFeedback; },{"70":70}],31:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var CommandInterceptor = _dereq_(98); var is = _dereq_(70).is; /** * BPMN specific remove behavior */ function RemoveParticipantBehavior(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); } RemoveParticipantBehavior.$inject = [ 'eventBus', 'modeling' ]; inherits(RemoveParticipantBehavior, CommandInterceptor); module.exports = RemoveParticipantBehavior; },{"243":243,"70":70,"98":98}],32:[function(_dereq_,module,exports){ 'use strict'; var forEach = _dereq_(255), find = _dereq_(254), inherits = _dereq_(243); var CommandInterceptor = _dereq_(98); var is = _dereq_(70).is; function ReplaceConnectionBehavior(eventBus, modeling, bpmnRules) { CommandInterceptor.call(this, eventBus); function fixConnection(connection) { var source = connection.source, target = connection.target, parent = connection.parent; // do not do anything if connection // is already deleted (may happen due to other // behaviors plugged-in before) if (!parent) { return; } 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, // unless it has been removed already if (remove) { modeling.removeConnection(connection); } // replace SequenceFlow <> MessageFlow if (replacementType) { modeling.connect(source, target, { type: replacementType, waypoints: connection.waypoints.slice() }); } } this.postExecuted('elements.move', function(context) { var closure = context.closure, allConnections = closure.allConnections; forEach(allConnections, fixConnection); }, true); this.postExecuted([ 'connection.reconnectStart', 'connection.reconnectEnd' ], function(event){ var connection = event.context.connection; fixConnection(connection); }); this.postExecuted('element.updateProperties', function(event) { var context = event.context, properties = context.properties, element = context.element, businessObject = element.businessObject, connection; // remove condition expression when morphing to default flow if (properties.default) { connection = find(element.outgoing, { id: element.businessObject.default.id }); if (connection) { modeling.updateProperties(connection, { conditionExpression: undefined }); } } // remove default property from source when morphing to conditional flow if (properties.conditionExpression && businessObject.sourceRef.default === businessObject) { modeling.updateProperties(element.source, { default: undefined }); } }); } inherits(ReplaceConnectionBehavior, CommandInterceptor); ReplaceConnectionBehavior.$inject = [ 'eventBus', 'modeling', 'bpmnRules' ]; module.exports = ReplaceConnectionBehavior; },{"243":243,"254":254,"255":255,"70":70,"98":98}],33:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var CommandInterceptor = _dereq_(98); var forEach = _dereq_(255); var isEventSubProcess = _dereq_(68).isEventSubProcess; var is = _dereq_(70).is; /** * Defines the behaviour of what happens to the elements inside a container * that morphs into another BPMN element */ function ReplaceElementBehaviour(eventBus, bpmnReplace, bpmnRules, elementRegistry, selection, modeling) { CommandInterceptor.call(this, eventBus); this._bpmnReplace = bpmnReplace; this._elementRegistry = elementRegistry; this._selection = selection; this._modeling = modeling; this.postExecuted([ 'elements.move' ], 500, function(event) { var context = event.context, target = context.newParent, newHost = context.newHost, elements = []; forEach(context.closure.topLevel, function(topLevelElements) { if (isEventSubProcess(topLevelElements)) { elements = elements.concat(topLevelElements.children); } else { elements = elements.concat(topLevelElements); } }); // Change target to host when the moving element is a `bpmn:BoundaryEvent` if (elements.length === 1 && newHost) { target = newHost; } var canReplace = bpmnRules.canReplace(elements, target); if (canReplace) { this.replaceElements(elements, canReplace.replacements, newHost); } }, this); // update attachments if the host is replaced this.postExecute([ 'shape.replace' ], 1500, function(e) { var context = e.context, oldShape = context.oldShape, newShape = context.newShape, attachers = oldShape.attachers, canReplace; if (attachers && attachers.length) { canReplace = bpmnRules.canReplace(attachers, newShape); this.replaceElements(attachers, canReplace.replacements); } }, this); } inherits(ReplaceElementBehaviour, CommandInterceptor); ReplaceElementBehaviour.prototype.replaceElements = function(elements, newElements, newHost) { var elementRegistry = this._elementRegistry, bpmnReplace = this._bpmnReplace, selection = this._selection, modeling = this._modeling; forEach(newElements, function(replacement) { var newElement = { type: replacement.newElementType }; var oldElement = elementRegistry.get(replacement.oldElementId); if (newHost && is(oldElement, 'bpmn:BoundaryEvent')) { modeling.updateAttachment(oldElement, null); } var idx = elements.indexOf(oldElement); elements[idx] = bpmnReplace.replaceElement(oldElement, newElement, { select: false }); if (newHost && is(elements[idx], 'bpmn:BoundaryEvent')) { modeling.updateAttachment(elements[idx], newHost); } }); if (newElements) { selection.select(elements); } }; ReplaceElementBehaviour.$inject = [ 'eventBus', 'bpmnReplace', 'bpmnRules', 'elementRegistry', 'selection', 'modeling' ]; module.exports = ReplaceElementBehaviour; },{"243":243,"255":255,"68":68,"70":70,"98":98}],34:[function(_dereq_,module,exports){ 'use strict'; var is = _dereq_(70).is; var roundBounds = _dereq_(208).roundBounds; var hasPrimaryModifier = _dereq_(228).hasPrimaryModifier; var SLIGHTLY_HIGHER_PRIORITY = 1001; /** * Invoke {@link Modeling#resizeLane} instead of * {@link Modeling#resizeShape} when resizing a Lane * or Participant shape. */ function ResizeLaneBehavior(eventBus, modeling) { eventBus.on('resize.start', SLIGHTLY_HIGHER_PRIORITY + 500, function(event) { var context = event.context, shape = context.shape; if (is(shape, 'bpmn:Lane') || is(shape, 'bpmn:Participant')) { // should we resize the opposite lane(s) in // order to compensate for the resize operation? context.balanced = !hasPrimaryModifier(event); } }); /** * Intercept resize end and call resize lane function instead. */ eventBus.on('resize.end', SLIGHTLY_HIGHER_PRIORITY, function(event) { var context = event.context, shape = context.shape, canExecute = context.canExecute, newBounds = context.newBounds; if (is(shape, 'bpmn:Lane') || is(shape, 'bpmn:Participant')) { if (canExecute) { // ensure we have actual pixel values for new bounds // (important when zoom level was > 1 during move) newBounds = roundBounds(newBounds); // perform the actual resize modeling.resizeLane(shape, newBounds, context.balanced); } // stop propagation return false; } }); } ResizeLaneBehavior.$inject = [ 'eventBus', 'modeling' ]; module.exports = ResizeLaneBehavior; },{"208":208,"228":228,"70":70}],35:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var CommandInterceptor = _dereq_(98); var is = _dereq_(70).is; var LOW_PRIORITY = 500, HIGH_PRIORITY = 5000; /** * BPMN specific delete lane behavior */ function UpdateFlowNodeRefsBehavior(eventBus, modeling, translate) { CommandInterceptor.call(this, eventBus); /** * Ok, this is it: * * We have to update the Lane#flowNodeRefs _and_ * FlowNode#lanes with every FlowNode move/resize and * Lane move/resize. * * We want to group that stuff to recompute containments * as efficient as possible. * * Yea! */ // the update context var context; function initContext() { context = context || new UpdateContext(); context.enter(); return context; } function getContext() { if (!context) { throw new Error(translate('out of bounds release')); } return context; } function releaseContext() { if (!context) { throw new Error(translate('out of bounds release')); } var triggerUpdate = context.leave(); if (triggerUpdate) { modeling.updateLaneRefs(context.flowNodes, context.lanes); context = null; } return triggerUpdate; } var laneRefUpdateEvents = [ 'spaceTool', 'lane.add', 'lane.resize', 'lane.split', 'elements.move', 'elements.delete', 'shape.create', 'shape.delete', 'shape.move', 'shape.resize' ]; // listen to a lot of stuff to group lane updates this.preExecute(laneRefUpdateEvents, HIGH_PRIORITY, function(event) { initContext(); }); this.postExecuted(laneRefUpdateEvents, LOW_PRIORITY, function(event) { releaseContext(); }); // Mark flow nodes + lanes that need an update this.preExecute([ 'shape.create', 'shape.move', 'shape.delete', 'shape.resize' ], function(event) { var context = event.context, shape = context.shape; var updateContext = getContext(); // no need to update labels if (shape.labelTarget) { return; } if (is(shape, 'bpmn:Lane')) { updateContext.addLane(shape); } if (is(shape, 'bpmn:FlowNode')) { updateContext.addFlowNode(shape); } }); } UpdateFlowNodeRefsBehavior.$inject = [ 'eventBus', 'modeling' , 'translate']; inherits(UpdateFlowNodeRefsBehavior, CommandInterceptor); module.exports = UpdateFlowNodeRefsBehavior; function UpdateContext() { this.flowNodes = []; this.lanes = []; this.counter = 0; this.addLane = function(lane) { this.lanes.push(lane); }; this.addFlowNode = function(flowNode) { this.flowNodes.push(flowNode); }; this.enter = function() { this.counter++; }; this.leave = function() { this.counter--; return !this.counter; }; } },{"243":243,"70":70,"98":98}],36:[function(_dereq_,module,exports){ module.exports = { __init__: [ 'appendBehavior', 'createBoundaryEventBehavior', 'createDataObjectBehavior', 'createOnFlowBehavior', 'createParticipantBehavior', 'dataInputAssociationBehavior', 'deleteLaneBehavior', 'labelBehavior', 'modelingFeedback', 'removeParticipantBehavior', 'replaceConnectionBehavior', 'replaceElementBehaviour', 'resizeLaneBehavior', 'updateFlowNodeRefsBehavior' ], appendBehavior: [ 'type', _dereq_(22) ], createBoundaryEventBehavior: [ 'type', _dereq_(23) ], createDataObjectBehavior: [ 'type', _dereq_(24) ], createOnFlowBehavior: [ 'type', _dereq_(25) ], createParticipantBehavior: [ 'type', _dereq_(26) ], dataInputAssociationBehavior: [ 'type', _dereq_(27) ], deleteLaneBehavior: [ 'type', _dereq_(28) ], labelBehavior: [ 'type', _dereq_(29) ], modelingFeedback: [ 'type', _dereq_(30) ], removeParticipantBehavior: [ 'type', _dereq_(31) ], replaceConnectionBehavior: [ 'type', _dereq_(32) ], replaceElementBehaviour: [ 'type', _dereq_(33) ], resizeLaneBehavior: [ 'type', _dereq_(34) ], updateFlowNodeRefsBehavior: [ 'type', _dereq_(35) ] }; },{"22":22,"23":23,"24":24,"25":25,"26":26,"27":27,"28":28,"29":29,"30":30,"31":31,"32":32,"33":33,"34":34,"35":35}],37:[function(_dereq_,module,exports){ 'use strict'; var filter = _dereq_(253); var Elements = _dereq_(221); var getLanesRoot = _dereq_(44).getLanesRoot, getChildLanes = _dereq_(44).getChildLanes, LANE_INDENTATION = _dereq_(44).LANE_INDENTATION; /** * A handler that allows us to add a new lane * above or below an existing one. * * @param {Modeling} modeling */ function AddLaneHandler(modeling, spaceTool) { this._modeling = modeling; this._spaceTool = spaceTool; } AddLaneHandler.$inject = [ 'modeling', 'spaceTool' ]; module.exports = AddLaneHandler; AddLaneHandler.prototype.preExecute = function(context) { var spaceTool = this._spaceTool, modeling = this._modeling; var shape = context.shape, location = context.location; var lanesRoot = getLanesRoot(shape); var isRoot = lanesRoot === shape, laneParent = isRoot ? shape : shape.parent; var existingChildLanes = getChildLanes(laneParent); // (0) add a lane if we currently got none and are adding to root if (!existingChildLanes.length) { modeling.createShape({ type: 'bpmn:Lane' }, { x: shape.x + LANE_INDENTATION, y: shape.y, width: shape.width - LANE_INDENTATION, height: shape.height }, laneParent); } // (1) collect affected elements to create necessary space var allAffected = []; Elements.eachElement(lanesRoot, function(element) { allAffected.push(element); if (element === shape) { return []; } return filter(element.children, function(c) { return c !== shape; }); }); var offset = location === 'top' ? -120 : 120, lanePosition = location === 'top' ? shape.y : shape.y + shape.height, spacePos = lanePosition + (location === 'top' ? 10 : -10), direction = location === 'top' ? 'n' : 's'; var adjustments = spaceTool.calculateAdjustments(allAffected, 'y', offset, spacePos); spaceTool.makeSpace(adjustments.movingShapes, adjustments.resizingShapes, { x: 0, y: offset }, direction); // (2) create new lane at open space context.newLane = modeling.createShape({ type: 'bpmn:Lane' }, { x: shape.x + (isRoot ? LANE_INDENTATION : 0), y: lanePosition - (location === 'top' ? 120 : 0), width: shape.width - (isRoot ? LANE_INDENTATION : 0), height: 120 }, laneParent); }; },{"221":221,"253":253,"44":44}],38:[function(_dereq_,module,exports){ 'use strict'; var is = _dereq_(70).is; var getLanesRoot = _dereq_(44).getLanesRoot, computeLanesResize = _dereq_(44).computeLanesResize; var eachElement = _dereq_(221).eachElement; var asTRBL = _dereq_(208).asTRBL, substractTRBL = _dereq_(180).substractTRBL; /** * A handler that resizes a lane. * * @param {Modeling} modeling */ function ResizeLaneHandler(modeling, spaceTool) { this._modeling = modeling; this._spaceTool = spaceTool; } ResizeLaneHandler.$inject = [ 'modeling', 'spaceTool' ]; module.exports = ResizeLaneHandler; ResizeLaneHandler.prototype.preExecute = function(context) { var shape = context.shape, newBounds = context.newBounds, balanced = context.balanced; if (balanced !== false) { this.resizeBalanced(shape, newBounds); } else { this.resizeSpace(shape, newBounds); } }; /** * Resize balanced, adjusting next / previous lane sizes. * * @param {djs.model.Shape} shape * @param {Bounds} newBounds */ ResizeLaneHandler.prototype.resizeBalanced = function(shape, newBounds) { var modeling = this._modeling; var resizeNeeded = computeLanesResize(shape, newBounds); // resize the lane modeling.resizeShape(shape, newBounds); // resize other lanes as needed resizeNeeded.forEach(function(r) { modeling.resizeShape(r.shape, r.newBounds); }); }; /** * Resize, making actual space and moving below / above elements. * * @param {djs.model.Shape} shape * @param {Bounds} newBounds */ ResizeLaneHandler.prototype.resizeSpace = function(shape, newBounds) { var spaceTool = this._spaceTool; var shapeTrbl = asTRBL(shape), newTrbl = asTRBL(newBounds); var trblDiff = substractTRBL(newTrbl, shapeTrbl); var lanesRoot = getLanesRoot(shape); var allAffected = [], allLanes = []; eachElement(lanesRoot, function(element) { allAffected.push(element); if (is(element, 'bpmn:Lane') || is(element, 'bpmn:Participant')) { allLanes.push(element); } return element.children; }); var change, spacePos, direction, offset, adjustments; if (trblDiff.bottom || trblDiff.top) { change = trblDiff.bottom || trblDiff.top; spacePos = shape.y + (trblDiff.bottom ? shape.height : 0) + (trblDiff.bottom ? -10 : 10); direction = trblDiff.bottom ? 's' : 'n'; offset = trblDiff.top > 0 || trblDiff.bottom < 0 ? -change : change; adjustments = spaceTool.calculateAdjustments(allAffected, 'y', offset, spacePos); spaceTool.makeSpace(adjustments.movingShapes, adjustments.resizingShapes, { x: 0, y: change }, direction); } if (trblDiff.left || trblDiff.right) { change = trblDiff.right || trblDiff.left; spacePos = shape.x + (trblDiff.right ? shape.width : 0) + (trblDiff.right ? -10 : 100); direction = trblDiff.right ? 'e' : 'w'; offset = trblDiff.left > 0 || trblDiff.right < 0 ? -change : change; adjustments = spaceTool.calculateAdjustments(allLanes, 'x', offset, spacePos); spaceTool.makeSpace(adjustments.movingShapes, adjustments.resizingShapes, { x: change, y: 0 }, direction); } }; },{"180":180,"208":208,"221":221,"44":44,"70":70}],39:[function(_dereq_,module,exports){ 'use strict'; var getChildLanes = _dereq_(44).getChildLanes; var LANE_INDENTATION = _dereq_(44).LANE_INDENTATION; /** * A handler that splits a lane into a number of sub-lanes, * creating new sub lanes, if neccessary. * * @param {Modeling} modeling */ function SplitLaneHandler(modeling, translate) { this._modeling = modeling; this._translate = translate; } SplitLaneHandler.$inject = [ 'modeling', 'translate']; module.exports = SplitLaneHandler; SplitLaneHandler.prototype.preExecute = function(context) { var modeling = this._modeling, translate = this._translate; var shape = context.shape, newLanesCount = context.count; var childLanes = getChildLanes(shape), existingLanesCount = childLanes.length; if (existingLanesCount > newLanesCount) { throw new Error(translate('more than {count} child lanes', { count: newLanesCount })); } var newLanesHeight = Math.round(shape.height / newLanesCount); // Iterate from top to bottom in child lane order, // resizing existing lanes and creating new ones // so that they split the parent proportionally. // // Due to rounding related errors, the bottom lane // needs to take up all the remaining space. var laneY, laneHeight, laneBounds, newLaneAttrs, idx; for (idx = 0; idx < newLanesCount; idx++) { laneY = shape.y + idx * newLanesHeight; // if bottom lane if (idx === newLanesCount - 1) { laneHeight = shape.height - (newLanesHeight * idx); } else { laneHeight = newLanesHeight; } laneBounds = { x: shape.x + LANE_INDENTATION, y: laneY, width: shape.width - LANE_INDENTATION, height: laneHeight }; if (idx < existingLanesCount) { // resize existing lane modeling.resizeShape(childLanes[idx], laneBounds); } else { // create a new lane at position newLaneAttrs = { type: 'bpmn:Lane' }; modeling.createShape(newLaneAttrs, laneBounds, shape); } } }; },{"44":44}],40:[function(_dereq_,module,exports){ 'use strict'; var Collections = _dereq_(219); 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; // TODO(nikku): return changed elements? // return [ newRoot, 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; // TODO(nikku): return changed elements? // return [ newRoot, oldRoot ]; }; },{"219":219}],41:[function(_dereq_,module,exports){ 'use strict'; var collectLanes = _dereq_(44).collectLanes; var getLanesRoot = _dereq_(44).getLanesRoot; var is = _dereq_(70).is; var Collections = _dereq_(219); var asTRBL = _dereq_(208).asTRBL; var FLOW_NODE_REFS_ATTR = 'flowNodeRef', LANES_ATTR = 'lanes'; /** * A handler that updates lane refs on changed elements */ function UpdateFlowNodeRefsHandler(elementRegistry) { this._elementRegistry = elementRegistry; } UpdateFlowNodeRefsHandler.$inject = [ 'elementRegistry' ]; module.exports = UpdateFlowNodeRefsHandler; UpdateFlowNodeRefsHandler.prototype.computeUpdates = function(flowNodeShapes, laneShapes) { var handledNodes = {}; var updates = []; var participantCache = {}; var allFlowNodeShapes = []; function isInLaneShape(element, laneShape) { var laneTrbl = asTRBL(laneShape); var elementMid = { x: element.x + element.width / 2, y: element.y + element.height / 2 }; return elementMid.x > laneTrbl.left && elementMid.x < laneTrbl.right && elementMid.y > laneTrbl.top && elementMid.y < laneTrbl.bottom; } function addFlowNodeShape(flowNodeShape) { if (!handledNodes[flowNodeShape.id]) { allFlowNodeShapes.push(flowNodeShape); handledNodes[flowNodeShape.id] = flowNodeShape; } } function getAllLaneShapes(flowNodeShape) { var root = getLanesRoot(flowNodeShape); if (!participantCache[root.id]) { participantCache[root.id] = collectLanes(root); } return participantCache[root.id]; } function getNewLanes(flowNodeShape) { if (!flowNodeShape.parent) { return []; } var allLaneShapes = getAllLaneShapes(flowNodeShape); return allLaneShapes.filter(function(l) { return isInLaneShape(flowNodeShape, l); }).map(function(shape) { return shape.businessObject; }); } laneShapes.forEach(function(laneShape) { var root = getLanesRoot(laneShape); if (!root || handledNodes[root.id]) { return; } var children = root.children.filter(function(c) { return is(c, 'bpmn:FlowNode'); }); children.forEach(addFlowNodeShape); handledNodes[root.id] = root; }); flowNodeShapes.forEach(addFlowNodeShape); allFlowNodeShapes.forEach(function(flowNodeShape) { var flowNode = flowNodeShape.businessObject; var lanes = flowNode.get(LANES_ATTR), remove = lanes.slice(), add = getNewLanes(flowNodeShape); updates.push({ flowNode: flowNode, remove: remove, add: add }); }); laneShapes.forEach(function(laneShape) { var lane = laneShape.businessObject; // lane got removed XX-) if (!laneShape.parent) { lane.get(FLOW_NODE_REFS_ATTR).forEach(function(flowNode) { updates.push({ flowNode: flowNode, remove: [ lane ], add: [] }); }); } }); return updates; }; UpdateFlowNodeRefsHandler.prototype.execute = function(context) { var updates = context.updates; if (!updates) { updates = context.updates = this.computeUpdates(context.flowNodeShapes, context.laneShapes); } updates.forEach(function(update) { var flowNode = update.flowNode, lanes = flowNode.get(LANES_ATTR); // unwire old update.remove.forEach(function(oldLane) { Collections.remove(lanes, oldLane); Collections.remove(oldLane.get(FLOW_NODE_REFS_ATTR), flowNode); }); // wire new update.add.forEach(function(newLane) { Collections.add(lanes, newLane); Collections.add(newLane.get(FLOW_NODE_REFS_ATTR), flowNode); }); }); // TODO(nikku): return changed elements // return [ ... ]; }; UpdateFlowNodeRefsHandler.prototype.revert = function(context) { var updates = context.updates; updates.forEach(function(update) { var flowNode = update.flowNode, lanes = flowNode.get(LANES_ATTR); // unwire new update.add.forEach(function(newLane) { Collections.remove(lanes, newLane); Collections.remove(newLane.get(FLOW_NODE_REFS_ATTR), flowNode); }); // wire old update.remove.forEach(function(oldLane) { Collections.add(lanes, oldLane); Collections.add(oldLane.get(FLOW_NODE_REFS_ATTR), flowNode); }); }); // TODO(nikku): return changed elements // return [ ... ]; }; },{"208":208,"219":219,"44":44,"70":70}],42:[function(_dereq_,module,exports){ 'use strict'; var reduce = _dereq_(384), keys = _dereq_(378), forEach = _dereq_(255), assign = _dereq_(377); var getBusinessObject = _dereq_(70).getBusinessObject; 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, moddle, translate) { this._elementRegistry = elementRegistry; this._moddle = moddle; this._translate = translate; } UpdatePropertiesHandler.$inject = [ 'elementRegistry', 'moddle', 'translate' ]; module.exports = UpdatePropertiesHandler; ////// 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], translate = this._translate; if (!element) { throw new Error(translate('element required')); } var elementRegistry = this._elementRegistry, ids = this._moddle.ids; var businessObject = element.businessObject, properties = unwrapBusinessObjects(context.properties), oldProperties = context.oldProperties || getProperties(businessObject, keys(properties)); if (isIdChange(properties, businessObject)) { ids.unclaim(businessObject[ID]); 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); // show the label element.label.hidden = !properties[NAME]; } // 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, properties = context.properties, oldProperties = context.oldProperties, businessObject = element.businessObject, elementRegistry = this._elementRegistry, ids = this._moddle.ids; // update properties setProperties(businessObject, oldProperties); if (isIdChange(properties, businessObject)) { ids.unclaim(properties[ID]); elementRegistry.updateId(element, oldProperties[ID]); } return context.changed; }; function isIdChange(properties, businessObject) { return ID in properties && properties[ID] !== businessObject[ID]; } 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); }); } var referencePropertyNames = [ 'default' ]; /** * Make sure we unwrap the actual business object * behind diagram element that may have been * passed as arguments. * * @param {Object} properties * * @return {Object} unwrappedProps */ function unwrapBusinessObjects(properties) { var unwrappedProps = assign({}, properties); referencePropertyNames.forEach(function(name) { if (name in properties) { unwrappedProps[name] = getBusinessObject(unwrappedProps[name]); } }); return unwrappedProps; } },{"255":255,"377":377,"378":378,"384":384,"70":70}],43:[function(_dereq_,module,exports){ module.exports = { __init__: [ 'modeling', 'bpmnUpdater' ], __depends__: [ _dereq_(36), _dereq_(16), _dereq_(59), _dereq_(47), _dereq_(57), _dereq_(100), _dereq_(200), _dereq_(139), _dereq_(112), _dereq_(189), _dereq_(120), _dereq_(196) ], bpmnFactory: [ 'type', _dereq_(17) ], bpmnUpdater: [ 'type', _dereq_(19) ], elementFactory: [ 'type', _dereq_(20) ], modeling: [ 'type', _dereq_(21) ], layouter: [ 'type', _dereq_(18) ], connectionDocking: [ 'type', _dereq_(207) ] }; },{"100":100,"112":112,"120":120,"139":139,"16":16,"17":17,"18":18,"189":189,"19":19,"196":196,"20":20,"200":200,"207":207,"21":21,"36":36,"47":47,"57":57,"59":59}],44:[function(_dereq_,module,exports){ 'use strict'; var is = _dereq_(70).is; var getParent = _dereq_(45).getParent; var asTRBL = _dereq_(208).asTRBL, substractTRBL = _dereq_(180).substractTRBL, resizeTRBL = _dereq_(180).resizeTRBL; var abs = Math.abs; function getTRBLResize(oldBounds, newBounds) { return substractTRBL(asTRBL(newBounds), asTRBL(oldBounds)); } var LANE_PARENTS = [ 'bpmn:Participant', 'bpmn:Process', 'bpmn:SubProcess' ]; var LANE_INDENTATION = 30; module.exports.LANE_INDENTATION = LANE_INDENTATION; /** * Collect all lane shapes in the given paren * * @param {djs.model.Shape} shape * @param {Array} [collectedShapes] * * @return {Array} */ function collectLanes(shape, collectedShapes) { collectedShapes = collectedShapes || []; shape.children.filter(function(s) { if (is(s, 'bpmn:Lane')) { collectLanes(s, collectedShapes); collectedShapes.push(s); } }); return collectedShapes; } module.exports.collectLanes = collectLanes; /** * Return the lane children of the given element. * * @param {djs.model.Shape} shape * * @return {Array} */ function getChildLanes(shape) { return shape.children.filter(function(c) { return is(c, 'bpmn:Lane'); }); } module.exports.getChildLanes = getChildLanes; /** * Return the root element containing the given lane shape * * @param {djs.model.Shape} shape * * @return {djs.model.Shape} */ function getLanesRoot(shape) { return getParent(shape, LANE_PARENTS) || shape; } module.exports.getLanesRoot = getLanesRoot; /** * Compute the required resize operations for lanes * adjacent to the given shape, assuming it will be * resized to the given new bounds. * * @param {djs.model.Shape} shape * @param {Bounds} newBounds * * @return {Array} */ function computeLanesResize(shape, newBounds) { var rootElement = getLanesRoot(shape); var initialShapes = is(rootElement, 'bpmn:Process') ? [] : [ rootElement ]; var allLanes = collectLanes(rootElement, initialShapes), shapeTrbl = asTRBL(shape), shapeNewTrbl = asTRBL(newBounds), trblResize = getTRBLResize(shape, newBounds), resizeNeeded = []; allLanes.forEach(function(other) { if (other === shape) { return; } var topResize = 0, rightResize = trblResize.right, bottomResize = 0, leftResize = trblResize.left; var otherTrbl = asTRBL(other); if (trblResize.top) { if (abs(otherTrbl.bottom - shapeTrbl.top) < 10) { bottomResize = shapeNewTrbl.top - otherTrbl.bottom; } if (abs(otherTrbl.top - shapeTrbl.top) < 5) { topResize = shapeNewTrbl.top - otherTrbl.top; } } if (trblResize.bottom) { if (abs(otherTrbl.top - shapeTrbl.bottom) < 10) { topResize = shapeNewTrbl.bottom - otherTrbl.top; } if (abs(otherTrbl.bottom - shapeTrbl.bottom) < 5) { bottomResize = shapeNewTrbl.bottom - otherTrbl.bottom; } } if (topResize || rightResize || bottomResize || leftResize) { resizeNeeded.push({ shape: other, newBounds: resizeTRBL(other, { top: topResize, right: rightResize, bottom: bottomResize, left: leftResize }) }); } }); return resizeNeeded; } module.exports.computeLanesResize = computeLanesResize; },{"180":180,"208":208,"45":45,"70":70}],45:[function(_dereq_,module,exports){ 'use strict'; var any = _dereq_(251); var is = _dereq_(70).is; function getParents(element) { var parents = []; while (element) { element = element.parent; if (element) { parents.push(element); } } return parents; } module.exports.getParents = getParents; /** * Return true if element has any of the given types. * * @param {djs.model.Base} element * @param {Array} types * * @return {Boolean} */ function isAny(element, types) { return any(types, function(t) { return is(element, t); }); } module.exports.isAny = isAny; /** * Return the parent of the element with any of the given types. * * @param {djs.model.Base} element * @param {String|Array} anyType * * @return {djs.model.Base} */ function getParent(element, anyType) { if (typeof anyType === 'string') { anyType = [ anyType ]; } while ((element = element.parent)) { if (isAny(element, anyType)) { return element; } } return null; } module.exports.getParent = getParent; },{"251":251,"70":70}],46:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var OrderingProvider = _dereq_(167); var isAny = _dereq_(45).isAny; var findIndex = _dereq_(244); var find = _dereq_(254); /** * a simple ordering provider that makes sure: * * (1) elements are ordered by a {level} property * (2) elements with {alwaysOnTop} are always added to the root */ function BpmnOrderingProvider(eventBus, translate) { OrderingProvider.call(this, eventBus); var orders = [ { type: 'label', order: { level: 10 } }, { type: 'bpmn:SubProcess', order: { level: 6 } }, { type: 'bpmn:SequenceFlow', order: { level: 5, containers: [ 'bpmn:Participant', 'bpmn:FlowElementsContainer' ] } }, { type: 'bpmn:Association', order: { level: 6, containers: [ 'bpmn:Participant', 'bpmn:FlowElementsContainer', 'bpmn:Collaboration' ] } }, { type: 'bpmn:MessageFlow', order: { level: 9, containers: [ 'bpmn:Collaboration' ] } }, { type: 'bpmn:BoundaryEvent', order: { level: 8 } }, { type: 'bpmn:Participant', order: { level: -2 } }, { type: 'bpmn:Lane', order: { level: -1 } } ]; function computeOrder(element) { var entry = find(orders, function(o) { return isAny(element, [ o.type ]); }); return entry && entry.order || { level: 1 }; } function getOrder(element) { var order = element.order; if (!order) { element.order = order = computeOrder(element); } return order; } function findActualParent(element, newParent, containers) { var actualParent = newParent; while (actualParent) { if (isAny(actualParent, containers)) { break; } actualParent = actualParent.parent; } if (!actualParent) { throw new Error(translate('no parent for {element} in {parent}', { element: element.id, parent: newParent.id })); } return actualParent; } this.getOrdering = function(element, newParent) { var elementOrder = getOrder(element); if (elementOrder.containers) { newParent = findActualParent(element, newParent, elementOrder.containers); } var currentIndex = newParent.children.indexOf(element); var insertIndex = findIndex(newParent.children, function(child) { // do not compare with labels, they are created // in the wrong order (right after elements) during import and // mess up the positioning. if (!element.labelTarget && child.labelTarget) { return false; } return elementOrder.level < getOrder(child).level; }); // if the element is already in the child list at // a smaller index, we need to adjust the inser index. // this takes into account that the element is being removed // before being re-inserted if (insertIndex !== -1) { if (currentIndex !== -1 && currentIndex < insertIndex) { insertIndex -= 1; } } return { index: insertIndex, parent: newParent }; }; } BpmnOrderingProvider.$inject = [ 'eventBus', 'translate' ]; inherits(BpmnOrderingProvider, OrderingProvider); module.exports = BpmnOrderingProvider; },{"167":167,"243":243,"244":244,"254":254,"45":45}],47:[function(_dereq_,module,exports){ module.exports = { __init__: [ 'bpmnOrderingProvider' ], __depends__: [ _dereq_(204) ], bpmnOrderingProvider: [ 'type', _dereq_(46) ] }; },{"204":204,"46":46}],48:[function(_dereq_,module,exports){ 'use strict'; var assign = _dereq_(377); /** * A palette provider for BPMN 2.0 elements. */ function PaletteProvider(palette, create, elementFactory, spaceTool, lassoTool, handTool, translate) { this._palette = palette; this._create = create; this._elementFactory = elementFactory; this._spaceTool = spaceTool; this._lassoTool = lassoTool; this._handTool = handTool; this._translate = translate; palette.registerProvider(this); } module.exports = PaletteProvider; PaletteProvider.$inject = [ 'palette', 'create', 'elementFactory', 'spaceTool', 'lassoTool', 'handTool', 'translate', 'eventBus' ]; PaletteProvider.prototype.getPaletteEntries = function(element) { var actions = {}, create = this._create, elementFactory = this._elementFactory, spaceTool = this._spaceTool, lassoTool = this._lassoTool, handTool = this._handTool, translate = this._translate; 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 || translate('Create {type}', { type: shortType }), action: { dragstart: createListener, click: createListener } }; } function createParticipant(event, collapsed) { create.start(event, elementFactory.createParticipantShape(collapsed)); } assign(actions, { 'hand-tool': { group: 'tools', className: 'bpmn-icon-hand-tool', title: translate('Activate the hand tool'), action: { click: function(event) { handTool.activateHand(event); } } }, 'lasso-tool': { group: 'tools', className: 'bpmn-icon-lasso-tool', title: translate('Activate the lasso tool'), action: { click: function(event) { lassoTool.activateSelection(event); } } }, 'space-tool': { group: 'tools', className: 'bpmn-icon-space-tool', title: translate('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', 'bpmn-icon-start-event-none' ), 'create.intermediate-event': createAction( 'bpmn:IntermediateThrowEvent', 'event', 'bpmn-icon-intermediate-event-none' ), 'create.end-event': createAction( 'bpmn:EndEvent', 'event', 'bpmn-icon-end-event-none' ), 'create.exclusive-gateway': createAction( 'bpmn:ExclusiveGateway', 'gateway', 'bpmn-icon-gateway-xor' ), 'create.task': createAction( 'bpmn:Task', 'activity', 'bpmn-icon-task' ), 'create.data-object': createAction( 'bpmn:DataObjectReference', 'data-object', 'bpmn-icon-data-object' ), 'create.data-store': createAction( 'bpmn:DataStoreReference', 'data-store', 'bpmn-icon-data-store' ), 'create.subprocess-expanded': createAction( 'bpmn:SubProcess', 'activity', 'bpmn-icon-subprocess-expanded', translate('Create expanded SubProcess'), { isExpanded: true } ), 'create.participant-expanded': { group: 'collaboration', className: 'bpmn-icon-participant', title: translate('Create Pool/Participant'), action: { dragstart: createParticipant, click: createParticipant } } }); return actions; }; },{"377":377}],49:[function(_dereq_,module,exports){ module.exports = { __depends__: [ _dereq_(173), _dereq_(126), _dereq_(196), _dereq_(141), _dereq_(133), _dereq_(204) ], __init__: [ 'paletteProvider' ], paletteProvider: [ 'type', _dereq_(48) ] }; },{"126":126,"133":133,"141":141,"173":173,"196":196,"204":204,"48":48}],50:[function(_dereq_,module,exports){ 'use strict'; var is = _dereq_(70).is, isEventSubProcess = _dereq_(68).isEventSubProcess, getBusinessObject = _dereq_(70).getBusinessObject, isExpanded = _dereq_(68).isExpanded, isDifferentType = _dereq_(52).isDifferentType; var forEach = _dereq_(255), filter = _dereq_(253); var replaceOptions = _dereq_(56); /** * This module is an element agnostic replace menu provider for the popup menu. */ function ReplaceMenuProvider(popupMenu, modeling, moddle, bpmnReplace, rules, translate) { this._popupMenu = popupMenu; this._modeling = modeling; this._moddle = moddle; this._bpmnReplace = bpmnReplace; this._rules = rules; this._translate = translate; this.register(); } ReplaceMenuProvider.$inject = [ 'popupMenu', 'modeling', 'moddle', 'bpmnReplace', 'rules', 'translate' ]; /** * Register replace menu provider in the popup menu */ ReplaceMenuProvider.prototype.register = function() { this._popupMenu.registerProvider('bpmn-replace', this); }; /** * Get all entries from replaceOptions for the given element and apply filters * on them. Get for example only elements, which are different from the current one. * * @param {djs.model.Base} element * * @return {Array} a list of menu entry items */ ReplaceMenuProvider.prototype.getEntries = function(element) { var businessObject = element.businessObject; var rules = this._rules; var entries; if (!rules.allowed('shape.replace', { element: element })) { return []; } var differentType = isDifferentType(element); // start events outside event sub processes if (is(businessObject, 'bpmn:StartEvent') && !isEventSubProcess(businessObject.$parent)) { entries = filter(replaceOptions.START_EVENT, differentType); return this._createEntries(element, entries); } // expanded/collapsed pools if (is(businessObject, 'bpmn:Participant')) { entries = filter(replaceOptions.PARTICIPANT, function(entry) { return isExpanded(businessObject) !== entry.target.isExpanded; }); return this._createEntries(element, entries); } // start events inside event sub processes if (is(businessObject, 'bpmn:StartEvent') && isEventSubProcess(businessObject.$parent)) { entries = filter(replaceOptions.EVENT_SUB_PROCESS_START_EVENT, function(entry) { var target = entry.target; var isInterrupting = target.isInterrupting !== false; var isInterruptingEqual = getBusinessObject(element).isInterrupting === isInterrupting; // filters elements which types and event definition are equal but have have different interrupting types return differentType(entry) || !differentType(entry) && !isInterruptingEqual; }); return this._createEntries(element, entries); } // end events if (is(businessObject, 'bpmn:EndEvent')) { entries = filter(replaceOptions.END_EVENT, function(entry) { var target = entry.target; // hide cancel end events outside transactions if (target.eventDefinition == 'bpmn:CancelEventDefinition' && !is(businessObject.$parent, 'bpmn:Transaction')) { return false; } return differentType(entry); }); return this._createEntries(element, entries); } // boundary events if (is(businessObject, 'bpmn:BoundaryEvent')) { entries = filter(replaceOptions.BOUNDARY_EVENT, function(entry) { var target = entry.target; if (target.eventDefinition == 'bpmn:CancelEventDefinition' && !is(businessObject.attachedToRef, 'bpmn:Transaction')) { return false; } var cancelActivity = target.cancelActivity !== false; var isCancelActivityEqual = businessObject.cancelActivity == cancelActivity; return differentType(entry) || !differentType(entry) && !isCancelActivityEqual; }); return this._createEntries(element, entries); } // intermediate events if (is(businessObject, 'bpmn:IntermediateCatchEvent') || is(businessObject, 'bpmn:IntermediateThrowEvent')) { entries = filter(replaceOptions.INTERMEDIATE_EVENT, differentType); return this._createEntries(element, entries); } // gateways if (is(businessObject, 'bpmn:Gateway')) { entries = filter(replaceOptions.GATEWAY, differentType); return this._createEntries(element, entries); } // transactions if (is(businessObject, 'bpmn:Transaction')) { entries = filter(replaceOptions.TRANSACTION, differentType); return this._createEntries(element, entries); } // expanded event sub processes if (isEventSubProcess(businessObject) && isExpanded(businessObject)) { entries = filter(replaceOptions.EVENT_SUB_PROCESS, differentType); return this._createEntries(element, entries); } // expanded sub processes if (is(businessObject, 'bpmn:SubProcess') && isExpanded(businessObject)) { entries = filter(replaceOptions.SUBPROCESS_EXPANDED, differentType); return this._createEntries(element, entries); } // collapsed ad hoc sub processes if (is(businessObject, 'bpmn:AdHocSubProcess') && !isExpanded(businessObject)) { entries = filter(replaceOptions.TASK, function(entry) { var target = entry.target; var isTargetSubProcess = target.type === 'bpmn:SubProcess'; return isDifferentType(element, target) && !isTargetSubProcess; }); return this._createEntries(element, entries); } // sequence flows if (is(businessObject, 'bpmn:SequenceFlow')) { return this._createSequenceFlowEntries(element, replaceOptions.SEQUENCE_FLOW); } // flow nodes if (is(businessObject, 'bpmn:FlowNode')) { entries = filter(replaceOptions.TASK, differentType); if (businessObject.isForCompensation) { // can only replace to compensation activities entries = filter(entries, function(entry) { return !/CallActivity/.test(entry.target.type); }); } return this._createEntries(element, entries); } return []; }; /** * Get a list of header items for the given element. This includes buttons * for multi instance markers and for the ad hoc marker. * * @param {djs.model.Base} element * * @return {Array} a list of menu entry items */ ReplaceMenuProvider.prototype.getHeaderEntries = function(element) { var headerEntries = []; if (is(element, 'bpmn:Activity') && !isEventSubProcess(element)) { headerEntries = headerEntries.concat(this._getLoopEntries(element)); } if (is(element, 'bpmn:SubProcess') && !is(element, 'bpmn:Transaction') && !isEventSubProcess(element)) { headerEntries.push(this._getAdHocEntry(element)); } return headerEntries; }; /** * Creates an array of menu entry objects for a given element and filters the replaceOptions * according to a filter function. * * @param {djs.model.Base} element * @param {Object} replaceOptions * * @return {Array} a list of menu items */ ReplaceMenuProvider.prototype._createEntries = function(element, replaceOptions) { var menuEntries = []; var self = this; forEach(replaceOptions, function(definition) { var entry = self._createMenuEntry(definition, element); menuEntries.push(entry); }); return menuEntries; }; /** * Creates an array of menu entry objects for a given sequence flow. * * @param {djs.model.Base} element * @param {Object} replaceOptions * @return {Array} a list of menu items */ ReplaceMenuProvider.prototype._createSequenceFlowEntries = function (element, replaceOptions) { var businessObject = getBusinessObject(element); var menuEntries = []; var modeling = this._modeling, moddle = this._moddle; var self = this; forEach(replaceOptions, function(entry) { switch (entry.actionName) { case 'replace-with-default-flow': if (businessObject.sourceRef.default !== businessObject && (is(businessObject.sourceRef, 'bpmn:ExclusiveGateway') || is(businessObject.sourceRef, 'bpmn:InclusiveGateway') || is(businessObject.sourceRef, 'bpmn:Activity'))) { menuEntries.push(self._createMenuEntry(entry, element, function() { modeling.updateProperties(element.source, { default: businessObject }); })); } break; case 'replace-with-conditional-flow': if (!businessObject.conditionExpression && is(businessObject.sourceRef, 'bpmn:Activity')) { menuEntries.push(self._createMenuEntry(entry, element, function() { var conditionExpression = moddle.create('bpmn:FormalExpression', { body: '' }); modeling.updateProperties(element, { conditionExpression: conditionExpression }); })); } break; default: // default flows if (is(businessObject.sourceRef, 'bpmn:Activity') && businessObject.conditionExpression) { return menuEntries.push(self._createMenuEntry(entry, element, function() { modeling.updateProperties(element, { conditionExpression: undefined }); })); } // conditional flows if ((is(businessObject.sourceRef, 'bpmn:ExclusiveGateway') || is(businessObject.sourceRef, 'bpmn:InclusiveGateway') || is(businessObject.sourceRef, 'bpmn:Activity')) && businessObject.sourceRef.default === businessObject) { return menuEntries.push(self._createMenuEntry(entry, element, function() { modeling.updateProperties(element.source, { default: undefined }); })); } } }); return menuEntries; }; /** * Creates and returns a single menu entry item. * * @param {Object} definition a single replace options definition object * @param {djs.model.Base} element * @param {Function} [action] an action callback function which gets called when * the menu entry is being triggered. * * @return {Object} menu entry item */ ReplaceMenuProvider.prototype._createMenuEntry = function(definition, element, action) { var translate = this._translate; var replaceElement = this._bpmnReplace.replaceElement; var replaceAction = function() { return replaceElement(element, definition.target); }; action = action || replaceAction; var menuEntry = { label: translate(definition.label), className: definition.className, id: definition.actionName, action: action }; return menuEntry; }; /** * Get a list of menu items containing buttons for multi instance markers * * @param {djs.model.Base} element * * @return {Array} a list of menu items */ ReplaceMenuProvider.prototype._getLoopEntries = function(element) { var self = this; var translate = this._translate; function toggleLoopEntry(event, entry) { var loopCharacteristics; if (entry.active) { loopCharacteristics = undefined; } else { loopCharacteristics = self._moddle.create(entry.options.loopCharacteristics); if (entry.options.isSequential) { loopCharacteristics.isSequential = entry.options.isSequential; } } self._modeling.updateProperties(element, { loopCharacteristics: loopCharacteristics }); } 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: 'bpmn-icon-parallel-mi-marker', title: translate('Parallel Multi Instance'), active: isParallel, action: toggleLoopEntry, options: { loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics', isSequential: false } }, { id: 'toggle-sequential-mi', className: 'bpmn-icon-sequential-mi-marker', title: translate('Sequential Multi Instance'), active: isSequential, action: toggleLoopEntry, options: { loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics', isSequential: true } }, { id: 'toggle-loop', className: 'bpmn-icon-loop-marker', title: translate('Loop'), active: isLoop, action: toggleLoopEntry, options: { loopCharacteristics: 'bpmn:StandardLoopCharacteristics' } } ]; return loopEntries; }; /** * Get the menu items containing a button for the ad hoc marker * * @param {djs.model.Base} element * * @return {Object} a menu item */ ReplaceMenuProvider.prototype._getAdHocEntry = function(element) { var translate = this._translate; var businessObject = getBusinessObject(element); var isAdHoc = is(businessObject, 'bpmn:AdHocSubProcess'); var replaceElement = this._bpmnReplace.replaceElement; var adHocEntry = { id: 'toggle-adhoc', className: 'bpmn-icon-ad-hoc-marker', title: translate('Ad-hoc'), active: isAdHoc, action: function(event, entry) { if (isAdHoc) { return replaceElement(element, { type: 'bpmn:SubProcess' }); } else { return replaceElement(element, { type: 'bpmn:AdHocSubProcess' }); } } }; return adHocEntry; }; module.exports = ReplaceMenuProvider; },{"253":253,"255":255,"52":52,"56":56,"68":68,"70":70}],51:[function(_dereq_,module,exports){ module.exports = { __depends__: [ _dereq_(175), _dereq_(57) ], __init__: [ 'replaceMenuProvider' ], replaceMenuProvider: [ 'type', _dereq_(50) ] }; },{"175":175,"50":50,"57":57}],52:[function(_dereq_,module,exports){ 'use strict'; var getBusinessObject = _dereq_(70).getBusinessObject; /** * Returns true, if an element is from a different type * than a target definition. Takes into account the type, * event definition type and triggeredByEvent property. * * @param {djs.model.Base} element * * @return {Boolean} */ function isDifferentType(element) { return function(entry) { var target = entry.target; var businessObject = getBusinessObject(element), eventDefinition = businessObject.eventDefinitions && businessObject.eventDefinitions[0]; var isEventDefinitionEqual = (eventDefinition && eventDefinition.$type) === target.eventDefinitionType, isTypeEqual = businessObject.$type === target.type, isTriggeredByEventEqual = businessObject.triggeredByEvent == target.triggeredByEvent; return !isTypeEqual || !isEventDefinitionEqual || !isTriggeredByEventEqual; }; } module.exports.isDifferentType = isDifferentType; },{"70":70}],53:[function(_dereq_,module,exports){ 'use strict'; var CommandInterceptor = _dereq_(98); var inherits = _dereq_(243); var assign = _dereq_(377), forEach = _dereq_(255); var LOW_PRIORITY = 250; function BpmnReplacePreview(eventBus, elementRegistry, elementFactory, canvas, moveVisuals) { CommandInterceptor.call(this, eventBus); /** * Replace the visuals of all elements in the context which can be replaced * * @param {Object} context */ function replaceVisual(context) { var replacements = context.canExecute.replacements; forEach(replacements, function(replacement) { var id = replacement.oldElementId; var newElement = { type: replacement.newElementType }; // if the visual of the element is already replaced if (context.visualReplacements[id]) { return; } var element = elementRegistry.get(id); assign(newElement, { x: element.x, y: element.y }); // create a temporary shape var tempShape = elementFactory.createShape(newElement); canvas.addShape(tempShape, element.parent); // select the original SVG element related to the element and hide it var gfx = context.dragGroup.select('[data-element-id=' + element.id + ']'); if (gfx) { gfx.attr({ display: 'none' }); } // clone the gfx of the temporary shape and add it to the drag group var dragger = moveVisuals.addDragger(context, tempShape); context.visualReplacements[id] = dragger; canvas.removeShape(tempShape); }); } /** * Restore the original visuals of the previously replaced elements * * @param {Object} context */ function restoreVisual(context) { var visualReplacements = context.visualReplacements; forEach(visualReplacements, function(dragger, id) { var originalGfx = context.dragGroup.select('[data-element-id=' + id + ']'); if (originalGfx) { originalGfx.attr({ display: 'inline' }); } dragger.remove(); if (visualReplacements[id]) { delete visualReplacements[id]; } }); } eventBus.on('shape.move.move', LOW_PRIORITY, function(event) { var context = event.context, canExecute = context.canExecute; if (!context.visualReplacements) { context.visualReplacements = {}; } if (canExecute.replacements) { replaceVisual(context); } else { restoreVisual(context); } }); } BpmnReplacePreview.$inject = [ 'eventBus', 'elementRegistry', 'elementFactory', 'canvas', 'moveVisuals' ]; inherits(BpmnReplacePreview, CommandInterceptor); module.exports = BpmnReplacePreview; },{"243":243,"255":255,"377":377,"98":98}],54:[function(_dereq_,module,exports){ module.exports = { __depends__: [ _dereq_(166) ], __init__: ['bpmnReplacePreview'], bpmnReplacePreview: [ 'type', _dereq_(53) ] }; },{"166":166,"53":53}],55:[function(_dereq_,module,exports){ 'use strict'; var pick = _dereq_(383), assign = _dereq_(377); var is = _dereq_(70).is, isExpanded = _dereq_(68).isExpanded, isEventSubProcess = _dereq_(68).isEventSubProcess; var CUSTOM_PROPERTIES = [ 'cancelActivity', 'instantiate', 'eventGatewayType', 'triggeredByEvent', 'isInterrupting' ]; /** * This module takes care of replacing BPMN elements */ function BpmnReplace(bpmnFactory, replace, selection, modeling) { /** * Prepares a new business object for the replacement element * and triggers the replace operation. * * @param {djs.model.Base} element * @param {Object} target * @param {Object} [hints] * * @return {djs.model.Base} the newly created element */ function replaceElement(element, target, hints) { hints = hints || {}; var type = target.type, oldBusinessObject = element.businessObject, newBusinessObject = bpmnFactory.create(type); var newElement = { type: type, businessObject: newBusinessObject }; // initialize custom BPMN extensions if (target.eventDefinitionType) { newElement.eventDefinitionType = target.eventDefinitionType; } // initialize special properties defined in target definition assign(newBusinessObject, 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); } // transform collapsed/expanded pools if (is(oldBusinessObject, 'bpmn:Participant')) { // create expanded pool if (target.isExpanded === true) { newBusinessObject.processRef = bpmnFactory.create('bpmn:Process'); } else { // remove children when transforming to collapsed pool hints.moveChildren = false; } // apply same size newElement.width = element.width; newElement.height = element.height; } newBusinessObject.name = oldBusinessObject.name; // retain loop characteristics if the target element is not an event sub process if (!isEventSubProcess(newBusinessObject)) { newBusinessObject.loopCharacteristics = oldBusinessObject.loopCharacteristics; } // retain default flow's reference between inclusive <-> exclusive gateways and activities if ((is(oldBusinessObject, 'bpmn:ExclusiveGateway') || is(oldBusinessObject, 'bpmn:InclusiveGateway') || is(oldBusinessObject, 'bpmn:Activity')) && (is(newBusinessObject, 'bpmn:ExclusiveGateway') || is(newBusinessObject, 'bpmn:InclusiveGateway') || is(newBusinessObject, 'bpmn:Activity'))) { newBusinessObject.default = oldBusinessObject.default; } if (oldBusinessObject.isForCompensation) { newBusinessObject.isForCompensation = true; } newElement = replace.replaceElement(element, newElement, hints); if (hints.select !== false) { selection.select(newElement); } return newElement; } this.replaceElement = replaceElement; } BpmnReplace.$inject = [ 'bpmnFactory', 'replace', 'selection', 'modeling' ]; module.exports = BpmnReplace; },{"377":377,"383":383,"68":68,"70":70}],56:[function(_dereq_,module,exports){ 'use strict'; module.exports.START_EVENT = [ { label: 'Start Event', actionName: 'replace-with-none-start', className: 'bpmn-icon-start-event-none', target: { type: 'bpmn:StartEvent' } }, { label: 'Intermediate Throw Event', actionName: 'replace-with-none-intermediate-throwing', className: 'bpmn-icon-intermediate-event-none', target: { type: 'bpmn:IntermediateThrowEvent' } }, { label: 'End Event', actionName: 'replace-with-none-end', className: 'bpmn-icon-end-event-none', target: { type: 'bpmn:EndEvent' } }, { label: 'Message Start Event', actionName: 'replace-with-message-start', className: 'bpmn-icon-start-event-message', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:MessageEventDefinition' } }, { label: 'Timer Start Event', actionName: 'replace-with-timer-start', className: 'bpmn-icon-start-event-timer', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:TimerEventDefinition' } }, { label: 'Conditional Start Event', actionName: 'replace-with-conditional-start', className: 'bpmn-icon-start-event-condition', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:ConditionalEventDefinition' } }, { label: 'Signal Start Event', actionName: 'replace-with-signal-start', className: 'bpmn-icon-start-event-signal', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:SignalEventDefinition' } } ]; module.exports.INTERMEDIATE_EVENT = [ { label: 'Start Event', actionName: 'replace-with-none-start', className: 'bpmn-icon-start-event-none', target: { type: 'bpmn:StartEvent' } }, { label: 'Intermediate Throw Event', actionName: 'replace-with-none-intermediate-throw', className: 'bpmn-icon-intermediate-event-none', target: { type: 'bpmn:IntermediateThrowEvent' } }, { label: 'End Event', actionName: 'replace-with-none-end', className: 'bpmn-icon-end-event-none', target: { type: 'bpmn:EndEvent' } }, { label: 'Message Intermediate Catch Event', actionName: 'replace-with-message-intermediate-catch', className: 'bpmn-icon-intermediate-event-catch-message', target: { type: 'bpmn:IntermediateCatchEvent', eventDefinitionType: 'bpmn:MessageEventDefinition' } }, { label: 'Message Intermediate Throw Event', actionName: 'replace-with-message-intermediate-throw', className: 'bpmn-icon-intermediate-event-throw-message', target: { type: 'bpmn:IntermediateThrowEvent', eventDefinitionType: 'bpmn:MessageEventDefinition' } }, { label: 'Timer Intermediate Catch Event', actionName: 'replace-with-timer-intermediate-catch', className: 'bpmn-icon-intermediate-event-catch-timer', target: { type: 'bpmn:IntermediateCatchEvent', eventDefinitionType: 'bpmn:TimerEventDefinition' } }, { label: 'Escalation Intermediate Throw Event', actionName: 'replace-with-escalation-intermediate-throw', className: 'bpmn-icon-intermediate-event-throw-escalation', target: { type: 'bpmn:IntermediateThrowEvent', eventDefinitionType: 'bpmn:EscalationEventDefinition' } }, { label: 'Conditional Intermediate Catch Event', actionName: 'replace-with-conditional-intermediate-catch', className: 'bpmn-icon-intermediate-event-catch-condition', target: { type: 'bpmn:IntermediateCatchEvent', eventDefinitionType: 'bpmn:ConditionalEventDefinition' } }, { label: 'Link Intermediate Catch Event', actionName: 'replace-with-link-intermediate-catch', className: 'bpmn-icon-intermediate-event-catch-link', target: { type: 'bpmn:IntermediateCatchEvent', eventDefinitionType: 'bpmn:LinkEventDefinition' } }, { label: 'Link Intermediate Throw Event', actionName: 'replace-with-link-intermediate-throw', className: 'bpmn-icon-intermediate-event-throw-link', target: { type: 'bpmn:IntermediateThrowEvent', eventDefinitionType: 'bpmn:LinkEventDefinition' } }, { label: 'Compensation Intermediate Throw Event', actionName: 'replace-with-compensation-intermediate-throw', className: 'bpmn-icon-intermediate-event-throw-compensation', target: { type: 'bpmn:IntermediateThrowEvent', eventDefinitionType: 'bpmn:CompensateEventDefinition' } }, { label: 'Signal Intermediate Catch Event', actionName: 'replace-with-signal-intermediate-catch', className: 'bpmn-icon-intermediate-event-catch-signal', target: { type: 'bpmn:IntermediateCatchEvent', eventDefinitionType: 'bpmn:SignalEventDefinition' } }, { label: 'Signal Intermediate Throw Event', actionName: 'replace-with-signal-intermediate-throw', className: 'bpmn-icon-intermediate-event-throw-signal', target: { type: 'bpmn:IntermediateThrowEvent', eventDefinitionType: 'bpmn:SignalEventDefinition' } } ]; module.exports.END_EVENT = [ { label: 'Start Event', actionName: 'replace-with-none-start', className: 'bpmn-icon-start-event-none', target: { type: 'bpmn:StartEvent' } }, { label: 'Intermediate Throw Event', actionName: 'replace-with-none-intermediate-throw', className: 'bpmn-icon-intermediate-event-none', target: { type: 'bpmn:IntermediateThrowEvent' } }, { label: 'End Event', actionName: 'replace-with-none-end', className: 'bpmn-icon-end-event-none', target: { type: 'bpmn:EndEvent' } }, { label: 'Message End Event', actionName: 'replace-with-message-end', className: 'bpmn-icon-end-event-message', target: { type: 'bpmn:EndEvent', eventDefinitionType: 'bpmn:MessageEventDefinition' } }, { label: 'Escalation End Event', actionName: 'replace-with-escalation-end', className: 'bpmn-icon-end-event-escalation', target: { type: 'bpmn:EndEvent', eventDefinitionType: 'bpmn:EscalationEventDefinition' } }, { label: 'Error End Event', actionName: 'replace-with-error-end', className: 'bpmn-icon-end-event-error', target: { type: 'bpmn:EndEvent', eventDefinitionType: 'bpmn:ErrorEventDefinition' } }, { label: 'Cancel End Event', actionName: 'replace-with-cancel-end', className: 'bpmn-icon-end-event-cancel', target: { type: 'bpmn:EndEvent', eventDefinitionType: 'bpmn:CancelEventDefinition' } }, { label: 'Compensation End Event', actionName: 'replace-with-compensation-end', className: 'bpmn-icon-end-event-compensation', target: { type: 'bpmn:EndEvent', eventDefinitionType: 'bpmn:CompensateEventDefinition' } }, { label: 'Signal End Event', actionName: 'replace-with-signal-end', className: 'bpmn-icon-end-event-signal', target: { type: 'bpmn:EndEvent', eventDefinitionType: 'bpmn:SignalEventDefinition' } }, { label: 'Terminate End Event', actionName: 'replace-with-terminate-end', className: 'bpmn-icon-end-event-terminate', target: { type: 'bpmn:EndEvent', eventDefinitionType: 'bpmn:TerminateEventDefinition' } } ]; module.exports.GATEWAY = [ { label: 'Exclusive Gateway', actionName: 'replace-with-exclusive-gateway', className: 'bpmn-icon-gateway-xor', target: { type: 'bpmn:ExclusiveGateway' } }, { label: 'Parallel Gateway', actionName: 'replace-with-parallel-gateway', className: 'bpmn-icon-gateway-parallel', target: { type: 'bpmn:ParallelGateway' } }, { label: 'Inclusive Gateway', actionName: 'replace-with-inclusive-gateway', className: 'bpmn-icon-gateway-or', target: { type: 'bpmn:InclusiveGateway' } }, { label: 'Complex Gateway', actionName: 'replace-with-complex-gateway', className: 'bpmn-icon-gateway-complex', target: { type: 'bpmn:ComplexGateway' } }, { label: 'Event based Gateway', actionName: 'replace-with-event-based-gateway', className: 'bpmn-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: 'bpmn-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: 'bpmn-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: 'bpmn-icon-transaction', target: { type: 'bpmn:Transaction', isExpanded: true } }, { label: 'Event Sub Process', actionName: 'replace-with-event-subprocess', className: 'bpmn-icon-event-subprocess-expanded', target: { type: 'bpmn:SubProcess', triggeredByEvent: true, isExpanded: true } } ]; module.exports.TRANSACTION = [ { label: 'Sub Process', actionName: 'replace-with-subprocess', className: 'bpmn-icon-subprocess-expanded', target: { type: 'bpmn:SubProcess', isExpanded: true } }, { label: 'Event Sub Process', actionName: 'replace-with-event-subprocess', className: 'bpmn-icon-event-subprocess-expanded', target: { type: 'bpmn:SubProcess', triggeredByEvent: true, isExpanded: true } } ]; module.exports.EVENT_SUB_PROCESS = [ { label: 'Sub Process', actionName: 'replace-with-subprocess', className: 'bpmn-icon-subprocess-expanded', target: { type: 'bpmn:SubProcess', isExpanded: true } }, { label: 'Transaction', actionName: 'replace-with-transaction', className: 'bpmn-icon-transaction', target: { type: 'bpmn:Transaction', isExpanded: true } }, ]; module.exports.TASK = [ { label: 'Task', actionName: 'replace-with-task', className: 'bpmn-icon-task', target: { type: 'bpmn:Task' } }, { label: 'Send Task', actionName: 'replace-with-send-task', className: 'bpmn-icon-send', target: { type: 'bpmn:SendTask' } }, { label: 'Receive Task', actionName: 'replace-with-receive-task', className: 'bpmn-icon-receive', target: { type: 'bpmn:ReceiveTask' } }, { label: 'User Task', actionName: 'replace-with-user-task', className: 'bpmn-icon-user', target: { type: 'bpmn:UserTask' } }, { label: 'Manual Task', actionName: 'replace-with-manual-task', className: 'bpmn-icon-manual', target: { type: 'bpmn:ManualTask' } }, { label: 'Business Rule Task', actionName: 'replace-with-rule-task', className: 'bpmn-icon-business-rule', target: { type: 'bpmn:BusinessRuleTask' } }, { label: 'Service Task', actionName: 'replace-with-service-task', className: 'bpmn-icon-service', target: { type: 'bpmn:ServiceTask' } }, { label: 'Script Task', actionName: 'replace-with-script-task', className: 'bpmn-icon-script', target: { type: 'bpmn:ScriptTask' } }, { label: 'Call Activity', actionName: 'replace-with-call-activity', className: 'bpmn-icon-call-activity', target: { type: 'bpmn:CallActivity' } }, { label: 'Sub Process (collapsed)', actionName: 'replace-with-collapsed-subprocess', className: 'bpmn-icon-subprocess-collapsed', target: { type: 'bpmn:SubProcess', isExpanded: false } } ]; module.exports.BOUNDARY_EVENT = [ { label: 'Message Boundary Event', actionName: 'replace-with-message-boundary', className: 'bpmn-icon-intermediate-event-catch-message', target: { type: 'bpmn:BoundaryEvent', eventDefinitionType: 'bpmn:MessageEventDefinition' } }, { label: 'Timer Boundary Event', actionName: 'replace-with-timer-boundary', className: 'bpmn-icon-intermediate-event-catch-timer', target: { type: 'bpmn:BoundaryEvent', eventDefinitionType: 'bpmn:TimerEventDefinition' } }, { label: 'Escalation Boundary Event', actionName: 'replace-with-escalation-boundary', className: 'bpmn-icon-intermediate-event-catch-escalation', target: { type: 'bpmn:BoundaryEvent', eventDefinitionType: 'bpmn:EscalationEventDefinition' } }, { label: 'Conditional Boundary Event', actionName: 'replace-with-conditional-boundary', className: 'bpmn-icon-intermediate-event-catch-condition', target: { type: 'bpmn:BoundaryEvent', eventDefinitionType: 'bpmn:ConditionalEventDefinition' } }, { label: 'Error Boundary Event', actionName: 'replace-with-error-boundary', className: 'bpmn-icon-intermediate-event-catch-error', target: { type: 'bpmn:BoundaryEvent', eventDefinitionType: 'bpmn:ErrorEventDefinition' } }, { label: 'Cancel Boundary Event', actionName: 'replace-with-cancel-boundary', className: 'bpmn-icon-intermediate-event-catch-cancel', target: { type: 'bpmn:BoundaryEvent', eventDefinitionType: 'bpmn:CancelEventDefinition' } }, { label: 'Signal Boundary Event', actionName: 'replace-with-signal-boundary', className: 'bpmn-icon-intermediate-event-catch-signal', target: { type: 'bpmn:BoundaryEvent', eventDefinitionType: 'bpmn:SignalEventDefinition' } }, { label: 'Compensation Boundary Event', actionName: 'replace-with-compensation-boundary', className: 'bpmn-icon-intermediate-event-catch-compensation', target: { type: 'bpmn:BoundaryEvent', eventDefinitionType: 'bpmn:CompensateEventDefinition' } }, { label: 'Message Boundary Event (non-interrupting)', actionName: 'replace-with-non-interrupting-message-boundary', className: 'bpmn-icon-intermediate-event-catch-non-interrupting-message', target: { type: 'bpmn:BoundaryEvent', eventDefinitionType: 'bpmn:MessageEventDefinition', cancelActivity: false } }, { label: 'Timer Boundary Event (non-interrupting)', actionName: 'replace-with-non-interrupting-timer-boundary', className: 'bpmn-icon-intermediate-event-catch-non-interrupting-timer', target: { type: 'bpmn:BoundaryEvent', eventDefinitionType: 'bpmn:TimerEventDefinition', cancelActivity: false } }, { label: 'Escalation Boundary Event (non-interrupting)', actionName: 'replace-with-non-interrupting-escalation-boundary', className: 'bpmn-icon-intermediate-event-catch-non-interrupting-escalation', target: { type: 'bpmn:BoundaryEvent', eventDefinitionType: 'bpmn:EscalationEventDefinition', cancelActivity: false } }, { label: 'Conditional Boundary Event (non-interrupting)', actionName: 'replace-with-non-interrupting-conditional-boundary', className: 'bpmn-icon-intermediate-event-catch-non-interrupting-condition', target: { type: 'bpmn:BoundaryEvent', eventDefinitionType: 'bpmn:ConditionalEventDefinition', cancelActivity: false } }, { label: 'Signal Boundary Event (non-interrupting)', actionName: 'replace-with-non-interrupting-signal-boundary', className: 'bpmn-icon-intermediate-event-catch-non-interrupting-signal', target: { type: 'bpmn:BoundaryEvent', eventDefinitionType: 'bpmn:SignalEventDefinition', cancelActivity: false } }, ]; module.exports.EVENT_SUB_PROCESS_START_EVENT = [ { label: 'Message Start Event', actionName: 'replace-with-message-start', className: 'bpmn-icon-start-event-message', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:MessageEventDefinition' } }, { label: 'Timer Start Event', actionName: 'replace-with-timer-start', className: 'bpmn-icon-start-event-timer', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:TimerEventDefinition' } }, { label: 'Conditional Start Event', actionName: 'replace-with-conditional-start', className: 'bpmn-icon-start-event-condition', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:ConditionalEventDefinition' } }, { label: 'Signal Start Event', actionName: 'replace-with-signal-start', className: 'bpmn-icon-start-event-signal', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:SignalEventDefinition' } }, { label: 'Error Start Event', actionName: 'replace-with-error-start', className: 'bpmn-icon-start-event-error', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:ErrorEventDefinition' } }, { label: 'Escalation Start Event', actionName: 'replace-with-escalation-start', className: 'bpmn-icon-start-event-escalation', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:EscalationEventDefinition' } }, { label: 'Compensation Start Event', actionName: 'replace-with-compensation-start', className: 'bpmn-icon-start-event-compensation', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:CompensateEventDefinition' } }, { label: 'Message Start Event (non-interrupting)', actionName: 'replace-with-non-interrupting-message-start', className: 'bpmn-icon-start-event-non-interrupting-message', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:MessageEventDefinition', isInterrupting: false } }, { label: 'Timer Start Event (non-interrupting)', actionName: 'replace-with-non-interrupting-timer-start', className: 'bpmn-icon-start-event-non-interrupting-timer', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:TimerEventDefinition', isInterrupting: false } }, { label: 'Conditional Start Event (non-interrupting)', actionName: 'replace-with-non-interrupting-conditional-start', className: 'bpmn-icon-start-event-non-interrupting-condition', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:ConditionalEventDefinition', isInterrupting: false } }, { label: 'Signal Start Event (non-interrupting)', actionName: 'replace-with-non-interrupting-signal-start', className: 'bpmn-icon-start-event-non-interrupting-signal', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:SignalEventDefinition', isInterrupting: false } }, { label: 'Escalation Start Event (non-interrupting)', actionName: 'replace-with-non-interrupting-escalation-start', className: 'bpmn-icon-start-event-non-interrupting-escalation', target: { type: 'bpmn:StartEvent', eventDefinitionType: 'bpmn:EscalationEventDefinition', isInterrupting: false } }, ]; module.exports.SEQUENCE_FLOW = [ { label: 'Sequence Flow', actionName: 'replace-with-sequence-flow', className: 'bpmn-icon-connection' }, { label: 'Default Flow', actionName: 'replace-with-default-flow', className: 'bpmn-icon-default-flow' }, { label: 'Conditional Flow', actionName: 'replace-with-conditional-flow', className: 'bpmn-icon-conditional-flow' } ]; module.exports.PARTICIPANT = [ { label: 'Expanded Pool', actionName: 'replace-with-expanded-pool', className: 'bpmn-icon-participant', target: { type: 'bpmn:Participant', isExpanded: true } }, { label: 'Collapsed Pool', actionName: 'replace-with-collapsed-pool', // TODO(@janstuemmel): maybe design new icon className: 'bpmn-icon-lane', target: { type: 'bpmn:Participant', isExpanded: false } } ]; },{}],57:[function(_dereq_,module,exports){ module.exports = { __depends__: [ _dereq_(177), _dereq_(189) ], bpmnReplace: [ 'type', _dereq_(55) ] }; },{"177":177,"189":189,"55":55}],58:[function(_dereq_,module,exports){ 'use strict'; var find = _dereq_(254), any = _dereq_(251), filter = _dereq_(253), forEach = _dereq_(255), inherits = _dereq_(243); var getParents = _dereq_(45).getParents, is = _dereq_(70).is, isAny = _dereq_(45).isAny, getBusinessObject = _dereq_(70).getBusinessObject, isExpanded = _dereq_(68).isExpanded, isEventSubProcess = _dereq_(68).isEventSubProcess, isInterrupting = _dereq_(68).isInterrupting; var RuleProvider = _dereq_(183); var isBoundaryAttachment = _dereq_(61).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('elements.move', function(context) { var target = context.target, shapes = context.shapes, position = context.position; return canAttach(shapes, target, null, position) || canReplace(shapes, target, 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); }); this.addRule([ 'elements.delete' ], function(context) { // do not allow deletion of labels return filter(context.elements, function(e) { return !isLabel(e); }); }); }; BpmnRules.prototype.canConnectMessageFlow = canConnectMessageFlow; BpmnRules.prototype.canConnectSequenceFlow = canConnectSequenceFlow; BpmnRules.prototype.canConnectDataAssociation = canConnectDataAssociation; BpmnRules.prototype.canConnectAssociation = canConnectAssociation; BpmnRules.prototype.canMove = canMove; BpmnRules.prototype.canAttach = canAttach; BpmnRules.prototype.canReplace = canReplace; 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 isTextAnnotation(element) { return is(element, 'bpmn:TextAnnotation'); } function isCompensationBoundary(element) { return is(element, 'bpmn:BoundaryEvent') && hasEventDefinition(element, 'bpmn:CompensateEventDefinition'); } function isForCompensation(e) { return getBusinessObject(e).isForCompensation; } function isSameOrganization(a, b) { var parentA = getOrganizationalParent(a), parentB = getOrganizationalParent(b); return parentA === parentB; } function isMessageFlowSource(element) { return is(element, 'bpmn:InteractionNode') && !isForCompensation(element) && ( !is(element, 'bpmn:Event') || ( is(element, 'bpmn:ThrowEvent') && hasEventDefinitionOrNone(element, 'bpmn:MessageEventDefinition') ) ); } function isMessageFlowTarget(element) { return is(element, 'bpmn:InteractionNode') && !isForCompensation(element) && ( !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') && !isEventSubProcess(element) && !(is(element, 'bpmn:IntermediateThrowEvent') && hasEventDefinition(element, 'bpmn:LinkEventDefinition') ) && !isCompensationBoundary(element) && !isForCompensation(element); } function isSequenceFlowTarget(element) { return is(element, 'bpmn:FlowNode') && !is(element, 'bpmn:StartEvent') && !is(element, 'bpmn:BoundaryEvent') && !isEventSubProcess(element) && !(is(element, 'bpmn:IntermediateCatchEvent') && hasEventDefinition(element, 'bpmn:LinkEventDefinition') ) && !isForCompensation(element); } 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 (!is(connection, 'bpmn:DataAssociation')) { if (canConnectMessageFlow(source, target)) { return { type: 'bpmn:MessageFlow' }; } if (canConnectSequenceFlow(source, target)) { return { type: 'bpmn:SequenceFlow' }; } } var connectDataAssociation = canConnectDataAssociation(source, target); if (connectDataAssociation) { return connectDataAssociation; } if (isCompensationBoundary(source) && isForCompensation(target)) { return { type: 'bpmn:Association', associationDirection: 'One' }; } if (is(connection, 'bpmn:Association') && canConnectAssociation(source, target)) { return { type: 'bpmn:Association' }; } if (isTextAnnotation(source) || isTextAnnotation(target)) { return { type: 'bpmn:Association' }; } return false; } /** * Can an element be dropped into the target element * * @return {Boolean} */ function canDrop(element, target, position) { // can move labels everywhere if (isLabel(element) && !isConnection(target)) { return true; } // disallow to create elements on collapsed pools if (is(target, 'bpmn:Participant') && !isExpanded(target)) { return false; } // 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'); } // allow creating lanes on participants and other lanes only if (is(element, 'bpmn:Lane')) { return is(target, 'bpmn:Participant') || is(target, 'bpmn:Lane'); } if (is(element, 'bpmn:BoundaryEvent')) { return false; } // drop flow elements onto flow element containers // and participants if (is(element, 'bpmn:FlowElement') || is(element, 'bpmn:DataAssociation')) { if (is(target, 'bpmn:FlowElementsContainer')) { return isExpanded(target); } return isAny(target, [ 'bpmn:Participant', 'bpmn:Lane' ]); } if (is(element, 'bpmn:Artifact')) { return isAny(target, [ 'bpmn:Collaboration', 'bpmn:Lane', 'bpmn:Participant', 'bpmn:Process', 'bpmn:SubProcess' ]); } if (is(element, 'bpmn:MessageFlow')) { return is(target, 'bpmn:Collaboration'); } return false; } function isBoundaryEvent(element) { return !isLabel(element) && is(element, 'bpmn:BoundaryEvent'); } function isLane(element) { return is(element, 'bpmn:Lane'); } /** * 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) { if (!Array.isArray(elements)) { elements = [ elements ]; } // 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; } // disallow drop on event sub processes if (isEventSubProcess(target)) { return false; } // only allow drop on non compensation activities if (!is(target, 'bpmn:Activity') || isForCompensation(target)) { return false; } // only attach to subprocess border if (position && !isBoundaryAttachment(position, target)) { return false; } return 'attach'; } /** * Defines how to replace elements for a given target. * * Returns an array containing all elements which will be replaced. * * @example * * [{ id: 'IntermediateEvent_2', * type: 'bpmn:StartEvent' * }, * { id: 'IntermediateEvent_5', * type: 'bpmn:EndEvent' * }] * * @param {Array} elements * @param {Object} target * * @return {Object} an object containing all elements which have to be replaced */ function canReplace(elements, target, position) { if (!target) { return false; } var canExecute = { replacements: [] }; forEach(elements, function(element) { // replace a non-interrupting start event by a blank interrupting start event // when the target is not an event sub process if (!isEventSubProcess(target)) { if (is(element, 'bpmn:StartEvent') && !isInterrupting(element) && element.type !== 'label' && canDrop(element, target)) { canExecute.replacements.push({ oldElementId: element.id, newElementType: 'bpmn:StartEvent' }); } } if (!is(target, 'bpmn:Transaction')) { if (hasEventDefinition(element, 'bpmn:CancelEventDefinition') && element.type !== 'label') { if (is(element, 'bpmn:EndEvent') && canDrop(element, target)) { canExecute.replacements.push({ oldElementId: element.id, newElementType: 'bpmn:EndEvent' }); } if (is(element, 'bpmn:BoundaryEvent') && canAttach(element, target, null, position)) { canExecute.replacements.push({ oldElementId: element.id, newElementType: 'bpmn:BoundaryEvent' }); } } } }); return canExecute.replacements.length ? canExecute : false; } function canMove(elements, target) { // do not move selection containing boundary events if (any(elements, isBoundaryEvent)) { return false; } // do not move selection containing lanes if (any(elements, isLane)) { 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:Lane')) { return !newBounds || (newBounds.width >= 130 && newBounds.height >= 60); } if (is(shape, 'bpmn:Participant')) { return !newBounds || (newBounds.width >= 250 && newBounds.height >= 50); } if (isTextAnnotation(shape)) { 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 canConnectDataAssociation(source, target) { if (isAny(source, [ 'bpmn:DataObjectReference', 'bpmn:DataStoreReference' ]) && isAny(target, [ 'bpmn:Activity', 'bpmn:ThrowEvent' ])) { return { type: 'bpmn:DataInputAssociation' }; } if (isAny(target, [ 'bpmn:DataObjectReference', 'bpmn:DataStoreReference' ]) && isAny(source, [ 'bpmn:Activity', 'bpmn:CatchEvent' ])) { return { type: 'bpmn:DataOutputAssociation' }; } return false; } 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 ( isAny(flow, [ 'bpmn:SequenceFlow', 'bpmn:MessageFlow' ]) && is(shape, 'bpmn:FlowNode') && !is(shape, 'bpmn:BoundaryEvent') && canDrop(shape, flow.parent, position)); } },{"183":183,"243":243,"251":251,"253":253,"254":254,"255":255,"45":45,"61":61,"68":68,"70":70}],59:[function(_dereq_,module,exports){ module.exports = { __depends__: [ _dereq_(185) ], __init__: [ 'bpmnRules' ], bpmnRules: [ 'type', _dereq_(58) ] }; },{"185":185,"58":58}],60:[function(_dereq_,module,exports){ 'use strict'; var inherits = _dereq_(243); var forEach = _dereq_(255); var getBoundingBox = _dereq_(221).getBBox; var is = _dereq_(70).is, isAny = _dereq_(45).isAny, isExpanded = _dereq_(68).isExpanded; var Snapping = _dereq_(192), SnapUtil = _dereq_(191); var asTRBL = _dereq_(208).asTRBL; var round = Math.round; var mid = SnapUtil.mid, topLeft = SnapUtil.topLeft, bottomRight = SnapUtil.bottomRight, isSnapped = SnapUtil.isSnapped, setSnapped = SnapUtil.setSnapped; var getBoundaryAttachment = _dereq_(61).getBoundaryAttachment, getParticipantSizeConstraints = _dereq_(61).getParticipantSizeConstraints, getLanesRoot = _dereq_(44).getLanesRoot; /** * 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, elementRegistry) { // 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', '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); } }); /** * Adjust parent for flowElements to the target participant * when droping onto lanes. */ eventBus.on([ 'shape.move.hover', 'shape.move.move', 'shape.move.end', 'create.hover', 'create.move', 'create.end' ], 1500, function(event) { var context = event.context, shape = context.shape, hover = event.hover; if (is(hover, 'bpmn:Lane') && !isAny(shape, [ 'bpmn:Lane', 'bpmn:Participant' ])) { event.hover = getLanesRoot(hover); event.hoverGfx = elementRegistry.getGraphics(event.hover); } }); var abs = Math.abs; var filter = _dereq_(253), assign = _dereq_(377); eventBus.on([ 'create.move', 'shape.move.move' ], function(event) { var context = event.context, shape = context.shape, target = context.target; var threshold = 30; if (is(shape, 'bpmn:Lane')) { if (isAny(target, [ 'bpmn:Lane', 'bpmn:Participant' ])) { var childLanes = filter(target.children, function(c) { return is(c, 'bpmn:Lane'); }); var y = event.y, targetTrbl; var insert = childLanes.reduce(function(insert, l) { var laneTrbl = asTRBL(l); if (abs(laneTrbl.top - y) < threshold) { insert = assign(insert || {}, { before: { element: l, y: laneTrbl.top } }); } else if (abs(laneTrbl.bottom - y) < threshold) { insert = assign(insert || {}, { after: { element: l, y: laneTrbl.bottom } }); } else if (laneTrbl.top < y && laneTrbl.bottom > y) { if (abs(laneTrbl.top - y) > abs(laneTrbl.bottom - y)) { insert = assign(insert || {}, { after: { element: l, y: laneTrbl.bottom } }); } else { insert = assign(insert || {}, { before: { element: l, y: laneTrbl.top } }); } } return insert; }, false); if (!insert) { targetTrbl = asTRBL(target); if (abs(targetTrbl.top - y) < threshold) { insert = { before: { element: target, y: targetTrbl.top } }; } else if (abs(targetTrbl.bottom - y) < threshold) { insert = { after: { element: target, y: targetTrbl.bottom } }; } else { insert = { into: { element: target, y: (targetTrbl.top + targetTrbl.bottom) / 2 } }; } } if (insert.before && insert.after) { console.log('insert between', insert.before.element.id, 'and', insert.after.element.id); setSnapped(event, 'x', insert.before.element.x + insert.before.element.width / 2); setSnapped(event, 'y', insert.before.y); } else if (insert.after) { console.log('insert after', insert.after.element.id); setSnapped(event, 'x', insert.after.element.x + insert.after.element.width / 2); setSnapped(event, 'y', insert.after.y); } else if (insert.before) { console.log('insert before', insert.before.element.id); setSnapped(event, 'x', insert.before.element.x + insert.before.element.width / 2); setSnapped(event, 'y', insert.before.y); } else if (insert.into) { console.log('insert into', insert.into.element.id); setSnapped(event, 'x', insert.into.element.x + insert.into.element.width / 2); setSnapped(event, 'y', insert.into.y); } } } }); 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 }; } if (is(shape, 'bpmn:Lane') || is(shape, 'bpmn:Participant')) { context.resizeConstraints = getParticipantSizeConstraints(shape, context.direction, context.balanced); } if (is(shape, 'bpmn:TextAnnotation')) { context.minDimensions = { width: 50, height: 30 }; } }); } inherits(BpmnSnapping, Snapping); BpmnSnapping.$inject = [ 'eventBus', 'canvas', 'bpmnRules', 'elementRegistry' ]; 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') && shape.type !== 'label') { 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) { // do not snap to lanes if (is(s, 'bpmn:Lane')) { return; } 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 ///////////////////////// function snapBoundaryEvent(event, shape, target) { var targetTRBL = 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); } } },{"191":191,"192":192,"208":208,"221":221,"243":243,"253":253,"255":255,"377":377,"44":44,"45":45,"61":61,"68":68,"70":70}],61:[function(_dereq_,module,exports){ 'use strict'; var getOrientation = _dereq_(208).getOrientation; function getBoundaryAttachment(position, targetBounds) { var orientation = getOrientation(position, targetBounds, -15); if (orientation !== 'intersect') { return orientation; } else { return null; } } module.exports.getBoundaryAttachment = getBoundaryAttachment; // participant snapping box implementation ///////////////// var is = _dereq_(70).is; var asTRBL = _dereq_(208).asTRBL; var collectLanes = _dereq_(44).collectLanes, getLanesRoot = _dereq_(44).getLanesRoot; var abs = Math.abs, min = Math.min, max = Math.max; function addToTrbl(trbl, attr, value, choice) { var current = trbl[attr]; // make sure to set the value if it does not exist // or apply the correct value by comparing against // choice(value, currentValue) trbl[attr] = current === undefined ? value : choice(value, current); } function addMin(trbl, attr, value) { return addToTrbl(trbl, attr, value, min); } function addMax(trbl, attr, value) { return addToTrbl(trbl, attr, value, max); } var LANE_MIN_HEIGHT = 60, LANE_MIN_WIDTH = 300, LANE_RIGHT_PADDING = 20, LANE_LEFT_PADDING = 50, LANE_TOP_PADDING = 20, LANE_BOTTOM_PADDING = 20; function getParticipantSizeConstraints(laneShape, resizeDirection, balanced) { var lanesRoot = getLanesRoot(laneShape); var isFirst = true, isLast = true; ///// max top/bottom size for lanes var allLanes = collectLanes(lanesRoot, [ lanesRoot ]); var laneTrbl = asTRBL(laneShape); var maxTrbl = {}, minTrbl = {}; if (/e/.test(resizeDirection)) { minTrbl.right = laneTrbl.left + LANE_MIN_WIDTH; } else if (/w/.test(resizeDirection)) { minTrbl.left = laneTrbl.right - LANE_MIN_WIDTH; } allLanes.forEach(function(other) { var otherTrbl = asTRBL(other); if (/n/.test(resizeDirection)) { if (otherTrbl.top < (laneTrbl.top - 10)) { isFirst = false; } // max top size (based on next element) if (balanced && abs(laneTrbl.top - otherTrbl.bottom) < 10) { addMax(maxTrbl, 'top', otherTrbl.top + LANE_MIN_HEIGHT); } // min top size (based on self or nested element) if (abs(laneTrbl.top - otherTrbl.top) < 5) { addMin(minTrbl, 'top', otherTrbl.bottom - LANE_MIN_HEIGHT); } } if (/s/.test(resizeDirection)) { if (otherTrbl.bottom > (laneTrbl.bottom + 10)) { isLast = false; } // max bottom size (based on previous element) if (balanced && abs(laneTrbl.bottom - otherTrbl.top) < 10) { addMin(maxTrbl, 'bottom', otherTrbl.bottom - LANE_MIN_HEIGHT); } // min bottom size (based on self or nested element) if (abs(laneTrbl.bottom - otherTrbl.bottom) < 5) { addMax(minTrbl, 'bottom', otherTrbl.top + LANE_MIN_HEIGHT); } } }); ///// max top/bottom/left/right size based on flow nodes var flowElements = lanesRoot.children.filter(function(s) { return !s.hidden && !s.waypoints && (is(s, 'bpmn:FlowElement') || is(s, 'bpmn:Artifact')); }); flowElements.forEach(function(flowElement) { var flowElementTrbl = asTRBL(flowElement); if (isFirst && /n/.test(resizeDirection)) { addMin(minTrbl, 'top', flowElementTrbl.top - LANE_TOP_PADDING); } if (/e/.test(resizeDirection)) { addMax(minTrbl, 'right', flowElementTrbl.right + LANE_RIGHT_PADDING); } if (isLast && /s/.test(resizeDirection)) { addMax(minTrbl, 'bottom', flowElementTrbl.bottom + LANE_BOTTOM_PADDING); } if (/w/.test(resizeDirection)) { addMin(minTrbl, 'left', flowElementTrbl.left - LANE_LEFT_PADDING); } }); return { min: minTrbl, max: maxTrbl }; } module.exports.getParticipantSizeConstraints = getParticipantSizeConstraints; },{"208":208,"44":44,"70":70}],62:[function(_dereq_,module,exports){ module.exports = { __init__: [ 'snapping' ], snapping: [ 'type', _dereq_(60) ] }; },{"60":60}],63:[function(_dereq_,module,exports){ 'use strict'; var assign = _dereq_(377), map = _dereq_(258); var LabelUtil = _dereq_(69); var is = _dereq_(70).is; var hasExternalLabel = LabelUtil.hasExternalLabel, getExternalLabelBounds = LabelUtil.getExternalLabelBounds, isExpanded = _dereq_(68).isExpanded, elementToString = _dereq_(66).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(translate, semantic, refSemantic, property) { return new Error(translate('element {element} referenced by {referenced}#{property} not yet drawn', { element: elementToString(refSemantic), referenced: elementToString(semantic), property: property })); } /** * 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, translate) { this._eventBus = eventBus; this._canvas = canvas; this._elementFactory = elementFactory; this._elementRegistry = elementRegistry; this._translate = translate; } BpmnImporter.$inject = [ 'eventBus', 'canvas', 'elementFactory', 'elementRegistry', 'translate' ]; 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, translate = this._translate; // ROOT ELEMENT // handle the special case that we deal with a // invisible root element (process or collaboration) if (is(di, 'bpmndi:BPMNPlane')) { // add a virtual element (not being drawn) element = this._elementFactory.createRoot(elementData(semantic)); this._canvas.setRootElement(element); } // SHAPE else if (is(di, '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 (is(di, '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(translate('unknown di {di} for element {semantic}', { di: elementToString(di), semantic: 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 translate = this._translate; var hostSemantic = boundarySemantic.attachedToRef; if (!hostSemantic) { throw new Error(translate('missing {semantic}#attachedToRef', { semantic: elementToString(boundarySemantic) })); } var host = this._elementRegistry.get(hostSemantic.id), attachers = host && host.attachers; if (!host) { throw notYetDrawn(translate, 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 || !semantic.name, 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, translate = this._translate; 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(translate, semantic, refSemantic, side + 'Ref'); } else { throw new Error(translate('{semantic}#{side} Ref not specified', { semantic: elementToString(semantic), side: side })); } }; 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); }; },{"258":258,"377":377,"66":66,"68":68,"69":69,"70":70}],64:[function(_dereq_,module,exports){ 'use strict'; var filter = _dereq_(253), find = _dereq_(254), forEach = _dereq_(255); var Refs = _dereq_(407); var elementToString = _dereq_(66).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, translate) { // list of containers already walked var handledElements = {}; // 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 handled(element) { handledElements[element.id] = element; } function isHandled(element) { return handledElements[element.id]; } function visit(element, ctx) { var gfx = element.gfx; // avoid multiple rendering of elements if (gfx) { throw new Error( translate('already rendered {element}', { element: elementToString(element) }) ); } // call handler return handler.element(element, ctx); } function visitRoot(element, diagram) { return handler.root(element, diagram); } function visitIfDi(element, ctx) { try { var gfx = element.di && visit(element, ctx); handled(element); return gfx; } catch (e) { logError(e.message, { element: element, error: e }); console.error(translate('failed to import {element}', { element: 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( translate('multiple DI elements defined for {element}', { element: elementToString(bpmnElement) }), { element: bpmnElement } ); } else { diRefs.bind(bpmnElement, 'di'); bpmnElement.di = di; } } else { logError( translate('no bpmnElement referenced in {element}', { element: 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 ////////////////////// /** * Handle definitions and return the rendered diagram (if any) * * @param {ModdleElement} definitions to walk and import * @param {ModdleElement} [diagram] specific diagram to import and display * * @throws {Error} if no diagram to display could be found */ function handleDefinitions(definitions, diagram) { // make sure we walk the correct bpmnElement var diagrams = definitions.diagrams; if (diagram && diagrams.indexOf(diagram) === -1) { throw new Error(translate('diagram not part of bpmn:Definitions')); } if (!diagram && diagrams && diagrams.length) { diagram = diagrams[0]; } // no diagram -> nothing to import if (!diagram) { throw new Error(translate('no diagram to display')); } // load DI from selected diagram only handleDiagram(diagram); var plane = diagram.plane; if (!plane) { throw new Error(translate( 'no plane for {element}', { element: 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) { throw new Error(translate('no process or collaboration to display')); } else { logError( translate('correcting missing bpmnElement on {plane} to {rootElement}', { plane: elementToString(plane), rootElement: 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( translate('unsupported bpmnElement for {plane}: {rootElement}', { plane: elementToString(plane), rootElement: 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 handled(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 !isHandled(e) && is(e, 'bpmn:Process') && e.laneSets; }); 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); } if (is(flowNode, 'bpmn:Activity')) { handleIoSpecification(flowNode.ioSpecification, context); } // defer handling of associations // affected types: // // * bpmn:Activity // * bpmn:ThrowEvent // * bpmn:CatchEvent // deferred.push(function() { forEach(flowNode.dataInputAssociations, contextual(handleDataAssociation, context)); forEach(flowNode.dataOutputAssociations, contextual(handleDataAssociation, 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); } wireFlowNodeRefs(lane); } 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); } handleFlowElements(container.flowElements, 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); } 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( translate('unrecognized flowElement {element} in context {context}', { element: elementToString(e), 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); }); } function wireFlowNodeRefs(lane) { // wire the virtual flowNodeRefs <-> relationship forEach(lane.flowNodeRef, function(flowNode) { var lanes = flowNode.get('lanes'); if (lanes) { lanes.push(lane); } }); } ///// API //////////////////////////////// return { handleDefinitions: handleDefinitions }; } module.exports = BpmnTreeWalker; },{"253":253,"254":254,"255":255,"407":407,"66":66}],65:[function(_dereq_,module,exports){ 'use strict'; var BpmnTreeWalker = _dereq_(64); /** * 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'), translate = diagram.get('translate'); var error, warnings = []; /** * Walk the diagram semantically, importing (=drawing) * all elements you encounter. * * @param {ModdleElement} definitions */ function render(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, translate); // traverse BPMN 2.0 document model, // starting at definitions walker.handleDefinitions(definitions); } eventBus.fire('import.render.start', { definitions: definitions }); try { render(definitions); } catch (e) { error = e; } eventBus.fire('import.render.complete', { error: error, warnings: warnings }); done(error, warnings); } module.exports.importBpmnDiagram = importBpmnDiagram; },{"64":64}],66:[function(_dereq_,module,exports){ 'use strict'; module.exports.elementToString = function(e) { if (!e) { return ''; } return '<' + e.$type + (e.id ? ' id="' + e.id : '') + '" />'; }; },{}],67:[function(_dereq_,module,exports){ module.exports = { __depends__: [ _dereq_(204) ], bpmnImporter: [ 'type', _dereq_(63) ] }; },{"204":204,"63":63}],68:[function(_dereq_,module,exports){ 'use strict'; var is = _dereq_(70).is, getBusinessObject = _dereq_(70).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; }; module.exports.isInterrupting = function(element) { return element && getBusinessObject(element).isInterrupting !== false; }; module.exports.isEventSubProcess = function(element) { return element && !!getBusinessObject(element).triggeredByEvent; }; },{"70":70}],69:[function(_dereq_,module,exports){ 'use strict'; var assign = _dereq_(377); var is = _dereq_(70).is; 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 is(semantic, 'bpmn:Event') || is(semantic, 'bpmn:Gateway') || is(semantic, 'bpmn:DataStoreReference') || is(semantic, 'bpmn:DataObjectReference') || is(semantic, 'bpmn:SequenceFlow') || is(semantic, 'bpmn:MessageFlow'); }; /** * Get the middle of a number of waypoints * * @param {Array} waypoints * @return {Point} the mid point */ function getWaypointsMid(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 }; } module.exports.getWaypointsMid = getWaypointsMid; function getExternalLabelMid(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 }; } } module.exports.getExternalLabelMid = getExternalLabelMid; /** * 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); }; },{"377":377,"70":70}],70:[function(_dereq_,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 && (typeof bo.$instanceOf === 'function') && 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; },{}],71:[function(_dereq_,module,exports){ /** * This file must not be changed or exchanged. * * @see http://bpmn.io/license for more information. */ 'use strict'; var domify = _dereq_(394); var domDelegate = _dereq_(393); /* jshint -W101 */ // inlined ../resources/bpmnjs.png var logoData = module.exports.BPMNIO_LOGO = 'iVBORw0KGgoAAAANSUhEUgAAADQAAAA0CAMAAADypuvZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADBQTFRFiMte9PrwldFwfcZPqtqN0+zEyOe1XLgjvuKncsJAZ70y6fXh3vDT////UrQV////G2zN+AAAABB0Uk5T////////////////////AOAjXRkAAAHDSURBVHjavJZJkoUgDEBJmAX8979tM8u3E6x20VlYJfFFMoL4vBDxATxZcakIOJTWSmxvKWVIkJ8jHvlRv1F2LFrVISCZI+tCtQx+XfewgVTfyY3plPiQEAzI3zWy+kR6NBhFBYeBuscJLOUuA2WVLpCjVIaFzrNQZArxAZKUQm6gsj37L9Cb7dnIBUKxENaaMJQqMpDXvSL+ktxdGRm2IsKgJGGPg7atwUG5CcFUEuSv+CwQqizTrvDTNXdMU2bMiDWZd8d7QIySWVRsb2vBBioxOFt4OinPBapL+neAb5KL5IJ8szOza2/DYoipUCx+CjO0Bpsv0V6mktNZ+k8rlABlWG0FrOpKYVo8DT3dBeLEjUBAj7moDogVii7nSS9QzZnFcOVBp1g2PyBQ3Vr5aIapN91VJy33HTJLC1iX2FY6F8gRdaAeIEfVONgtFCzZTmoLEdOjBDfsIOA6128gw3eu1shAajdZNAORxuQDJN5A5PbEG6gNIu24QJD5iNyRMZIr6bsHbCtCU/OaOaSvgkUyDMdDa1BXGf5HJ1To+/Ym6mCKT02Y+/Sa126ZKyd3jxhzpc1r8zVL6YM1Qy/kR4ABAFJ6iQUnivhAAAAAAElFTkSuQmCC'; /* jshint +W101 */ function css(attrs) { return attrs.join(';'); } var LIGHTBOX_STYLES = css([ 'z-index: 1001', 'position: fixed', 'top: 0', 'left: 0', 'right: 0', 'bottom: 0' ]); var BACKDROP_STYLES = css([ 'width: 100%', 'height: 100%', 'background: rgba(0,0,0,0.2)' ]); var NOTICE_STYLES = css([ 'position: absolute', 'left: 50%', 'top: 40%', 'margin: 0 -130px', 'width: 260px', 'padding: 10px', 'background: white', 'border: solid 1px #AAA', 'border-radius: 3px', 'font-family: Helvetica, Arial, sans-serif', 'font-size: 14px', 'line-height: 1.2em' ]); var LIGHTBOX_MARKUP = '
' + '
' + '
' + '' + '' + '' + 'Web-based tooling for BPMN, DMN and CMMN diagrams ' + 'powered by bpmn.io.' + '
' + '
'; var lightbox; function open() { if (!lightbox) { lightbox = domify(LIGHTBOX_MARKUP); domDelegate.bind(lightbox, '.backdrop', 'click', function(event) { document.body.removeChild(lightbox); }); } document.body.appendChild(lightbox); } module.exports.open = open; },{"393":393,"394":394}],72:[function(_dereq_,module,exports){ module.exports = _dereq_(74); },{"74":74}],73:[function(_dereq_,module,exports){ 'use strict'; var isString = _dereq_(374), isFunction = _dereq_(369), assign = _dereq_(377); var Moddle = _dereq_(80), XmlReader = _dereq_(76), XmlWriter = _dereq_(77); /** * 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); } }; },{"369":369,"374":374,"377":377,"76":76,"77":77,"80":80}],74:[function(_dereq_,module,exports){ 'use strict'; var assign = _dereq_(377); var BpmnModdle = _dereq_(73); var packages = { bpmn: _dereq_(89), bpmndi: _dereq_(90), dc: _dereq_(91), di: _dereq_(92) }; module.exports = function(additionalPackages, options) { return new BpmnModdle(assign({}, packages, additionalPackages), options); }; },{"377":377,"73":73,"89":89,"90":90,"91":91,"92":92}],75:[function(_dereq_,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'; }; },{}],76:[function(_dereq_,module,exports){ 'use strict'; var reduce = _dereq_(259), forEach = _dereq_(255), find = _dereq_(254), assign = _dereq_(377), defer = _dereq_(266); var Stack = _dereq_(79), SaxParser = _dereq_(78).parser, Moddle = _dereq_(80), parseNameNs = _dereq_(85).parseName, Types = _dereq_(88), coerceType = Types.coerceType, isSimpleType = Types.isSimple, common = _dereq_(75), 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); }); } function error(message) { return new Error(message); } /** * Get the moddle descriptor for a given instance or type. * * @param {ModdleElement|Function} element * * @return {Object} the moddle descriptor */ function getModdleDescriptor(element) { return element.$descriptor; } /** * A parse context. * * @class * * @param {Object} options * @param {ElementHandler} options.rootHandler the root handler for parsing a document * @param {boolean} [options.lax=false] whether or not to ignore invalid elements */ function Context(options) { /** * @property {ElementHandler} rootHandler */ /** * @property {Boolean} lax */ assign(this, options); this.elementsById = {}; this.references = []; this.warnings = []; /** * Add an unresolved reference. * * @param {Object} reference */ this.addReference = function(reference) { this.references.push(reference); }; /** * Add a processed element. * * @param {ModdleElement} element */ this.addElement = function(element) { if (!element) { throw error('expected element'); } var descriptor = getModdleDescriptor(element); var idProperty = descriptor.idProperty, id; if (idProperty) { id = element.get(idProperty.name); if (id) { this.elementsById[id] = element; } } }; /** * Add an import warning. * * @param {Object} warning * @param {String} warning.message * @param {Error} [warning.error] */ this.addWarning = function(warning) { this.warnings.push(warning); }; } 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 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(node) { 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; if (!element) { element = this.element = this.createElement(node); this.context.addElement(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 = getModdleDescriptor(element), 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 = getModdleDescriptor(Type), context = this.context, instance = new Type({}); forEach(attributes, function(value, name) { var prop = descriptor.propertiesByName[name], values; if (prop && prop.isReference) { if (!prop.isMany) { context.addReference({ element: instance, property: prop.ns.name, id: value }); } else { // IDREFS: parse references as whitespace-separated list values = value.split(' '); forEach(values, function(v) { context.addReference({ element: instance, property: prop.ns.name, id: v }); }); } } 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 = getModdleDescriptor(type); 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: getModdleDescriptor(elementType).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: getModdleDescriptor(elementType).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 error('unrecognized element <' + nameNs.name + '>'); }; ElementHandler.prototype.toString = function() { return 'ElementDescriptor[' + getModdleDescriptor(this.type).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); } /** * Parse the given XML into a moddle document tree. * * @param {String} xml * @param {ElementHandler|Object} options or rootHandler * @param {Function} done */ XMLReader.prototype.fromXML = function(xml, options, done) { var rootHandler = options.rootHandler; if (options instanceof ElementHandler) { // root handler passed via (xml, { rootHandler: ElementHandler }, ...) rootHandler = options; options = {}; } else { if (typeof options === 'string') { // rootHandler passed via (xml, 'someString', ...) rootHandler = this.handler(options); options = {}; } else if (typeof rootHandler === 'string') { // rootHandler passed via (xml, { rootHandler: 'someString' }, ...) rootHandler = this.handler(rootHandler); } } var model = this.model, lax = this.lax; var context = new Context(assign({}, options, { rootHandler: rootHandler })), 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 = getModdleDescriptor(element).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); // we replace an existing place holder (idx != -1) or // append to the collection instead if (idx === -1) { idx = collection.length; } if (!reference) { // remove unresolvable reference collection.splice(idx, 1); } else { // add or update reference in collection 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 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; },{"254":254,"255":255,"259":259,"266":266,"377":377,"75":75,"78":78,"79":79,"80":80,"85":85,"88":88}],77:[function(_dereq_,module,exports){ 'use strict'; var map = _dereq_(258), forEach = _dereq_(255), isString = _dereq_(374), filter = _dereq_(253), assign = _dereq_(377); var Types = _dereq_(88), parseNameNs = _dereq_(85).parseName, common = _dereq_(75), 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 getNsAttrs(namespaces) { function isUsed(ns) { return namespaces.used[ns.uri]; } function toAttr(ns) { var name = 'xmlns' + (ns.prefix ? ':' + ns.prefix : ''); return { name: name, value: ns.uri }; } var allNs = [].concat(namespaces.wellknown, namespaces.custom); return map(filter(allNs, isUsed), toAttr); } 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; if (p.isVirtual) { return false; } // 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' && value.search(ESCAPE_CHARS) !== -1) { 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; }; /** * Get the actual ns attribute name for the given element. * * @param {Object} element * @param {Boolean} [inherited=false] * * @return {Object} nsName */ ElementSerializer.prototype.nsAttributeName = function(element) { var ns; if (isString(element)) { ns = parseNameNs(element); } else { ns = element.ns; } // return just local name for inherited attributes if (element.inherited) { return { localName: ns.localName }; } // parse + log effective 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 model = element.$model; 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); var ns; // parse xmlns:foo="http://foo.bar" if (nameNs.prefix === 'xmlns') { ns = { prefix: nameNs.localName, uri: value }; } // parse xmlns="http://foo.bar" if (!nameNs.prefix && nameNs.localName === 'xmlns') { ns = { uri: value }; } if (ns) { if (model.getPackage(value)) { // register well known namespace self.logNamespace(ns, true); } else { // log custom namespace directly as used self.logNamespaceUsed(ns); } } 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( '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() { var namespaces = this.namespaces, parent = this.parent; if (!namespaces) { namespaces = this.namespaces = parent ? parent.getNamespaces() : { prefixMap: {}, uriMap: {}, used: {}, wellknown: [], custom: [] }; } return namespaces; }; ElementSerializer.prototype.logNamespace = function(ns, wellknown) { var namespaces = this.getNamespaces(); var nsUri = ns.uri; var existing = namespaces.uriMap[nsUri]; if (!existing) { namespaces.uriMap[nsUri] = ns; if (wellknown) { namespaces.wellknown.push(ns); } else { namespaces.custom.push(ns); } } namespaces.prefixMap[ns.prefix] = nsUri; 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 wellknownUri = DEFAULT_NS_MAP[prefix] || model && (model.getPackage(prefix) || {}).uri; var uri = ns.uri || namespaces.prefixMap[prefix] || wellknownUri; 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 }, wellknownUri); } 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) { var value = element.get(p.name); if (p.isReference) { if (!p.isMany) { value = value.id; } else { var values = []; forEach(value, function(v) { values.push(v.id); }); // IDREFS is a whitespace-separated list of references. value = values.join(' '); } } 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; if (root) { attrs = getNsAttrs(this.namespaces).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; },{"253":253,"255":255,"258":258,"374":374,"377":377,"75":75,"85":85,"88":88}],78:[function(_dereq_,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 = _dereq_("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 = _dereq_('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++ //