bpmn-js 0.20.3 → 0.20.7

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.
package/.travis.yml CHANGED
@@ -1,6 +1,8 @@
1
1
  language: node_js
2
2
  node_js: '4.0'
3
3
 
4
+ sudo: false
5
+
4
6
  addons:
5
7
  firefox: "latest-esr"
6
8
 
@@ -1827,8 +1827,9 @@ function isThrowEvent(event) {
1827
1827
  }
1828
1828
 
1829
1829
  function isCollection(element) {
1830
- return element.isCollection ||
1831
- (element.elementObjectRef && element.elementObjectRef.isCollection);
1830
+ var dataObject = element.dataObjectRef;
1831
+
1832
+ return element.isCollection || (dataObject && dataObject.isCollection);
1832
1833
  }
1833
1834
 
1834
1835
  function getDi(element) {
@@ -30,7 +30,9 @@ function removeProperties(element, properties) {
30
30
  });
31
31
  }
32
32
 
33
- function BpmnCopyPaste(bpmnFactory, eventBus, copyPaste, clipboard, moddle, canvas, bpmnRules) {
33
+ function BpmnCopyPaste(
34
+ bpmnFactory, eventBus, copyPaste,
35
+ clipboard, canvas, bpmnRules) {
34
36
 
35
37
  var helper = new ModelCloneHelper(eventBus);
36
38
 
@@ -138,6 +140,14 @@ function BpmnCopyPaste(bpmnFactory, eventBus, copyPaste, clipboard, moddle, canv
138
140
  'triggeredByEvent'
139
141
  ]);
140
142
  });
143
+
144
+
145
+ eventBus.on('commandStack.elements.paste.postExecuted', function() {
146
+ // temporarily disable multi paste until #686
147
+ // is addressed
148
+ clipboard.clear();
149
+ });
150
+
141
151
  }
142
152
 
143
153
 
@@ -146,7 +156,6 @@ BpmnCopyPaste.$inject = [
146
156
  'eventBus',
147
157
  'copyPaste',
148
158
  'clipboard',
149
- 'moddle',
150
159
  'canvas',
151
160
  'bpmnRules'
152
161
  ];
@@ -74,19 +74,23 @@ function BpmnUpdater(eventBus, bpmnFactory, connectionDocking, translate) {
74
74
  self.updateParent(element, oldParent);
75
75
  }
76
76
 
77
- this.executed([ 'shape.move',
78
- 'shape.create',
79
- 'shape.delete',
80
- 'connection.create',
81
- 'connection.move',
82
- 'connection.delete' ], ifBpmn(updateParent));
83
-
84
- this.reverted([ 'shape.move',
85
- 'shape.create',
86
- 'shape.delete',
87
- 'connection.create',
88
- 'connection.move',
89
- 'connection.delete' ], ifBpmn(reverseUpdateParent));
77
+ this.executed([
78
+ 'shape.move',
79
+ 'shape.create',
80
+ 'shape.delete',
81
+ 'connection.create',
82
+ 'connection.move',
83
+ 'connection.delete'
84
+ ], ifBpmn(updateParent));
85
+
86
+ this.reverted([
87
+ 'shape.move',
88
+ 'shape.create',
89
+ 'shape.delete',
90
+ 'connection.create',
91
+ 'connection.move',
92
+ 'connection.delete'
93
+ ], ifBpmn(reverseUpdateParent));
90
94
 
91
95
  /*
92
96
  * ## Updating Parent
@@ -81,7 +81,7 @@ ElementFactory.prototype.createBpmnElement = function(elementType, attrs) {
81
81
  delete attrs.colors;
82
82
  }
83
83
 
84
- this.setAttrs(businessObject, attrs, [
84
+ applyAttributes(businessObject, attrs, [
85
85
  'processRef',
86
86
  'isInterrupting',
87
87
  'associationDirection',
@@ -89,7 +89,7 @@ ElementFactory.prototype.createBpmnElement = function(elementType, attrs) {
89
89
  ]);
90
90
 
91
91
  if (attrs.isExpanded) {
92
- this.setAttr(businessObject.di, attrs, 'isExpanded');
92
+ applyAttribute(businessObject.di, attrs, 'isExpanded');
93
93
  }
94
94
 
95
95
  if (is(businessObject, 'bpmn:ExclusiveGateway')) {
@@ -122,23 +122,6 @@ ElementFactory.prototype.createBpmnElement = function(elementType, attrs) {
122
122
  };
123
123
 
124
124
 
125
- ElementFactory.prototype.setAttrs = function(element, attrs, properties) {
126
-
127
- forEach(properties, function(property) {
128
- if (attrs[property] !== undefined) {
129
- this.setAttr(element, attrs, property);
130
- }
131
- }, this);
132
- };
133
-
134
-
135
- ElementFactory.prototype.setAttr = function(element, attrs, property) {
136
- element[property] = attrs[property];
137
-
138
- delete attrs[property];
139
- };
140
-
141
-
142
125
  ElementFactory.prototype._getDefaultSize = function(semantic) {
143
126
 
144
127
  if (is(semantic, 'bpmn:SubProcess')) {
@@ -200,3 +183,37 @@ ElementFactory.prototype.createParticipantShape = function(collapsed) {
200
183
 
201
184
  return this.createShape(attrs);
202
185
  };
186
+
187
+
188
+ //////////// helpers ////////////////////////////////////
189
+
190
+ /**
191
+ * Apply attributes from a map to the given element,
192
+ * remove attribute from the map on application.
193
+ *
194
+ * @param {Base} element
195
+ * @param {Object} attrs (in/out map of attributes)
196
+ * @param {Array<String>} attributeNames name of attributes to apply
197
+ */
198
+ function applyAttributes(element, attrs, attributeNames) {
199
+
200
+ forEach(attributeNames, function(property) {
201
+ if (attrs[property] !== undefined) {
202
+ applyAttribute(element, attrs, property);
203
+ }
204
+ });
205
+ }
206
+
207
+ /**
208
+ * Apply named property to element and drain it from the attrs
209
+ * collection.
210
+ *
211
+ * @param {Base} element
212
+ * @param {Object} attrs (in/out map of attributes)
213
+ * @param {String} attributeName to apply
214
+ */
215
+ function applyAttribute(element, attrs, attributeName) {
216
+ element[attributeName] = attrs[attributeName];
217
+
218
+ delete attrs[attributeName];
219
+ }
@@ -64,7 +64,11 @@ Modeling.prototype.connect = function(source, target, attrs, hints) {
64
64
  var bpmnRules = this._bpmnRules;
65
65
 
66
66
  if (!attrs) {
67
- attrs = bpmnRules.canConnect(source, target) || { type: 'bpmn:Association' };
67
+ attrs = bpmnRules.canConnect(source, target);
68
+ }
69
+
70
+ if (!attrs) {
71
+ return;
68
72
  }
69
73
 
70
74
  return this.createConnection(source, target, attrs, source.parent, hints);
@@ -110,7 +110,9 @@ ReplaceElementBehaviour.prototype.replaceElements = function(elements, newElemen
110
110
  }
111
111
  };
112
112
 
113
- ReplaceElementBehaviour.$inject = [ 'eventBus', 'bpmnReplace', 'bpmnRules', 'elementRegistry',
114
- 'selection', 'modeling' ];
113
+ ReplaceElementBehaviour.$inject = [
114
+ 'eventBus', 'bpmnReplace', 'bpmnRules',
115
+ 'elementRegistry', 'selection', 'modeling'
116
+ ];
115
117
 
116
118
  module.exports = ReplaceElementBehaviour;
@@ -112,7 +112,7 @@ function getLabelAdjustment(label, newWaypoints, oldWaypoints, hints) {
112
112
  oldLabelLineIndex = attachment.segmentIndex,
113
113
  newLabelLineIndex = findNewLabelLineStartIndex(oldWaypoints, newWaypoints, attachment, hints);
114
114
 
115
- if ( newLabelLineIndex === null ) {
115
+ if (newLabelLineIndex === null) {
116
116
  return { x: x, y: y };
117
117
  }
118
118
 
@@ -210,8 +210,9 @@ function getLine(waypoints, idx) {
210
210
  }
211
211
 
212
212
  function getRelativeFootPosition(line, foot) {
213
+
213
214
  var length = getDistancePointPoint(line[0], line[1]),
214
215
  lengthToFoot = getDistancePointPoint(line[0], foot);
215
216
 
216
- return lengthToFoot / length;
217
+ return length === 0 ? 0 : lengthToFoot / length;
217
218
  }
@@ -2,7 +2,8 @@
2
2
 
3
3
  var sqrt = Math.sqrt,
4
4
  min = Math.min,
5
- max = Math.max;
5
+ max = Math.max,
6
+ abs = Math.abs;
6
7
 
7
8
  /**
8
9
  * Calculate the square (power to two) of a number.
@@ -74,15 +75,15 @@ function getAttachment(point, line) {
74
75
  segmentEnd = line[idx + 1];
75
76
 
76
77
  if (pointsEqual(segmentStart, segmentEnd)) {
77
- continue;
78
- }
79
-
80
- segmentStartDistance = getDistance(point, segmentStart);
81
- segmentEndDistance = getDistance(point, segmentEnd);
78
+ intersections = [ segmentStart ];
79
+ } else {
80
+ segmentStartDistance = getDistance(point, segmentStart);
81
+ segmentEndDistance = getDistance(point, segmentEnd);
82
82
 
83
- minDistance = min(segmentStartDistance, segmentEndDistance);
83
+ minDistance = min(segmentStartDistance, segmentEndDistance);
84
84
 
85
- intersections = getCircleSegmentIntersections(segmentStart, segmentEnd, point, minDistance);
85
+ intersections = getCircleSegmentIntersections(segmentStart, segmentEnd, point, minDistance);
86
+ }
86
87
 
87
88
  if (intersections.length < 1) {
88
89
  throw new Error('expected between [1, 2] circle -> line intersections');
@@ -136,12 +137,6 @@ module.exports.getAttachment = getAttachment;
136
137
  */
137
138
  function getCircleSegmentIntersections(s1, s2, cc, cr) {
138
139
 
139
- // silently round values
140
- s1 = roundPoint(s1);
141
- s2 = roundPoint(s2);
142
- cc = roundPoint(cc);
143
- cr = min(getDistance(s1, cc), getDistance(s2, cc));
144
-
145
140
  var baX = s2.x - s1.x;
146
141
  var baY = s2.y - s1.y;
147
142
  var caX = cc.x - s1.x;
@@ -155,6 +150,14 @@ function getCircleSegmentIntersections(s1, s2, cc, cr) {
155
150
  var q = c / a;
156
151
 
157
152
  var disc = pBy2 * pBy2 - q;
153
+
154
+ // check against negative value to work around
155
+ // negative, very close to zero results (-4e-15)
156
+ // being produced in some environments
157
+ if (disc < 0 && disc > -0.000001) {
158
+ disc = 0;
159
+ }
160
+
158
161
  if (disc < 0) {
159
162
  return [];
160
163
  }
@@ -165,8 +168,8 @@ function getCircleSegmentIntersections(s1, s2, cc, cr) {
165
168
  var abScalingFactor2 = -pBy2 - tmpSqrt;
166
169
 
167
170
  var i1 = {
168
- x: round(s1.x - baX * abScalingFactor1),
169
- y: round(s1.y - baY * abScalingFactor1)
171
+ x: s1.x - baX * abScalingFactor1,
172
+ y: s1.y - baY * abScalingFactor1
170
173
  };
171
174
 
172
175
  if (disc === 0) { // abScalingFactor1 == abScalingFactor2
@@ -174,10 +177,11 @@ function getCircleSegmentIntersections(s1, s2, cc, cr) {
174
177
  }
175
178
 
176
179
  var i2 = {
177
- x: round(s1.x - baX * abScalingFactor2),
178
- y: round(s1.y - baY * abScalingFactor2)
180
+ x: s1.x - baX * abScalingFactor2,
181
+ y: s1.y - baY * abScalingFactor2
179
182
  };
180
183
 
184
+ // return only points on line segment
181
185
  return [ i1, i2 ].filter(function(p) {
182
186
  return isPointInSegment(p, s1, s2);
183
187
  });
@@ -192,7 +196,14 @@ function isPointInSegment(p, segmentStart, segmentEnd) {
192
196
  }
193
197
 
194
198
  function fenced(n, rangeStart, rangeEnd) {
195
- return min(rangeStart, rangeEnd) <= n && n <= max(rangeStart, rangeEnd);
199
+
200
+ // use matching threshold to work around
201
+ // precisison errors in intersection computation
202
+
203
+ return (
204
+ n >= min(rangeStart, rangeEnd) - EQUAL_THRESHOLD &&
205
+ n <= max(rangeStart, rangeEnd) + EQUAL_THRESHOLD
206
+ );
196
207
  }
197
208
 
198
209
  /**
@@ -211,17 +222,12 @@ function mid(p1, p2) {
211
222
  };
212
223
  }
213
224
 
214
- function round(n) {
215
- return Math.round(n * 1000) / 1000;
216
- }
217
-
218
- function roundPoint(p) {
219
- return {
220
- x: round(p.x),
221
- y: round(p.y)
222
- };
223
- }
225
+ var EQUAL_THRESHOLD = 0.1;
224
226
 
225
227
  function pointsEqual(p1, p2) {
226
- return p1.x === p2.x && p1.y === p2.y;
228
+
229
+ return (
230
+ abs(p1.x - p2.x) <= EQUAL_THRESHOLD &&
231
+ abs(p1.y - p2.y) <= EQUAL_THRESHOLD
232
+ );
227
233
  }
@@ -369,14 +369,7 @@ function canConnect(source, target, connection) {
369
369
  };
370
370
  }
371
371
 
372
- if (is(connection, 'bpmn:Association') && canConnectAssociation(source, target)) {
373
-
374
- return {
375
- type: 'bpmn:Association'
376
- };
377
- }
378
-
379
- if (isTextAnnotation(source) || isTextAnnotation(target)) {
372
+ if (canConnectAssociation(source, target)) {
380
373
 
381
374
  return {
382
375
  type: 'bpmn:Association'
@@ -705,6 +698,22 @@ function canResize(shape, newBounds) {
705
698
  return false;
706
699
  }
707
700
 
701
+ /**
702
+ * Check, whether one side of the relationship
703
+ * is a text annotation.
704
+ */
705
+ function isOneTextAnnotation(source, target) {
706
+
707
+ var sourceTextAnnotation = isTextAnnotation(source),
708
+ targetTextAnnotation = isTextAnnotation(target);
709
+
710
+ return (
711
+ (sourceTextAnnotation || targetTextAnnotation) &&
712
+ (sourceTextAnnotation !== targetTextAnnotation)
713
+ );
714
+ }
715
+
716
+
708
717
  function canConnectAssociation(source, target) {
709
718
 
710
719
  // do not connect connections
@@ -712,9 +721,18 @@ function canConnectAssociation(source, target) {
712
721
  return false;
713
722
  }
714
723
 
715
- // connect if different parent
716
- return !isParent(target, source) &&
717
- !isParent(source, target);
724
+ // compensation boundary events are exception
725
+ if (isCompensationBoundary(source) && isForCompensation(target)) {
726
+ return true;
727
+ }
728
+
729
+ // don't connect parent <-> child
730
+ if (isParent(target, source) || isParent(source, target)) {
731
+ return false;
732
+ }
733
+
734
+ // allow connection of associations between <!TextAnnotation> and <TextAnnotation>
735
+ return isOneTextAnnotation(source, target);
718
736
  }
719
737
 
720
738
  function canConnectMessageFlow(source, target) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bpmn-js",
3
- "version": "0.20.3",
3
+ "version": "0.20.7",
4
4
  "description": "A bpmn 2.0 toolkit and web modeler",
5
5
  "scripts": {
6
6
  "all": "grunt",
@@ -37,34 +37,34 @@
37
37
  "browserify": "^13.0.0",
38
38
  "browserify-derequire": "^0.9.1",
39
39
  "bundle-collapser": "^1.1.1",
40
- "chai": "~2.2.0",
41
- "eslint": "^2.11.1",
42
- "eslint-plugin-mocha": "^2.2.0",
40
+ "chai": "^3.5.0",
41
+ "eslint": "^3.19.0",
42
+ "eslint-plugin-mocha": "^4.9.0",
43
43
  "grunt": "^0.4.4",
44
44
  "grunt-cli": "^0.1.13",
45
45
  "grunt-contrib-copy": "^0.7.0",
46
- "grunt-eslint": "^18.1.0",
47
- "grunt-karma": "^0.12.0",
46
+ "grunt-eslint": "^19.0.0",
47
+ "grunt-karma": "^2.0.0",
48
48
  "grunt-release": "^0.7.0",
49
49
  "jsondiffpatch": "^0.1.26",
50
- "karma": "^0.13.0",
51
- "karma-browserify": "^5.0.1",
50
+ "karma": "^1.7.0",
51
+ "karma-browserify": "^5.1.1",
52
52
  "karma-chai": "^0.1.0",
53
- "karma-chrome-launcher": "^0.2.2",
53
+ "karma-chrome-launcher": "^2.1.1",
54
54
  "karma-env-preprocessor": "^0.1.1",
55
- "karma-firefox-launcher": "^0.1.3",
56
- "karma-ie-launcher": "^0.2.0",
57
- "karma-mocha": "~0.1.0",
58
- "karma-phantomjs-launcher": "^1.0.2",
59
- "karma-safari-launcher": "^0.1.1",
60
- "karma-sinon-chai": "~0.3.0",
61
- "karma-spec-reporter": "0.0.26",
55
+ "karma-firefox-launcher": "^1.0.1",
56
+ "karma-ie-launcher": "^1.0.0",
57
+ "karma-mocha": "^1.3.0",
58
+ "karma-phantomjs-launcher": "^1.0.4",
59
+ "karma-safari-launcher": "^1.0.0",
60
+ "karma-sinon-chai": "^1.3.1",
61
+ "karma-spec-reporter": "0.0.31",
62
62
  "load-grunt-tasks": "^0.3.0",
63
- "mocha": "^2.2.5",
63
+ "mocha": "^3.4.1",
64
64
  "mocha-test-container-support": "0.2.0",
65
65
  "phantomjs-prebuilt": "^2.1.12",
66
- "sinon": "~1.14.1",
67
- "sinon-chai": "~2.7.0",
66
+ "sinon": "^2.2.0",
67
+ "sinon-chai": "^2.10.0",
68
68
  "source-map-concat": "^1.0.0",
69
69
  "stringify": "^3.1.0",
70
70
  "time-grunt": "^0.3.2",
@@ -73,7 +73,7 @@
73
73
  },
74
74
  "dependencies": {
75
75
  "bpmn-moddle": "^0.14.0",
76
- "diagram-js": "^0.19.1",
76
+ "diagram-js": "^0.19.6",
77
77
  "diagram-js-direct-editing": "^0.17.1",
78
78
  "diagram-js-origin": "^0.15.1",
79
79
  "ids": "^0.2.0",
@@ -154,7 +154,7 @@ describe('custom elements', function() {
154
154
  );
155
155
 
156
156
 
157
- it('should connect a bpmn element to a custom one',
157
+ it('should not connect a bpmn element to a custom one',
158
158
  inject(function(elementFactory, dragging, elementRegistry, connect) {
159
159
 
160
160
  // given
@@ -170,11 +170,8 @@ describe('custom elements', function() {
170
170
 
171
171
  dragging.end();
172
172
 
173
- var connection = triangle.incoming[0];
174
-
175
173
  // then
176
- expect(connection.type).to.equal('bpmn:Association');
177
- expect(connection.source).to.equal(subProcess);
174
+ expect(triangle.incoming).to.have.lengthOf(0);
178
175
  })
179
176
  );
180
177
 
@@ -58,6 +58,38 @@ describe('features/copy-paste', function() {
58
58
  });
59
59
 
60
60
 
61
+ it('should forbid multi paste', inject(
62
+ function(elementRegistry, canvas, copyPaste) {
63
+ // given
64
+ var element = elementRegistry.get('SubProcess_1kd6ist'),
65
+ rootElement = canvas.getRootElement();
66
+
67
+ // when
68
+ copyPaste.copy(element);
69
+
70
+ copyPaste.paste({
71
+ element: rootElement,
72
+ point: {
73
+ x: 600,
74
+ y: 100
75
+ }
76
+ });
77
+
78
+ copyPaste.paste({
79
+ element: rootElement,
80
+ point: {
81
+ x: 600,
82
+ y: 275
83
+ }
84
+ });
85
+
86
+ // then
87
+ // pasted was only once
88
+ expect(rootElement.children).to.have.length(2);
89
+ }
90
+ ));
91
+
92
+
61
93
  describe('integration', function() {
62
94
 
63
95
  it('should retain label\'s relative position',
@@ -489,6 +521,7 @@ describe('features/copy-paste', function() {
489
521
  it('multiple participants', inject(integrationTest([ 'Participant_0pgdgt4', 'Participant_1id96b4' ])));
490
522
 
491
523
  it('multiple participants', inject(integrationTest([ 'Participant_0pgdgt4', 'Participant_1id96b4' ])));
524
+
492
525
  });
493
526
 
494
527
  });