bpmn-js 0.13.1 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/.travis.yml +1 -1
  2. package/.wiredeps +5 -5
  3. package/lib/Modeler.js +52 -9
  4. package/lib/Viewer.js +205 -105
  5. package/lib/draw/BpmnRenderer.js +4 -0
  6. package/lib/features/context-pad/ContextPadProvider.js +21 -15
  7. package/lib/features/label-editing/LabelEditingProvider.js +21 -6
  8. package/lib/features/label-editing/LabelUtil.js +6 -6
  9. package/lib/features/label-editing/cmd/UpdateLabelHandler.js +19 -17
  10. package/lib/features/modeling/BpmnUpdater.js +12 -4
  11. package/lib/features/modeling/ElementFactory.js +25 -11
  12. package/lib/features/modeling/{BpmnLabelSupport.js → behavior/LabelBehavior.js} +14 -4
  13. package/lib/features/modeling/behavior/ModelingFeedback.js +3 -3
  14. package/lib/features/modeling/behavior/UpdateFlowNodeRefsBehavior.js +4 -4
  15. package/lib/features/modeling/behavior/index.js +2 -0
  16. package/lib/features/modeling/cmd/SplitLaneHandler.js +6 -4
  17. package/lib/features/modeling/cmd/UpdateCanvasRootHandler.js +6 -0
  18. package/lib/features/modeling/cmd/UpdateFlowNodeRefsHandler.js +6 -0
  19. package/lib/features/modeling/cmd/UpdatePropertiesHandler.js +6 -4
  20. package/lib/features/modeling/index.js +1 -2
  21. package/lib/features/ordering/BpmnOrderingProvider.js +7 -4
  22. package/lib/features/ordering/index.js +3 -0
  23. package/lib/features/palette/PaletteProvider.js +13 -9
  24. package/lib/features/palette/index.js +2 -1
  25. package/lib/features/popup-menu/ReplaceMenuProvider.js +22 -10
  26. package/lib/features/popup-menu/index.js +4 -0
  27. package/lib/features/replace/BpmnReplace.js +17 -1
  28. package/lib/features/replace/ReplaceOptions.js +22 -0
  29. package/lib/features/replace/index.js +0 -1
  30. package/lib/features/rules/BpmnRules.js +14 -0
  31. package/lib/features/snapping/BpmnSnapping.js +2 -2
  32. package/lib/import/BpmnImporter.js +30 -18
  33. package/lib/import/BpmnTreeWalker.js +42 -15
  34. package/lib/import/Importer.js +19 -7
  35. package/lib/import/index.js +3 -0
  36. package/package.json +8 -7
  37. package/test/fixtures/bpmn/extension/custom-override.bpmn +54 -0
  38. package/test/fixtures/bpmn/extension/custom.bpmn +54 -0
  39. package/test/fixtures/bpmn/features/modeling/update-label.bpmn +24 -0
  40. package/test/fixtures/json/model/custom-override.json +39 -0
  41. package/test/fixtures/json/model/custom.json +39 -0
  42. package/test/helper/index.js +6 -1
  43. package/test/integration/ReimportSpec.js +89 -0
  44. package/test/spec/ModelerSpec.js +155 -9
  45. package/test/spec/ViewerSpec.js +328 -43
  46. package/test/spec/features/context-pad/ContextPadProviderSpec.js +5 -5
  47. package/test/spec/features/label-editing/LabelEditingProviderSpec.js +201 -128
  48. package/test/spec/features/modeling/AppendShapeSpec.js +0 -43
  49. package/test/spec/features/modeling/UpdateLabelSpec.js +129 -0
  50. package/test/spec/features/modeling/append/TextAnnotationSpec.js +13 -0
  51. package/test/spec/features/modeling/behavior/LabelBehaviorSpec.js +144 -0
  52. package/test/spec/features/modeling/layout/LayoutAssociationSpec.js +3 -3
  53. package/test/spec/features/ordering/BpmnOrderingProviderSpec.js +41 -2
  54. package/test/spec/features/ordering/ordering-subprocesses.bpmn +14 -2
  55. package/test/spec/features/popup-menu/ReplaceMenuProviderSpec.js +0 -4
  56. package/test/spec/features/replace/BpmnReplace.collaboration.bpmn +70 -0
  57. package/test/spec/features/replace/BpmnReplaceSpec.js +37 -0
  58. package/test/spec/features/rules/BpmnRules.collaboration.bpmn +6 -1
  59. package/test/spec/features/rules/BpmnRulesSpec.js +32 -0
  60. package/test/spec/features/snapping/BpmnSnappingSpec.js +16 -6
  61. package/test/spec/i18n/custom-translate/custom-translate.js +15 -0
  62. package/test/spec/i18n/custom-translate/index.js +3 -0
  63. package/test/spec/i18n/translateSpec.js +53 -0
  64. package/test/spec/import/ImporterSpec.js +3 -3
  65. package/test/spec/features/modeling/BpmnLabelSupportSpec.js +0 -37
package/.travis.yml CHANGED
@@ -5,5 +5,5 @@ script:
5
5
  - grunt jshint test
6
6
 
7
7
  before_install:
8
- - npm install -g grunt-cli wiredeps
8
+ - npm install -g wiredeps
9
9
  - wiredeps --branch=$TRAVIS_BRANCH --tag=$TRAVIS_TAG --verbose
package/.wiredeps CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bpmn-js",
3
- "version": "0.8.0",
3
+ "version": "0.13.0",
4
4
  "dependencies": {
5
5
  "diagram-js": {
6
6
  "version": "bpmn-io/diagram-js",
@@ -13,6 +13,9 @@
13
13
  },
14
14
  "snapsvg": {
15
15
  "version": "https://github.com/Nikku/Snap.svg/archive/v0.3.0-browserify.tar.gz"
16
+ },
17
+ "didi": {
18
+ "version": "0.1.0"
16
19
  }
17
20
  }
18
21
  },
@@ -47,11 +50,8 @@
47
50
  "diagram-js-direct-editing": {
48
51
  "version": "bpmn-io/diagram-js-direct-editing"
49
52
  },
50
- "didi": {
51
- "version": "0.1.0"
52
- },
53
53
  "ids": {
54
- "version": "0.1.1",
54
+ "version": "0.2.0",
55
55
  "dependencies": {
56
56
  "hat": {
57
57
  "version": "0.0.3"
package/lib/Modeler.js CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  var inherits = require('inherits');
4
4
 
5
- var IdSupport = require('bpmn-moddle/lib/id-support'),
6
- Ids = require('ids');
5
+ var Ids = require('ids');
7
6
 
8
7
  var Viewer = require('./Viewer');
9
8
 
@@ -102,22 +101,69 @@ var initialDiagram =
102
101
  */
103
102
  function Modeler(options) {
104
103
  Viewer.call(this, options);
104
+
105
+ // hook ID collection into the modeler
106
+ this.on('import.parse.complete', function(event) {
107
+ if (!event.error) {
108
+ this._collectIds(event.definitions, event.context);
109
+ }
110
+ }, this);
111
+
112
+ this.on('diagram.destroy', function() {
113
+ this.moddle.ids.clear();
114
+ }, this);
105
115
  }
106
116
 
107
117
  inherits(Modeler, Viewer);
108
118
 
119
+ module.exports = Modeler;
120
+
121
+ /**
122
+ * Create a new diagram to start modeling.
123
+ *
124
+ * @param {Function} [done]
125
+ */
109
126
  Modeler.prototype.createDiagram = function(done) {
110
127
  return this.importXML(initialDiagram, done);
111
128
  };
112
129
 
113
- Modeler.prototype.createModdle = function() {
114
- var moddle = Viewer.prototype.createModdle.call(this);
130
+ /**
131
+ * Create a moddle instance, attaching ids to it.
132
+ *
133
+ * @param {Object} options
134
+ */
135
+ Modeler.prototype._createModdle = function(options) {
136
+ var moddle = Viewer.prototype._createModdle.call(this, options);
115
137
 
116
- IdSupport.extend(moddle, new Ids([ 32, 36, 1 ]));
138
+ // attach ids to moddle to be able to track
139
+ // and validated ids in the BPMN 2.0 XML document
140
+ // tree
141
+ moddle.ids = new Ids([ 32, 36, 1 ]);
117
142
 
118
143
  return moddle;
119
144
  };
120
145
 
146
+ /**
147
+ * Collect ids processed during parsing of the
148
+ * definitions object.
149
+ *
150
+ * @param {ModdleElement} definitions
151
+ * @param {Context} context
152
+ */
153
+ Modeler.prototype._collectIds = function(definitions, context) {
154
+
155
+ var moddle = definitions.$model,
156
+ ids = moddle.ids,
157
+ id;
158
+
159
+ // remove references from previous import
160
+ ids.clear();
161
+
162
+ for (id in context.elementsById) {
163
+ ids.claim(id, context.elementsById[id]);
164
+ }
165
+ };
166
+
121
167
 
122
168
  Modeler.prototype._interactionModules = [
123
169
  // non-modeling components
@@ -154,7 +200,4 @@ Modeler.prototype._modelingModules = [
154
200
  Modeler.prototype._modules = [].concat(
155
201
  Modeler.prototype._modules,
156
202
  Modeler.prototype._interactionModules,
157
- Modeler.prototype._modelingModules);
158
-
159
-
160
- module.exports = Modeler;
203
+ Modeler.prototype._modelingModules);
package/lib/Viewer.js CHANGED
@@ -18,16 +18,11 @@ var domify = require('min-dom/lib/domify'),
18
18
  var Diagram = require('diagram-js'),
19
19
  BpmnModdle = require('bpmn-moddle');
20
20
 
21
- var Importer = require('./import/Importer');
22
21
 
22
+ var inherits = require('inherits');
23
23
 
24
- function initListeners(diagram, listeners) {
25
- var events = diagram.get('eventBus');
24
+ var Importer = require('./import/Importer');
26
25
 
27
- listeners.forEach(function(l) {
28
- events.on(l.event, l.priority, l.handler, l.that);
29
- });
30
- }
31
26
 
32
27
  function checkValidationError(err) {
33
28
 
@@ -110,63 +105,98 @@ function ensureUnit(val) {
110
105
  */
111
106
  function Viewer(options) {
112
107
 
113
- this.options = options = assign({}, DEFAULT_OPTIONS, options || {});
114
-
115
- var parent = options.container;
116
-
117
- // support jquery element
118
- // unwrap it if passed
119
- if (parent.get) {
120
- parent = parent.get(0);
121
- }
108
+ options = assign({}, DEFAULT_OPTIONS, options);
122
109
 
123
- // support selector
124
- if (isString(parent)) {
125
- parent = domQuery(parent);
126
- }
110
+ this.moddle = this._createModdle(options);
127
111
 
128
- var container = this.container = domify('<div class="bjs-container"></div>');
129
- parent.appendChild(container);
130
-
131
- assign(container.style, {
132
- width: ensureUnit(options.width),
133
- height: ensureUnit(options.height),
134
- position: options.position
135
- });
112
+ this.container = this._createContainer(options);
136
113
 
137
114
  /* <project-logo> */
138
115
 
139
- addProjectLogo(container);
116
+ addProjectLogo(this.container);
140
117
 
141
118
  /* </project-logo> */
119
+
120
+ this._init(this.container, this.moddle, options);
142
121
  }
143
122
 
123
+ inherits(Viewer, Diagram);
124
+
144
125
  module.exports = Viewer;
145
126
 
146
127
 
128
+ /**
129
+ * Parse and render a BPMN 2.0 diagram.
130
+ *
131
+ * Once finished the viewer reports back the result to the
132
+ * provided callback function with (err, warnings).
133
+ *
134
+ * ## Life-Cycle Events
135
+ *
136
+ * During import the viewer will fire life-cycle events:
137
+ *
138
+ * * import.parse.start (about to read model from xml)
139
+ * * import.parse.complete (model read; may have worked or not)
140
+ * * import.render.start (graphical import start)
141
+ * * import.render.complete (graphical import finished)
142
+ * * import.done (everything done)
143
+ *
144
+ * You can use these events to hook into the life-cycle.
145
+ *
146
+ * @param {String} xml the BPMN 2.0 xml
147
+ * @param {Function} [done] invoked with (err, warnings=[])
148
+ */
147
149
  Viewer.prototype.importXML = function(xml, done) {
148
150
 
151
+ // done is optional
152
+ done = done || function() {};
153
+
149
154
  var self = this;
150
155
 
151
- this.moddle = this.createModdle();
156
+ // hook in pre-parse listeners +
157
+ // allow xml manipulation
158
+ xml = this._emit('import.parse.start', { xml: xml }) || xml;
152
159
 
153
160
  this.moddle.fromXML(xml, 'bpmn:Definitions', function(err, definitions, context) {
154
161
 
162
+ // hook in post parse listeners +
163
+ // allow definitions manipulation
164
+ definitions = self._emit('import.parse.complete', {
165
+ error: err,
166
+ definitions: definitions,
167
+ context: context
168
+ }) || definitions;
169
+
155
170
  if (err) {
156
171
  err = checkValidationError(err);
172
+
173
+ self._emit('import.done', { error: err });
174
+
157
175
  return done(err);
158
176
  }
159
177
 
160
178
  var parseWarnings = context.warnings;
161
179
 
162
180
  self.importDefinitions(definitions, function(err, importWarnings) {
163
- var allWarnings = parseWarnings.concat(importWarnings || []);
181
+ var allWarnings = [].concat(parseWarnings, importWarnings || []);
182
+
183
+ self._emit('import.done', { error: err, warnings: allWarnings });
164
184
 
165
185
  done(err, allWarnings);
166
186
  });
167
187
  });
168
188
  };
169
189
 
190
+ /**
191
+ * Export the currently displayed BPMN 2.0 diagram as
192
+ * a BPMN 2.0 XML document.
193
+ *
194
+ * @param {Object} [options] export options
195
+ * @param {Boolean} [options.format=false] output formated XML
196
+ * @param {Boolean} [options.preamble=true] output preamble
197
+ *
198
+ * @param {Function} done invoked with (err, xml)
199
+ */
170
200
  Viewer.prototype.saveXML = function(options, done) {
171
201
 
172
202
  if (!done) {
@@ -183,10 +213,13 @@ Viewer.prototype.saveXML = function(options, done) {
183
213
  this.moddle.toXML(definitions, options, done);
184
214
  };
185
215
 
186
- Viewer.prototype.createModdle = function() {
187
- return new BpmnModdle(this.options.moddleExtensions);
188
- };
189
-
216
+ /**
217
+ * Export the currently displayed BPMN 2.0 diagram as
218
+ * an SVG image.
219
+ *
220
+ * @param {Object} [options]
221
+ * @param {Function} done invoked with (err, svgStr)
222
+ */
190
223
  Viewer.prototype.saveSVG = function(options, done) {
191
224
 
192
225
  if (!done) {
@@ -217,124 +250,191 @@ Viewer.prototype.saveSVG = function(options, done) {
217
250
  done(null, svg);
218
251
  };
219
252
 
220
- Viewer.prototype.get = function(name) {
221
-
222
- if (!this.diagram) {
223
- throw new Error('no diagram loaded');
224
- }
225
-
226
- return this.diagram.get(name);
227
- };
228
-
229
- Viewer.prototype.invoke = function(fn) {
253
+ /**
254
+ * Get a named diagram service.
255
+ *
256
+ * @example
257
+ *
258
+ * var elementRegistry = viewer.get('elementRegistry');
259
+ * var startEventShape = elementRegistry.get('StartEvent_1');
260
+ *
261
+ * @param {String} name
262
+ *
263
+ * @return {Object} diagram service instance
264
+ *
265
+ * @method Viewer#get
266
+ */
230
267
 
231
- if (!this.diagram) {
232
- throw new Error('no diagram loaded');
233
- }
268
+ /**
269
+ * Invoke a function in the context of this viewer.
270
+ *
271
+ * @example
272
+ *
273
+ * viewer.invoke(function(elementRegistry) {
274
+ * var startEventShape = elementRegistry.get('StartEvent_1');
275
+ * });
276
+ *
277
+ * @param {Function} fn to be invoked
278
+ *
279
+ * @return {Object} the functions return value
280
+ *
281
+ * @method Viewer#invoke
282
+ */
234
283
 
235
- return this.diagram.invoke(fn);
236
- };
284
+ /**
285
+ * Remove all drawn elements from the viewer.
286
+ *
287
+ * After calling this method the viewer can still
288
+ * be reused for opening another diagram.
289
+ *
290
+ * @method Viewer#clear
291
+ */
237
292
 
238
293
  Viewer.prototype.importDefinitions = function(definitions, done) {
239
294
 
240
295
  // use try/catch to not swallow synchronous exceptions
241
296
  // that may be raised during model parsing
242
297
  try {
243
- if (this.diagram) {
298
+
299
+ if (this.definitions) {
300
+ // clear existing rendered diagram
244
301
  this.clear();
245
302
  }
246
303
 
304
+ // update definitions
247
305
  this.definitions = definitions;
248
306
 
249
- var diagram = this.diagram = this._createDiagram(this.options);
250
-
251
- this._init(diagram);
252
-
253
- Importer.importBpmnDiagram(diagram, definitions, done);
307
+ // perform graphical import
308
+ Importer.importBpmnDiagram(this, definitions, done);
254
309
  } catch (e) {
310
+
311
+ // handle synchronous errors
255
312
  done(e);
256
313
  }
257
314
  };
258
315
 
259
- Viewer.prototype._init = function(diagram) {
260
- initListeners(diagram, this.__listeners || []);
316
+ Viewer.prototype.getModules = function() {
317
+ return this._modules;
261
318
  };
262
319
 
263
- Viewer.prototype._createDiagram = function(options) {
264
-
265
- var modules = [].concat(options.modules || this.getModules(), options.additionalModules || []);
266
-
267
- // add self as an available service
268
- modules.unshift({
269
- bpmnjs: [ 'value', this ],
270
- moddle: [ 'value', this.moddle ]
271
- });
272
-
273
- options = omit(options, 'additionalModules');
274
-
275
- options = assign(options, {
276
- canvas: assign({}, options.canvas, { container: this.container }),
277
- modules: modules
278
- });
279
-
280
- return new Diagram(options);
281
- };
320
+ /**
321
+ * Destroy the viewer instance and remove all its
322
+ * remainders from the document tree.
323
+ */
324
+ Viewer.prototype.destroy = function() {
282
325
 
326
+ // diagram destroy
327
+ Diagram.prototype.destroy.call(this);
283
328
 
284
- Viewer.prototype.getModules = function() {
285
- return this._modules;
329
+ // dom detach
330
+ domRemove(this.container);
286
331
  };
287
332
 
288
333
  /**
289
- * Remove all drawn elements from the viewer.
334
+ * Register an event listener
290
335
  *
291
- * After calling this method the viewer can still
292
- * be reused for opening another diagram.
336
+ * Remove a previously added listener via {@link #off(event, callback)}.
337
+ *
338
+ * @param {String} event
339
+ * @param {Number} [priority]
340
+ * @param {Function} callback
341
+ * @param {Object} [that]
293
342
  */
294
- Viewer.prototype.clear = function() {
295
- var diagram = this.diagram;
296
-
297
- if (diagram) {
298
- diagram.destroy();
299
- }
343
+ Viewer.prototype.on = function(event, priority, callback, target) {
344
+ return this.get('eventBus').on(event, priority, callback, target);
300
345
  };
301
346
 
302
347
  /**
303
- * Destroy the viewer instance and remove all its remainders
304
- * from the document tree.
348
+ * De-register an event listener
349
+ *
350
+ * @param {String} event
351
+ * @param {Function} callback
305
352
  */
306
- Viewer.prototype.destroy = function() {
307
- // clear underlying diagram
308
- this.clear();
353
+ Viewer.prototype.off = function(event, callback) {
354
+ this.get('eventBus').off(event, callback);
355
+ };
309
356
 
310
- // remove container
311
- domRemove(this.container);
357
+
358
+ Viewer.prototype._init = function(container, moddle, options) {
359
+
360
+ var baseModules = options.modules || this.getModules(),
361
+ additionalModules = options.additionalModules || [],
362
+ staticModules = [
363
+ {
364
+ bpmnjs: [ 'value', this ],
365
+ moddle: [ 'value', moddle ]
366
+ }
367
+ ];
368
+
369
+ var diagramModules = [].concat(staticModules, baseModules, additionalModules);
370
+
371
+ var diagramOptions = assign(omit(options, 'additionalModules'), {
372
+ canvas: assign({}, options.canvas, { container: container }),
373
+ modules: diagramModules
374
+ });
375
+
376
+ // invoke diagram constructor
377
+ Diagram.call(this, diagramOptions);
312
378
  };
313
379
 
314
380
  /**
315
- * Register an event listener on the viewer
381
+ * Emit an event on the underlying {@link EventBus}
316
382
  *
317
- * @param {String} event
318
- * @param {Function} handler
383
+ * @param {String} type
384
+ * @param {Object} event
385
+ *
386
+ * @return {Object} event processing result (if any)
319
387
  */
320
- Viewer.prototype.on = function(event, priority, handler, that) {
321
- var diagram = this.diagram,
322
- listeners = this.__listeners = this.__listeners || [];
388
+ Viewer.prototype._emit = function(type, event) {
389
+ return this.get('eventBus').fire(type, event);
390
+ };
391
+
392
+ Viewer.prototype._createContainer = function(options) {
323
393
 
324
- listeners.push({ event: event, priority: priority, handler: handler, that: that });
394
+ var parent = options.container,
395
+ container;
396
+
397
+ // support jquery element
398
+ // unwrap it if passed
399
+ if (parent.get) {
400
+ parent = parent.get(0);
401
+ }
325
402
 
326
- if (diagram) {
327
- diagram.get('eventBus').on(event, priority, handler, that);
403
+ // support selector
404
+ if (isString(parent)) {
405
+ parent = domQuery(parent);
328
406
  }
407
+
408
+ container = domify('<div class="bjs-container"></div>');
409
+
410
+ assign(container.style, {
411
+ width: ensureUnit(options.width),
412
+ height: ensureUnit(options.height),
413
+ position: options.position
414
+ });
415
+
416
+ parent.appendChild(container);
417
+
418
+ return container;
329
419
  };
330
420
 
421
+ Viewer.prototype._createModdle = function(options) {
422
+ var moddleOptions = assign({}, this._moddleExtensions, options.moddleExtensions);
423
+
424
+ return new BpmnModdle(moddleOptions);
425
+ };
426
+
427
+
331
428
  // modules the viewer is composed of
332
429
  Viewer.prototype._modules = [
333
430
  require('./core'),
431
+ require('diagram-js/lib/i18n/translate'),
334
432
  require('diagram-js/lib/features/selection'),
335
433
  require('diagram-js/lib/features/overlays')
336
434
  ];
337
435
 
436
+ // default moddle extensions the viewer is composed of
437
+ Viewer.prototype._moddleExtensions = {};
338
438
 
339
439
  /* <project-logo> */
340
440
 
@@ -372,4 +472,4 @@ function addProjectLogo(container) {
372
472
  });
373
473
  }
374
474
 
375
- /* </project-logo> */
475
+ /* </project-logo> */
@@ -835,6 +835,9 @@ function BpmnRenderer(eventBus, styles, pathMap, priority) {
835
835
  return task;
836
836
  },
837
837
  'bpmn:SubProcess': function(p, element, attrs) {
838
+
839
+ attrs = assign({ fillOpacity: 0.95 }, attrs);
840
+
838
841
  var rect = renderer('bpmn:Activity')(p, element, attrs);
839
842
 
840
843
  var expanded = DiUtil.isExpanded(element);
@@ -877,6 +880,7 @@ function BpmnRenderer(eventBus, styles, pathMap, priority) {
877
880
  'bpmn:Participant': function(p, element) {
878
881
 
879
882
  var lane = renderer('bpmn:Lane')(p, element, {
883
+ fillOpacity: 0.95,
880
884
  fill: 'White'
881
885
  });
882
886