UNPKG

446 kBJavaScriptView Raw
1/*!
2 * bpmn-js - bpmn-navigated-viewer v3.0.4
3 *
4 * Copyright (c) 2014-present, camunda Services GmbH
5 *
6 * Released under the bpmn.io license
7 * http://bpmn.io/license
8 *
9 * Source Code: https://github.com/bpmn-io/bpmn-js
10 *
11 * Date: 2018-12-04
12 */
13(function (global, factory) {
14 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
15 typeof define === 'function' && define.amd ? define(factory) :
16 (global.BpmnJS = factory());
17}(this, (function () { 'use strict';
18
19 var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
20
21 function createCommonjsModule(fn, module) {
22 return module = { exports: {} }, fn(module, module.exports), module.exports;
23 }
24
25 function getCjsExportFromNamespace (n) {
26 return n && n.default || n;
27 }
28
29 var inherits_browser = createCommonjsModule(function (module) {
30 if (typeof Object.create === 'function') {
31 // implementation from standard node.js 'util' module
32 module.exports = function inherits(ctor, superCtor) {
33 ctor.super_ = superCtor;
34 ctor.prototype = Object.create(superCtor.prototype, {
35 constructor: {
36 value: ctor,
37 enumerable: false,
38 writable: true,
39 configurable: true
40 }
41 });
42 };
43 } else {
44 // old school shim for old browsers
45 module.exports = function inherits(ctor, superCtor) {
46 ctor.super_ = superCtor;
47 var TempCtor = function () {};
48 TempCtor.prototype = superCtor.prototype;
49 ctor.prototype = new TempCtor();
50 ctor.prototype.constructor = ctor;
51 };
52 }
53 });
54
55 /**
56 * Flatten array, one level deep.
57 *
58 * @param {Array<?>} arr
59 *
60 * @return {Array<?>}
61 */
62
63 var nativeToString = Object.prototype.toString;
64 var nativeHasOwnProperty = Object.prototype.hasOwnProperty;
65
66 function isUndefined(obj) {
67 return obj === undefined;
68 }
69
70 function isDefined(obj) {
71 return obj !== undefined;
72 }
73
74 function isArray(obj) {
75 return nativeToString.call(obj) === '[object Array]';
76 }
77
78 function isObject(obj) {
79 return nativeToString.call(obj) === '[object Object]';
80 }
81
82 function isNumber(obj) {
83 return nativeToString.call(obj) === '[object Number]';
84 }
85
86 function isFunction(obj) {
87 return nativeToString.call(obj) === '[object Function]';
88 }
89
90 function isString(obj) {
91 return nativeToString.call(obj) === '[object String]';
92 }
93
94 /**
95 * Return true, if target owns a property with the given key.
96 *
97 * @param {Object} target
98 * @param {String} key
99 *
100 * @return {Boolean}
101 */
102 function has(target, key) {
103 return nativeHasOwnProperty.call(target, key);
104 }
105
106 /**
107 * Find element in collection.
108 *
109 * @param {Array|Object} collection
110 * @param {Function|Object} matcher
111 *
112 * @return {Object}
113 */
114 function find(collection, matcher) {
115
116 matcher = toMatcher(matcher);
117
118 var match;
119
120 forEach(collection, function (val, key) {
121 if (matcher(val, key)) {
122 match = val;
123
124 return false;
125 }
126 });
127
128 return match;
129 }
130
131 /**
132 * Find element in collection.
133 *
134 * @param {Array|Object} collection
135 * @param {Function} matcher
136 *
137 * @return {Array} result
138 */
139 function filter(collection, matcher) {
140
141 var result = [];
142
143 forEach(collection, function (val, key) {
144 if (matcher(val, key)) {
145 result.push(val);
146 }
147 });
148
149 return result;
150 }
151
152 /**
153 * Iterate over collection; returning something
154 * (non-undefined) will stop iteration.
155 *
156 * @param {Array|Object} collection
157 * @param {Function} iterator
158 *
159 * @return {Object} return result that stopped the iteration
160 */
161 function forEach(collection, iterator) {
162
163 if (isUndefined(collection)) {
164 return;
165 }
166
167 var convertKey = isArray(collection) ? toNum : identity;
168
169 for (var key in collection) {
170
171 if (has(collection, key)) {
172 var val = collection[key];
173
174 var result = iterator(val, convertKey(key));
175
176 if (result === false) {
177 return;
178 }
179 }
180 }
181 }
182
183 /**
184 * Reduce collection, returning a single result.
185 *
186 * @param {Object|Array} collection
187 * @param {Function} iterator
188 * @param {Any} result
189 *
190 * @return {Any} result returned from last iterator
191 */
192 function reduce(collection, iterator, result) {
193
194 forEach(collection, function (value, idx) {
195 result = iterator(result, value, idx);
196 });
197
198 return result;
199 }
200
201 /**
202 * Return true if every element in the collection
203 * matches the criteria.
204 *
205 * @param {Object|Array} collection
206 * @param {Function} matcher
207 *
208 * @return {Boolean}
209 */
210 function every(collection, matcher) {
211
212 return reduce(collection, function (matches, val, key) {
213 return matches && matcher(val, key);
214 }, true);
215 }
216
217 /**
218 * Return true if some elements in the collection
219 * match the criteria.
220 *
221 * @param {Object|Array} collection
222 * @param {Function} matcher
223 *
224 * @return {Boolean}
225 */
226 function some(collection, matcher) {
227
228 return !!find(collection, matcher);
229 }
230
231 /**
232 * Transform a collection into another collection
233 * by piping each member through the given fn.
234 *
235 * @param {Object|Array} collection
236 * @param {Function} fn
237 *
238 * @return {Array} transformed collection
239 */
240 function map(collection, fn) {
241
242 var result = [];
243
244 forEach(collection, function (val, key) {
245 result.push(fn(val, key));
246 });
247
248 return result;
249 }
250
251 /**
252 * Create an object pattern matcher.
253 *
254 * @example
255 *
256 * const matcher = matchPattern({ id: 1 });
257 *
258 * var element = find(elements, matcher);
259 *
260 * @param {Object} pattern
261 *
262 * @return {Function} matcherFn
263 */
264 function matchPattern(pattern) {
265
266 return function (el) {
267
268 return every(pattern, function (val, key) {
269 return el[key] === val;
270 });
271 };
272 }
273
274 function toMatcher(matcher) {
275 return isFunction(matcher) ? matcher : function (e) {
276 return e === matcher;
277 };
278 }
279
280 function identity(arg) {
281 return arg;
282 }
283
284 function toNum(arg) {
285 return Number(arg);
286 }
287
288 function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
289
290 var slice = Array.prototype.slice;
291
292 /**
293 * Debounce fn, calling it only once if
294 * the given time elapsed between calls.
295 *
296 * @param {Function} fn
297 * @param {Number} timeout
298 *
299 * @return {Function} debounced function
300 */
301 function debounce(fn, timeout) {
302
303 var timer;
304
305 return function () {
306
307 var args = slice.call(arguments);
308
309 if (timer) {
310 clearTimeout(timer);
311 }
312
313 timer = setTimeout(function () {
314 fn.apply(undefined, _toConsumableArray(args));
315 }, timeout);
316 };
317 }
318
319 /**
320 * Bind function against target <this>.
321 *
322 * @param {Function} fn
323 * @param {Object} target
324 *
325 * @return {Function} bound function
326 */
327 function bind(fn, target) {
328 return fn.bind(target);
329 }
330
331 var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
332
333 /**
334 * Convenience wrapper for `Object.assign`.
335 *
336 * @param {Object} target
337 * @param {...Object} others
338 *
339 * @return {Object} the target
340 */
341 function assign(target) {
342 for (var _len = arguments.length, others = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
343 others[_key - 1] = arguments[_key];
344 }
345
346 return _extends.apply(undefined, [target].concat(others));
347 }
348
349 /**
350 * Pick given properties from the target object.
351 *
352 * @param {Object} target
353 * @param {Array} properties
354 *
355 * @return {Object} target
356 */
357 function pick(target, properties) {
358
359 var result = {};
360
361 var obj = Object(target);
362
363 forEach(properties, function (prop) {
364
365 if (prop in obj) {
366 result[prop] = target[prop];
367 }
368 });
369
370 return result;
371 }
372
373 /**
374 * Pick all target properties, excluding the given ones.
375 *
376 * @param {Object} target
377 * @param {Array} properties
378 *
379 * @return {Object} target
380 */
381 function omit(target, properties) {
382
383 var result = {};
384
385 var obj = Object(target);
386
387 forEach(obj, function (prop, key) {
388
389 if (properties.indexOf(key) === -1) {
390 result[key] = prop;
391 }
392 });
393
394 return result;
395 }
396
397 /**
398 * Set attribute `name` to `val`, or get attr `name`.
399 *
400 * @param {Element} el
401 * @param {String} name
402 * @param {String} [val]
403 * @api public
404 */
405 function attr(el, name, val) {
406 // get
407 if (arguments.length == 2) {
408 return el.getAttribute(name);
409 }
410
411 // remove
412 if (val === null) {
413 return el.removeAttribute(name);
414 }
415
416 // set
417 el.setAttribute(name, val);
418
419 return el;
420 }
421
422 var indexOf = [].indexOf;
423
424 var indexof = function(arr, obj){
425 if (indexOf) return arr.indexOf(obj);
426 for (var i = 0; i < arr.length; ++i) {
427 if (arr[i] === obj) return i;
428 }
429 return -1;
430 };
431
432 /**
433 * Taken from https://github.com/component/classes
434 *
435 * Without the component bits.
436 */
437
438 /**
439 * Whitespace regexp.
440 */
441
442 var re = /\s+/;
443
444 /**
445 * toString reference.
446 */
447
448 var toString = Object.prototype.toString;
449
450 /**
451 * Wrap `el` in a `ClassList`.
452 *
453 * @param {Element} el
454 * @return {ClassList}
455 * @api public
456 */
457
458 function classes(el) {
459 return new ClassList(el);
460 }
461
462 /**
463 * Initialize a new ClassList for `el`.
464 *
465 * @param {Element} el
466 * @api private
467 */
468
469 function ClassList(el) {
470 if (!el || !el.nodeType) {
471 throw new Error('A DOM element reference is required');
472 }
473 this.el = el;
474 this.list = el.classList;
475 }
476
477 /**
478 * Add class `name` if not already present.
479 *
480 * @param {String} name
481 * @return {ClassList}
482 * @api public
483 */
484
485 ClassList.prototype.add = function (name) {
486 // classList
487 if (this.list) {
488 this.list.add(name);
489 return this;
490 }
491
492 // fallback
493 var arr = this.array();
494 var i = indexof(arr, name);
495 if (!~i) arr.push(name);
496 this.el.className = arr.join(' ');
497 return this;
498 };
499
500 /**
501 * Remove class `name` when present, or
502 * pass a regular expression to remove
503 * any which match.
504 *
505 * @param {String|RegExp} name
506 * @return {ClassList}
507 * @api public
508 */
509
510 ClassList.prototype.remove = function (name) {
511 if ('[object RegExp]' == toString.call(name)) {
512 return this.removeMatching(name);
513 }
514
515 // classList
516 if (this.list) {
517 this.list.remove(name);
518 return this;
519 }
520
521 // fallback
522 var arr = this.array();
523 var i = indexof(arr, name);
524 if (~i) arr.splice(i, 1);
525 this.el.className = arr.join(' ');
526 return this;
527 };
528
529 /**
530 * Remove all classes matching `re`.
531 *
532 * @param {RegExp} re
533 * @return {ClassList}
534 * @api private
535 */
536
537 ClassList.prototype.removeMatching = function (re) {
538 var arr = this.array();
539 for (var i = 0; i < arr.length; i++) {
540 if (re.test(arr[i])) {
541 this.remove(arr[i]);
542 }
543 }
544 return this;
545 };
546
547 /**
548 * Toggle class `name`, can force state via `force`.
549 *
550 * For browsers that support classList, but do not support `force` yet,
551 * the mistake will be detected and corrected.
552 *
553 * @param {String} name
554 * @param {Boolean} force
555 * @return {ClassList}
556 * @api public
557 */
558
559 ClassList.prototype.toggle = function (name, force) {
560 // classList
561 if (this.list) {
562 if ('undefined' !== typeof force) {
563 if (force !== this.list.toggle(name, force)) {
564 this.list.toggle(name); // toggle again to correct
565 }
566 } else {
567 this.list.toggle(name);
568 }
569 return this;
570 }
571
572 // fallback
573 if ('undefined' !== typeof force) {
574 if (!force) {
575 this.remove(name);
576 } else {
577 this.add(name);
578 }
579 } else {
580 if (this.has(name)) {
581 this.remove(name);
582 } else {
583 this.add(name);
584 }
585 }
586
587 return this;
588 };
589
590 /**
591 * Return an array of classes.
592 *
593 * @return {Array}
594 * @api public
595 */
596
597 ClassList.prototype.array = function () {
598 var className = this.el.getAttribute('class') || '';
599 var str = className.replace(/^\s+|\s+$/g, '');
600 var arr = str.split(re);
601 if ('' === arr[0]) arr.shift();
602 return arr;
603 };
604
605 /**
606 * Check if class `name` is present.
607 *
608 * @param {String} name
609 * @return {ClassList}
610 * @api public
611 */
612
613 ClassList.prototype.has = ClassList.prototype.contains = function (name) {
614 return this.list ? this.list.contains(name) : !!~indexof(this.array(), name);
615 };
616
617 /**
618 * Remove all children from the given element.
619 */
620 function clear(el) {
621
622 var c;
623
624 while (el.childNodes.length) {
625 c = el.childNodes[0];
626 el.removeChild(c);
627 }
628
629 return el;
630 }
631
632 /**
633 * Element prototype.
634 */
635
636 var proto = Element.prototype;
637
638 /**
639 * Vendor function.
640 */
641
642 var vendor = proto.matchesSelector
643 || proto.webkitMatchesSelector
644 || proto.mozMatchesSelector
645 || proto.msMatchesSelector
646 || proto.oMatchesSelector;
647
648 /**
649 * Expose `match()`.
650 */
651
652 var matchesSelector = match;
653
654 /**
655 * Match `el` to `selector`.
656 *
657 * @param {Element} el
658 * @param {String} selector
659 * @return {Boolean}
660 * @api public
661 */
662
663 function match(el, selector) {
664 if (vendor) return vendor.call(el, selector);
665 var nodes = el.parentNode.querySelectorAll(selector);
666 for (var i = 0; i < nodes.length; ++i) {
667 if (nodes[i] == el) return true;
668 }
669 return false;
670 }
671
672 var closest = function (element, selector, checkYoSelf) {
673 var parent = checkYoSelf ? element : element.parentNode;
674
675 while (parent && parent !== document) {
676 if (matchesSelector(parent, selector)) return parent;
677 parent = parent.parentNode;
678 }
679 };
680
681 var bind$1 = window.addEventListener ? 'addEventListener' : 'attachEvent',
682 unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent',
683 prefix = bind$1 !== 'addEventListener' ? 'on' : '';
684
685 /**
686 * Bind `el` event `type` to `fn`.
687 *
688 * @param {Element} el
689 * @param {String} type
690 * @param {Function} fn
691 * @param {Boolean} capture
692 * @return {Function}
693 * @api public
694 */
695
696 var bind_1 = function(el, type, fn, capture){
697 el[bind$1](prefix + type, fn, capture || false);
698 return fn;
699 };
700
701 /**
702 * Unbind `el` event `type`'s callback `fn`.
703 *
704 * @param {Element} el
705 * @param {String} type
706 * @param {Function} fn
707 * @param {Boolean} capture
708 * @return {Function}
709 * @api public
710 */
711
712 var unbind_1 = function(el, type, fn, capture){
713 el[unbind](prefix + type, fn, capture || false);
714 return fn;
715 };
716
717 var componentEvent = {
718 bind: bind_1,
719 unbind: unbind_1
720 };
721
722 /**
723 * Module dependencies.
724 */
725
726
727
728 /**
729 * Delegate event `type` to `selector`
730 * and invoke `fn(e)`. A callback function
731 * is returned which may be passed to `.unbind()`.
732 *
733 * @param {Element} el
734 * @param {String} selector
735 * @param {String} type
736 * @param {Function} fn
737 * @param {Boolean} capture
738 * @return {Function}
739 * @api public
740 */
741
742 // Some events don't bubble, so we want to bind to the capture phase instead
743 // when delegating.
744 var forceCaptureEvents = ['focus', 'blur'];
745
746 var bind$1$1 = function(el, selector, type, fn, capture){
747 if (forceCaptureEvents.indexOf(type) !== -1) capture = true;
748
749 return componentEvent.bind(el, type, function(e){
750 var target = e.target || e.srcElement;
751 e.delegateTarget = closest(target, selector, true, el);
752 if (e.delegateTarget) fn.call(el, e);
753 }, capture);
754 };
755
756 /**
757 * Unbind event `type`'s callback `fn`.
758 *
759 * @param {Element} el
760 * @param {String} type
761 * @param {Function} fn
762 * @param {Boolean} capture
763 * @api public
764 */
765
766 var unbind$1 = function(el, type, fn, capture){
767 if (forceCaptureEvents.indexOf(type) !== -1) capture = true;
768
769 componentEvent.unbind(el, type, fn, capture);
770 };
771
772 var delegateEvents = {
773 bind: bind$1$1,
774 unbind: unbind$1
775 };
776
777 /**
778 * Expose `parse`.
779 */
780
781 var domify = parse;
782
783 /**
784 * Tests for browser support.
785 */
786
787 var innerHTMLBug = false;
788 var bugTestDiv;
789 if (typeof document !== 'undefined') {
790 bugTestDiv = document.createElement('div');
791 // Setup
792 bugTestDiv.innerHTML = ' <link/><table></table><a href="/a">a</a><input type="checkbox"/>';
793 // Make sure that link elements get serialized correctly by innerHTML
794 // This requires a wrapper element in IE
795 innerHTMLBug = !bugTestDiv.getElementsByTagName('link').length;
796 bugTestDiv = undefined;
797 }
798
799 /**
800 * Wrap map from jquery.
801 */
802
803 var map$1 = {
804 legend: [1, '<fieldset>', '</fieldset>'],
805 tr: [2, '<table><tbody>', '</tbody></table>'],
806 col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
807 // for script/link/style tags to work in IE6-8, you have to wrap
808 // in a div with a non-whitespace character in front, ha!
809 _default: innerHTMLBug ? [1, 'X<div>', '</div>'] : [0, '', '']
810 };
811
812 map$1.td =
813 map$1.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
814
815 map$1.option =
816 map$1.optgroup = [1, '<select multiple="multiple">', '</select>'];
817
818 map$1.thead =
819 map$1.tbody =
820 map$1.colgroup =
821 map$1.caption =
822 map$1.tfoot = [1, '<table>', '</table>'];
823
824 map$1.polyline =
825 map$1.ellipse =
826 map$1.polygon =
827 map$1.circle =
828 map$1.text =
829 map$1.line =
830 map$1.path =
831 map$1.rect =
832 map$1.g = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'];
833
834 /**
835 * Parse `html` and return a DOM Node instance, which could be a TextNode,
836 * HTML DOM Node of some kind (<div> for example), or a DocumentFragment
837 * instance, depending on the contents of the `html` string.
838 *
839 * @param {String} html - HTML string to "domify"
840 * @param {Document} doc - The `document` instance to create the Node for
841 * @return {DOMNode} the TextNode, DOM Node, or DocumentFragment instance
842 * @api private
843 */
844
845 function parse(html, doc) {
846 if ('string' != typeof html) throw new TypeError('String expected');
847
848 // default to the global `document` object
849 if (!doc) doc = document;
850
851 // tag name
852 var m = /<([\w:]+)/.exec(html);
853 if (!m) return doc.createTextNode(html);
854
855 html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace
856
857 var tag = m[1];
858
859 // body support
860 if (tag == 'body') {
861 var el = doc.createElement('html');
862 el.innerHTML = html;
863 return el.removeChild(el.lastChild);
864 }
865
866 // wrap map
867 var wrap = map$1[tag] || map$1._default;
868 var depth = wrap[0];
869 var prefix = wrap[1];
870 var suffix = wrap[2];
871 var el = doc.createElement('div');
872 el.innerHTML = prefix + html + suffix;
873 while (depth--) el = el.lastChild;
874
875 // one element
876 if (el.firstChild == el.lastChild) {
877 return el.removeChild(el.firstChild);
878 }
879
880 // several elements
881 var fragment = doc.createDocumentFragment();
882 while (el.firstChild) {
883 fragment.appendChild(el.removeChild(el.firstChild));
884 }
885
886 return fragment;
887 }
888
889 var proto$1 = typeof Element !== 'undefined' ? Element.prototype : {};
890 var vendor$1 = proto$1.matches
891 || proto$1.matchesSelector
892 || proto$1.webkitMatchesSelector
893 || proto$1.mozMatchesSelector
894 || proto$1.msMatchesSelector
895 || proto$1.oMatchesSelector;
896
897 var matchesSelector$1 = match$1;
898
899 /**
900 * Match `el` to `selector`.
901 *
902 * @param {Element} el
903 * @param {String} selector
904 * @return {Boolean}
905 * @api public
906 */
907
908 function match$1(el, selector) {
909 if (!el || el.nodeType !== 1) return false;
910 if (vendor$1) return vendor$1.call(el, selector);
911 var nodes = el.parentNode.querySelectorAll(selector);
912 for (var i = 0; i < nodes.length; i++) {
913 if (nodes[i] == el) return true;
914 }
915 return false;
916 }
917
918 function query(selector, el) {
919 el = el || document;
920
921 return el.querySelector(selector);
922 }
923
924 function remove(el) {
925 el.parentNode && el.parentNode.removeChild(el);
926 }
927
928 function ensureImported(element, target) {
929
930 if (element.ownerDocument !== target.ownerDocument) {
931 try {
932 // may fail on webkit
933 return target.ownerDocument.importNode(element, true);
934 } catch (e) {
935 // ignore
936 }
937 }
938
939 return element;
940 }
941
942 /**
943 * appendTo utility
944 */
945
946 /**
947 * Append a node to a target element and return the appended node.
948 *
949 * @param {SVGElement} element
950 * @param {SVGElement} target
951 *
952 * @return {SVGElement} the appended node
953 */
954 function appendTo(element, target) {
955 return target.appendChild(ensureImported(element, target));
956 }
957
958 /**
959 * append utility
960 */
961
962 /**
963 * Append a node to an element
964 *
965 * @param {SVGElement} element
966 * @param {SVGElement} node
967 *
968 * @return {SVGElement} the element
969 */
970 function append(target, node) {
971 appendTo(node, target);
972 return target;
973 }
974
975 /**
976 * attribute accessor utility
977 */
978
979 var LENGTH_ATTR = 2;
980
981 var CSS_PROPERTIES = {
982 'alignment-baseline': 1,
983 'baseline-shift': 1,
984 'clip': 1,
985 'clip-path': 1,
986 'clip-rule': 1,
987 'color': 1,
988 'color-interpolation': 1,
989 'color-interpolation-filters': 1,
990 'color-profile': 1,
991 'color-rendering': 1,
992 'cursor': 1,
993 'direction': 1,
994 'display': 1,
995 'dominant-baseline': 1,
996 'enable-background': 1,
997 'fill': 1,
998 'fill-opacity': 1,
999 'fill-rule': 1,
1000 'filter': 1,
1001 'flood-color': 1,
1002 'flood-opacity': 1,
1003 'font': 1,
1004 'font-family': 1,
1005 'font-size': LENGTH_ATTR,
1006 'font-size-adjust': 1,
1007 'font-stretch': 1,
1008 'font-style': 1,
1009 'font-variant': 1,
1010 'font-weight': 1,
1011 'glyph-orientation-horizontal': 1,
1012 'glyph-orientation-vertical': 1,
1013 'image-rendering': 1,
1014 'kerning': 1,
1015 'letter-spacing': 1,
1016 'lighting-color': 1,
1017 'marker': 1,
1018 'marker-end': 1,
1019 'marker-mid': 1,
1020 'marker-start': 1,
1021 'mask': 1,
1022 'opacity': 1,
1023 'overflow': 1,
1024 'pointer-events': 1,
1025 'shape-rendering': 1,
1026 'stop-color': 1,
1027 'stop-opacity': 1,
1028 'stroke': 1,
1029 'stroke-dasharray': 1,
1030 'stroke-dashoffset': 1,
1031 'stroke-linecap': 1,
1032 'stroke-linejoin': 1,
1033 'stroke-miterlimit': 1,
1034 'stroke-opacity': 1,
1035 'stroke-width': LENGTH_ATTR,
1036 'text-anchor': 1,
1037 'text-decoration': 1,
1038 'text-rendering': 1,
1039 'unicode-bidi': 1,
1040 'visibility': 1,
1041 'word-spacing': 1,
1042 'writing-mode': 1
1043 };
1044
1045
1046 function getAttribute(node, name) {
1047 if (CSS_PROPERTIES[name]) {
1048 return node.style[name];
1049 } else {
1050 return node.getAttributeNS(null, name);
1051 }
1052 }
1053
1054 function setAttribute(node, name, value) {
1055 var hyphenated = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
1056
1057 var type = CSS_PROPERTIES[hyphenated];
1058
1059 if (type) {
1060 // append pixel unit, unless present
1061 if (type === LENGTH_ATTR && typeof value === 'number') {
1062 value = String(value) + 'px';
1063 }
1064
1065 node.style[hyphenated] = value;
1066 } else {
1067 node.setAttributeNS(null, name, value);
1068 }
1069 }
1070
1071 function setAttributes(node, attrs) {
1072
1073 var names = Object.keys(attrs), i, name;
1074
1075 for (i = 0, name; (name = names[i]); i++) {
1076 setAttribute(node, name, attrs[name]);
1077 }
1078 }
1079
1080 /**
1081 * Gets or sets raw attributes on a node.
1082 *
1083 * @param {SVGElement} node
1084 * @param {Object} [attrs]
1085 * @param {String} [name]
1086 * @param {String} [value]
1087 *
1088 * @return {String}
1089 */
1090 function attr$1(node, name, value) {
1091 if (typeof name === 'string') {
1092 if (value !== undefined) {
1093 setAttribute(node, name, value);
1094 } else {
1095 return getAttribute(node, name);
1096 }
1097 } else {
1098 setAttributes(node, name);
1099 }
1100
1101 return node;
1102 }
1103
1104 /**
1105 * Clear utility
1106 */
1107 function index(arr, obj) {
1108 if (arr.indexOf) {
1109 return arr.indexOf(obj);
1110 }
1111
1112
1113 for (var i = 0; i < arr.length; ++i) {
1114 if (arr[i] === obj) {
1115 return i;
1116 }
1117 }
1118
1119 return -1;
1120 }
1121
1122 var re$1 = /\s+/;
1123
1124 var toString$1 = Object.prototype.toString;
1125
1126 function defined(o) {
1127 return typeof o !== 'undefined';
1128 }
1129
1130 /**
1131 * Wrap `el` in a `ClassList`.
1132 *
1133 * @param {Element} el
1134 * @return {ClassList}
1135 * @api public
1136 */
1137
1138 function classes$1(el) {
1139 return new ClassList$1(el);
1140 }
1141
1142 function ClassList$1(el) {
1143 if (!el || !el.nodeType) {
1144 throw new Error('A DOM element reference is required');
1145 }
1146 this.el = el;
1147 this.list = el.classList;
1148 }
1149
1150 /**
1151 * Add class `name` if not already present.
1152 *
1153 * @param {String} name
1154 * @return {ClassList}
1155 * @api public
1156 */
1157
1158 ClassList$1.prototype.add = function(name) {
1159
1160 // classList
1161 if (this.list) {
1162 this.list.add(name);
1163 return this;
1164 }
1165
1166 // fallback
1167 var arr = this.array();
1168 var i = index(arr, name);
1169 if (!~i) {
1170 arr.push(name);
1171 }
1172
1173 if (defined(this.el.className.baseVal)) {
1174 this.el.className.baseVal = arr.join(' ');
1175 } else {
1176 this.el.className = arr.join(' ');
1177 }
1178
1179 return this;
1180 };
1181
1182 /**
1183 * Remove class `name` when present, or
1184 * pass a regular expression to remove
1185 * any which match.
1186 *
1187 * @param {String|RegExp} name
1188 * @return {ClassList}
1189 * @api public
1190 */
1191
1192 ClassList$1.prototype.remove = function(name) {
1193 if ('[object RegExp]' === toString$1.call(name)) {
1194 return this.removeMatching(name);
1195 }
1196
1197 // classList
1198 if (this.list) {
1199 this.list.remove(name);
1200 return this;
1201 }
1202
1203 // fallback
1204 var arr = this.array();
1205 var i = index(arr, name);
1206 if (~i) {
1207 arr.splice(i, 1);
1208 }
1209 this.el.className.baseVal = arr.join(' ');
1210 return this;
1211 };
1212
1213 /**
1214 * Remove all classes matching `re`.
1215 *
1216 * @param {RegExp} re
1217 * @return {ClassList}
1218 * @api private
1219 */
1220
1221 ClassList$1.prototype.removeMatching = function(re) {
1222 var arr = this.array();
1223 for (var i = 0; i < arr.length; i++) {
1224 if (re.test(arr[i])) {
1225 this.remove(arr[i]);
1226 }
1227 }
1228 return this;
1229 };
1230
1231 /**
1232 * Toggle class `name`, can force state via `force`.
1233 *
1234 * For browsers that support classList, but do not support `force` yet,
1235 * the mistake will be detected and corrected.
1236 *
1237 * @param {String} name
1238 * @param {Boolean} force
1239 * @return {ClassList}
1240 * @api public
1241 */
1242
1243 ClassList$1.prototype.toggle = function(name, force) {
1244 // classList
1245 if (this.list) {
1246 if (defined(force)) {
1247 if (force !== this.list.toggle(name, force)) {
1248 this.list.toggle(name); // toggle again to correct
1249 }
1250 } else {
1251 this.list.toggle(name);
1252 }
1253 return this;
1254 }
1255
1256 // fallback
1257 if (defined(force)) {
1258 if (!force) {
1259 this.remove(name);
1260 } else {
1261 this.add(name);
1262 }
1263 } else {
1264 if (this.has(name)) {
1265 this.remove(name);
1266 } else {
1267 this.add(name);
1268 }
1269 }
1270
1271 return this;
1272 };
1273
1274 /**
1275 * Return an array of classes.
1276 *
1277 * @return {Array}
1278 * @api public
1279 */
1280
1281 ClassList$1.prototype.array = function() {
1282 var className = this.el.getAttribute('class') || '';
1283 var str = className.replace(/^\s+|\s+$/g, '');
1284 var arr = str.split(re$1);
1285 if ('' === arr[0]) {
1286 arr.shift();
1287 }
1288 return arr;
1289 };
1290
1291 /**
1292 * Check if class `name` is present.
1293 *
1294 * @param {String} name
1295 * @return {ClassList}
1296 * @api public
1297 */
1298
1299 ClassList$1.prototype.has =
1300 ClassList$1.prototype.contains = function(name) {
1301 return (
1302 this.list ?
1303 this.list.contains(name) :
1304 !! ~index(this.array(), name)
1305 );
1306 };
1307
1308 function remove$1(element) {
1309 var parent = element.parentNode;
1310
1311 if (parent) {
1312 parent.removeChild(element);
1313 }
1314
1315 return element;
1316 }
1317
1318 /**
1319 * Clear utility
1320 */
1321
1322 /**
1323 * Removes all children from the given element
1324 *
1325 * @param {DOMElement} element
1326 * @return {DOMElement} the element (for chaining)
1327 */
1328 function clear$1(element) {
1329 var child;
1330
1331 while ((child = element.firstChild)) {
1332 remove$1(child);
1333 }
1334
1335 return element;
1336 }
1337
1338 var ns = {
1339 svg: 'http://www.w3.org/2000/svg'
1340 };
1341
1342 /**
1343 * DOM parsing utility
1344 */
1345
1346 var SVG_START = '<svg xmlns="' + ns.svg + '"';
1347
1348 function parse$1(svg) {
1349
1350 var unwrap = false;
1351
1352 // ensure we import a valid svg document
1353 if (svg.substring(0, 4) === '<svg') {
1354 if (svg.indexOf(ns.svg) === -1) {
1355 svg = SVG_START + svg.substring(4);
1356 }
1357 } else {
1358 // namespace svg
1359 svg = SVG_START + '>' + svg + '</svg>';
1360 unwrap = true;
1361 }
1362
1363 var parsed = parseDocument(svg);
1364
1365 if (!unwrap) {
1366 return parsed;
1367 }
1368
1369 var fragment = document.createDocumentFragment();
1370
1371 var parent = parsed.firstChild;
1372
1373 while (parent.firstChild) {
1374 fragment.appendChild(parent.firstChild);
1375 }
1376
1377 return fragment;
1378 }
1379
1380 function parseDocument(svg) {
1381
1382 var parser;
1383
1384 // parse
1385 parser = new DOMParser();
1386 parser.async = false;
1387
1388 return parser.parseFromString(svg, 'text/xml');
1389 }
1390
1391 /**
1392 * Create utility for SVG elements
1393 */
1394
1395
1396 /**
1397 * Create a specific type from name or SVG markup.
1398 *
1399 * @param {String} name the name or markup of the element
1400 * @param {Object} [attrs] attributes to set on the element
1401 *
1402 * @returns {SVGElement}
1403 */
1404 function create(name, attrs) {
1405 var element;
1406
1407 if (name.charAt(0) === '<') {
1408 element = parse$1(name).firstChild;
1409 element = document.importNode(element, true);
1410 } else {
1411 element = document.createElementNS(ns.svg, name);
1412 }
1413
1414 if (attrs) {
1415 attr$1(element, attrs);
1416 }
1417
1418 return element;
1419 }
1420
1421 /**
1422 * Geometry helpers
1423 */
1424
1425 // fake node used to instantiate svg geometry elements
1426 var node = create('svg');
1427
1428 function extend(object, props) {
1429 var i, k, keys = Object.keys(props);
1430
1431 for (i = 0; (k = keys[i]); i++) {
1432 object[k] = props[k];
1433 }
1434
1435 return object;
1436 }
1437
1438 function createMatrix(a, b, c, d, e, f) {
1439 var matrix = node.createSVGMatrix();
1440
1441 switch (arguments.length) {
1442 case 0:
1443 return matrix;
1444 case 6:
1445 a = {
1446 a: a,
1447 b: b,
1448 c: c,
1449 d: d,
1450 e: e,
1451 f: f
1452 };
1453 break;
1454 }
1455
1456 return extend(matrix, a);
1457 }
1458
1459 function createTransform(matrix) {
1460 if (matrix) {
1461 return node.createSVGTransformFromMatrix(matrix);
1462 } else {
1463 return node.createSVGTransform();
1464 }
1465 }
1466
1467 /**
1468 * Serialization util
1469 */
1470
1471 var TEXT_ENTITIES = /([&<>]{1})/g;
1472 var ATTR_ENTITIES = /([\n\r"]{1})/g;
1473
1474 var ENTITY_REPLACEMENT = {
1475 '&': '&amp;',
1476 '<': '&lt;',
1477 '>': '&gt;',
1478 '"': '\''
1479 };
1480
1481 function escape(str, pattern) {
1482
1483 function replaceFn(match, entity) {
1484 return ENTITY_REPLACEMENT[entity] || entity;
1485 }
1486
1487 return str.replace(pattern, replaceFn);
1488 }
1489
1490 function serialize(node, output) {
1491
1492 var i, len, attrMap, attrNode, childNodes;
1493
1494 switch (node.nodeType) {
1495 // TEXT
1496 case 3:
1497 // replace special XML characters
1498 output.push(escape(node.textContent, TEXT_ENTITIES));
1499 break;
1500
1501 // ELEMENT
1502 case 1:
1503 output.push('<', node.tagName);
1504
1505 if (node.hasAttributes()) {
1506 attrMap = node.attributes;
1507 for (i = 0, len = attrMap.length; i < len; ++i) {
1508 attrNode = attrMap.item(i);
1509 output.push(' ', attrNode.name, '="', escape(attrNode.value, ATTR_ENTITIES), '"');
1510 }
1511 }
1512
1513 if (node.hasChildNodes()) {
1514 output.push('>');
1515 childNodes = node.childNodes;
1516 for (i = 0, len = childNodes.length; i < len; ++i) {
1517 serialize(childNodes.item(i), output);
1518 }
1519 output.push('</', node.tagName, '>');
1520 } else {
1521 output.push('/>');
1522 }
1523 break;
1524
1525 // COMMENT
1526 case 8:
1527 output.push('<!--', escape(node.nodeValue, TEXT_ENTITIES), '-->');
1528 break;
1529
1530 // CDATA
1531 case 4:
1532 output.push('<![CDATA[', node.nodeValue, ']]>');
1533 break;
1534
1535 default:
1536 throw new Error('unable to handle node ' + node.nodeType);
1537 }
1538
1539 return output;
1540 }
1541
1542 /**
1543 * innerHTML like functionality for SVG elements.
1544 * based on innerSVG (https://code.google.com/p/innersvg)
1545 */
1546
1547
1548 function set(element, svg) {
1549
1550 var parsed = parse$1(svg);
1551
1552 // clear element contents
1553 clear$1(element);
1554
1555 if (!svg) {
1556 return;
1557 }
1558
1559 if (!isFragment(parsed)) {
1560 // extract <svg> from parsed document
1561 parsed = parsed.documentElement;
1562 }
1563
1564 var nodes = slice$1(parsed.childNodes);
1565
1566 // import + append each node
1567 for (var i = 0; i < nodes.length; i++) {
1568 appendTo(nodes[i], element);
1569 }
1570
1571 }
1572
1573 function get(element) {
1574 var child = element.firstChild,
1575 output = [];
1576
1577 while (child) {
1578 serialize(child, output);
1579 child = child.nextSibling;
1580 }
1581
1582 return output.join('');
1583 }
1584
1585 function isFragment(node) {
1586 return node.nodeName === '#document-fragment';
1587 }
1588
1589 function innerSVG(element, svg) {
1590
1591 if (svg !== undefined) {
1592
1593 try {
1594 set(element, svg);
1595 } catch (e) {
1596 throw new Error('error parsing SVG: ' + e.message);
1597 }
1598
1599 return element;
1600 } else {
1601 return get(element);
1602 }
1603 }
1604
1605
1606 function slice$1(arr) {
1607 return Array.prototype.slice.call(arr);
1608 }
1609
1610 /**
1611 * transform accessor utility
1612 */
1613
1614 function wrapMatrix(transformList, transform) {
1615 if (transform instanceof SVGMatrix) {
1616 return transformList.createSVGTransformFromMatrix(transform);
1617 } else {
1618 return transform;
1619 }
1620 }
1621
1622 function setTransforms(transformList, transforms) {
1623 var i, t;
1624
1625 transformList.clear();
1626
1627 for (i = 0; (t = transforms[i]); i++) {
1628 transformList.appendItem(wrapMatrix(transformList, t));
1629 }
1630
1631 transformList.consolidate();
1632 }
1633
1634 function transform(node, transforms) {
1635 var transformList = node.transform.baseVal;
1636
1637 if (arguments.length === 1) {
1638 return transformList.consolidate();
1639 } else {
1640 if (transforms.length) {
1641 setTransforms(transformList, transforms);
1642 } else {
1643 transformList.initialize(wrapMatrix(transformList, transforms));
1644 }
1645 }
1646 }
1647
1648 var CLASS_PATTERN = /^class /;
1649
1650 function isClass(fn) {
1651 return CLASS_PATTERN.test(fn.toString());
1652 }
1653
1654 function isArray$1(obj) {
1655 return Object.prototype.toString.call(obj) === '[object Array]';
1656 }
1657
1658 function annotate() {
1659 var args = Array.prototype.slice.call(arguments);
1660
1661 if (args.length === 1 && isArray$1(args[0])) {
1662 args = args[0];
1663 }
1664
1665 var fn = args.pop();
1666
1667 fn.$inject = args;
1668
1669 return fn;
1670 }
1671
1672 // Current limitations:
1673 // - can't put into "function arg" comments
1674 // function /* (no parenthesis like this) */ (){}
1675 // function abc( /* xx (no parenthesis like this) */ a, b) {}
1676 //
1677 // Just put the comment before function or inside:
1678 // /* (((this is fine))) */ function(a, b) {}
1679 // function abc(a) { /* (((this is fine))) */}
1680 //
1681 // - can't reliably auto-annotate constructor; we'll match the
1682 // first constructor(...) pattern found which may be the one
1683 // of a nested class, too.
1684
1685 var CONSTRUCTOR_ARGS = /constructor\s*[^(]*\(\s*([^)]*)\)/m;
1686 var FN_ARGS = /^function\s*[^(]*\(\s*([^)]*)\)/m;
1687 var FN_ARG = /\/\*([^*]*)\*\//m;
1688
1689 function parse$2(fn) {
1690
1691 if (typeof fn !== 'function') {
1692 throw new Error('Cannot annotate "' + fn + '". Expected a function!');
1693 }
1694
1695 var match = fn.toString().match(isClass(fn) ? CONSTRUCTOR_ARGS : FN_ARGS);
1696
1697 // may parse class without constructor
1698 if (!match) {
1699 return [];
1700 }
1701
1702 return match[1] && match[1].split(',').map(function (arg) {
1703 match = arg.match(FN_ARG);
1704 return match ? match[1].trim() : arg.trim();
1705 }) || [];
1706 }
1707
1708 function Module() {
1709 var providers = [];
1710
1711 this.factory = function (name, factory) {
1712 providers.push([name, 'factory', factory]);
1713 return this;
1714 };
1715
1716 this.value = function (name, value) {
1717 providers.push([name, 'value', value]);
1718 return this;
1719 };
1720
1721 this.type = function (name, type) {
1722 providers.push([name, 'type', type]);
1723 return this;
1724 };
1725
1726 this.forEach = function (iterator) {
1727 providers.forEach(iterator);
1728 };
1729 }
1730
1731 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
1732
1733 function _toConsumableArray$1(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
1734
1735 function Injector(modules, parent) {
1736 parent = parent || {
1737 get: function get(name, strict) {
1738 currentlyResolving.push(name);
1739
1740 if (strict === false) {
1741 return null;
1742 } else {
1743 throw error('No provider for "' + name + '"!');
1744 }
1745 }
1746 };
1747
1748 var currentlyResolving = [];
1749 var providers = this._providers = Object.create(parent._providers || null);
1750 var instances = this._instances = Object.create(null);
1751
1752 var self = instances.injector = this;
1753
1754 var error = function error(msg) {
1755 var stack = currentlyResolving.join(' -> ');
1756 currentlyResolving.length = 0;
1757 return new Error(stack ? msg + ' (Resolving: ' + stack + ')' : msg);
1758 };
1759
1760 /**
1761 * Return a named service.
1762 *
1763 * @param {String} name
1764 * @param {Boolean} [strict=true] if false, resolve missing services to null
1765 *
1766 * @return {Object}
1767 */
1768 var get = function get(name, strict) {
1769 if (!providers[name] && name.indexOf('.') !== -1) {
1770 var parts = name.split('.');
1771 var pivot = get(parts.shift());
1772
1773 while (parts.length) {
1774 pivot = pivot[parts.shift()];
1775 }
1776
1777 return pivot;
1778 }
1779
1780 if (hasProp(instances, name)) {
1781 return instances[name];
1782 }
1783
1784 if (hasProp(providers, name)) {
1785 if (currentlyResolving.indexOf(name) !== -1) {
1786 currentlyResolving.push(name);
1787 throw error('Cannot resolve circular dependency!');
1788 }
1789
1790 currentlyResolving.push(name);
1791 instances[name] = providers[name][0](providers[name][1]);
1792 currentlyResolving.pop();
1793
1794 return instances[name];
1795 }
1796
1797 return parent.get(name, strict);
1798 };
1799
1800 var fnDef = function fnDef(fn) {
1801 var locals = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1802
1803 if (typeof fn !== 'function') {
1804 if (isArray$1(fn)) {
1805 fn = annotate(fn.slice());
1806 } else {
1807 throw new Error('Cannot invoke "' + fn + '". Expected a function!');
1808 }
1809 }
1810
1811 var inject = fn.$inject || parse$2(fn);
1812 var dependencies = inject.map(function (dep) {
1813 if (hasProp(locals, dep)) {
1814 return locals[dep];
1815 } else {
1816 return get(dep);
1817 }
1818 });
1819
1820 return {
1821 fn: fn,
1822 dependencies: dependencies
1823 };
1824 };
1825
1826 var instantiate = function instantiate(Type) {
1827 var _fnDef = fnDef(Type),
1828 dependencies = _fnDef.dependencies,
1829 fn = _fnDef.fn;
1830
1831 return new (Function.prototype.bind.apply(fn, [null].concat(_toConsumableArray$1(dependencies))))();
1832 };
1833
1834 var invoke = function invoke(func, context, locals) {
1835 var _fnDef2 = fnDef(func, locals),
1836 dependencies = _fnDef2.dependencies,
1837 fn = _fnDef2.fn;
1838
1839 return fn.call.apply(fn, [context].concat(_toConsumableArray$1(dependencies)));
1840 };
1841
1842 var createPrivateInjectorFactory = function createPrivateInjectorFactory(privateChildInjector) {
1843 return annotate(function (key) {
1844 return privateChildInjector.get(key);
1845 });
1846 };
1847
1848 var createChild = function createChild(modules, forceNewInstances) {
1849 if (forceNewInstances && forceNewInstances.length) {
1850 var fromParentModule = Object.create(null);
1851 var matchedScopes = Object.create(null);
1852
1853 var privateInjectorsCache = [];
1854 var privateChildInjectors = [];
1855 var privateChildFactories = [];
1856
1857 var provider;
1858 var cacheIdx;
1859 var privateChildInjector;
1860 var privateChildInjectorFactory;
1861 for (var name in providers) {
1862 provider = providers[name];
1863
1864 if (forceNewInstances.indexOf(name) !== -1) {
1865 if (provider[2] === 'private') {
1866 cacheIdx = privateInjectorsCache.indexOf(provider[3]);
1867 if (cacheIdx === -1) {
1868 privateChildInjector = provider[3].createChild([], forceNewInstances);
1869 privateChildInjectorFactory = createPrivateInjectorFactory(privateChildInjector);
1870 privateInjectorsCache.push(provider[3]);
1871 privateChildInjectors.push(privateChildInjector);
1872 privateChildFactories.push(privateChildInjectorFactory);
1873 fromParentModule[name] = [privateChildInjectorFactory, name, 'private', privateChildInjector];
1874 } else {
1875 fromParentModule[name] = [privateChildFactories[cacheIdx], name, 'private', privateChildInjectors[cacheIdx]];
1876 }
1877 } else {
1878 fromParentModule[name] = [provider[2], provider[1]];
1879 }
1880 matchedScopes[name] = true;
1881 }
1882
1883 if ((provider[2] === 'factory' || provider[2] === 'type') && provider[1].$scope) {
1884 /* jshint -W083 */
1885 forceNewInstances.forEach(function (scope) {
1886 if (provider[1].$scope.indexOf(scope) !== -1) {
1887 fromParentModule[name] = [provider[2], provider[1]];
1888 matchedScopes[scope] = true;
1889 }
1890 });
1891 }
1892 }
1893
1894 forceNewInstances.forEach(function (scope) {
1895 if (!matchedScopes[scope]) {
1896 throw new Error('No provider for "' + scope + '". Cannot use provider from the parent!');
1897 }
1898 });
1899
1900 modules.unshift(fromParentModule);
1901 }
1902
1903 return new Injector(modules, self);
1904 };
1905
1906 var factoryMap = {
1907 factory: invoke,
1908 type: instantiate,
1909 value: function value(_value) {
1910 return _value;
1911 }
1912 };
1913
1914 modules.forEach(function (module) {
1915
1916 function arrayUnwrap(type, value) {
1917 if (type !== 'value' && isArray$1(value)) {
1918 value = annotate(value.slice());
1919 }
1920
1921 return value;
1922 }
1923
1924 // TODO(vojta): handle wrong inputs (modules)
1925 if (module instanceof Module) {
1926 module.forEach(function (provider) {
1927 var name = provider[0];
1928 var type = provider[1];
1929 var value = provider[2];
1930
1931 providers[name] = [factoryMap[type], arrayUnwrap(type, value), type];
1932 });
1933 } else if ((typeof module === 'undefined' ? 'undefined' : _typeof(module)) === 'object') {
1934 if (module.__exports__) {
1935 var clonedModule = Object.keys(module).reduce(function (m, key) {
1936 if (key.substring(0, 2) !== '__') {
1937 m[key] = module[key];
1938 }
1939 return m;
1940 }, Object.create(null));
1941
1942 var privateInjector = new Injector((module.__modules__ || []).concat([clonedModule]), self);
1943 var getFromPrivateInjector = annotate(function (key) {
1944 return privateInjector.get(key);
1945 });
1946 module.__exports__.forEach(function (key) {
1947 providers[key] = [getFromPrivateInjector, key, 'private', privateInjector];
1948 });
1949 } else {
1950 Object.keys(module).forEach(function (name) {
1951 if (module[name][2] === 'private') {
1952 providers[name] = module[name];
1953 return;
1954 }
1955
1956 var type = module[name][0];
1957 var value = module[name][1];
1958
1959 providers[name] = [factoryMap[type], arrayUnwrap(type, value), type];
1960 });
1961 }
1962 }
1963 });
1964
1965 // public API
1966 this.get = get;
1967 this.invoke = invoke;
1968 this.instantiate = instantiate;
1969 this.createChild = createChild;
1970 }
1971
1972 // helpers /////////////////
1973
1974 function hasProp(obj, prop) {
1975 return Object.hasOwnProperty.call(obj, prop);
1976 }
1977
1978 var DEFAULT_RENDER_PRIORITY = 1000;
1979
1980 /**
1981 * The base implementation of shape and connection renderers.
1982 *
1983 * @param {EventBus} eventBus
1984 * @param {Number} [renderPriority=1000]
1985 */
1986 function BaseRenderer(eventBus, renderPriority) {
1987 var self = this;
1988
1989 renderPriority = renderPriority || DEFAULT_RENDER_PRIORITY;
1990
1991 eventBus.on([ 'render.shape', 'render.connection' ], renderPriority, function(evt, context) {
1992 var type = evt.type,
1993 element = context.element,
1994 visuals = context.gfx;
1995
1996 if (self.canRender(element)) {
1997 if (type === 'render.shape') {
1998 return self.drawShape(visuals, element);
1999 } else {
2000 return self.drawConnection(visuals, element);
2001 }
2002 }
2003 });
2004
2005 eventBus.on([ 'render.getShapePath', 'render.getConnectionPath'], renderPriority, function(evt, element) {
2006 if (self.canRender(element)) {
2007 if (evt.type === 'render.getShapePath') {
2008 return self.getShapePath(element);
2009 } else {
2010 return self.getConnectionPath(element);
2011 }
2012 }
2013 });
2014 }
2015
2016 /**
2017 * Should check whether *this* renderer can render
2018 * the element/connection.
2019 *
2020 * @param {element} element
2021 *
2022 * @returns {Boolean}
2023 */
2024 BaseRenderer.prototype.canRender = function() {};
2025
2026 /**
2027 * Provides the shape's snap svg element to be drawn on the `canvas`.
2028 *
2029 * @param {djs.Graphics} visuals
2030 * @param {Shape} shape
2031 *
2032 * @returns {Snap.svg} [returns a Snap.svg paper element ]
2033 */
2034 BaseRenderer.prototype.drawShape = function() {};
2035
2036 /**
2037 * Provides the shape's snap svg element to be drawn on the `canvas`.
2038 *
2039 * @param {djs.Graphics} visuals
2040 * @param {Connection} connection
2041 *
2042 * @returns {Snap.svg} [returns a Snap.svg paper element ]
2043 */
2044 BaseRenderer.prototype.drawConnection = function() {};
2045
2046 /**
2047 * Gets the SVG path of a shape that represents it's visual bounds.
2048 *
2049 * @param {Shape} shape
2050 *
2051 * @return {string} svg path
2052 */
2053 BaseRenderer.prototype.getShapePath = function() {};
2054
2055 /**
2056 * Gets the SVG path of a connection that represents it's visual bounds.
2057 *
2058 * @param {Connection} connection
2059 *
2060 * @return {string} svg path
2061 */
2062 BaseRenderer.prototype.getConnectionPath = function() {};
2063
2064 function componentsToPath(elements) {
2065 return elements.join(',').replace(/,?([A-z]),?/g, '$1');
2066 }
2067
2068 function toSVGPoints(points) {
2069 var result = '';
2070
2071 for (var i = 0, p; (p = points[i]); i++) {
2072 result += p.x + ',' + p.y + ' ';
2073 }
2074
2075 return result;
2076 }
2077
2078 function createLine(points, attrs) {
2079
2080 var line = create('polyline');
2081 attr$1(line, { points: toSVGPoints(points) });
2082
2083 if (attrs) {
2084 attr$1(line, attrs);
2085 }
2086
2087 return line;
2088 }
2089
2090 function updateLine(gfx, points) {
2091 attr$1(gfx, { points: toSVGPoints(points) });
2092
2093 return gfx;
2094 }
2095
2096 // apply default renderer with lowest possible priority
2097 // so that it only kicks in if noone else could render
2098 var DEFAULT_RENDER_PRIORITY$1 = 1;
2099
2100 /**
2101 * The default renderer used for shapes and connections.
2102 *
2103 * @param {EventBus} eventBus
2104 * @param {Styles} styles
2105 */
2106 function DefaultRenderer(eventBus, styles) {
2107 //
2108 BaseRenderer.call(this, eventBus, DEFAULT_RENDER_PRIORITY$1);
2109
2110 this.CONNECTION_STYLE = styles.style([ 'no-fill' ], { strokeWidth: 5, stroke: 'fuchsia' });
2111 this.SHAPE_STYLE = styles.style({ fill: 'white', stroke: 'fuchsia', strokeWidth: 2 });
2112 }
2113
2114 inherits_browser(DefaultRenderer, BaseRenderer);
2115
2116
2117 DefaultRenderer.prototype.canRender = function() {
2118 return true;
2119 };
2120
2121 DefaultRenderer.prototype.drawShape = function drawShape(visuals, element) {
2122
2123 var rect = create('rect');
2124 attr$1(rect, {
2125 x: 0,
2126 y: 0,
2127 width: element.width || 0,
2128 height: element.height || 0
2129 });
2130 attr$1(rect, this.SHAPE_STYLE);
2131
2132 append(visuals, rect);
2133
2134 return rect;
2135 };
2136
2137 DefaultRenderer.prototype.drawConnection = function drawConnection(visuals, connection) {
2138
2139 var line = createLine(connection.waypoints, this.CONNECTION_STYLE);
2140 append(visuals, line);
2141
2142 return line;
2143 };
2144
2145 DefaultRenderer.prototype.getShapePath = function getShapePath(shape) {
2146
2147 var x = shape.x,
2148 y = shape.y,
2149 width = shape.width,
2150 height = shape.height;
2151
2152 var shapePath = [
2153 ['M', x, y],
2154 ['l', width, 0],
2155 ['l', 0, height],
2156 ['l', -width, 0],
2157 ['z']
2158 ];
2159
2160 return componentsToPath(shapePath);
2161 };
2162
2163 DefaultRenderer.prototype.getConnectionPath = function getConnectionPath(connection) {
2164 var waypoints = connection.waypoints;
2165
2166 var idx, point, connectionPath = [];
2167
2168 for (idx = 0; (point = waypoints[idx]); idx++) {
2169
2170 // take invisible docking into account
2171 // when creating the path
2172 point = point.original || point;
2173
2174 connectionPath.push([ idx === 0 ? 'M' : 'L', point.x, point.y ]);
2175 }
2176
2177 return componentsToPath(connectionPath);
2178 };
2179
2180
2181 DefaultRenderer.$inject = [ 'eventBus', 'styles' ];
2182
2183 /**
2184 * A component that manages shape styles
2185 */
2186 function Styles() {
2187
2188 var defaultTraits = {
2189
2190 'no-fill': {
2191 fill: 'none'
2192 },
2193 'no-border': {
2194 strokeOpacity: 0.0
2195 },
2196 'no-events': {
2197 pointerEvents: 'none'
2198 }
2199 };
2200
2201 var self = this;
2202
2203 /**
2204 * Builds a style definition from a className, a list of traits and an object of additional attributes.
2205 *
2206 * @param {String} className
2207 * @param {Array<String>} traits
2208 * @param {Object} additionalAttrs
2209 *
2210 * @return {Object} the style defintion
2211 */
2212 this.cls = function(className, traits, additionalAttrs) {
2213 var attrs = this.style(traits, additionalAttrs);
2214
2215 return assign(attrs, { 'class': className });
2216 };
2217
2218 /**
2219 * Builds a style definition from a list of traits and an object of additional attributes.
2220 *
2221 * @param {Array<String>} traits
2222 * @param {Object} additionalAttrs
2223 *
2224 * @return {Object} the style defintion
2225 */
2226 this.style = function(traits, additionalAttrs) {
2227
2228 if (!isArray(traits) && !additionalAttrs) {
2229 additionalAttrs = traits;
2230 traits = [];
2231 }
2232
2233 var attrs = reduce(traits, function(attrs, t) {
2234 return assign(attrs, defaultTraits[t] || {});
2235 }, {});
2236
2237 return additionalAttrs ? assign(attrs, additionalAttrs) : attrs;
2238 };
2239
2240 this.computeStyle = function(custom, traits, defaultStyles) {
2241 if (!isArray(traits)) {
2242 defaultStyles = traits;
2243 traits = [];
2244 }
2245
2246 return self.style(traits || [], assign({}, defaultStyles, custom || {}));
2247 };
2248 }
2249
2250 var DrawModule = {
2251 __init__: [ 'defaultRenderer' ],
2252 defaultRenderer: [ 'type', DefaultRenderer ],
2253 styles: [ 'type', Styles ]
2254 };
2255
2256 /**
2257 * Failsafe remove an element from a collection
2258 *
2259 * @param {Array<Object>} [collection]
2260 * @param {Object} [element]
2261 *
2262 * @return {Number} the previous index of the element
2263 */
2264 function remove$2(collection, element) {
2265
2266 if (!collection || !element) {
2267 return -1;
2268 }
2269
2270 var idx = collection.indexOf(element);
2271
2272 if (idx !== -1) {
2273 collection.splice(idx, 1);
2274 }
2275
2276 return idx;
2277 }
2278
2279 /**
2280 * Fail save add an element to the given connection, ensuring
2281 * it does not yet exist.
2282 *
2283 * @param {Array<Object>} collection
2284 * @param {Object} element
2285 * @param {Number} idx
2286 */
2287 function add(collection, element, idx) {
2288
2289 if (!collection || !element) {
2290 return;
2291 }
2292
2293 if (typeof idx !== 'number') {
2294 idx = -1;
2295 }
2296
2297 var currentIdx = collection.indexOf(element);
2298
2299 if (currentIdx !== -1) {
2300
2301 if (currentIdx === idx) {
2302 // nothing to do, position has not changed
2303 return;
2304 } else {
2305
2306 if (idx !== -1) {
2307 // remove from current position
2308 collection.splice(currentIdx, 1);
2309 } else {
2310 // already exists in collection
2311 return;
2312 }
2313 }
2314 }
2315
2316 if (idx !== -1) {
2317 // insert at specified position
2318 collection.splice(idx, 0, element);
2319 } else {
2320 // push to end
2321 collection.push(element);
2322 }
2323 }
2324
2325 /**
2326 * Returns the surrounding bbox for all elements in
2327 * the array or the element primitive.
2328 *
2329 * @param {Array<djs.model.Shape>|djs.model.Shape} elements
2330 * @param {Boolean} stopRecursion
2331 */
2332 function getBBox(elements, stopRecursion) {
2333
2334 stopRecursion = !!stopRecursion;
2335 if (!isArray(elements)) {
2336 elements = [elements];
2337 }
2338
2339 var minX,
2340 minY,
2341 maxX,
2342 maxY;
2343
2344 forEach(elements, function(element) {
2345
2346 // If element is a connection the bbox must be computed first
2347 var bbox = element;
2348 if (element.waypoints && !stopRecursion) {
2349 bbox = getBBox(element.waypoints, true);
2350 }
2351
2352 var x = bbox.x,
2353 y = bbox.y,
2354 height = bbox.height || 0,
2355 width = bbox.width || 0;
2356
2357 if (x < minX || minX === undefined) {
2358 minX = x;
2359 }
2360 if (y < minY || minY === undefined) {
2361 minY = y;
2362 }
2363
2364 if ((x + width) > maxX || maxX === undefined) {
2365 maxX = x + width;
2366 }
2367 if ((y + height) > maxY || maxY === undefined) {
2368 maxY = y + height;
2369 }
2370 });
2371
2372 return {
2373 x: minX,
2374 y: minY,
2375 height: maxY - minY,
2376 width: maxX - minX
2377 };
2378 }
2379
2380
2381 function getType(element) {
2382
2383 if ('waypoints' in element) {
2384 return 'connection';
2385 }
2386
2387 if ('x' in element) {
2388 return 'shape';
2389 }
2390
2391 return 'root';
2392 }
2393
2394 function round(number, resolution) {
2395 return Math.round(number * resolution) / resolution;
2396 }
2397
2398 function ensurePx(number) {
2399 return isNumber(number) ? number + 'px' : number;
2400 }
2401
2402 /**
2403 * Creates a HTML container element for a SVG element with
2404 * the given configuration
2405 *
2406 * @param {Object} options
2407 * @return {HTMLElement} the container element
2408 */
2409 function createContainer(options) {
2410
2411 options = assign({}, { width: '100%', height: '100%' }, options);
2412
2413 var container = options.container || document.body;
2414
2415 // create a <div> around the svg element with the respective size
2416 // this way we can always get the correct container size
2417 // (this is impossible for <svg> elements at the moment)
2418 var parent = document.createElement('div');
2419 parent.setAttribute('class', 'djs-container');
2420
2421 assign(parent.style, {
2422 position: 'relative',
2423 overflow: 'hidden',
2424 width: ensurePx(options.width),
2425 height: ensurePx(options.height)
2426 });
2427
2428 container.appendChild(parent);
2429
2430 return parent;
2431 }
2432
2433 function createGroup(parent, cls, childIndex) {
2434 var group = create('g');
2435 classes$1(group).add(cls);
2436
2437 var index = childIndex !== undefined ? childIndex : parent.childNodes.length - 1;
2438
2439 // must ensure second argument is node or _null_
2440 // cf. https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore
2441 parent.insertBefore(group, parent.childNodes[index] || null);
2442
2443 return group;
2444 }
2445
2446 var BASE_LAYER = 'base';
2447
2448
2449 var REQUIRED_MODEL_ATTRS = {
2450 shape: [ 'x', 'y', 'width', 'height' ],
2451 connection: [ 'waypoints' ]
2452 };
2453
2454 /**
2455 * The main drawing canvas.
2456 *
2457 * @class
2458 * @constructor
2459 *
2460 * @emits Canvas#canvas.init
2461 *
2462 * @param {Object} config
2463 * @param {EventBus} eventBus
2464 * @param {GraphicsFactory} graphicsFactory
2465 * @param {ElementRegistry} elementRegistry
2466 */
2467 function Canvas(config, eventBus, graphicsFactory, elementRegistry) {
2468
2469 this._eventBus = eventBus;
2470 this._elementRegistry = elementRegistry;
2471 this._graphicsFactory = graphicsFactory;
2472
2473 this._init(config || {});
2474 }
2475
2476 Canvas.$inject = [
2477 'config.canvas',
2478 'eventBus',
2479 'graphicsFactory',
2480 'elementRegistry'
2481 ];
2482
2483
2484 Canvas.prototype._init = function(config) {
2485
2486 var eventBus = this._eventBus;
2487
2488 // Creates a <svg> element that is wrapped into a <div>.
2489 // This way we are always able to correctly figure out the size of the svg element
2490 // by querying the parent node.
2491 //
2492 // (It is not possible to get the size of a svg element cross browser @ 2014-04-01)
2493 //
2494 // <div class="djs-container" style="width: {desired-width}, height: {desired-height}">
2495 // <svg width="100%" height="100%">
2496 // ...
2497 // </svg>
2498 // </div>
2499
2500 // html container
2501 var container = this._container = createContainer(config);
2502
2503 var svg = this._svg = create('svg');
2504 attr$1(svg, { width: '100%', height: '100%' });
2505
2506 append(container, svg);
2507
2508 var viewport = this._viewport = createGroup(svg, 'viewport');
2509
2510 this._layers = {};
2511
2512 // debounce canvas.viewbox.changed events
2513 // for smoother diagram interaction
2514 if (config.deferUpdate !== false) {
2515 this._viewboxChanged = debounce(bind(this._viewboxChanged, this), 300);
2516 }
2517
2518 eventBus.on('diagram.init', function() {
2519
2520 /**
2521 * An event indicating that the canvas is ready to be drawn on.
2522 *
2523 * @memberOf Canvas
2524 *
2525 * @event canvas.init
2526 *
2527 * @type {Object}
2528 * @property {SVGElement} svg the created svg element
2529 * @property {SVGElement} viewport the direct parent of diagram elements and shapes
2530 */
2531 eventBus.fire('canvas.init', {
2532 svg: svg,
2533 viewport: viewport
2534 });
2535
2536 }, this);
2537
2538 // reset viewbox on shape changes to
2539 // recompute the viewbox
2540 eventBus.on([
2541 'shape.added',
2542 'connection.added',
2543 'shape.removed',
2544 'connection.removed',
2545 'elements.changed'
2546 ], function() {
2547 delete this._cachedViewbox;
2548 }, this);
2549
2550 eventBus.on('diagram.destroy', 500, this._destroy, this);
2551 eventBus.on('diagram.clear', 500, this._clear, this);
2552 };
2553
2554 Canvas.prototype._destroy = function(emit) {
2555 this._eventBus.fire('canvas.destroy', {
2556 svg: this._svg,
2557 viewport: this._viewport
2558 });
2559
2560 var parent = this._container.parentNode;
2561
2562 if (parent) {
2563 parent.removeChild(this._container);
2564 }
2565
2566 delete this._svg;
2567 delete this._container;
2568 delete this._layers;
2569 delete this._rootElement;
2570 delete this._viewport;
2571 };
2572
2573 Canvas.prototype._clear = function() {
2574
2575 var self = this;
2576
2577 var allElements = this._elementRegistry.getAll();
2578
2579 // remove all elements
2580 allElements.forEach(function(element) {
2581 var type = getType(element);
2582
2583 if (type === 'root') {
2584 self.setRootElement(null, true);
2585 } else {
2586 self._removeElement(element, type);
2587 }
2588 });
2589
2590 // force recomputation of view box
2591 delete this._cachedViewbox;
2592 };
2593
2594 /**
2595 * Returns the default layer on which
2596 * all elements are drawn.
2597 *
2598 * @returns {SVGElement}
2599 */
2600 Canvas.prototype.getDefaultLayer = function() {
2601 return this.getLayer(BASE_LAYER, 0);
2602 };
2603
2604 /**
2605 * Returns a layer that is used to draw elements
2606 * or annotations on it.
2607 *
2608 * Non-existing layers retrieved through this method
2609 * will be created. During creation, the optional index
2610 * may be used to create layers below or above existing layers.
2611 * A layer with a certain index is always created above all
2612 * existing layers with the same index.
2613 *
2614 * @param {String} name
2615 * @param {Number} index
2616 *
2617 * @returns {SVGElement}
2618 */
2619 Canvas.prototype.getLayer = function(name, index) {
2620
2621 if (!name) {
2622 throw new Error('must specify a name');
2623 }
2624
2625 var layer = this._layers[name];
2626
2627 if (!layer) {
2628 layer = this._layers[name] = this._createLayer(name, index);
2629 }
2630
2631 // throw an error if layer creation / retrival is
2632 // requested on different index
2633 if (typeof index !== 'undefined' && layer.index !== index) {
2634 throw new Error('layer <' + name + '> already created at index <' + index + '>');
2635 }
2636
2637 return layer.group;
2638 };
2639
2640 /**
2641 * Creates a given layer and returns it.
2642 *
2643 * @param {String} name
2644 * @param {Number} [index=0]
2645 *
2646 * @return {Object} layer descriptor with { index, group: SVGGroup }
2647 */
2648 Canvas.prototype._createLayer = function(name, index) {
2649
2650 if (!index) {
2651 index = 0;
2652 }
2653
2654 var childIndex = reduce(this._layers, function(childIndex, layer) {
2655 if (index >= layer.index) {
2656 childIndex++;
2657 }
2658
2659 return childIndex;
2660 }, 0);
2661
2662 return {
2663 group: createGroup(this._viewport, 'layer-' + name, childIndex),
2664 index: index
2665 };
2666
2667 };
2668
2669 /**
2670 * Returns the html element that encloses the
2671 * drawing canvas.
2672 *
2673 * @return {DOMNode}
2674 */
2675 Canvas.prototype.getContainer = function() {
2676 return this._container;
2677 };
2678
2679
2680 // markers //////////////////////
2681
2682 Canvas.prototype._updateMarker = function(element, marker, add$$1) {
2683 var container;
2684
2685 if (!element.id) {
2686 element = this._elementRegistry.get(element);
2687 }
2688
2689 // we need to access all
2690 container = this._elementRegistry._elements[element.id];
2691
2692 if (!container) {
2693 return;
2694 }
2695
2696 forEach([ container.gfx, container.secondaryGfx ], function(gfx) {
2697 if (gfx) {
2698 // invoke either addClass or removeClass based on mode
2699 if (add$$1) {
2700 classes$1(gfx).add(marker);
2701 } else {
2702 classes$1(gfx).remove(marker);
2703 }
2704 }
2705 });
2706
2707 /**
2708 * An event indicating that a marker has been updated for an element
2709 *
2710 * @event element.marker.update
2711 * @type {Object}
2712 * @property {djs.model.Element} element the shape
2713 * @property {Object} gfx the graphical representation of the shape
2714 * @property {String} marker
2715 * @property {Boolean} add true if the marker was added, false if it got removed
2716 */
2717 this._eventBus.fire('element.marker.update', { element: element, gfx: container.gfx, marker: marker, add: !!add$$1 });
2718 };
2719
2720
2721 /**
2722 * Adds a marker to an element (basically a css class).
2723 *
2724 * Fires the element.marker.update event, making it possible to
2725 * integrate extension into the marker life-cycle, too.
2726 *
2727 * @example
2728 * canvas.addMarker('foo', 'some-marker');
2729 *
2730 * var fooGfx = canvas.getGraphics('foo');
2731 *
2732 * fooGfx; // <g class="... some-marker"> ... </g>
2733 *
2734 * @param {String|djs.model.Base} element
2735 * @param {String} marker
2736 */
2737 Canvas.prototype.addMarker = function(element, marker) {
2738 this._updateMarker(element, marker, true);
2739 };
2740
2741
2742 /**
2743 * Remove a marker from an element.
2744 *
2745 * Fires the element.marker.update event, making it possible to
2746 * integrate extension into the marker life-cycle, too.
2747 *
2748 * @param {String|djs.model.Base} element
2749 * @param {String} marker
2750 */
2751 Canvas.prototype.removeMarker = function(element, marker) {
2752 this._updateMarker(element, marker, false);
2753 };
2754
2755 /**
2756 * Check the existence of a marker on element.
2757 *
2758 * @param {String|djs.model.Base} element
2759 * @param {String} marker
2760 */
2761 Canvas.prototype.hasMarker = function(element, marker) {
2762 if (!element.id) {
2763 element = this._elementRegistry.get(element);
2764 }
2765
2766 var gfx = this.getGraphics(element);
2767
2768 return classes$1(gfx).has(marker);
2769 };
2770
2771 /**
2772 * Toggles a marker on an element.
2773 *
2774 * Fires the element.marker.update event, making it possible to
2775 * integrate extension into the marker life-cycle, too.
2776 *
2777 * @param {String|djs.model.Base} element
2778 * @param {String} marker
2779 */
2780 Canvas.prototype.toggleMarker = function(element, marker) {
2781 if (this.hasMarker(element, marker)) {
2782 this.removeMarker(element, marker);
2783 } else {
2784 this.addMarker(element, marker);
2785 }
2786 };
2787
2788 Canvas.prototype.getRootElement = function() {
2789 if (!this._rootElement) {
2790 this.setRootElement({ id: '__implicitroot', children: [] });
2791 }
2792
2793 return this._rootElement;
2794 };
2795
2796
2797
2798 // root element handling //////////////////////
2799
2800 /**
2801 * Sets a given element as the new root element for the canvas
2802 * and returns the new root element.
2803 *
2804 * @param {Object|djs.model.Root} element
2805 * @param {Boolean} [override] whether to override the current root element, if any
2806 *
2807 * @return {Object|djs.model.Root} new root element
2808 */
2809 Canvas.prototype.setRootElement = function(element, override) {
2810
2811 if (element) {
2812 this._ensureValid('root', element);
2813 }
2814
2815 var currentRoot = this._rootElement,
2816 elementRegistry = this._elementRegistry,
2817 eventBus = this._eventBus;
2818
2819 if (currentRoot) {
2820 if (!override) {
2821 throw new Error('rootElement already set, need to specify override');
2822 }
2823
2824 // simulate element remove event sequence
2825 eventBus.fire('root.remove', { element: currentRoot });
2826 eventBus.fire('root.removed', { element: currentRoot });
2827
2828 elementRegistry.remove(currentRoot);
2829 }
2830
2831 if (element) {
2832 var gfx = this.getDefaultLayer();
2833
2834 // resemble element add event sequence
2835 eventBus.fire('root.add', { element: element });
2836
2837 elementRegistry.add(element, gfx, this._svg);
2838
2839 eventBus.fire('root.added', { element: element, gfx: gfx });
2840 }
2841
2842 this._rootElement = element;
2843
2844 return element;
2845 };
2846
2847
2848
2849 // add functionality //////////////////////
2850
2851 Canvas.prototype._ensureValid = function(type, element) {
2852 if (!element.id) {
2853 throw new Error('element must have an id');
2854 }
2855
2856 if (this._elementRegistry.get(element.id)) {
2857 throw new Error('element with id ' + element.id + ' already exists');
2858 }
2859
2860 var requiredAttrs = REQUIRED_MODEL_ATTRS[type];
2861
2862 var valid = every(requiredAttrs, function(attr$$1) {
2863 return typeof element[attr$$1] !== 'undefined';
2864 });
2865
2866 if (!valid) {
2867 throw new Error(
2868 'must supply { ' + requiredAttrs.join(', ') + ' } with ' + type);
2869 }
2870 };
2871
2872 Canvas.prototype._setParent = function(element, parent, parentIndex) {
2873 add(parent.children, element, parentIndex);
2874 element.parent = parent;
2875 };
2876
2877 /**
2878 * Adds an element to the canvas.
2879 *
2880 * This wires the parent <-> child relationship between the element and
2881 * a explicitly specified parent or an implicit root element.
2882 *
2883 * During add it emits the events
2884 *
2885 * * <{type}.add> (element, parent)
2886 * * <{type}.added> (element, gfx)
2887 *
2888 * Extensions may hook into these events to perform their magic.
2889 *
2890 * @param {String} type
2891 * @param {Object|djs.model.Base} element
2892 * @param {Object|djs.model.Base} [parent]
2893 * @param {Number} [parentIndex]
2894 *
2895 * @return {Object|djs.model.Base} the added element
2896 */
2897 Canvas.prototype._addElement = function(type, element, parent, parentIndex) {
2898
2899 parent = parent || this.getRootElement();
2900
2901 var eventBus = this._eventBus,
2902 graphicsFactory = this._graphicsFactory;
2903
2904 this._ensureValid(type, element);
2905
2906 eventBus.fire(type + '.add', { element: element, parent: parent });
2907
2908 this._setParent(element, parent, parentIndex);
2909
2910 // create graphics
2911 var gfx = graphicsFactory.create(type, element, parentIndex);
2912
2913 this._elementRegistry.add(element, gfx);
2914
2915 // update its visual
2916 graphicsFactory.update(type, element, gfx);
2917
2918 eventBus.fire(type + '.added', { element: element, gfx: gfx });
2919
2920 return element;
2921 };
2922
2923 /**
2924 * Adds a shape to the canvas
2925 *
2926 * @param {Object|djs.model.Shape} shape to add to the diagram
2927 * @param {djs.model.Base} [parent]
2928 * @param {Number} [parentIndex]
2929 *
2930 * @return {djs.model.Shape} the added shape
2931 */
2932 Canvas.prototype.addShape = function(shape, parent, parentIndex) {
2933 return this._addElement('shape', shape, parent, parentIndex);
2934 };
2935
2936 /**
2937 * Adds a connection to the canvas
2938 *
2939 * @param {Object|djs.model.Connection} connection to add to the diagram
2940 * @param {djs.model.Base} [parent]
2941 * @param {Number} [parentIndex]
2942 *
2943 * @return {djs.model.Connection} the added connection
2944 */
2945 Canvas.prototype.addConnection = function(connection, parent, parentIndex) {
2946 return this._addElement('connection', connection, parent, parentIndex);
2947 };
2948
2949
2950 /**
2951 * Internal remove element
2952 */
2953 Canvas.prototype._removeElement = function(element, type) {
2954
2955 var elementRegistry = this._elementRegistry,
2956 graphicsFactory = this._graphicsFactory,
2957 eventBus = this._eventBus;
2958
2959 element = elementRegistry.get(element.id || element);
2960
2961 if (!element) {
2962 // element was removed already
2963 return;
2964 }
2965
2966 eventBus.fire(type + '.remove', { element: element });
2967
2968 graphicsFactory.remove(element);
2969
2970 // unset parent <-> child relationship
2971 remove$2(element.parent && element.parent.children, element);
2972 element.parent = null;
2973
2974 eventBus.fire(type + '.removed', { element: element });
2975
2976 elementRegistry.remove(element);
2977
2978 return element;
2979 };
2980
2981
2982 /**
2983 * Removes a shape from the canvas
2984 *
2985 * @param {String|djs.model.Shape} shape or shape id to be removed
2986 *
2987 * @return {djs.model.Shape} the removed shape
2988 */
2989 Canvas.prototype.removeShape = function(shape) {
2990
2991 /**
2992 * An event indicating that a shape is about to be removed from the canvas.
2993 *
2994 * @memberOf Canvas
2995 *
2996 * @event shape.remove
2997 * @type {Object}
2998 * @property {djs.model.Shape} element the shape descriptor
2999 * @property {Object} gfx the graphical representation of the shape
3000 */
3001
3002 /**
3003 * An event indicating that a shape has been removed from the canvas.
3004 *
3005 * @memberOf Canvas
3006 *
3007 * @event shape.removed
3008 * @type {Object}
3009 * @property {djs.model.Shape} element the shape descriptor
3010 * @property {Object} gfx the graphical representation of the shape
3011 */
3012 return this._removeElement(shape, 'shape');
3013 };
3014
3015
3016 /**
3017 * Removes a connection from the canvas
3018 *
3019 * @param {String|djs.model.Connection} connection or connection id to be removed
3020 *
3021 * @return {djs.model.Connection} the removed connection
3022 */
3023 Canvas.prototype.removeConnection = function(connection) {
3024
3025 /**
3026 * An event indicating that a connection is about to be removed from the canvas.
3027 *
3028 * @memberOf Canvas
3029 *
3030 * @event connection.remove
3031 * @type {Object}
3032 * @property {djs.model.Connection} element the connection descriptor
3033 * @property {Object} gfx the graphical representation of the connection
3034 */
3035
3036 /**
3037 * An event indicating that a connection has been removed from the canvas.
3038 *
3039 * @memberOf Canvas
3040 *
3041 * @event connection.removed
3042 * @type {Object}
3043 * @property {djs.model.Connection} element the connection descriptor
3044 * @property {Object} gfx the graphical representation of the connection
3045 */
3046 return this._removeElement(connection, 'connection');
3047 };
3048
3049
3050 /**
3051 * Return the graphical object underlaying a certain diagram element
3052 *
3053 * @param {String|djs.model.Base} element descriptor of the element
3054 * @param {Boolean} [secondary=false] whether to return the secondary connected element
3055 *
3056 * @return {SVGElement}
3057 */
3058 Canvas.prototype.getGraphics = function(element, secondary) {
3059 return this._elementRegistry.getGraphics(element, secondary);
3060 };
3061
3062
3063 /**
3064 * Perform a viewbox update via a given change function.
3065 *
3066 * @param {Function} changeFn
3067 */
3068 Canvas.prototype._changeViewbox = function(changeFn) {
3069
3070 // notify others of the upcoming viewbox change
3071 this._eventBus.fire('canvas.viewbox.changing');
3072
3073 // perform actual change
3074 changeFn.apply(this);
3075
3076 // reset the cached viewbox so that
3077 // a new get operation on viewbox or zoom
3078 // triggers a viewbox re-computation
3079 this._cachedViewbox = null;
3080
3081 // notify others of the change; this step
3082 // may or may not be debounced
3083 this._viewboxChanged();
3084 };
3085
3086 Canvas.prototype._viewboxChanged = function() {
3087 this._eventBus.fire('canvas.viewbox.changed', { viewbox: this.viewbox() });
3088 };
3089
3090
3091 /**
3092 * Gets or sets the view box of the canvas, i.e. the
3093 * area that is currently displayed.
3094 *
3095 * The getter may return a cached viewbox (if it is currently
3096 * changing). To force a recomputation, pass `false` as the first argument.
3097 *
3098 * @example
3099 *
3100 * canvas.viewbox({ x: 100, y: 100, width: 500, height: 500 })
3101 *
3102 * // sets the visible area of the diagram to (100|100) -> (600|100)
3103 * // and and scales it according to the diagram width
3104 *
3105 * var viewbox = canvas.viewbox(); // pass `false` to force recomputing the box.
3106 *
3107 * console.log(viewbox);
3108 * // {
3109 * // inner: Dimensions,
3110 * // outer: Dimensions,
3111 * // scale,
3112 * // x, y,
3113 * // width, height
3114 * // }
3115 *
3116 * // if the current diagram is zoomed and scrolled, you may reset it to the
3117 * // default zoom via this method, too:
3118 *
3119 * var zoomedAndScrolledViewbox = canvas.viewbox();
3120 *
3121 * canvas.viewbox({
3122 * x: 0,
3123 * y: 0,
3124 * width: zoomedAndScrolledViewbox.outer.width,
3125 * height: zoomedAndScrolledViewbox.outer.height
3126 * });
3127 *
3128 * @param {Object} [box] the new view box to set
3129 * @param {Number} box.x the top left X coordinate of the canvas visible in view box
3130 * @param {Number} box.y the top left Y coordinate of the canvas visible in view box
3131 * @param {Number} box.width the visible width
3132 * @param {Number} box.height
3133 *
3134 * @return {Object} the current view box
3135 */
3136 Canvas.prototype.viewbox = function(box) {
3137
3138 if (box === undefined && this._cachedViewbox) {
3139 return this._cachedViewbox;
3140 }
3141
3142 var viewport = this._viewport,
3143 innerBox,
3144 outerBox = this.getSize(),
3145 matrix,
3146 transform$$1,
3147 scale,
3148 x, y;
3149
3150 if (!box) {
3151 // compute the inner box based on the
3152 // diagrams default layer. This allows us to exclude
3153 // external components, such as overlays
3154 innerBox = this.getDefaultLayer().getBBox();
3155
3156 transform$$1 = transform(viewport);
3157 matrix = transform$$1 ? transform$$1.matrix : createMatrix();
3158 scale = round(matrix.a, 1000);
3159
3160 x = round(-matrix.e || 0, 1000);
3161 y = round(-matrix.f || 0, 1000);
3162
3163 box = this._cachedViewbox = {
3164 x: x ? x / scale : 0,
3165 y: y ? y / scale : 0,
3166 width: outerBox.width / scale,
3167 height: outerBox.height / scale,
3168 scale: scale,
3169 inner: {
3170 width: innerBox.width,
3171 height: innerBox.height,
3172 x: innerBox.x,
3173 y: innerBox.y
3174 },
3175 outer: outerBox
3176 };
3177
3178 return box;
3179 } else {
3180
3181 this._changeViewbox(function() {
3182 scale = Math.min(outerBox.width / box.width, outerBox.height / box.height);
3183
3184 var matrix = this._svg.createSVGMatrix()
3185 .scale(scale)
3186 .translate(-box.x, -box.y);
3187
3188 transform(viewport, matrix);
3189 });
3190 }
3191
3192 return box;
3193 };
3194
3195
3196 /**
3197 * Gets or sets the scroll of the canvas.
3198 *
3199 * @param {Object} [delta] the new scroll to apply.
3200 *
3201 * @param {Number} [delta.dx]
3202 * @param {Number} [delta.dy]
3203 */
3204 Canvas.prototype.scroll = function(delta) {
3205
3206 var node = this._viewport;
3207 var matrix = node.getCTM();
3208
3209 if (delta) {
3210 this._changeViewbox(function() {
3211 delta = assign({ dx: 0, dy: 0 }, delta || {});
3212
3213 matrix = this._svg.createSVGMatrix().translate(delta.dx, delta.dy).multiply(matrix);
3214
3215 setCTM(node, matrix);
3216 });
3217 }
3218
3219 return { x: matrix.e, y: matrix.f };
3220 };
3221
3222
3223 /**
3224 * Gets or sets the current zoom of the canvas, optionally zooming
3225 * to the specified position.
3226 *
3227 * The getter may return a cached zoom level. Call it with `false` as
3228 * the first argument to force recomputation of the current level.
3229 *
3230 * @param {String|Number} [newScale] the new zoom level, either a number, i.e. 0.9,
3231 * or `fit-viewport` to adjust the size to fit the current viewport
3232 * @param {String|Point} [center] the reference point { x: .., y: ..} to zoom to, 'auto' to zoom into mid or null
3233 *
3234 * @return {Number} the current scale
3235 */
3236 Canvas.prototype.zoom = function(newScale, center) {
3237
3238 if (!newScale) {
3239 return this.viewbox(newScale).scale;
3240 }
3241
3242 if (newScale === 'fit-viewport') {
3243 return this._fitViewport(center);
3244 }
3245
3246 var outer,
3247 matrix;
3248
3249 this._changeViewbox(function() {
3250
3251 if (typeof center !== 'object') {
3252 outer = this.viewbox().outer;
3253
3254 center = {
3255 x: outer.width / 2,
3256 y: outer.height / 2
3257 };
3258 }
3259
3260 matrix = this._setZoom(newScale, center);
3261 });
3262
3263 return round(matrix.a, 1000);
3264 };
3265
3266 function setCTM(node, m) {
3267 var mstr = 'matrix(' + m.a + ',' + m.b + ',' + m.c + ',' + m.d + ',' + m.e + ',' + m.f + ')';
3268 node.setAttribute('transform', mstr);
3269 }
3270
3271 Canvas.prototype._fitViewport = function(center) {
3272
3273 var vbox = this.viewbox(),
3274 outer = vbox.outer,
3275 inner = vbox.inner,
3276 newScale,
3277 newViewbox;
3278
3279 // display the complete diagram without zooming in.
3280 // instead of relying on internal zoom, we perform a
3281 // hard reset on the canvas viewbox to realize this
3282 //
3283 // if diagram does not need to be zoomed in, we focus it around
3284 // the diagram origin instead
3285
3286 if (inner.x >= 0 &&
3287 inner.y >= 0 &&
3288 inner.x + inner.width <= outer.width &&
3289 inner.y + inner.height <= outer.height &&
3290 !center) {
3291
3292 newViewbox = {
3293 x: 0,
3294 y: 0,
3295 width: Math.max(inner.width + inner.x, outer.width),
3296 height: Math.max(inner.height + inner.y, outer.height)
3297 };
3298 } else {
3299
3300 newScale = Math.min(1, outer.width / inner.width, outer.height / inner.height);
3301 newViewbox = {
3302 x: inner.x + (center ? inner.width / 2 - outer.width / newScale / 2 : 0),
3303 y: inner.y + (center ? inner.height / 2 - outer.height / newScale / 2 : 0),
3304 width: outer.width / newScale,
3305 height: outer.height / newScale
3306 };
3307 }
3308
3309 this.viewbox(newViewbox);
3310
3311 return this.viewbox(false).scale;
3312 };
3313
3314
3315 Canvas.prototype._setZoom = function(scale, center) {
3316
3317 var svg = this._svg,
3318 viewport = this._viewport;
3319
3320 var matrix = svg.createSVGMatrix();
3321 var point = svg.createSVGPoint();
3322
3323 var centerPoint,
3324 originalPoint,
3325 currentMatrix,
3326 scaleMatrix,
3327 newMatrix;
3328
3329 currentMatrix = viewport.getCTM();
3330
3331 var currentScale = currentMatrix.a;
3332
3333 if (center) {
3334 centerPoint = assign(point, center);
3335
3336 // revert applied viewport transformations
3337 originalPoint = centerPoint.matrixTransform(currentMatrix.inverse());
3338
3339 // create scale matrix
3340 scaleMatrix = matrix
3341 .translate(originalPoint.x, originalPoint.y)
3342 .scale(1 / currentScale * scale)
3343 .translate(-originalPoint.x, -originalPoint.y);
3344
3345 newMatrix = currentMatrix.multiply(scaleMatrix);
3346 } else {
3347 newMatrix = matrix.scale(scale);
3348 }
3349
3350 setCTM(this._viewport, newMatrix);
3351
3352 return newMatrix;
3353 };
3354
3355
3356 /**
3357 * Returns the size of the canvas
3358 *
3359 * @return {Dimensions}
3360 */
3361 Canvas.prototype.getSize = function() {
3362 return {
3363 width: this._container.clientWidth,
3364 height: this._container.clientHeight
3365 };
3366 };
3367
3368
3369 /**
3370 * Return the absolute bounding box for the given element
3371 *
3372 * The absolute bounding box may be used to display overlays in the
3373 * callers (browser) coordinate system rather than the zoomed in/out
3374 * canvas coordinates.
3375 *
3376 * @param {ElementDescriptor} element
3377 * @return {Bounds} the absolute bounding box
3378 */
3379 Canvas.prototype.getAbsoluteBBox = function(element) {
3380 var vbox = this.viewbox();
3381 var bbox;
3382
3383 // connection
3384 // use svg bbox
3385 if (element.waypoints) {
3386 var gfx = this.getGraphics(element);
3387
3388 bbox = gfx.getBBox();
3389 }
3390 // shapes
3391 // use data
3392 else {
3393 bbox = element;
3394 }
3395
3396 var x = bbox.x * vbox.scale - vbox.x * vbox.scale;
3397 var y = bbox.y * vbox.scale - vbox.y * vbox.scale;
3398
3399 var width = bbox.width * vbox.scale;
3400 var height = bbox.height * vbox.scale;
3401
3402 return {
3403 x: x,
3404 y: y,
3405 width: width,
3406 height: height
3407 };
3408 };
3409
3410 /**
3411 * Fires an event in order other modules can react to the
3412 * canvas resizing
3413 */
3414 Canvas.prototype.resized = function() {
3415
3416 // force recomputation of view box
3417 delete this._cachedViewbox;
3418
3419 this._eventBus.fire('canvas.resized');
3420 };
3421
3422 var ELEMENT_ID = 'data-element-id';
3423
3424
3425 /**
3426 * @class
3427 *
3428 * A registry that keeps track of all shapes in the diagram.
3429 */
3430 function ElementRegistry(eventBus) {
3431 this._elements = {};
3432
3433 this._eventBus = eventBus;
3434 }
3435
3436 ElementRegistry.$inject = [ 'eventBus' ];
3437
3438 /**
3439 * Register a pair of (element, gfx, (secondaryGfx)).
3440 *
3441 * @param {djs.model.Base} element
3442 * @param {SVGElement} gfx
3443 * @param {SVGElement} [secondaryGfx] optional other element to register, too
3444 */
3445 ElementRegistry.prototype.add = function(element, gfx, secondaryGfx) {
3446
3447 var id = element.id;
3448
3449 this._validateId(id);
3450
3451 // associate dom node with element
3452 attr$1(gfx, ELEMENT_ID, id);
3453
3454 if (secondaryGfx) {
3455 attr$1(secondaryGfx, ELEMENT_ID, id);
3456 }
3457
3458 this._elements[id] = { element: element, gfx: gfx, secondaryGfx: secondaryGfx };
3459 };
3460
3461 /**
3462 * Removes an element from the registry.
3463 *
3464 * @param {djs.model.Base} element
3465 */
3466 ElementRegistry.prototype.remove = function(element) {
3467 var elements = this._elements,
3468 id = element.id || element,
3469 container = id && elements[id];
3470
3471 if (container) {
3472
3473 // unset element id on gfx
3474 attr$1(container.gfx, ELEMENT_ID, '');
3475
3476 if (container.secondaryGfx) {
3477 attr$1(container.secondaryGfx, ELEMENT_ID, '');
3478 }
3479
3480 delete elements[id];
3481 }
3482 };
3483
3484 /**
3485 * Update the id of an element
3486 *
3487 * @param {djs.model.Base} element
3488 * @param {String} newId
3489 */
3490 ElementRegistry.prototype.updateId = function(element, newId) {
3491
3492 this._validateId(newId);
3493
3494 if (typeof element === 'string') {
3495 element = this.get(element);
3496 }
3497
3498 this._eventBus.fire('element.updateId', {
3499 element: element,
3500 newId: newId
3501 });
3502
3503 var gfx = this.getGraphics(element),
3504 secondaryGfx = this.getGraphics(element, true);
3505
3506 this.remove(element);
3507
3508 element.id = newId;
3509
3510 this.add(element, gfx, secondaryGfx);
3511 };
3512
3513 /**
3514 * Return the model element for a given id or graphics.
3515 *
3516 * @example
3517 *
3518 * elementRegistry.get('SomeElementId_1');
3519 * elementRegistry.get(gfx);
3520 *
3521 *
3522 * @param {String|SVGElement} filter for selecting the element
3523 *
3524 * @return {djs.model.Base}
3525 */
3526 ElementRegistry.prototype.get = function(filter) {
3527 var id;
3528
3529 if (typeof filter === 'string') {
3530 id = filter;
3531 } else {
3532 id = filter && attr$1(filter, ELEMENT_ID);
3533 }
3534
3535 var container = this._elements[id];
3536 return container && container.element;
3537 };
3538
3539 /**
3540 * Return all elements that match a given filter function.
3541 *
3542 * @param {Function} fn
3543 *
3544 * @return {Array<djs.model.Base>}
3545 */
3546 ElementRegistry.prototype.filter = function(fn) {
3547
3548 var filtered = [];
3549
3550 this.forEach(function(element, gfx) {
3551 if (fn(element, gfx)) {
3552 filtered.push(element);
3553 }
3554 });
3555
3556 return filtered;
3557 };
3558
3559 /**
3560 * Return all rendered model elements.
3561 *
3562 * @return {Array<djs.model.Base>}
3563 */
3564 ElementRegistry.prototype.getAll = function() {
3565 return this.filter(function(e) { return e; });
3566 };
3567
3568 /**
3569 * Iterate over all diagram elements.
3570 *
3571 * @param {Function} fn
3572 */
3573 ElementRegistry.prototype.forEach = function(fn) {
3574
3575 var map = this._elements;
3576
3577 Object.keys(map).forEach(function(id) {
3578 var container = map[id],
3579 element = container.element,
3580 gfx = container.gfx;
3581
3582 return fn(element, gfx);
3583 });
3584 };
3585
3586 /**
3587 * Return the graphical representation of an element or its id.
3588 *
3589 * @example
3590 * elementRegistry.getGraphics('SomeElementId_1');
3591 * elementRegistry.getGraphics(rootElement); // <g ...>
3592 *
3593 * elementRegistry.getGraphics(rootElement, true); // <svg ...>
3594 *
3595 *
3596 * @param {String|djs.model.Base} filter
3597 * @param {Boolean} [secondary=false] whether to return the secondary connected element
3598 *
3599 * @return {SVGElement}
3600 */
3601 ElementRegistry.prototype.getGraphics = function(filter, secondary) {
3602 var id = filter.id || filter;
3603
3604 var container = this._elements[id];
3605 return container && (secondary ? container.secondaryGfx : container.gfx);
3606 };
3607
3608 /**
3609 * Validate the suitability of the given id and signals a problem
3610 * with an exception.
3611 *
3612 * @param {String} id
3613 *
3614 * @throws {Error} if id is empty or already assigned
3615 */
3616 ElementRegistry.prototype._validateId = function(id) {
3617 if (!id) {
3618 throw new Error('element must have an id');
3619 }
3620
3621 if (this._elements[id]) {
3622 throw new Error('element with id ' + id + ' already added');
3623 }
3624 };
3625
3626 /**
3627 * An empty collection stub. Use {@link RefsCollection.extend} to extend a
3628 * collection with ref semantics.
3629 *
3630 * @class RefsCollection
3631 */
3632
3633 /**
3634 * Extends a collection with {@link Refs} aware methods
3635 *
3636 * @memberof RefsCollection
3637 * @static
3638 *
3639 * @param {Array<Object>} collection
3640 * @param {Refs} refs instance
3641 * @param {Object} property represented by the collection
3642 * @param {Object} target object the collection is attached to
3643 *
3644 * @return {RefsCollection<Object>} the extended array
3645 */
3646 function extend$1(collection, refs, property, target) {
3647
3648 var inverseProperty = property.inverse;
3649
3650 /**
3651 * Removes the given element from the array and returns it.
3652 *
3653 * @method RefsCollection#remove
3654 *
3655 * @param {Object} element the element to remove
3656 */
3657 Object.defineProperty(collection, 'remove', {
3658 value: function(element) {
3659 var idx = this.indexOf(element);
3660 if (idx !== -1) {
3661 this.splice(idx, 1);
3662
3663 // unset inverse
3664 refs.unset(element, inverseProperty, target);
3665 }
3666
3667 return element;
3668 }
3669 });
3670
3671 /**
3672 * Returns true if the collection contains the given element
3673 *
3674 * @method RefsCollection#contains
3675 *
3676 * @param {Object} element the element to check for
3677 */
3678 Object.defineProperty(collection, 'contains', {
3679 value: function(element) {
3680 return this.indexOf(element) !== -1;
3681 }
3682 });
3683
3684 /**
3685 * Adds an element to the array, unless it exists already (set semantics).
3686 *
3687 * @method RefsCollection#add
3688 *
3689 * @param {Object} element the element to add
3690 * @param {Number} optional index to add element to
3691 * (possibly moving other elements around)
3692 */
3693 Object.defineProperty(collection, 'add', {
3694 value: function(element, idx) {
3695
3696 var currentIdx = this.indexOf(element);
3697
3698 if (typeof idx === 'undefined') {
3699
3700 if (currentIdx !== -1) {
3701 // element already in collection (!)
3702 return;
3703 }
3704
3705 // add to end of array, as no idx is specified
3706 idx = this.length;
3707 }
3708
3709 // handle already in collection
3710 if (currentIdx !== -1) {
3711
3712 // remove element from currentIdx
3713 this.splice(currentIdx, 1);
3714 }
3715
3716 // add element at idx
3717 this.splice(idx, 0, element);
3718
3719 if (currentIdx === -1) {
3720 // set inverse, unless element was
3721 // in collection already
3722 refs.set(element, inverseProperty, target);
3723 }
3724 }
3725 });
3726
3727 // a simple marker, identifying this element
3728 // as being a refs collection
3729 Object.defineProperty(collection, '__refs_collection', {
3730 value: true
3731 });
3732
3733 return collection;
3734 }
3735
3736
3737 function isExtended(collection) {
3738 return collection.__refs_collection === true;
3739 }
3740
3741 var extend_1 = extend$1;
3742
3743 var isExtended_1 = isExtended;
3744
3745 var collection = {
3746 extend: extend_1,
3747 isExtended: isExtended_1
3748 };
3749
3750 function hasOwnProperty(e, property) {
3751 return Object.prototype.hasOwnProperty.call(e, property.name || property);
3752 }
3753
3754 function defineCollectionProperty(ref, property, target) {
3755
3756 var collection$$1 = collection.extend(target[property.name] || [], ref, property, target);
3757
3758 Object.defineProperty(target, property.name, {
3759 enumerable: property.enumerable,
3760 value: collection$$1
3761 });
3762
3763 if (collection$$1.length) {
3764
3765 collection$$1.forEach(function(o) {
3766 ref.set(o, property.inverse, target);
3767 });
3768 }
3769 }
3770
3771
3772 function defineProperty(ref, property, target) {
3773
3774 var inverseProperty = property.inverse;
3775
3776 var _value = target[property.name];
3777
3778 Object.defineProperty(target, property.name, {
3779 configurable: property.configurable,
3780 enumerable: property.enumerable,
3781
3782 get: function() {
3783 return _value;
3784 },
3785
3786 set: function(value) {
3787
3788 // return if we already performed all changes
3789 if (value === _value) {
3790 return;
3791 }
3792
3793 var old = _value;
3794
3795 // temporary set null
3796 _value = null;
3797
3798 if (old) {
3799 ref.unset(old, inverseProperty, target);
3800 }
3801
3802 // set new value
3803 _value = value;
3804
3805 // set inverse value
3806 ref.set(_value, inverseProperty, target);
3807 }
3808 });
3809
3810 }
3811
3812 /**
3813 * Creates a new references object defining two inversly related
3814 * attribute descriptors a and b.
3815 *
3816 * <p>
3817 * When bound to an object using {@link Refs#bind} the references
3818 * get activated and ensure that add and remove operations are applied
3819 * reversely, too.
3820 * </p>
3821 *
3822 * <p>
3823 * For attributes represented as collections {@link Refs} provides the
3824 * {@link RefsCollection#add}, {@link RefsCollection#remove} and {@link RefsCollection#contains} extensions
3825 * that must be used to properly hook into the inverse change mechanism.
3826 * </p>
3827 *
3828 * @class Refs
3829 *
3830 * @classdesc A bi-directional reference between two attributes.
3831 *
3832 * @param {Refs.AttributeDescriptor} a property descriptor
3833 * @param {Refs.AttributeDescriptor} b property descriptor
3834 *
3835 * @example
3836 *
3837 * var refs = Refs({ name: 'wheels', collection: true, enumerable: true }, { name: 'car' });
3838 *
3839 * var car = { name: 'toyota' };
3840 * var wheels = [{ pos: 'front-left' }, { pos: 'front-right' }];
3841 *
3842 * refs.bind(car, 'wheels');
3843 *
3844 * car.wheels // []
3845 * car.wheels.add(wheels[0]);
3846 * car.wheels.add(wheels[1]);
3847 *
3848 * car.wheels // [{ pos: 'front-left' }, { pos: 'front-right' }]
3849 *
3850 * wheels[0].car // { name: 'toyota' };
3851 * car.wheels.remove(wheels[0]);
3852 *
3853 * wheels[0].car // undefined
3854 */
3855 function Refs(a, b) {
3856
3857 if (!(this instanceof Refs)) {
3858 return new Refs(a, b);
3859 }
3860
3861 // link
3862 a.inverse = b;
3863 b.inverse = a;
3864
3865 this.props = {};
3866 this.props[a.name] = a;
3867 this.props[b.name] = b;
3868 }
3869
3870 /**
3871 * Binds one side of a bi-directional reference to a
3872 * target object.
3873 *
3874 * @memberOf Refs
3875 *
3876 * @param {Object} target
3877 * @param {String} property
3878 */
3879 Refs.prototype.bind = function(target, property) {
3880 if (typeof property === 'string') {
3881 if (!this.props[property]) {
3882 throw new Error('no property <' + property + '> in ref');
3883 }
3884 property = this.props[property];
3885 }
3886
3887 if (property.collection) {
3888 defineCollectionProperty(this, property, target);
3889 } else {
3890 defineProperty(this, property, target);
3891 }
3892 };
3893
3894 Refs.prototype.ensureRefsCollection = function(target, property) {
3895
3896 var collection$$1 = target[property.name];
3897
3898 if (!collection.isExtended(collection$$1)) {
3899 defineCollectionProperty(this, property, target);
3900 }
3901
3902 return collection$$1;
3903 };
3904
3905 Refs.prototype.ensureBound = function(target, property) {
3906 if (!hasOwnProperty(target, property)) {
3907 this.bind(target, property);
3908 }
3909 };
3910
3911 Refs.prototype.unset = function(target, property, value) {
3912
3913 if (target) {
3914 this.ensureBound(target, property);
3915
3916 if (property.collection) {
3917 this.ensureRefsCollection(target, property).remove(value);
3918 } else {
3919 target[property.name] = undefined;
3920 }
3921 }
3922 };
3923
3924 Refs.prototype.set = function(target, property, value) {
3925
3926 if (target) {
3927 this.ensureBound(target, property);
3928
3929 if (property.collection) {
3930 this.ensureRefsCollection(target, property).add(value);
3931 } else {
3932 target[property.name] = value;
3933 }
3934 }
3935 };
3936
3937 var refs = Refs;
3938
3939 var objectRefs = refs;
3940
3941 var Collection = collection;
3942 objectRefs.Collection = Collection;
3943
3944 var parentRefs = new objectRefs({ name: 'children', enumerable: true, collection: true }, { name: 'parent' }),
3945 labelRefs = new objectRefs({ name: 'labels', enumerable: true, collection: true }, { name: 'labelTarget' }),
3946 attacherRefs = new objectRefs({ name: 'attachers', collection: true }, { name: 'host' }),
3947 outgoingRefs = new objectRefs({ name: 'outgoing', collection: true }, { name: 'source' }),
3948 incomingRefs = new objectRefs({ name: 'incoming', collection: true }, { name: 'target' });
3949
3950 /**
3951 * @namespace djs.model
3952 */
3953
3954 /**
3955 * @memberOf djs.model
3956 */
3957
3958 /**
3959 * The basic graphical representation
3960 *
3961 * @class
3962 *
3963 * @abstract
3964 */
3965 function Base() {
3966
3967 /**
3968 * The object that backs up the shape
3969 *
3970 * @name Base#businessObject
3971 * @type Object
3972 */
3973 Object.defineProperty(this, 'businessObject', {
3974 writable: true
3975 });
3976
3977
3978 /**
3979 * Single label support, will mapped to multi label array
3980 *
3981 * @name Base#label
3982 * @type Object
3983 */
3984 Object.defineProperty(this, 'label', {
3985 get: function() {
3986 return this.labels[0];
3987 },
3988 set: function(newLabel) {
3989
3990 var label = this.label,
3991 labels = this.labels;
3992
3993 if (!newLabel && label) {
3994 labels.remove(label);
3995 } else {
3996 labels.add(newLabel, 0);
3997 }
3998 }
3999 });
4000
4001 /**
4002 * The parent shape
4003 *
4004 * @name Base#parent
4005 * @type Shape
4006 */
4007 parentRefs.bind(this, 'parent');
4008
4009 /**
4010 * The list of labels
4011 *
4012 * @name Base#labels
4013 * @type Label
4014 */
4015 labelRefs.bind(this, 'labels');
4016
4017 /**
4018 * The list of outgoing connections
4019 *
4020 * @name Base#outgoing
4021 * @type Array<Connection>
4022 */
4023 outgoingRefs.bind(this, 'outgoing');
4024
4025 /**
4026 * The list of incoming connections
4027 *
4028 * @name Base#incoming
4029 * @type Array<Connection>
4030 */
4031 incomingRefs.bind(this, 'incoming');
4032 }
4033
4034
4035 /**
4036 * A graphical object
4037 *
4038 * @class
4039 * @constructor
4040 *
4041 * @extends Base
4042 */
4043 function Shape() {
4044 Base.call(this);
4045
4046 /**
4047 * The list of children
4048 *
4049 * @name Shape#children
4050 * @type Array<Base>
4051 */
4052 parentRefs.bind(this, 'children');
4053
4054 /**
4055 * @name Shape#host
4056 * @type Shape
4057 */
4058 attacherRefs.bind(this, 'host');
4059
4060 /**
4061 * @name Shape#attachers
4062 * @type Shape
4063 */
4064 attacherRefs.bind(this, 'attachers');
4065 }
4066
4067 inherits_browser(Shape, Base);
4068
4069
4070 /**
4071 * A root graphical object
4072 *
4073 * @class
4074 * @constructor
4075 *
4076 * @extends Shape
4077 */
4078 function Root() {
4079 Shape.call(this);
4080 }
4081
4082 inherits_browser(Root, Shape);
4083
4084
4085 /**
4086 * A label for an element
4087 *
4088 * @class
4089 * @constructor
4090 *
4091 * @extends Shape
4092 */
4093 function Label() {
4094 Shape.call(this);
4095
4096 /**
4097 * The labeled element
4098 *
4099 * @name Label#labelTarget
4100 * @type Base
4101 */
4102 labelRefs.bind(this, 'labelTarget');
4103 }
4104
4105 inherits_browser(Label, Shape);
4106
4107
4108 /**
4109 * A connection between two elements
4110 *
4111 * @class
4112 * @constructor
4113 *
4114 * @extends Base
4115 */
4116 function Connection() {
4117 Base.call(this);
4118
4119 /**
4120 * The element this connection originates from
4121 *
4122 * @name Connection#source
4123 * @type Base
4124 */
4125 outgoingRefs.bind(this, 'source');
4126
4127 /**
4128 * The element this connection points to
4129 *
4130 * @name Connection#target
4131 * @type Base
4132 */
4133 incomingRefs.bind(this, 'target');
4134 }
4135
4136 inherits_browser(Connection, Base);
4137
4138
4139 var types = {
4140 connection: Connection,
4141 shape: Shape,
4142 label: Label,
4143 root: Root
4144 };
4145
4146 /**
4147 * Creates a new model element of the specified type
4148 *
4149 * @method create
4150 *
4151 * @example
4152 *
4153 * var shape1 = Model.create('shape', { x: 10, y: 10, width: 100, height: 100 });
4154 * var shape2 = Model.create('shape', { x: 210, y: 210, width: 100, height: 100 });
4155 *
4156 * var connection = Model.create('connection', { waypoints: [ { x: 110, y: 55 }, {x: 210, y: 55 } ] });
4157 *
4158 * @param {String} type lower-cased model name
4159 * @param {Object} attrs attributes to initialize the new model instance with
4160 *
4161 * @return {Base} the new model instance
4162 */
4163 function create$1(type, attrs) {
4164 var Type = types[type];
4165 if (!Type) {
4166 throw new Error('unknown type: <' + type + '>');
4167 }
4168 return assign(new Type(), attrs);
4169 }
4170
4171 /**
4172 * A factory for diagram-js shapes
4173 */
4174 function ElementFactory() {
4175 this._uid = 12;
4176 }
4177
4178
4179 ElementFactory.prototype.createRoot = function(attrs) {
4180 return this.create('root', attrs);
4181 };
4182
4183 ElementFactory.prototype.createLabel = function(attrs) {
4184 return this.create('label', attrs);
4185 };
4186
4187 ElementFactory.prototype.createShape = function(attrs) {
4188 return this.create('shape', attrs);
4189 };
4190
4191 ElementFactory.prototype.createConnection = function(attrs) {
4192 return this.create('connection', attrs);
4193 };
4194
4195 /**
4196 * Create a model element with the given type and
4197 * a number of pre-set attributes.
4198 *
4199 * @param {String} type
4200 * @param {Object} attrs
4201 * @return {djs.model.Base} the newly created model instance
4202 */
4203 ElementFactory.prototype.create = function(type, attrs) {
4204
4205 attrs = assign({}, attrs || {});
4206
4207 if (!attrs.id) {
4208 attrs.id = type + '_' + (this._uid++);
4209 }
4210
4211 return create$1(type, attrs);
4212 };
4213
4214 var FN_REF = '__fn';
4215
4216 var DEFAULT_PRIORITY = 1000;
4217
4218 var slice$2 = Array.prototype.slice;
4219
4220 /**
4221 * A general purpose event bus.
4222 *
4223 * This component is used to communicate across a diagram instance.
4224 * Other parts of a diagram can use it to listen to and broadcast events.
4225 *
4226 *
4227 * ## Registering for Events
4228 *
4229 * The event bus provides the {@link EventBus#on} and {@link EventBus#once}
4230 * methods to register for events. {@link EventBus#off} can be used to
4231 * remove event registrations. Listeners receive an instance of {@link Event}
4232 * as the first argument. It allows them to hook into the event execution.
4233 *
4234 * ```javascript
4235 *
4236 * // listen for event
4237 * eventBus.on('foo', function(event) {
4238 *
4239 * // access event type
4240 * event.type; // 'foo'
4241 *
4242 * // stop propagation to other listeners
4243 * event.stopPropagation();
4244 *
4245 * // prevent event default
4246 * event.preventDefault();
4247 * });
4248 *
4249 * // listen for event with custom payload
4250 * eventBus.on('bar', function(event, payload) {
4251 * console.log(payload);
4252 * });
4253 *
4254 * // listen for event returning value
4255 * eventBus.on('foobar', function(event) {
4256 *
4257 * // stop event propagation + prevent default
4258 * return false;
4259 *
4260 * // stop event propagation + return custom result
4261 * return {
4262 * complex: 'listening result'
4263 * };
4264 * });
4265 *
4266 *
4267 * // listen with custom priority (default=1000, higher is better)
4268 * eventBus.on('priorityfoo', 1500, function(event) {
4269 * console.log('invoked first!');
4270 * });
4271 *
4272 *
4273 * // listen for event and pass the context (`this`)
4274 * eventBus.on('foobar', function(event) {
4275 * this.foo();
4276 * }, this);
4277 * ```
4278 *
4279 *
4280 * ## Emitting Events
4281 *
4282 * Events can be emitted via the event bus using {@link EventBus#fire}.
4283 *
4284 * ```javascript
4285 *
4286 * // false indicates that the default action
4287 * // was prevented by listeners
4288 * if (eventBus.fire('foo') === false) {
4289 * console.log('default has been prevented!');
4290 * };
4291 *
4292 *
4293 * // custom args + return value listener
4294 * eventBus.on('sum', function(event, a, b) {
4295 * return a + b;
4296 * });
4297 *
4298 * // you can pass custom arguments + retrieve result values.
4299 * var sum = eventBus.fire('sum', 1, 2);
4300 * console.log(sum); // 3
4301 * ```
4302 */
4303 function EventBus() {
4304 this._listeners = {};
4305
4306 // cleanup on destroy on lowest priority to allow
4307 // message passing until the bitter end
4308 this.on('diagram.destroy', 1, this._destroy, this);
4309 }
4310
4311
4312 /**
4313 * Register an event listener for events with the given name.
4314 *
4315 * The callback will be invoked with `event, ...additionalArguments`
4316 * that have been passed to {@link EventBus#fire}.
4317 *
4318 * Returning false from a listener will prevent the events default action
4319 * (if any is specified). To stop an event from being processed further in
4320 * other listeners execute {@link Event#stopPropagation}.
4321 *
4322 * Returning anything but `undefined` from a listener will stop the listener propagation.
4323 *
4324 * @param {String|Array<String>} events
4325 * @param {Number} [priority=1000] the priority in which this listener is called, larger is higher
4326 * @param {Function} callback
4327 * @param {Object} [that] Pass context (`this`) to the callback
4328 */
4329 EventBus.prototype.on = function(events, priority, callback, that) {
4330
4331 events = isArray(events) ? events : [ events ];
4332
4333 if (isFunction(priority)) {
4334 that = callback;
4335 callback = priority;
4336 priority = DEFAULT_PRIORITY;
4337 }
4338
4339 if (!isNumber(priority)) {
4340 throw new Error('priority must be a number');
4341 }
4342
4343 var actualCallback = callback;
4344
4345 if (that) {
4346 actualCallback = bind(callback, that);
4347
4348 // make sure we remember and are able to remove
4349 // bound callbacks via {@link #off} using the original
4350 // callback
4351 actualCallback[FN_REF] = callback[FN_REF] || callback;
4352 }
4353
4354 var self = this,
4355 listener = { priority: priority, callback: actualCallback };
4356
4357 events.forEach(function(e) {
4358 self._addListener(e, listener);
4359 });
4360 };
4361
4362
4363 /**
4364 * Register an event listener that is executed only once.
4365 *
4366 * @param {String} event the event name to register for
4367 * @param {Function} callback the callback to execute
4368 * @param {Object} [that] Pass context (`this`) to the callback
4369 */
4370 EventBus.prototype.once = function(event, priority, callback, that) {
4371 var self = this;
4372
4373 if (isFunction(priority)) {
4374 that = callback;
4375 callback = priority;
4376 priority = DEFAULT_PRIORITY;
4377 }
4378
4379 if (!isNumber(priority)) {
4380 throw new Error('priority must be a number');
4381 }
4382
4383 function wrappedCallback() {
4384 self.off(event, wrappedCallback);
4385 return callback.apply(that, arguments);
4386 }
4387
4388 // make sure we remember and are able to remove
4389 // bound callbacks via {@link #off} using the original
4390 // callback
4391 wrappedCallback[FN_REF] = callback;
4392
4393 this.on(event, priority, wrappedCallback);
4394 };
4395
4396
4397 /**
4398 * Removes event listeners by event and callback.
4399 *
4400 * If no callback is given, all listeners for a given event name are being removed.
4401 *
4402 * @param {String|Array<String>} events
4403 * @param {Function} [callback]
4404 */
4405 EventBus.prototype.off = function(events, callback) {
4406
4407 events = isArray(events) ? events : [ events ];
4408
4409 var self = this;
4410
4411 events.forEach(function(event) {
4412 self._removeListener(event, callback);
4413 });
4414
4415 };
4416
4417
4418 /**
4419 * Create an EventBus event.
4420 *
4421 * @param {Object} data
4422 *
4423 * @return {Object} event, recognized by the eventBus
4424 */
4425 EventBus.prototype.createEvent = function(data) {
4426 var event = new InternalEvent();
4427
4428 event.init(data);
4429
4430 return event;
4431 };
4432
4433
4434 /**
4435 * Fires a named event.
4436 *
4437 * @example
4438 *
4439 * // fire event by name
4440 * events.fire('foo');
4441 *
4442 * // fire event object with nested type
4443 * var event = { type: 'foo' };
4444 * events.fire(event);
4445 *
4446 * // fire event with explicit type
4447 * var event = { x: 10, y: 20 };
4448 * events.fire('element.moved', event);
4449 *
4450 * // pass additional arguments to the event
4451 * events.on('foo', function(event, bar) {
4452 * alert(bar);
4453 * });
4454 *
4455 * events.fire({ type: 'foo' }, 'I am bar!');
4456 *
4457 * @param {String} [name] the optional event name
4458 * @param {Object} [event] the event object
4459 * @param {...Object} additional arguments to be passed to the callback functions
4460 *
4461 * @return {Boolean} the events return value, if specified or false if the
4462 * default action was prevented by listeners
4463 */
4464 EventBus.prototype.fire = function(type, data) {
4465
4466 var event,
4467 listeners,
4468 returnValue,
4469 args;
4470
4471 args = slice$2.call(arguments);
4472
4473 if (typeof type === 'object') {
4474 event = type;
4475 type = event.type;
4476 }
4477
4478 if (!type) {
4479 throw new Error('no event type specified');
4480 }
4481
4482 listeners = this._listeners[type];
4483
4484 if (!listeners) {
4485 return;
4486 }
4487
4488 // we make sure we fire instances of our home made
4489 // events here. We wrap them only once, though
4490 if (data instanceof InternalEvent) {
4491 // we are fine, we alread have an event
4492 event = data;
4493 } else {
4494 event = this.createEvent(data);
4495 }
4496
4497 // ensure we pass the event as the first parameter
4498 args[0] = event;
4499
4500 // original event type (in case we delegate)
4501 var originalType = event.type;
4502
4503 // update event type before delegation
4504 if (type !== originalType) {
4505 event.type = type;
4506 }
4507
4508 try {
4509 returnValue = this._invokeListeners(event, args, listeners);
4510 } finally {
4511 // reset event type after delegation
4512 if (type !== originalType) {
4513 event.type = originalType;
4514 }
4515 }
4516
4517 // set the return value to false if the event default
4518 // got prevented and no other return value exists
4519 if (returnValue === undefined && event.defaultPrevented) {
4520 returnValue = false;
4521 }
4522
4523 return returnValue;
4524 };
4525
4526
4527 EventBus.prototype.handleError = function(error) {
4528 return this.fire('error', { error: error }) === false;
4529 };
4530
4531
4532 EventBus.prototype._destroy = function() {
4533 this._listeners = {};
4534 };
4535
4536 EventBus.prototype._invokeListeners = function(event, args, listeners) {
4537
4538 var idx,
4539 listener,
4540 returnValue;
4541
4542 for (idx = 0; (listener = listeners[idx]); idx++) {
4543
4544 // handle stopped propagation
4545 if (event.cancelBubble) {
4546 break;
4547 }
4548
4549 returnValue = this._invokeListener(event, args, listener);
4550 }
4551
4552 return returnValue;
4553 };
4554
4555 EventBus.prototype._invokeListener = function(event, args, listener) {
4556
4557 var returnValue;
4558
4559 try {
4560 // returning false prevents the default action
4561 returnValue = invokeFunction(listener.callback, args);
4562
4563 // stop propagation on return value
4564 if (returnValue !== undefined) {
4565 event.returnValue = returnValue;
4566 event.stopPropagation();
4567 }
4568
4569 // prevent default on return false
4570 if (returnValue === false) {
4571 event.preventDefault();
4572 }
4573 } catch (e) {
4574 if (!this.handleError(e)) {
4575 console.error('unhandled error in event listener');
4576 console.error(e.stack);
4577
4578 throw e;
4579 }
4580 }
4581
4582 return returnValue;
4583 };
4584
4585 /*
4586 * Add new listener with a certain priority to the list
4587 * of listeners (for the given event).
4588 *
4589 * The semantics of listener registration / listener execution are
4590 * first register, first serve: New listeners will always be inserted
4591 * after existing listeners with the same priority.
4592 *
4593 * Example: Inserting two listeners with priority 1000 and 1300
4594 *
4595 * * before: [ 1500, 1500, 1000, 1000 ]
4596 * * after: [ 1500, 1500, (new=1300), 1000, 1000, (new=1000) ]
4597 *
4598 * @param {String} event
4599 * @param {Object} listener { priority, callback }
4600 */
4601 EventBus.prototype._addListener = function(event, newListener) {
4602
4603 var listeners = this._getListeners(event),
4604 existingListener,
4605 idx;
4606
4607 // ensure we order listeners by priority from
4608 // 0 (high) to n > 0 (low)
4609 for (idx = 0; (existingListener = listeners[idx]); idx++) {
4610 if (existingListener.priority < newListener.priority) {
4611
4612 // prepend newListener at before existingListener
4613 listeners.splice(idx, 0, newListener);
4614 return;
4615 }
4616 }
4617
4618 listeners.push(newListener);
4619 };
4620
4621
4622 EventBus.prototype._getListeners = function(name) {
4623 var listeners = this._listeners[name];
4624
4625 if (!listeners) {
4626 this._listeners[name] = listeners = [];
4627 }
4628
4629 return listeners;
4630 };
4631
4632
4633 EventBus.prototype._removeListener = function(event, callback) {
4634
4635 var listeners = this._getListeners(event),
4636 listener,
4637 listenerCallback,
4638 idx;
4639
4640 if (callback) {
4641
4642 // move through listeners from back to front
4643 // and remove matching listeners
4644 for (idx = listeners.length - 1; (listener = listeners[idx]); idx--) {
4645 listenerCallback = listener.callback;
4646
4647 if (listenerCallback === callback || listenerCallback[FN_REF] === callback) {
4648 listeners.splice(idx, 1);
4649 }
4650 }
4651 } else {
4652 // clear listeners
4653 listeners.length = 0;
4654 }
4655 };
4656
4657
4658 /**
4659 * A event that is emitted via the event bus.
4660 */
4661 function InternalEvent() { }
4662
4663 InternalEvent.prototype.stopPropagation = function() {
4664 this.cancelBubble = true;
4665 };
4666
4667 InternalEvent.prototype.preventDefault = function() {
4668 this.defaultPrevented = true;
4669 };
4670
4671 InternalEvent.prototype.init = function(data) {
4672 assign(this, data || {});
4673 };
4674
4675
4676 /**
4677 * Invoke function. Be fast...
4678 *
4679 * @param {Function} fn
4680 * @param {Array<Object>} args
4681 *
4682 * @return {Any}
4683 */
4684 function invokeFunction(fn, args) {
4685 return fn.apply(null, args);
4686 }
4687
4688 /**
4689 * SVGs for elements are generated by the {@link GraphicsFactory}.
4690 *
4691 * This utility gives quick access to the important semantic
4692 * parts of an element.
4693 */
4694
4695 /**
4696 * Returns the visual part of a diagram element
4697 *
4698 * @param {Snap<SVGElement>} gfx
4699 *
4700 * @return {Snap<SVGElement>}
4701 */
4702 function getVisual(gfx) {
4703 return query('.djs-visual', gfx);
4704 }
4705
4706 /**
4707 * Returns the children for a given diagram element.
4708 *
4709 * @param {Snap<SVGElement>} gfx
4710 * @return {Snap<SVGElement>}
4711 */
4712 function getChildren(gfx) {
4713 return gfx.parentNode.childNodes[1];
4714 }
4715
4716 /**
4717 * @param {<SVGElement>} element
4718 * @param {Number} x
4719 * @param {Number} y
4720 * @param {Number} angle
4721 * @param {Number} amount
4722 */
4723 function transform$1(gfx, x, y, angle, amount) {
4724 var translate = createTransform();
4725 translate.setTranslate(x, y);
4726
4727 var rotate = createTransform();
4728 rotate.setRotate(angle, 0, 0);
4729
4730 var scale = createTransform();
4731 scale.setScale(amount || 1, amount || 1);
4732
4733 transform(gfx, [ translate, rotate, scale ]);
4734 }
4735
4736
4737 /**
4738 * @param {SVGElement} element
4739 * @param {Number} x
4740 * @param {Number} y
4741 */
4742 function translate(gfx, x, y) {
4743 var translate = createTransform();
4744 translate.setTranslate(x, y);
4745
4746 transform(gfx, translate);
4747 }
4748
4749
4750 /**
4751 * @param {SVGElement} element
4752 * @param {Number} angle
4753 */
4754 function rotate(gfx, angle) {
4755 var rotate = createTransform();
4756 rotate.setRotate(angle, 0, 0);
4757
4758 transform(gfx, rotate);
4759 }
4760
4761 /**
4762 * A factory that creates graphical elements
4763 *
4764 * @param {EventBus} eventBus
4765 * @param {ElementRegistry} elementRegistry
4766 */
4767 function GraphicsFactory(eventBus, elementRegistry) {
4768 this._eventBus = eventBus;
4769 this._elementRegistry = elementRegistry;
4770 }
4771
4772 GraphicsFactory.$inject = [ 'eventBus' , 'elementRegistry' ];
4773
4774
4775 GraphicsFactory.prototype._getChildren = function(element) {
4776
4777 var gfx = this._elementRegistry.getGraphics(element);
4778
4779 var childrenGfx;
4780
4781 // root element
4782 if (!element.parent) {
4783 childrenGfx = gfx;
4784 } else {
4785 childrenGfx = getChildren(gfx);
4786 if (!childrenGfx) {
4787 childrenGfx = create('g');
4788 classes$1(childrenGfx).add('djs-children');
4789
4790 append(gfx.parentNode, childrenGfx);
4791 }
4792 }
4793
4794 return childrenGfx;
4795 };
4796
4797 /**
4798 * Clears the graphical representation of the element and returns the
4799 * cleared visual (the <g class="djs-visual" /> element).
4800 */
4801 GraphicsFactory.prototype._clear = function(gfx) {
4802 var visual = getVisual(gfx);
4803
4804 clear(visual);
4805
4806 return visual;
4807 };
4808
4809 /**
4810 * Creates a gfx container for shapes and connections
4811 *
4812 * The layout is as follows:
4813 *
4814 * <g class="djs-group">
4815 *
4816 * <!-- the gfx -->
4817 * <g class="djs-element djs-(shape|connection)">
4818 * <g class="djs-visual">
4819 * <!-- the renderer draws in here -->
4820 * </g>
4821 *
4822 * <!-- extensions (overlays, click box, ...) goes here
4823 * </g>
4824 *
4825 * <!-- the gfx child nodes -->
4826 * <g class="djs-children"></g>
4827 * </g>
4828 *
4829 * @param {Object} parent
4830 * @param {String} type the type of the element, i.e. shape | connection
4831 * @param {Number} [parentIndex] position to create container in parent
4832 */
4833 GraphicsFactory.prototype._createContainer = function(type, childrenGfx, parentIndex) {
4834 var outerGfx = create('g');
4835 classes$1(outerGfx).add('djs-group');
4836
4837 // insert node at position
4838 if (typeof parentIndex !== 'undefined') {
4839 prependTo$1(outerGfx, childrenGfx, childrenGfx.childNodes[parentIndex]);
4840 } else {
4841 append(childrenGfx, outerGfx);
4842 }
4843
4844 var gfx = create('g');
4845 classes$1(gfx).add('djs-element');
4846 classes$1(gfx).add('djs-' + type);
4847
4848 append(outerGfx, gfx);
4849
4850 // create visual
4851 var visual = create('g');
4852 classes$1(visual).add('djs-visual');
4853
4854 append(gfx, visual);
4855
4856 return gfx;
4857 };
4858
4859 GraphicsFactory.prototype.create = function(type, element, parentIndex) {
4860 var childrenGfx = this._getChildren(element.parent);
4861 return this._createContainer(type, childrenGfx, parentIndex);
4862 };
4863
4864 GraphicsFactory.prototype.updateContainments = function(elements) {
4865
4866 var self = this,
4867 elementRegistry = this._elementRegistry,
4868 parents;
4869
4870 parents = reduce(elements, function(map$$1, e) {
4871
4872 if (e.parent) {
4873 map$$1[e.parent.id] = e.parent;
4874 }
4875
4876 return map$$1;
4877 }, {});
4878
4879 // update all parents of changed and reorganized their children
4880 // in the correct order (as indicated in our model)
4881 forEach(parents, function(parent) {
4882
4883 var children = parent.children;
4884
4885 if (!children) {
4886 return;
4887 }
4888
4889 var childGfx = self._getChildren(parent);
4890
4891 forEach(children.slice().reverse(), function(c) {
4892 var gfx = elementRegistry.getGraphics(c);
4893
4894 prependTo$1(gfx.parentNode, childGfx);
4895 });
4896 });
4897 };
4898
4899 GraphicsFactory.prototype.drawShape = function(visual, element) {
4900 var eventBus = this._eventBus;
4901
4902 return eventBus.fire('render.shape', { gfx: visual, element: element });
4903 };
4904
4905 GraphicsFactory.prototype.getShapePath = function(element) {
4906 var eventBus = this._eventBus;
4907
4908 return eventBus.fire('render.getShapePath', element);
4909 };
4910
4911 GraphicsFactory.prototype.drawConnection = function(visual, element) {
4912 var eventBus = this._eventBus;
4913
4914 return eventBus.fire('render.connection', { gfx: visual, element: element });
4915 };
4916
4917 GraphicsFactory.prototype.getConnectionPath = function(waypoints) {
4918 var eventBus = this._eventBus;
4919
4920 return eventBus.fire('render.getConnectionPath', waypoints);
4921 };
4922
4923 GraphicsFactory.prototype.update = function(type, element, gfx) {
4924 // Do not update root element
4925 if (!element.parent) {
4926 return;
4927 }
4928
4929 var visual = this._clear(gfx);
4930
4931 // redraw
4932 if (type === 'shape') {
4933 this.drawShape(visual, element);
4934
4935 // update positioning
4936 translate(gfx, element.x, element.y);
4937 } else
4938 if (type === 'connection') {
4939 this.drawConnection(visual, element);
4940 } else {
4941 throw new Error('unknown type: ' + type);
4942 }
4943
4944 if (element.hidden) {
4945 attr$1(gfx, 'display', 'none');
4946 } else {
4947 attr$1(gfx, 'display', 'block');
4948 }
4949 };
4950
4951 GraphicsFactory.prototype.remove = function(element) {
4952 var gfx = this._elementRegistry.getGraphics(element);
4953
4954 // remove
4955 remove$1(gfx.parentNode);
4956 };
4957
4958
4959 // helpers //////////////////////
4960
4961 function prependTo$1(newNode, parentNode, siblingNode) {
4962 parentNode.insertBefore(newNode, siblingNode || parentNode.firstChild);
4963 }
4964
4965 var CoreModule = {
4966 __depends__: [ DrawModule ],
4967 __init__: [ 'canvas' ],
4968 canvas: [ 'type', Canvas ],
4969 elementRegistry: [ 'type', ElementRegistry ],
4970 elementFactory: [ 'type', ElementFactory ],
4971 eventBus: [ 'type', EventBus ],
4972 graphicsFactory: [ 'type', GraphicsFactory ]
4973 };
4974
4975 /**
4976 * Bootstrap an injector from a list of modules, instantiating a number of default components
4977 *
4978 * @ignore
4979 * @param {Array<didi.Module>} bootstrapModules
4980 *
4981 * @return {didi.Injector} a injector to use to access the components
4982 */
4983 function bootstrap(bootstrapModules) {
4984
4985 var modules = [],
4986 components = [];
4987
4988 function hasModule(m) {
4989 return modules.indexOf(m) >= 0;
4990 }
4991
4992 function addModule(m) {
4993 modules.push(m);
4994 }
4995
4996 function visit(m) {
4997 if (hasModule(m)) {
4998 return;
4999 }
5000
5001 (m.__depends__ || []).forEach(visit);
5002
5003 if (hasModule(m)) {
5004 return;
5005 }
5006
5007 addModule(m);
5008
5009 (m.__init__ || []).forEach(function(c) {
5010 components.push(c);
5011 });
5012 }
5013
5014 bootstrapModules.forEach(visit);
5015
5016 var injector = new Injector(modules);
5017
5018 components.forEach(function(c) {
5019
5020 try {
5021 // eagerly resolve component (fn or string)
5022 injector[typeof c === 'string' ? 'get' : 'invoke'](c);
5023 } catch (e) {
5024 console.error('Failed to instantiate component');
5025 console.error(e.stack);
5026
5027 throw e;
5028 }
5029 });
5030
5031 return injector;
5032 }
5033
5034 /**
5035 * Creates an injector from passed options.
5036 *
5037 * @ignore
5038 * @param {Object} options
5039 * @return {didi.Injector}
5040 */
5041 function createInjector(options) {
5042
5043 options = options || {};
5044
5045 var configModule = {
5046 'config': ['value', options]
5047 };
5048
5049 var modules = [ configModule, CoreModule ].concat(options.modules || []);
5050
5051 return bootstrap(modules);
5052 }
5053
5054
5055 /**
5056 * The main diagram-js entry point that bootstraps the diagram with the given
5057 * configuration.
5058 *
5059 * To register extensions with the diagram, pass them as Array<didi.Module> to the constructor.
5060 *
5061 * @class djs.Diagram
5062 * @memberOf djs
5063 * @constructor
5064 *
5065 * @example
5066 *
5067 * <caption>Creating a plug-in that logs whenever a shape is added to the canvas.</caption>
5068 *
5069 * // plug-in implemenentation
5070 * function MyLoggingPlugin(eventBus) {
5071 * eventBus.on('shape.added', function(event) {
5072 * console.log('shape ', event.shape, ' was added to the diagram');
5073 * });
5074 * }
5075 *
5076 * // export as module
5077 * export default {
5078 * __init__: [ 'myLoggingPlugin' ],
5079 * myLoggingPlugin: [ 'type', MyLoggingPlugin ]
5080 * };
5081 *
5082 *
5083 * // instantiate the diagram with the new plug-in
5084 *
5085 * import MyLoggingModule from 'path-to-my-logging-plugin';
5086 *
5087 * var diagram = new Diagram({
5088 * modules: [
5089 * MyLoggingModule
5090 * ]
5091 * });
5092 *
5093 * diagram.invoke([ 'canvas', function(canvas) {
5094 * // add shape to drawing canvas
5095 * canvas.addShape({ x: 10, y: 10 });
5096 * });
5097 *
5098 * // 'shape ... was added to the diagram' logged to console
5099 *
5100 * @param {Object} options
5101 * @param {Array<didi.Module>} [options.modules] external modules to instantiate with the diagram
5102 * @param {didi.Injector} [injector] an (optional) injector to bootstrap the diagram with
5103 */
5104 function Diagram(options, injector) {
5105
5106 // create injector unless explicitly specified
5107 this.injector = injector = injector || createInjector(options);
5108
5109 // API
5110
5111 /**
5112 * Resolves a diagram service
5113 *
5114 * @method Diagram#get
5115 *
5116 * @param {String} name the name of the diagram service to be retrieved
5117 * @param {Boolean} [strict=true] if false, resolve missing services to null
5118 */
5119 this.get = injector.get;
5120
5121 /**
5122 * Executes a function into which diagram services are injected
5123 *
5124 * @method Diagram#invoke
5125 *
5126 * @param {Function|Object[]} fn the function to resolve
5127 * @param {Object} locals a number of locals to use to resolve certain dependencies
5128 */
5129 this.invoke = injector.invoke;
5130
5131 // init
5132
5133 // indicate via event
5134
5135
5136 /**
5137 * An event indicating that all plug-ins are loaded.
5138 *
5139 * Use this event to fire other events to interested plug-ins
5140 *
5141 * @memberOf Diagram
5142 *
5143 * @event diagram.init
5144 *
5145 * @example
5146 *
5147 * eventBus.on('diagram.init', function() {
5148 * eventBus.fire('my-custom-event', { foo: 'BAR' });
5149 * });
5150 *
5151 * @type {Object}
5152 */
5153 this.get('eventBus').fire('diagram.init');
5154 }
5155
5156
5157 /**
5158 * Destroys the diagram
5159 *
5160 * @method Diagram#destroy
5161 */
5162 Diagram.prototype.destroy = function() {
5163 this.get('eventBus').fire('diagram.destroy');
5164 };
5165
5166 /**
5167 * Clear the diagram, removing all contents.
5168 */
5169 Diagram.prototype.clear = function() {
5170 this.get('eventBus').fire('diagram.clear');
5171 };
5172
5173 var Diagram$1 = /*#__PURE__*/Object.freeze({
5174 default: Diagram
5175 });
5176
5177 var require$$0 = getCjsExportFromNamespace(Diagram$1);
5178
5179 var diagramJs = require$$0;
5180
5181 /**
5182 * Moddle base element.
5183 */
5184 function Base$1() { }
5185
5186 Base$1.prototype.get = function(name) {
5187 return this.$model.properties.get(this, name);
5188 };
5189
5190 Base$1.prototype.set = function(name, value) {
5191 this.$model.properties.set(this, name, value);
5192 };
5193
5194 /**
5195 * A model element factory.
5196 *
5197 * @param {Moddle} model
5198 * @param {Properties} properties
5199 */
5200 function Factory(model, properties) {
5201 this.model = model;
5202 this.properties = properties;
5203 }
5204
5205
5206 Factory.prototype.createType = function(descriptor) {
5207
5208 var model = this.model;
5209
5210 var props = this.properties,
5211 prototype = Object.create(Base$1.prototype);
5212
5213 // initialize default values
5214 forEach(descriptor.properties, function(p) {
5215 if (!p.isMany && p.default !== undefined) {
5216 prototype[p.name] = p.default;
5217 }
5218 });
5219
5220 props.defineModel(prototype, model);
5221 props.defineDescriptor(prototype, descriptor);
5222
5223 var name = descriptor.ns.name;
5224
5225 /**
5226 * The new type constructor
5227 */
5228 function ModdleElement(attrs) {
5229 props.define(this, '$type', { value: name, enumerable: true });
5230 props.define(this, '$attrs', { value: {} });
5231 props.define(this, '$parent', { writable: true });
5232
5233 forEach(attrs, bind(function(val, key) {
5234 this.set(key, val);
5235 }, this));
5236 }
5237
5238 ModdleElement.prototype = prototype;
5239
5240 ModdleElement.hasType = prototype.$instanceOf = this.model.hasType;
5241
5242 // static links
5243 props.defineModel(ModdleElement, model);
5244 props.defineDescriptor(ModdleElement, descriptor);
5245
5246 return ModdleElement;
5247 };
5248
5249 /**
5250 * Built-in moddle types
5251 */
5252 var BUILTINS = {
5253 String: true,
5254 Boolean: true,
5255 Integer: true,
5256 Real: true,
5257 Element: true
5258 };
5259
5260 /**
5261 * Converters for built in types from string representations
5262 */
5263 var TYPE_CONVERTERS = {
5264 String: function(s) { return s; },
5265 Boolean: function(s) { return s === 'true'; },
5266 Integer: function(s) { return parseInt(s, 10); },
5267 Real: function(s) { return parseFloat(s, 10); }
5268 };
5269
5270 /**
5271 * Convert a type to its real representation
5272 */
5273 function coerceType(type, value) {
5274
5275 var converter = TYPE_CONVERTERS[type];
5276
5277 if (converter) {
5278 return converter(value);
5279 } else {
5280 return value;
5281 }
5282 }
5283
5284 /**
5285 * Return whether the given type is built-in
5286 */
5287 function isBuiltIn(type) {
5288 return !!BUILTINS[type];
5289 }
5290
5291 /**
5292 * Return whether the given type is simple
5293 */
5294 function isSimple(type) {
5295 return !!TYPE_CONVERTERS[type];
5296 }
5297
5298 /**
5299 * Parses a namespaced attribute name of the form (ns:)localName to an object,
5300 * given a default prefix to assume in case no explicit namespace is given.
5301 *
5302 * @param {String} name
5303 * @param {String} [defaultPrefix] the default prefix to take, if none is present.
5304 *
5305 * @return {Object} the parsed name
5306 */
5307 function parseName(name, defaultPrefix) {
5308 var parts = name.split(/:/),
5309 localName, prefix;
5310
5311 // no prefix (i.e. only local name)
5312 if (parts.length === 1) {
5313 localName = name;
5314 prefix = defaultPrefix;
5315 } else
5316 // prefix + local name
5317 if (parts.length === 2) {
5318 localName = parts[1];
5319 prefix = parts[0];
5320 } else {
5321 throw new Error('expected <prefix:localName> or <localName>, got ' + name);
5322 }
5323
5324 name = (prefix ? prefix + ':' : '') + localName;
5325
5326 return {
5327 name: name,
5328 prefix: prefix,
5329 localName: localName
5330 };
5331 }
5332
5333 /**
5334 * A utility to build element descriptors.
5335 */
5336 function DescriptorBuilder(nameNs) {
5337 this.ns = nameNs;
5338 this.name = nameNs.name;
5339 this.allTypes = [];
5340 this.allTypesByName = {};
5341 this.properties = [];
5342 this.propertiesByName = {};
5343 }
5344
5345
5346 DescriptorBuilder.prototype.build = function() {
5347 return pick(this, [
5348 'ns',
5349 'name',
5350 'allTypes',
5351 'allTypesByName',
5352 'properties',
5353 'propertiesByName',
5354 'bodyProperty',
5355 'idProperty'
5356 ]);
5357 };
5358
5359 /**
5360 * Add property at given index.
5361 *
5362 * @param {Object} p
5363 * @param {Number} [idx]
5364 * @param {Boolean} [validate=true]
5365 */
5366 DescriptorBuilder.prototype.addProperty = function(p, idx, validate) {
5367
5368 if (typeof idx === 'boolean') {
5369 validate = idx;
5370 idx = undefined;
5371 }
5372
5373 this.addNamedProperty(p, validate !== false);
5374
5375 var properties = this.properties;
5376
5377 if (idx !== undefined) {
5378 properties.splice(idx, 0, p);
5379 } else {
5380 properties.push(p);
5381 }
5382 };
5383
5384
5385 DescriptorBuilder.prototype.replaceProperty = function(oldProperty, newProperty, replace) {
5386 var oldNameNs = oldProperty.ns;
5387
5388 var props = this.properties,
5389 propertiesByName = this.propertiesByName,
5390 rename = oldProperty.name !== newProperty.name;
5391
5392 if (oldProperty.isId) {
5393 if (!newProperty.isId) {
5394 throw new Error(
5395 'property <' + newProperty.ns.name + '> must be id property ' +
5396 'to refine <' + oldProperty.ns.name + '>');
5397 }
5398
5399 this.setIdProperty(newProperty, false);
5400 }
5401
5402 if (oldProperty.isBody) {
5403
5404 if (!newProperty.isBody) {
5405 throw new Error(
5406 'property <' + newProperty.ns.name + '> must be body property ' +
5407 'to refine <' + oldProperty.ns.name + '>');
5408 }
5409
5410 // TODO: Check compatibility
5411 this.setBodyProperty(newProperty, false);
5412 }
5413
5414 // validate existence and get location of old property
5415 var idx = props.indexOf(oldProperty);
5416 if (idx === -1) {
5417 throw new Error('property <' + oldNameNs.name + '> not found in property list');
5418 }
5419
5420 // remove old property
5421 props.splice(idx, 1);
5422
5423 // replacing the named property is intentional
5424 //
5425 // * validate only if this is a "rename" operation
5426 // * add at specific index unless we "replace"
5427 //
5428 this.addProperty(newProperty, replace ? undefined : idx, rename);
5429
5430 // make new property available under old name
5431 propertiesByName[oldNameNs.name] = propertiesByName[oldNameNs.localName] = newProperty;
5432 };
5433
5434
5435 DescriptorBuilder.prototype.redefineProperty = function(p, targetPropertyName, replace) {
5436
5437 var nsPrefix = p.ns.prefix;
5438 var parts = targetPropertyName.split('#');
5439
5440 var name = parseName(parts[0], nsPrefix);
5441 var attrName = parseName(parts[1], name.prefix).name;
5442
5443 var redefinedProperty = this.propertiesByName[attrName];
5444 if (!redefinedProperty) {
5445 throw new Error('refined property <' + attrName + '> not found');
5446 } else {
5447 this.replaceProperty(redefinedProperty, p, replace);
5448 }
5449
5450 delete p.redefines;
5451 };
5452
5453 DescriptorBuilder.prototype.addNamedProperty = function(p, validate) {
5454 var ns = p.ns,
5455 propsByName = this.propertiesByName;
5456
5457 if (validate) {
5458 this.assertNotDefined(p, ns.name);
5459 this.assertNotDefined(p, ns.localName);
5460 }
5461
5462 propsByName[ns.name] = propsByName[ns.localName] = p;
5463 };
5464
5465 DescriptorBuilder.prototype.removeNamedProperty = function(p) {
5466 var ns = p.ns,
5467 propsByName = this.propertiesByName;
5468
5469 delete propsByName[ns.name];
5470 delete propsByName[ns.localName];
5471 };
5472
5473 DescriptorBuilder.prototype.setBodyProperty = function(p, validate) {
5474
5475 if (validate && this.bodyProperty) {
5476 throw new Error(
5477 'body property defined multiple times ' +
5478 '(<' + this.bodyProperty.ns.name + '>, <' + p.ns.name + '>)');
5479 }
5480
5481 this.bodyProperty = p;
5482 };
5483
5484 DescriptorBuilder.prototype.setIdProperty = function(p, validate) {
5485
5486 if (validate && this.idProperty) {
5487 throw new Error(
5488 'id property defined multiple times ' +
5489 '(<' + this.idProperty.ns.name + '>, <' + p.ns.name + '>)');
5490 }
5491
5492 this.idProperty = p;
5493 };
5494
5495 DescriptorBuilder.prototype.assertNotDefined = function(p, name) {
5496 var propertyName = p.name,
5497 definedProperty = this.propertiesByName[propertyName];
5498
5499 if (definedProperty) {
5500 throw new Error(
5501 'property <' + propertyName + '> already defined; ' +
5502 'override of <' + definedProperty.definedBy.ns.name + '#' + definedProperty.ns.name + '> by ' +
5503 '<' + p.definedBy.ns.name + '#' + p.ns.name + '> not allowed without redefines');
5504 }
5505 };
5506
5507 DescriptorBuilder.prototype.hasProperty = function(name) {
5508 return this.propertiesByName[name];
5509 };
5510
5511 DescriptorBuilder.prototype.addTrait = function(t, inherited) {
5512
5513 var typesByName = this.allTypesByName,
5514 types = this.allTypes;
5515
5516 var typeName = t.name;
5517
5518 if (typeName in typesByName) {
5519 return;
5520 }
5521
5522 forEach(t.properties, bind(function(p) {
5523
5524 // clone property to allow extensions
5525 p = assign({}, p, {
5526 name: p.ns.localName,
5527 inherited: inherited
5528 });
5529
5530 Object.defineProperty(p, 'definedBy', {
5531 value: t
5532 });
5533
5534 var replaces = p.replaces,
5535 redefines = p.redefines;
5536
5537 // add replace/redefine support
5538 if (replaces || redefines) {
5539 this.redefineProperty(p, replaces || redefines, replaces);
5540 } else {
5541 if (p.isBody) {
5542 this.setBodyProperty(p);
5543 }
5544 if (p.isId) {
5545 this.setIdProperty(p);
5546 }
5547 this.addProperty(p);
5548 }
5549 }, this));
5550
5551 types.push(t);
5552 typesByName[typeName] = t;
5553 };
5554
5555 /**
5556 * A registry of Moddle packages.
5557 *
5558 * @param {Array<Package>} packages
5559 * @param {Properties} properties
5560 */
5561 function Registry(packages, properties) {
5562 this.packageMap = {};
5563 this.typeMap = {};
5564
5565 this.packages = [];
5566
5567 this.properties = properties;
5568
5569 forEach(packages, bind(this.registerPackage, this));
5570 }
5571
5572
5573 Registry.prototype.getPackage = function(uriOrPrefix) {
5574 return this.packageMap[uriOrPrefix];
5575 };
5576
5577 Registry.prototype.getPackages = function() {
5578 return this.packages;
5579 };
5580
5581
5582 Registry.prototype.registerPackage = function(pkg) {
5583
5584 // copy package
5585 pkg = assign({}, pkg);
5586
5587 var pkgMap = this.packageMap;
5588
5589 ensureAvailable(pkgMap, pkg, 'prefix');
5590 ensureAvailable(pkgMap, pkg, 'uri');
5591
5592 // register types
5593 forEach(pkg.types, bind(function(descriptor) {
5594 this.registerType(descriptor, pkg);
5595 }, this));
5596
5597 pkgMap[pkg.uri] = pkgMap[pkg.prefix] = pkg;
5598 this.packages.push(pkg);
5599 };
5600
5601
5602 /**
5603 * Register a type from a specific package with us
5604 */
5605 Registry.prototype.registerType = function(type, pkg) {
5606
5607 type = assign({}, type, {
5608 superClass: (type.superClass || []).slice(),
5609 extends: (type.extends || []).slice(),
5610 properties: (type.properties || []).slice(),
5611 meta: assign((type.meta || {}))
5612 });
5613
5614 var ns = parseName(type.name, pkg.prefix),
5615 name = ns.name,
5616 propertiesByName = {};
5617
5618 // parse properties
5619 forEach(type.properties, bind(function(p) {
5620
5621 // namespace property names
5622 var propertyNs = parseName(p.name, ns.prefix),
5623 propertyName = propertyNs.name;
5624
5625 // namespace property types
5626 if (!isBuiltIn(p.type)) {
5627 p.type = parseName(p.type, propertyNs.prefix).name;
5628 }
5629
5630 assign(p, {
5631 ns: propertyNs,
5632 name: propertyName
5633 });
5634
5635 propertiesByName[propertyName] = p;
5636 }, this));
5637
5638 // update ns + name
5639 assign(type, {
5640 ns: ns,
5641 name: name,
5642 propertiesByName: propertiesByName
5643 });
5644
5645 forEach(type.extends, bind(function(extendsName) {
5646 var extended = this.typeMap[extendsName];
5647
5648 extended.traits = extended.traits || [];
5649 extended.traits.push(name);
5650 }, this));
5651
5652 // link to package
5653 this.definePackage(type, pkg);
5654
5655 // register
5656 this.typeMap[name] = type;
5657 };
5658
5659
5660 /**
5661 * Traverse the type hierarchy from bottom to top,
5662 * calling iterator with (type, inherited) for all elements in
5663 * the inheritance chain.
5664 *
5665 * @param {Object} nsName
5666 * @param {Function} iterator
5667 * @param {Boolean} [trait=false]
5668 */
5669 Registry.prototype.mapTypes = function(nsName, iterator, trait) {
5670
5671 var type = isBuiltIn(nsName.name) ? { name: nsName.name } : this.typeMap[nsName.name];
5672
5673 var self = this;
5674
5675 /**
5676 * Traverse the selected trait.
5677 *
5678 * @param {String} cls
5679 */
5680 function traverseTrait(cls) {
5681 return traverseSuper(cls, true);
5682 }
5683
5684 /**
5685 * Traverse the selected super type or trait
5686 *
5687 * @param {String} cls
5688 * @param {Boolean} [trait=false]
5689 */
5690 function traverseSuper(cls, trait) {
5691 var parentNs = parseName(cls, isBuiltIn(cls) ? '' : nsName.prefix);
5692 self.mapTypes(parentNs, iterator, trait);
5693 }
5694
5695 if (!type) {
5696 throw new Error('unknown type <' + nsName.name + '>');
5697 }
5698
5699 forEach(type.superClass, trait ? traverseTrait : traverseSuper);
5700
5701 // call iterator with (type, inherited=!trait)
5702 iterator(type, !trait);
5703
5704 forEach(type.traits, traverseTrait);
5705 };
5706
5707
5708 /**
5709 * Returns the effective descriptor for a type.
5710 *
5711 * @param {String} type the namespaced name (ns:localName) of the type
5712 *
5713 * @return {Descriptor} the resulting effective descriptor
5714 */
5715 Registry.prototype.getEffectiveDescriptor = function(name) {
5716
5717 var nsName = parseName(name);
5718
5719 var builder = new DescriptorBuilder(nsName);
5720
5721 this.mapTypes(nsName, function(type, inherited) {
5722 builder.addTrait(type, inherited);
5723 });
5724
5725 var descriptor = builder.build();
5726
5727 // define package link
5728 this.definePackage(descriptor, descriptor.allTypes[descriptor.allTypes.length - 1].$pkg);
5729
5730 return descriptor;
5731 };
5732
5733
5734 Registry.prototype.definePackage = function(target, pkg) {
5735 this.properties.define(target, '$pkg', { value: pkg });
5736 };
5737
5738
5739
5740 ///////// helpers ////////////////////////////
5741
5742 function ensureAvailable(packageMap, pkg, identifierKey) {
5743
5744 var value = pkg[identifierKey];
5745
5746 if (value in packageMap) {
5747 throw new Error('package with ' + identifierKey + ' <' + value + '> already defined');
5748 }
5749 }
5750
5751 /**
5752 * A utility that gets and sets properties of model elements.
5753 *
5754 * @param {Model} model
5755 */
5756 function Properties(model) {
5757 this.model = model;
5758 }
5759
5760
5761 /**
5762 * Sets a named property on the target element.
5763 * If the value is undefined, the property gets deleted.
5764 *
5765 * @param {Object} target
5766 * @param {String} name
5767 * @param {Object} value
5768 */
5769 Properties.prototype.set = function(target, name, value) {
5770
5771 var property = this.model.getPropertyDescriptor(target, name);
5772
5773 var propertyName = property && property.name;
5774
5775 if (isUndefined$1(value)) {
5776 // unset the property, if the specified value is undefined;
5777 // delete from $attrs (for extensions) or the target itself
5778 if (property) {
5779 delete target[propertyName];
5780 } else {
5781 delete target.$attrs[name];
5782 }
5783 } else {
5784 // set the property, defining well defined properties on the fly
5785 // or simply updating them in target.$attrs (for extensions)
5786 if (property) {
5787 if (propertyName in target) {
5788 target[propertyName] = value;
5789 } else {
5790 defineProperty$1(target, property, value);
5791 }
5792 } else {
5793 target.$attrs[name] = value;
5794 }
5795 }
5796 };
5797
5798 /**
5799 * Returns the named property of the given element
5800 *
5801 * @param {Object} target
5802 * @param {String} name
5803 *
5804 * @return {Object}
5805 */
5806 Properties.prototype.get = function(target, name) {
5807
5808 var property = this.model.getPropertyDescriptor(target, name);
5809
5810 if (!property) {
5811 return target.$attrs[name];
5812 }
5813
5814 var propertyName = property.name;
5815
5816 // check if access to collection property and lazily initialize it
5817 if (!target[propertyName] && property.isMany) {
5818 defineProperty$1(target, property, []);
5819 }
5820
5821 return target[propertyName];
5822 };
5823
5824
5825 /**
5826 * Define a property on the target element
5827 *
5828 * @param {Object} target
5829 * @param {String} name
5830 * @param {Object} options
5831 */
5832 Properties.prototype.define = function(target, name, options) {
5833 Object.defineProperty(target, name, options);
5834 };
5835
5836
5837 /**
5838 * Define the descriptor for an element
5839 */
5840 Properties.prototype.defineDescriptor = function(target, descriptor) {
5841 this.define(target, '$descriptor', { value: descriptor });
5842 };
5843
5844 /**
5845 * Define the model for an element
5846 */
5847 Properties.prototype.defineModel = function(target, model) {
5848 this.define(target, '$model', { value: model });
5849 };
5850
5851
5852 function isUndefined$1(val) {
5853 return typeof val === 'undefined';
5854 }
5855
5856 function defineProperty$1(target, property, value) {
5857 Object.defineProperty(target, property.name, {
5858 enumerable: !property.isReference,
5859 writable: true,
5860 value: value,
5861 configurable: true
5862 });
5863 }
5864
5865 //// Moddle implementation /////////////////////////////////////////////////
5866
5867 /**
5868 * @class Moddle
5869 *
5870 * A model that can be used to create elements of a specific type.
5871 *
5872 * @example
5873 *
5874 * var Moddle = require('moddle');
5875 *
5876 * var pkg = {
5877 * name: 'mypackage',
5878 * prefix: 'my',
5879 * types: [
5880 * { name: 'Root' }
5881 * ]
5882 * };
5883 *
5884 * var moddle = new Moddle([pkg]);
5885 *
5886 * @param {Array<Package>} packages the packages to contain
5887 */
5888 function Moddle(packages) {
5889
5890 this.properties = new Properties(this);
5891
5892 this.factory = new Factory(this, this.properties);
5893 this.registry = new Registry(packages, this.properties);
5894
5895 this.typeCache = {};
5896 }
5897
5898
5899 /**
5900 * Create an instance of the specified type.
5901 *
5902 * @method Moddle#create
5903 *
5904 * @example
5905 *
5906 * var foo = moddle.create('my:Foo');
5907 * var bar = moddle.create('my:Bar', { id: 'BAR_1' });
5908 *
5909 * @param {String|Object} descriptor the type descriptor or name know to the model
5910 * @param {Object} attrs a number of attributes to initialize the model instance with
5911 * @return {Object} model instance
5912 */
5913 Moddle.prototype.create = function(descriptor, attrs) {
5914 var Type = this.getType(descriptor);
5915
5916 if (!Type) {
5917 throw new Error('unknown type <' + descriptor + '>');
5918 }
5919
5920 return new Type(attrs);
5921 };
5922
5923
5924 /**
5925 * Returns the type representing a given descriptor
5926 *
5927 * @method Moddle#getType
5928 *
5929 * @example
5930 *
5931 * var Foo = moddle.getType('my:Foo');
5932 * var foo = new Foo({ 'id' : 'FOO_1' });
5933 *
5934 * @param {String|Object} descriptor the type descriptor or name know to the model
5935 * @return {Object} the type representing the descriptor
5936 */
5937 Moddle.prototype.getType = function(descriptor) {
5938
5939 var cache = this.typeCache;
5940
5941 var name = isString(descriptor) ? descriptor : descriptor.ns.name;
5942
5943 var type = cache[name];
5944
5945 if (!type) {
5946 descriptor = this.registry.getEffectiveDescriptor(name);
5947 type = cache[name] = this.factory.createType(descriptor);
5948 }
5949
5950 return type;
5951 };
5952
5953
5954 /**
5955 * Creates an any-element type to be used within model instances.
5956 *
5957 * This can be used to create custom elements that lie outside the meta-model.
5958 * The created element contains all the meta-data required to serialize it
5959 * as part of meta-model elements.
5960 *
5961 * @method Moddle#createAny
5962 *
5963 * @example
5964 *
5965 * var foo = moddle.createAny('vendor:Foo', 'http://vendor', {
5966 * value: 'bar'
5967 * });
5968 *
5969 * var container = moddle.create('my:Container', 'http://my', {
5970 * any: [ foo ]
5971 * });
5972 *
5973 * // go ahead and serialize the stuff
5974 *
5975 *
5976 * @param {String} name the name of the element
5977 * @param {String} nsUri the namespace uri of the element
5978 * @param {Object} [properties] a map of properties to initialize the instance with
5979 * @return {Object} the any type instance
5980 */
5981 Moddle.prototype.createAny = function(name, nsUri, properties) {
5982
5983 var nameNs = parseName(name);
5984
5985 var element = {
5986 $type: name,
5987 $instanceOf: function(type) {
5988 return type === this.$type;
5989 }
5990 };
5991
5992 var descriptor = {
5993 name: name,
5994 isGeneric: true,
5995 ns: {
5996 prefix: nameNs.prefix,
5997 localName: nameNs.localName,
5998 uri: nsUri
5999 }
6000 };
6001
6002 this.properties.defineDescriptor(element, descriptor);
6003 this.properties.defineModel(element, this);
6004 this.properties.define(element, '$parent', { enumerable: false, writable: true });
6005
6006 forEach(properties, function(a, key) {
6007 if (isObject(a) && a.value !== undefined) {
6008 element[a.name] = a.value;
6009 } else {
6010 element[key] = a;
6011 }
6012 });
6013
6014 return element;
6015 };
6016
6017 /**
6018 * Returns a registered package by uri or prefix
6019 *
6020 * @return {Object} the package
6021 */
6022 Moddle.prototype.getPackage = function(uriOrPrefix) {
6023 return this.registry.getPackage(uriOrPrefix);
6024 };
6025
6026 /**
6027 * Returns a snapshot of all known packages
6028 *
6029 * @return {Object} the package
6030 */
6031 Moddle.prototype.getPackages = function() {
6032 return this.registry.getPackages();
6033 };
6034
6035 /**
6036 * Returns the descriptor for an element
6037 */
6038 Moddle.prototype.getElementDescriptor = function(element) {
6039 return element.$descriptor;
6040 };
6041
6042 /**
6043 * Returns true if the given descriptor or instance
6044 * represents the given type.
6045 *
6046 * May be applied to this, if element is omitted.
6047 */
6048 Moddle.prototype.hasType = function(element, type) {
6049 if (type === undefined) {
6050 type = element;
6051 element = this;
6052 }
6053
6054 var descriptor = element.$model.getElementDescriptor(element);
6055
6056 return (type in descriptor.allTypesByName);
6057 };
6058
6059 /**
6060 * Returns the descriptor of an elements named property
6061 */
6062 Moddle.prototype.getPropertyDescriptor = function(element, property) {
6063 return this.getElementDescriptor(element).propertiesByName[property];
6064 };
6065
6066 /**
6067 * Returns a mapped type's descriptor
6068 */
6069 Moddle.prototype.getTypeDescriptor = function(type) {
6070 return this.registry.typeMap[type];
6071 };
6072
6073 var tinyStack = createCommonjsModule(function (module, exports) {
6074
6075 var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
6076
6077 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6078
6079 /**
6080 * Tiny stack for browser or server
6081 *
6082 * @author Jason Mulligan <jason.mulligan@avoidwork.com>
6083 * @copyright 2018
6084 * @license BSD-3-Clause
6085 * @link http://avoidwork.github.io/tiny-stack
6086 * @version 1.1.0
6087 */
6088 (function (global) {
6089
6090 var TinyStack = function () {
6091 function TinyStack() {
6092 _classCallCheck(this, TinyStack);
6093
6094 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
6095 args[_key] = arguments[_key];
6096 }
6097
6098 this.data = [null].concat(args);
6099 this.top = this.data.length - 1;
6100 }
6101
6102 _createClass(TinyStack, [{
6103 key: "clear",
6104 value: function clear() {
6105 this.data.length = 1;
6106 this.top = 0;
6107
6108 return this;
6109 }
6110 }, {
6111 key: "empty",
6112 value: function empty() {
6113 return this.top === 0;
6114 }
6115 }, {
6116 key: "length",
6117 value: function length() {
6118 return this.top;
6119 }
6120 }, {
6121 key: "peek",
6122 value: function peek() {
6123 return this.data[this.top];
6124 }
6125 }, {
6126 key: "pop",
6127 value: function pop() {
6128 var result = void 0;
6129
6130 if (this.top > 0) {
6131 result = this.data.pop();
6132 this.top--;
6133 }
6134
6135 return result;
6136 }
6137 }, {
6138 key: "push",
6139 value: function push(arg) {
6140 this.data[++this.top] = arg;
6141
6142 return this;
6143 }
6144 }, {
6145 key: "search",
6146 value: function search(arg) {
6147 var index = this.data.indexOf(arg);
6148
6149 return index === -1 ? -1 : this.data.length - index;
6150 }
6151 }]);
6152
6153 return TinyStack;
6154 }();
6155
6156 function factory() {
6157 for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
6158 args[_key2] = arguments[_key2];
6159 }
6160
6161 return new (Function.prototype.bind.apply(TinyStack, [null].concat(args)))();
6162 }
6163
6164 // Node, AMD & window supported
6165 {
6166 module.exports = factory;
6167 }
6168 })(typeof window !== "undefined" ? window : commonjsGlobal);
6169 });
6170
6171 var fromCharCode = String.fromCharCode;
6172
6173 var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
6174
6175 var ENTITY_PATTERN = /&#(\d+);|&#x([0-9a-f]+);|&(\w+);/ig;
6176
6177 var ENTITY_MAPPING = {
6178 'amp': '&',
6179 'apos': '\'',
6180 'gt': '>',
6181 'lt': '<',
6182 'quot': '"'
6183 };
6184
6185 // map UPPERCASE variants of supported special chars
6186 Object.keys(ENTITY_MAPPING).forEach(function(k) {
6187 ENTITY_MAPPING[k.toUpperCase()] = ENTITY_MAPPING[k];
6188 });
6189
6190
6191 function replaceEntities(_, d, x, z) {
6192
6193 // reserved names, i.e. &nbsp;
6194 if (z) {
6195 if (hasOwnProperty$1.call(ENTITY_MAPPING, z)) {
6196 return ENTITY_MAPPING[z];
6197 } else {
6198 // fall back to original value
6199 return '&' + z + ';';
6200 }
6201 }
6202
6203 // decimal encoded char
6204 if (d) {
6205 return fromCharCode(d);
6206 }
6207
6208 // hex encoded char
6209 return fromCharCode(parseInt(x, 16));
6210 }
6211
6212
6213 /**
6214 * A basic entity decoder that can decode a minimal
6215 * sub-set of reserved names (&amp;) as well as
6216 * hex (&#xaaf;) and decimal (&#1231;) encoded characters.
6217 *
6218 * @param {string} str
6219 *
6220 * @return {string} decoded string
6221 */
6222 function decodeEntities(s) {
6223 if (s.length > 3 && s.indexOf('&') !== -1) {
6224 return s.replace(ENTITY_PATTERN, replaceEntities);
6225 }
6226
6227 return s;
6228 }
6229
6230 var XSI_URI = 'http://www.w3.org/2001/XMLSchema-instance';
6231 var XSI_PREFIX = 'xsi';
6232 var XSI_TYPE = 'xsi:type';
6233
6234 var NON_WHITESPACE_OUTSIDE_ROOT_NODE = 'non-whitespace outside of root node';
6235
6236 function error(msg) {
6237 return new Error(msg);
6238 }
6239
6240 function missingNamespaceForPrefix(prefix) {
6241 return 'missing namespace for prefix <' + prefix + '>';
6242 }
6243
6244 function getter(getFn) {
6245 return {
6246 'get': getFn,
6247 'enumerable': true
6248 };
6249 }
6250
6251 function cloneNsMatrix(nsMatrix) {
6252 var clone = {}, key;
6253 for (key in nsMatrix) {
6254 clone[key] = nsMatrix[key];
6255 }
6256 return clone;
6257 }
6258
6259 function uriPrefix(prefix) {
6260 return prefix + '$uri';
6261 }
6262
6263 function buildNsMatrix(nsUriToPrefix) {
6264 var nsMatrix = {},
6265 uri,
6266 prefix;
6267
6268 for (uri in nsUriToPrefix) {
6269 prefix = nsUriToPrefix[uri];
6270 nsMatrix[prefix] = prefix;
6271 nsMatrix[uriPrefix(prefix)] = uri;
6272 }
6273
6274 return nsMatrix;
6275 }
6276
6277 function noopGetContext() {
6278 return { 'line': 0, 'column': 0 };
6279 }
6280
6281 function throwFunc(err) {
6282 throw err;
6283 }
6284
6285 /**
6286 * Creates a new parser with the given options.
6287 *
6288 * @constructor
6289 *
6290 * @param {!Object<string, ?>=} options
6291 */
6292 function Parser(options) {
6293
6294 if (!this) {
6295 return new Parser(options);
6296 }
6297
6298 var proxy = options && options['proxy'];
6299
6300 var onText,
6301 onOpenTag,
6302 onCloseTag,
6303 onCDATA,
6304 onError = throwFunc,
6305 onWarning,
6306 onComment,
6307 onQuestion,
6308 onAttention;
6309
6310 var getContext = noopGetContext;
6311
6312 /**
6313 * Do we need to parse the current elements attributes for namespaces?
6314 *
6315 * @type {boolean}
6316 */
6317 var maybeNS = false;
6318
6319 /**
6320 * Do we process namespaces at all?
6321 *
6322 * @type {boolean}
6323 */
6324 var isNamespace = false;
6325
6326 /**
6327 * The caught error returned on parse end
6328 *
6329 * @type {Error}
6330 */
6331 var returnError = null;
6332
6333 /**
6334 * Should we stop parsing?
6335 *
6336 * @type {boolean}
6337 */
6338 var parseStop = false;
6339
6340 /**
6341 * A map of { uri: prefix } used by the parser.
6342 *
6343 * This map will ensure we can normalize prefixes during processing;
6344 * for each uri, only one prefix will be exposed to the handlers.
6345 *
6346 * @type {!Object<string, string>}}
6347 */
6348 var nsUriToPrefix;
6349
6350 /**
6351 * Handle parse error.
6352 *
6353 * @param {string|Error} err
6354 */
6355 function handleError(err) {
6356 if (!(err instanceof Error)) {
6357 err = error(err);
6358 }
6359
6360 returnError = err;
6361
6362 onError(err, getContext);
6363 }
6364
6365 /**
6366 * Handle parse error.
6367 *
6368 * @param {string|Error} err
6369 */
6370 function handleWarning(err) {
6371
6372 if (!onWarning) {
6373 return;
6374 }
6375
6376 if (!(err instanceof Error)) {
6377 err = error(err);
6378 }
6379
6380 onWarning(err, getContext);
6381 }
6382
6383 /**
6384 * Register parse listener.
6385 *
6386 * @param {string} name
6387 * @param {Function} cb
6388 *
6389 * @return {Parser}
6390 */
6391 this['on'] = function(name, cb) {
6392
6393 if (typeof cb !== 'function') {
6394 throw error('required args <name, cb>');
6395 }
6396
6397 switch (name) {
6398 case 'openTag': onOpenTag = cb; break;
6399 case 'text': onText = cb; break;
6400 case 'closeTag': onCloseTag = cb; break;
6401 case 'error': onError = cb; break;
6402 case 'warn': onWarning = cb; break;
6403 case 'cdata': onCDATA = cb; break;
6404 case 'attention': onAttention = cb; break; // <!XXXXX zzzz="eeee">
6405 case 'question': onQuestion = cb; break; // <? .... ?>
6406 case 'comment': onComment = cb; break;
6407 default:
6408 throw error('unsupported event: ' + name);
6409 }
6410
6411 return this;
6412 };
6413
6414 /**
6415 * Set the namespace to prefix mapping.
6416 *
6417 * @example
6418 *
6419 * parser.ns({
6420 * 'http://foo': 'foo',
6421 * 'http://bar': 'bar'
6422 * });
6423 *
6424 * @param {!Object<string, string>} nsMap
6425 *
6426 * @return {Parser}
6427 */
6428 this['ns'] = function(nsMap) {
6429
6430 if (typeof nsMap === 'undefined') {
6431 nsMap = {};
6432 }
6433
6434 if (typeof nsMap !== 'object') {
6435 throw error('required args <nsMap={}>');
6436 }
6437
6438 var _nsUriToPrefix = {}, k;
6439
6440 for (k in nsMap) {
6441 _nsUriToPrefix[k] = nsMap[k];
6442 }
6443
6444 // FORCE default mapping for schema instance
6445 _nsUriToPrefix[XSI_URI] = XSI_PREFIX;
6446
6447 isNamespace = true;
6448 nsUriToPrefix = _nsUriToPrefix;
6449
6450 return this;
6451 };
6452
6453 /**
6454 * Parse xml string.
6455 *
6456 * @param {string} xml
6457 *
6458 * @return {Error} returnError, if not thrown
6459 */
6460 this['parse'] = function(xml) {
6461 if (typeof xml !== 'string') {
6462 throw error('required args <xml=string>');
6463 }
6464
6465 returnError = null;
6466
6467 parse(xml);
6468
6469 getContext = noopGetContext;
6470 parseStop = false;
6471
6472 return returnError;
6473 };
6474
6475 /**
6476 * Stop parsing.
6477 */
6478 this['stop'] = function() {
6479 parseStop = true;
6480 };
6481
6482 /**
6483 * Parse string, invoking configured listeners on element.
6484 *
6485 * @param {string} xml
6486 */
6487 function parse(xml) {
6488 var nsMatrixStack = isNamespace ? [] : null,
6489 nsMatrix = isNamespace ? buildNsMatrix(nsUriToPrefix) : null,
6490 _nsMatrix,
6491 nodeStack = [],
6492 anonymousNsCount = 0,
6493 tagStart = false,
6494 tagEnd = false,
6495 i = 0, j = 0,
6496 x, y, q, w,
6497 xmlns,
6498 elementName,
6499 _elementName,
6500 elementProxy
6501 ;
6502
6503 var attrsString = '',
6504 attrsStart = 0,
6505 cachedAttrs // false = parsed with errors, null = needs parsing
6506 ;
6507
6508 /**
6509 * Parse attributes on demand and returns the parsed attributes.
6510 *
6511 * Return semantics: (1) `false` on attribute parse error,
6512 * (2) object hash on extracted attrs.
6513 *
6514 * @return {boolean|Object}
6515 */
6516 function getAttrs() {
6517 if (cachedAttrs !== null) {
6518 return cachedAttrs;
6519 }
6520
6521 var nsUri,
6522 nsUriPrefix,
6523 nsName,
6524 defaultAlias = isNamespace && nsMatrix['xmlns'],
6525 attrList = isNamespace && maybeNS ? [] : null,
6526 i = attrsStart,
6527 s = attrsString,
6528 l = s.length,
6529 hasNewMatrix,
6530 newalias,
6531 value,
6532 alias,
6533 name,
6534 attrs = {},
6535 seenAttrs = {},
6536 skipAttr,
6537 w,
6538 j;
6539
6540 parseAttr:
6541 for (; i < l; i++) {
6542 skipAttr = false;
6543 w = s.charCodeAt(i);
6544
6545 if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE={ \f\n\r\t\v}
6546 continue;
6547 }
6548
6549 // wait for non whitespace character
6550 if (w < 65 || w > 122 || (w > 90 && w < 97)) {
6551 if (w !== 95 && w !== 58) { // char 95"_" 58":"
6552 handleWarning('illegal first char attribute name');
6553 skipAttr = true;
6554 }
6555 }
6556
6557 // parse attribute name
6558 for (j = i + 1; j < l; j++) {
6559 w = s.charCodeAt(j);
6560
6561 if (
6562 w > 96 && w < 123 ||
6563 w > 64 && w < 91 ||
6564 w > 47 && w < 59 ||
6565 w === 46 || // '.'
6566 w === 45 || // '-'
6567 w === 95 // '_'
6568 ) {
6569 continue;
6570 }
6571
6572 // unexpected whitespace
6573 if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE
6574 handleWarning('missing attribute value');
6575 i = j;
6576
6577 continue parseAttr;
6578 }
6579
6580 // expected "="
6581 if (w === 61) { // "=" == 61
6582 break;
6583 }
6584
6585 handleWarning('illegal attribute name char');
6586 skipAttr = true;
6587 }
6588
6589 name = s.substring(i, j);
6590
6591 if (name === 'xmlns:xmlns') {
6592 handleWarning('illegal declaration of xmlns');
6593 skipAttr = true;
6594 }
6595
6596 w = s.charCodeAt(j + 1);
6597
6598 if (w === 34) { // '"'
6599 j = s.indexOf('"', i = j + 2);
6600
6601 if (j === -1) {
6602 j = s.indexOf('\'', i);
6603
6604 if (j !== -1) {
6605 handleWarning('attribute value quote missmatch');
6606 skipAttr = true;
6607 }
6608 }
6609
6610 } else if (w === 39) { // "'"
6611 j = s.indexOf('\'', i = j + 2);
6612
6613 if (j === -1) {
6614 j = s.indexOf('"', i);
6615
6616 if (j !== -1) {
6617 handleWarning('attribute value quote missmatch');
6618 skipAttr = true;
6619 }
6620 }
6621
6622 } else {
6623 handleWarning('missing attribute value quotes');
6624 skipAttr = true;
6625
6626 // skip to next space
6627 for (j = j + 1; j < l; j++) {
6628 w = s.charCodeAt(j + 1);
6629
6630 if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE
6631 break;
6632 }
6633 }
6634
6635 }
6636
6637 if (j === -1) {
6638 handleWarning('missing closing quotes');
6639
6640 j = l;
6641 skipAttr = true;
6642 }
6643
6644 if (!skipAttr) {
6645 value = s.substring(i, j);
6646 }
6647
6648 i = j;
6649
6650 // ensure SPACE follows attribute
6651 // skip illegal content otherwise
6652 // example a="b"c
6653 for (; j + 1 < l; j++) {
6654 w = s.charCodeAt(j + 1);
6655
6656 if (w === 32 || (w < 14 && w > 8)) { // WHITESPACE
6657 break;
6658 }
6659
6660 // FIRST ILLEGAL CHAR
6661 if (i === j) {
6662 handleWarning('illegal character after attribute end');
6663 skipAttr = true;
6664 }
6665 }
6666
6667 // advance cursor to next attribute
6668 i = j + 1;
6669
6670 if (skipAttr) {
6671 continue parseAttr;
6672 }
6673
6674 // check attribute re-declaration
6675 if (name in seenAttrs) {
6676 handleWarning('attribute <' + name + '> already defined');
6677 continue;
6678 }
6679
6680 seenAttrs[name] = true;
6681
6682 if (!isNamespace) {
6683 attrs[name] = value;
6684 continue;
6685 }
6686
6687 // try to extract namespace information
6688 if (maybeNS) {
6689 newalias = (
6690 name === 'xmlns'
6691 ? 'xmlns'
6692 : (name.charCodeAt(0) === 120 && name.substr(0, 6) === 'xmlns:')
6693 ? name.substr(6)
6694 : null
6695 );
6696
6697 // handle xmlns(:alias) assignment
6698 if (newalias !== null) {
6699 nsUri = decodeEntities(value);
6700 nsUriPrefix = uriPrefix(newalias);
6701
6702 alias = nsUriToPrefix[nsUri];
6703
6704 if (!alias) {
6705 // no prefix defined or prefix collision
6706 if (
6707 (newalias === 'xmlns') ||
6708 (nsUriPrefix in nsMatrix && nsMatrix[nsUriPrefix] !== nsUri)
6709 ) {
6710 // alocate free ns prefix
6711 do {
6712 alias = 'ns' + (anonymousNsCount++);
6713 } while (typeof nsMatrix[alias] !== 'undefined');
6714 } else {
6715 alias = newalias;
6716 }
6717
6718 nsUriToPrefix[nsUri] = alias;
6719 }
6720
6721 if (nsMatrix[newalias] !== alias) {
6722 if (!hasNewMatrix) {
6723 nsMatrix = cloneNsMatrix(nsMatrix);
6724 hasNewMatrix = true;
6725 }
6726
6727 nsMatrix[newalias] = alias;
6728 if (newalias === 'xmlns') {
6729 nsMatrix[uriPrefix(alias)] = nsUri;
6730 defaultAlias = alias;
6731 }
6732
6733 nsMatrix[nsUriPrefix] = nsUri;
6734 }
6735
6736 // expose xmlns(:asd)="..." in attributes
6737 attrs[name] = value;
6738 continue;
6739 }
6740
6741 // collect attributes until all namespace
6742 // declarations are processed
6743 attrList.push(name, value);
6744 continue;
6745
6746 } /** end if (maybeNs) */
6747
6748 // handle attributes on element without
6749 // namespace declarations
6750 w = name.indexOf(':');
6751 if (w === -1) {
6752 attrs[name] = value;
6753 continue;
6754 }
6755
6756 // normalize ns attribute name
6757 if (!(nsName = nsMatrix[name.substring(0, w)])) {
6758 handleWarning(missingNamespaceForPrefix(name.substring(0, w)));
6759 continue;
6760 }
6761
6762 name = defaultAlias === nsName
6763 ? name.substr(w + 1)
6764 : nsName + name.substr(w);
6765 // end: normalize ns attribute name
6766
6767 // normalize xsi:type ns attribute value
6768 if (name === XSI_TYPE) {
6769 w = value.indexOf(':');
6770
6771 if (w !== -1) {
6772 nsName = value.substring(0, w);
6773 // handle default prefixes, i.e. xs:String gracefully
6774 nsName = nsMatrix[nsName] || nsName;
6775 value = nsName + value.substring(w);
6776 } else {
6777 value = defaultAlias + ':' + value;
6778 }
6779 }
6780 // end: normalize xsi:type ns attribute value
6781
6782 attrs[name] = value;
6783 }
6784
6785
6786 // handle deferred, possibly namespaced attributes
6787 if (maybeNS) {
6788
6789 // normalize captured attributes
6790 for (i = 0, l = attrList.length; i < l; i++) {
6791
6792 name = attrList[i++];
6793 value = attrList[i];
6794
6795 w = name.indexOf(':');
6796
6797 if (w !== -1) {
6798 // normalize ns attribute name
6799 if (!(nsName = nsMatrix[name.substring(0, w)])) {
6800 handleWarning(missingNamespaceForPrefix(name.substring(0, w)));
6801 continue;
6802 }
6803
6804 name = defaultAlias === nsName
6805 ? name.substr(w + 1)
6806 : nsName + name.substr(w);
6807 // end: normalize ns attribute name
6808
6809 // normalize xsi:type ns attribute value
6810 if (name === XSI_TYPE) {
6811 w = value.indexOf(':');
6812
6813 if (w !== -1) {
6814 nsName = value.substring(0, w);
6815 // handle default prefixes, i.e. xs:String gracefully
6816 nsName = nsMatrix[nsName] || nsName;
6817 value = nsName + value.substring(w);
6818 } else {
6819 value = defaultAlias + ':' + value;
6820 }
6821 }
6822 // end: normalize xsi:type ns attribute value
6823 }
6824
6825 attrs[name] = value;
6826 }
6827 // end: normalize captured attributes
6828 }
6829
6830 return cachedAttrs = attrs;
6831 }
6832
6833 /**
6834 * Extract the parse context { line, column, part }
6835 * from the current parser position.
6836 *
6837 * @return {Object} parse context
6838 */
6839 function getParseContext() {
6840 var splitsRe = /(\r\n|\r|\n)/g;
6841
6842 var line = 0;
6843 var column = 0;
6844 var startOfLine = 0;
6845 var endOfLine = j;
6846 var match;
6847 var data;
6848
6849 while (i >= startOfLine) {
6850
6851 match = splitsRe.exec(xml);
6852
6853 if (!match) {
6854 break;
6855 }
6856
6857 // end of line = (break idx + break chars)
6858 endOfLine = match[0].length + match.index;
6859
6860 if (endOfLine > i) {
6861 break;
6862 }
6863
6864 // advance to next line
6865 line += 1;
6866
6867 startOfLine = endOfLine;
6868 }
6869
6870 // EOF errors
6871 if (i == -1) {
6872 column = endOfLine;
6873 data = xml.substring(j);
6874 } else
6875 // start errors
6876 if (j === 0) {
6877 console.log(i - startOfLine);
6878 data = xml.substring(j, i);
6879 }
6880 // other errors
6881 else {
6882 column = i - startOfLine;
6883 data = (j == -1 ? xml.substring(i) : xml.substring(i, j + 1));
6884 }
6885
6886 return {
6887 'data': data,
6888 'line': line,
6889 'column': column
6890 };
6891 }
6892
6893 getContext = getParseContext;
6894
6895
6896 if (proxy) {
6897 elementProxy = Object.create({}, {
6898 'name': getter(function() {
6899 return elementName;
6900 }),
6901 'originalName': getter(function() {
6902 return _elementName;
6903 }),
6904 'attrs': getter(getAttrs),
6905 'ns': getter(function() {
6906 return nsMatrix;
6907 })
6908 });
6909 }
6910
6911 // actual parse logic
6912 while (j !== -1) {
6913
6914 if (xml.charCodeAt(j) === 60) { // "<"
6915 i = j;
6916 } else {
6917 i = xml.indexOf('<', j);
6918 }
6919
6920 // parse end
6921 if (i === -1) {
6922 if (nodeStack.length) {
6923 return handleError('unexpected end of file');
6924 }
6925
6926 if (j === 0) {
6927 return handleError('missing start tag');
6928 }
6929
6930 if (j < xml.length) {
6931 if (xml.substring(j).trim()) {
6932 handleWarning(NON_WHITESPACE_OUTSIDE_ROOT_NODE);
6933 }
6934 }
6935
6936 return;
6937 }
6938
6939 // parse text
6940 if (j !== i) {
6941
6942 if (nodeStack.length) {
6943 if (onText) {
6944 onText(xml.substring(j, i), decodeEntities, getContext);
6945
6946 if (parseStop) {
6947 return;
6948 }
6949 }
6950 } else {
6951 if (xml.substring(j, i).trim()) {
6952 handleWarning(NON_WHITESPACE_OUTSIDE_ROOT_NODE);
6953
6954 if (parseStop) {
6955 return;
6956 }
6957 }
6958 }
6959 }
6960
6961 w = xml.charCodeAt(i+1);
6962
6963 // parse comments + CDATA
6964 if (w === 33) { // "!"
6965 w = xml.charCodeAt(i+2);
6966 if (w === 91 && xml.substr(i + 3, 6) === 'CDATA[') { // 91 == "["
6967 j = xml.indexOf(']]>', i);
6968 if (j === -1) {
6969 return handleError('unclosed cdata');
6970 }
6971
6972 if (onCDATA) {
6973 onCDATA(xml.substring(i + 9, j), getContext);
6974 if (parseStop) {
6975 return;
6976 }
6977 }
6978
6979 j += 3;
6980 continue;
6981 }
6982
6983
6984 if (w === 45 && xml.charCodeAt(i + 3) === 45) { // 45 == "-"
6985 j = xml.indexOf('-->', i);
6986 if (j === -1) {
6987 return handleError('unclosed comment');
6988 }
6989
6990
6991 if (onComment) {
6992 onComment(xml.substring(i + 4, j), decodeEntities, getContext);
6993 if (parseStop) {
6994 return;
6995 }
6996 }
6997
6998 j += 3;
6999 continue;
7000 }
7001
7002 j = xml.indexOf('>', i + 1);
7003 if (j === -1) {
7004 return handleError('unclosed tag');
7005 }
7006
7007 if (onAttention) {
7008 onAttention(xml.substring(i, j + 1), decodeEntities, getContext);
7009 if (parseStop) {
7010 return;
7011 }
7012 }
7013
7014 j += 1;
7015 continue;
7016 }
7017
7018 if (w === 63) { // "?"
7019 j = xml.indexOf('?>', i);
7020 if (j === -1) {
7021 return handleError('unclosed question');
7022 }
7023
7024 if (onQuestion) {
7025 onQuestion(xml.substring(i, j + 2), getContext);
7026 if (parseStop) {
7027 return;
7028 }
7029 }
7030
7031 j += 2;
7032 continue;
7033 }
7034
7035 j = xml.indexOf('>', i + 1);
7036
7037 if (j == -1) {
7038 return handleError('unclosed tag');
7039 }
7040
7041 // don't process attributes;
7042 // there are none
7043 cachedAttrs = {};
7044
7045 // if (xml.charCodeAt(i+1) === 47) { // </...
7046 if (w === 47) { // </...
7047 tagStart = false;
7048 tagEnd = true;
7049
7050 if (!nodeStack.length) {
7051 return handleError('missing open tag');
7052 }
7053
7054 // verify open <-> close tag match
7055 x = elementName = nodeStack.pop();
7056 q = i + 2 + x.length;
7057
7058 if (xml.substring(i + 2, q) !== x) {
7059 return handleError('closing tag mismatch');
7060 }
7061
7062 // verify chars in close tag
7063 for (; q < j; q++) {
7064 w = xml.charCodeAt(q);
7065
7066 if (w === 32 || (w > 8 && w < 14)) { // \f\n\r\t\v space
7067 continue;
7068 }
7069
7070 return handleError('close tag');
7071 }
7072
7073 } else {
7074 if (xml.charCodeAt(j - 1) === 47) { // .../>
7075 x = elementName = xml.substring(i + 1, j - 1);
7076
7077 tagStart = true;
7078 tagEnd = true;
7079
7080 } else {
7081 x = elementName = xml.substring(i + 1, j);
7082
7083 tagStart = true;
7084 tagEnd = false;
7085 }
7086
7087 if (!(w > 96 && w < 123 || w > 64 && w < 91 || w === 95 || w === 58)) { // char 95"_" 58":"
7088 return handleError('illegal first char nodeName');
7089 }
7090
7091 for (q = 1, y = x.length; q < y; q++) {
7092 w = x.charCodeAt(q);
7093
7094 if (w > 96 && w < 123 || w > 64 && w < 91 || w > 47 && w < 59 || w === 45 || w === 95 || w == 46) {
7095 continue;
7096 }
7097
7098 if (w === 32 || (w < 14 && w > 8)) { // \f\n\r\t\v space
7099 elementName = x.substring(0, q);
7100 // maybe there are attributes
7101 cachedAttrs = null;
7102 break;
7103 }
7104
7105 return handleError('invalid nodeName');
7106 }
7107
7108 if (!tagEnd) {
7109 nodeStack.push(elementName);
7110 }
7111 }
7112
7113 if (isNamespace) {
7114
7115 _nsMatrix = nsMatrix;
7116
7117 if (tagStart) {
7118 // remember old namespace
7119 // unless we're self-closing
7120 if (!tagEnd) {
7121 nsMatrixStack.push(_nsMatrix);
7122 }
7123
7124 if (cachedAttrs === null) {
7125 // quick check, whether there may be namespace
7126 // declarations on the node; if that is the case
7127 // we need to eagerly parse the node attributes
7128 if ((maybeNS = x.indexOf('xmlns', q) !== -1)) {
7129 attrsStart = q;
7130 attrsString = x;
7131
7132 getAttrs();
7133
7134 maybeNS = false;
7135 }
7136 }
7137 }
7138
7139 _elementName = elementName;
7140
7141 w = elementName.indexOf(':');
7142 if (w !== -1) {
7143 xmlns = nsMatrix[elementName.substring(0, w)];
7144
7145 // prefix given; namespace must exist
7146 if (!xmlns) {
7147 return handleError('missing namespace on <' + _elementName + '>');
7148 }
7149
7150 elementName = elementName.substr(w + 1);
7151 } else {
7152 xmlns = nsMatrix['xmlns'];
7153
7154 // if no default namespace is defined,
7155 // we'll import the element as anonymous.
7156 //
7157 // it is up to users to correct that to the document defined
7158 // targetNamespace, or whatever their undersanding of the
7159 // XML spec mandates.
7160 }
7161
7162 // adjust namespace prefixs as configured
7163 if (xmlns) {
7164 elementName = xmlns + ':' + elementName;
7165 }
7166
7167 }
7168
7169 if (tagStart) {
7170 attrsStart = q;
7171 attrsString = x;
7172
7173 if (onOpenTag) {
7174 if (proxy) {
7175 onOpenTag(elementProxy, decodeEntities, tagEnd, getContext);
7176 } else {
7177 onOpenTag(elementName, getAttrs, decodeEntities, tagEnd, getContext);
7178 }
7179
7180 if (parseStop) {
7181 return;
7182 }
7183 }
7184
7185 }
7186
7187 if (tagEnd) {
7188
7189 if (onCloseTag) {
7190 onCloseTag(proxy ? elementProxy : elementName, decodeEntities, tagStart, getContext);
7191
7192 if (parseStop) {
7193 return;
7194 }
7195 }
7196
7197 // restore old namespace
7198 if (isNamespace) {
7199 if (!tagStart) {
7200 nsMatrix = nsMatrixStack.pop();
7201 } else {
7202 nsMatrix = _nsMatrix;
7203 }
7204 }
7205 }
7206
7207 j += 1;
7208 }
7209 } /** end parse */
7210
7211 }
7212
7213 function hasLowerCaseAlias(pkg) {
7214 return pkg.xml && pkg.xml.tagAlias === 'lowerCase';
7215 }
7216
7217 var DEFAULT_NS_MAP = {
7218 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'
7219 };
7220
7221 var XSI_TYPE$1 = 'xsi:type';
7222
7223 function serializeFormat(element) {
7224 return element.xml && element.xml.serialize;
7225 }
7226
7227 function serializeAsType(element) {
7228 return serializeFormat(element) === XSI_TYPE$1;
7229 }
7230
7231 function serializeAsProperty(element) {
7232 return serializeFormat(element) === 'property';
7233 }
7234
7235 function capitalize(str) {
7236 return str.charAt(0).toUpperCase() + str.slice(1);
7237 }
7238
7239 function aliasToName(aliasNs, pkg) {
7240
7241 if (!hasLowerCaseAlias(pkg)) {
7242 return aliasNs.name;
7243 }
7244
7245 return aliasNs.prefix + ':' + capitalize(aliasNs.localName);
7246 }
7247
7248 function prefixedToName(nameNs, pkg) {
7249
7250 var name = nameNs.name,
7251 localName = nameNs.localName;
7252
7253 var typePrefix = pkg.xml && pkg.xml.typePrefix;
7254
7255 if (typePrefix && localName.indexOf(typePrefix) === 0) {
7256 return nameNs.prefix + ':' + localName.slice(typePrefix.length);
7257 } else {
7258 return name;
7259 }
7260 }
7261
7262 function normalizeXsiTypeName(name, model) {
7263
7264 var nameNs = parseName(name);
7265 var pkg = model.getPackage(nameNs.prefix);
7266
7267 return prefixedToName(nameNs, pkg);
7268 }
7269
7270 function error$1(message) {
7271 return new Error(message);
7272 }
7273
7274 /**
7275 * Get the moddle descriptor for a given instance or type.
7276 *
7277 * @param {ModdleElement|Function} element
7278 *
7279 * @return {Object} the moddle descriptor
7280 */
7281 function getModdleDescriptor(element) {
7282 return element.$descriptor;
7283 }
7284
7285 function defer(fn) {
7286 setTimeout(fn, 0);
7287 }
7288
7289 /**
7290 * A parse context.
7291 *
7292 * @class
7293 *
7294 * @param {Object} options
7295 * @param {ElementHandler} options.rootHandler the root handler for parsing a document
7296 * @param {boolean} [options.lax=false] whether or not to ignore invalid elements
7297 */
7298 function Context(options) {
7299
7300 /**
7301 * @property {ElementHandler} rootHandler
7302 */
7303
7304 /**
7305 * @property {Boolean} lax
7306 */
7307
7308 assign(this, options);
7309
7310 this.elementsById = {};
7311 this.references = [];
7312 this.warnings = [];
7313
7314 /**
7315 * Add an unresolved reference.
7316 *
7317 * @param {Object} reference
7318 */
7319 this.addReference = function(reference) {
7320 this.references.push(reference);
7321 };
7322
7323 /**
7324 * Add a processed element.
7325 *
7326 * @param {ModdleElement} element
7327 */
7328 this.addElement = function(element) {
7329
7330 if (!element) {
7331 throw error$1('expected element');
7332 }
7333
7334 var elementsById = this.elementsById;
7335
7336 var descriptor = getModdleDescriptor(element);
7337
7338 var idProperty = descriptor.idProperty,
7339 id;
7340
7341 if (idProperty) {
7342 id = element.get(idProperty.name);
7343
7344 if (id) {
7345
7346 if (elementsById[id]) {
7347 throw error$1('duplicate ID <' + id + '>');
7348 }
7349
7350 elementsById[id] = element;
7351 }
7352 }
7353 };
7354
7355 /**
7356 * Add an import warning.
7357 *
7358 * @param {Object} warning
7359 * @param {String} warning.message
7360 * @param {Error} [warning.error]
7361 */
7362 this.addWarning = function(warning) {
7363 this.warnings.push(warning);
7364 };
7365 }
7366
7367 function BaseHandler() {}
7368
7369 BaseHandler.prototype.handleEnd = function() {};
7370 BaseHandler.prototype.handleText = function() {};
7371 BaseHandler.prototype.handleNode = function() {};
7372
7373
7374 /**
7375 * A simple pass through handler that does nothing except for
7376 * ignoring all input it receives.
7377 *
7378 * This is used to ignore unknown elements and
7379 * attributes.
7380 */
7381 function NoopHandler() { }
7382
7383 NoopHandler.prototype = Object.create(BaseHandler.prototype);
7384
7385 NoopHandler.prototype.handleNode = function() {
7386 return this;
7387 };
7388
7389 function BodyHandler() {}
7390
7391 BodyHandler.prototype = Object.create(BaseHandler.prototype);
7392
7393 BodyHandler.prototype.handleText = function(text) {
7394 this.body = (this.body || '') + text;
7395 };
7396
7397 function ReferenceHandler(property, context) {
7398 this.property = property;
7399 this.context = context;
7400 }
7401
7402 ReferenceHandler.prototype = Object.create(BodyHandler.prototype);
7403
7404 ReferenceHandler.prototype.handleNode = function(node) {
7405
7406 if (this.element) {
7407 throw error$1('expected no sub nodes');
7408 } else {
7409 this.element = this.createReference(node);
7410 }
7411
7412 return this;
7413 };
7414
7415 ReferenceHandler.prototype.handleEnd = function() {
7416 this.element.id = this.body;
7417 };
7418
7419 ReferenceHandler.prototype.createReference = function(node) {
7420 return {
7421 property: this.property.ns.name,
7422 id: ''
7423 };
7424 };
7425
7426 function ValueHandler(propertyDesc, element) {
7427 this.element = element;
7428 this.propertyDesc = propertyDesc;
7429 }
7430
7431 ValueHandler.prototype = Object.create(BodyHandler.prototype);
7432
7433 ValueHandler.prototype.handleEnd = function() {
7434
7435 var value = this.body || '',
7436 element = this.element,
7437 propertyDesc = this.propertyDesc;
7438
7439 value = coerceType(propertyDesc.type, value);
7440
7441 if (propertyDesc.isMany) {
7442 element.get(propertyDesc.name).push(value);
7443 } else {
7444 element.set(propertyDesc.name, value);
7445 }
7446 };
7447
7448
7449 function BaseElementHandler() {}
7450
7451 BaseElementHandler.prototype = Object.create(BodyHandler.prototype);
7452
7453 BaseElementHandler.prototype.handleNode = function(node) {
7454 var parser = this,
7455 element = this.element;
7456
7457 if (!element) {
7458 element = this.element = this.createElement(node);
7459
7460 this.context.addElement(element);
7461 } else {
7462 parser = this.handleChild(node);
7463 }
7464
7465 return parser;
7466 };
7467
7468 /**
7469 * @class Reader.ElementHandler
7470 *
7471 */
7472 function ElementHandler(model, typeName, context) {
7473 this.model = model;
7474 this.type = model.getType(typeName);
7475 this.context = context;
7476 }
7477
7478 ElementHandler.prototype = Object.create(BaseElementHandler.prototype);
7479
7480 ElementHandler.prototype.addReference = function(reference) {
7481 this.context.addReference(reference);
7482 };
7483
7484 ElementHandler.prototype.handleEnd = function() {
7485
7486 var value = this.body,
7487 element = this.element,
7488 descriptor = getModdleDescriptor(element),
7489 bodyProperty = descriptor.bodyProperty;
7490
7491 if (bodyProperty && value !== undefined) {
7492 value = coerceType(bodyProperty.type, value);
7493 element.set(bodyProperty.name, value);
7494 }
7495 };
7496
7497 /**
7498 * Create an instance of the model from the given node.
7499 *
7500 * @param {Element} node the xml node
7501 */
7502 ElementHandler.prototype.createElement = function(node) {
7503 var attributes = node.attributes,
7504 Type = this.type,
7505 descriptor = getModdleDescriptor(Type),
7506 context = this.context,
7507 instance = new Type({}),
7508 model = this.model,
7509 propNameNs;
7510
7511 forEach(attributes, function(value, name) {
7512
7513 var prop = descriptor.propertiesByName[name],
7514 values$$1;
7515
7516 if (prop && prop.isReference) {
7517
7518 if (!prop.isMany) {
7519 context.addReference({
7520 element: instance,
7521 property: prop.ns.name,
7522 id: value
7523 });
7524 } else {
7525 // IDREFS: parse references as whitespace-separated list
7526 values$$1 = value.split(' ');
7527
7528 forEach(values$$1, function(v) {
7529 context.addReference({
7530 element: instance,
7531 property: prop.ns.name,
7532 id: v
7533 });
7534 });
7535 }
7536
7537 } else {
7538 if (prop) {
7539 value = coerceType(prop.type, value);
7540 } else
7541 if (name !== 'xmlns') {
7542 propNameNs = parseName(name, descriptor.ns.prefix);
7543
7544 // check whether attribute is defined in a well-known namespace
7545 // if that is the case we emit a warning to indicate potential misuse
7546 if (model.getPackage(propNameNs.prefix)) {
7547
7548 context.addWarning({
7549 message: 'unknown attribute <' + name + '>',
7550 element: instance,
7551 property: name,
7552 value: value
7553 });
7554 }
7555 }
7556
7557 instance.set(name, value);
7558 }
7559 });
7560
7561 return instance;
7562 };
7563
7564 ElementHandler.prototype.getPropertyForNode = function(node) {
7565
7566 var name = node.name;
7567 var nameNs = parseName(name);
7568
7569 var type = this.type,
7570 model = this.model,
7571 descriptor = getModdleDescriptor(type);
7572
7573 var propertyName = nameNs.name,
7574 property = descriptor.propertiesByName[propertyName],
7575 elementTypeName,
7576 elementType;
7577
7578 // search for properties by name first
7579
7580 if (property) {
7581
7582 if (serializeAsType(property)) {
7583 elementTypeName = node.attributes[XSI_TYPE$1];
7584
7585 // xsi type is optional, if it does not exists the
7586 // default type is assumed
7587 if (elementTypeName) {
7588
7589 // take possible type prefixes from XML
7590 // into account, i.e.: xsi:type="t{ActualType}"
7591 elementTypeName = normalizeXsiTypeName(elementTypeName, model);
7592
7593 elementType = model.getType(elementTypeName);
7594
7595 return assign({}, property, {
7596 effectiveType: getModdleDescriptor(elementType).name
7597 });
7598 }
7599 }
7600
7601 // search for properties by name first
7602 return property;
7603 }
7604
7605 var pkg = model.getPackage(nameNs.prefix);
7606
7607 if (pkg) {
7608 elementTypeName = aliasToName(nameNs, pkg);
7609 elementType = model.getType(elementTypeName);
7610
7611 // search for collection members later
7612 property = find(descriptor.properties, function(p) {
7613 return !p.isVirtual && !p.isReference && !p.isAttribute && elementType.hasType(p.type);
7614 });
7615
7616 if (property) {
7617 return assign({}, property, {
7618 effectiveType: getModdleDescriptor(elementType).name
7619 });
7620 }
7621 } else {
7622 // parse unknown element (maybe extension)
7623 property = find(descriptor.properties, function(p) {
7624 return !p.isReference && !p.isAttribute && p.type === 'Element';
7625 });
7626
7627 if (property) {
7628 return property;
7629 }
7630 }
7631
7632 throw error$1('unrecognized element <' + nameNs.name + '>');
7633 };
7634
7635 ElementHandler.prototype.toString = function() {
7636 return 'ElementDescriptor[' + getModdleDescriptor(this.type).name + ']';
7637 };
7638
7639 ElementHandler.prototype.valueHandler = function(propertyDesc, element) {
7640 return new ValueHandler(propertyDesc, element);
7641 };
7642
7643 ElementHandler.prototype.referenceHandler = function(propertyDesc) {
7644 return new ReferenceHandler(propertyDesc, this.context);
7645 };
7646
7647 ElementHandler.prototype.handler = function(type) {
7648 if (type === 'Element') {
7649 return new GenericElementHandler(this.model, type, this.context);
7650 } else {
7651 return new ElementHandler(this.model, type, this.context);
7652 }
7653 };
7654
7655 /**
7656 * Handle the child element parsing
7657 *
7658 * @param {Element} node the xml node
7659 */
7660 ElementHandler.prototype.handleChild = function(node) {
7661 var propertyDesc, type, element, childHandler;
7662
7663 propertyDesc = this.getPropertyForNode(node);
7664 element = this.element;
7665
7666 type = propertyDesc.effectiveType || propertyDesc.type;
7667
7668 if (isSimple(type)) {
7669 return this.valueHandler(propertyDesc, element);
7670 }
7671
7672 if (propertyDesc.isReference) {
7673 childHandler = this.referenceHandler(propertyDesc).handleNode(node);
7674 } else {
7675 childHandler = this.handler(type).handleNode(node);
7676 }
7677
7678 var newElement = childHandler.element;
7679
7680 // child handles may decide to skip elements
7681 // by not returning anything
7682 if (newElement !== undefined) {
7683
7684 if (propertyDesc.isMany) {
7685 element.get(propertyDesc.name).push(newElement);
7686 } else {
7687 element.set(propertyDesc.name, newElement);
7688 }
7689
7690 if (propertyDesc.isReference) {
7691 assign(newElement, {
7692 element: element
7693 });
7694
7695 this.context.addReference(newElement);
7696 } else {
7697 // establish child -> parent relationship
7698 newElement.$parent = element;
7699 }
7700 }
7701
7702 return childHandler;
7703 };
7704
7705 /**
7706 * An element handler that performs special validation
7707 * to ensure the node it gets initialized with matches
7708 * the handlers type (namespace wise).
7709 *
7710 * @param {Moddle} model
7711 * @param {String} typeName
7712 * @param {Context} context
7713 */
7714 function RootElementHandler(model, typeName, context) {
7715 ElementHandler.call(this, model, typeName, context);
7716 }
7717
7718 RootElementHandler.prototype = Object.create(ElementHandler.prototype);
7719
7720 RootElementHandler.prototype.createElement = function(node) {
7721
7722 var name = node.name,
7723 nameNs = parseName(name),
7724 model = this.model,
7725 type = this.type,
7726 pkg = model.getPackage(nameNs.prefix),
7727 typeName = pkg && aliasToName(nameNs, pkg) || name;
7728
7729 // verify the correct namespace if we parse
7730 // the first element in the handler tree
7731 //
7732 // this ensures we don't mistakenly import wrong namespace elements
7733 if (!type.hasType(typeName)) {
7734 throw error$1('unexpected element <' + node.originalName + '>');
7735 }
7736
7737 return ElementHandler.prototype.createElement.call(this, node);
7738 };
7739
7740
7741 function GenericElementHandler(model, typeName, context) {
7742 this.model = model;
7743 this.context = context;
7744 }
7745
7746 GenericElementHandler.prototype = Object.create(BaseElementHandler.prototype);
7747
7748 GenericElementHandler.prototype.createElement = function(node) {
7749
7750 var name = node.name,
7751 ns = parseName(name),
7752 prefix = ns.prefix,
7753 uri = node.ns[prefix + '$uri'],
7754 attributes = node.attributes;
7755
7756 return this.model.createAny(name, uri, attributes);
7757 };
7758
7759 GenericElementHandler.prototype.handleChild = function(node) {
7760
7761 var handler = new GenericElementHandler(this.model, 'Element', this.context).handleNode(node),
7762 element = this.element;
7763
7764 var newElement = handler.element,
7765 children;
7766
7767 if (newElement !== undefined) {
7768 children = element.$children = element.$children || [];
7769 children.push(newElement);
7770
7771 // establish child -> parent relationship
7772 newElement.$parent = element;
7773 }
7774
7775 return handler;
7776 };
7777
7778 GenericElementHandler.prototype.handleText = function(text) {
7779 this.body = this.body || '' + text;
7780 };
7781
7782 GenericElementHandler.prototype.handleEnd = function() {
7783 if (this.body) {
7784 this.element.$body = this.body;
7785 }
7786 };
7787
7788 /**
7789 * A reader for a meta-model
7790 *
7791 * @param {Object} options
7792 * @param {Model} options.model used to read xml files
7793 * @param {Boolean} options.lax whether to make parse errors warnings
7794 */
7795 function Reader(options) {
7796
7797 if (options instanceof Moddle) {
7798 options = {
7799 model: options
7800 };
7801 }
7802
7803 assign(this, { lax: false }, options);
7804 }
7805
7806
7807 /**
7808 * Parse the given XML into a moddle document tree.
7809 *
7810 * @param {String} xml
7811 * @param {ElementHandler|Object} options or rootHandler
7812 * @param {Function} done
7813 */
7814 Reader.prototype.fromXML = function(xml, options, done) {
7815
7816 var rootHandler = options.rootHandler;
7817
7818 if (options instanceof ElementHandler) {
7819 // root handler passed via (xml, { rootHandler: ElementHandler }, ...)
7820 rootHandler = options;
7821 options = {};
7822 } else {
7823 if (typeof options === 'string') {
7824 // rootHandler passed via (xml, 'someString', ...)
7825 rootHandler = this.handler(options);
7826 options = {};
7827 } else if (typeof rootHandler === 'string') {
7828 // rootHandler passed via (xml, { rootHandler: 'someString' }, ...)
7829 rootHandler = this.handler(rootHandler);
7830 }
7831 }
7832
7833 var model = this.model,
7834 lax = this.lax;
7835
7836 var context = new Context(assign({}, options, { rootHandler: rootHandler })),
7837 parser = new Parser({ proxy: true }),
7838 stack = new tinyStack();
7839
7840 rootHandler.context = context;
7841
7842 // push root handler
7843 stack.push(rootHandler);
7844
7845
7846 /**
7847 * Handle error.
7848 *
7849 * @param {Error} err
7850 * @param {Function} getContext
7851 * @param {boolean} lax
7852 *
7853 * @return {boolean} true if handled
7854 */
7855 function handleError(err, getContext, lax) {
7856
7857 var ctx = getContext();
7858
7859 var line = ctx.line,
7860 column = ctx.column,
7861 data = ctx.data;
7862
7863 // we receive the full context data here,
7864 // for elements trim down the information
7865 // to the tag name, only
7866 if (data.charAt(0) === '<' && data.indexOf(' ') !== -1) {
7867 data = data.slice(0, data.indexOf(' ')) + '>';
7868 }
7869
7870 var message =
7871 'unparsable content ' + (data ? data + ' ' : '') + 'detected\n\t' +
7872 'line: ' + line + '\n\t' +
7873 'column: ' + column + '\n\t' +
7874 'nested error: ' + err.message;
7875
7876 if (lax) {
7877 context.addWarning({
7878 message: message,
7879 error: err
7880 });
7881
7882 console.warn('could not parse node');
7883 console.warn(err);
7884
7885 return true;
7886 } else {
7887 console.error('could not parse document');
7888 console.error(err);
7889
7890 throw error$1(message);
7891 }
7892 }
7893
7894 function handleWarning(err, getContext) {
7895 // just like handling errors in <lax=true> mode
7896 return handleError(err, getContext, true);
7897 }
7898
7899 /**
7900 * Resolve collected references on parse end.
7901 */
7902 function resolveReferences() {
7903
7904 var elementsById = context.elementsById;
7905 var references = context.references;
7906
7907 var i, r;
7908
7909 for (i = 0; (r = references[i]); i++) {
7910 var element = r.element;
7911 var reference = elementsById[r.id];
7912 var property = getModdleDescriptor(element).propertiesByName[r.property];
7913
7914 if (!reference) {
7915 context.addWarning({
7916 message: 'unresolved reference <' + r.id + '>',
7917 element: r.element,
7918 property: r.property,
7919 value: r.id
7920 });
7921 }
7922
7923 if (property.isMany) {
7924 var collection = element.get(property.name),
7925 idx = collection.indexOf(r);
7926
7927 // we replace an existing place holder (idx != -1) or
7928 // append to the collection instead
7929 if (idx === -1) {
7930 idx = collection.length;
7931 }
7932
7933 if (!reference) {
7934 // remove unresolvable reference
7935 collection.splice(idx, 1);
7936 } else {
7937 // add or update reference in collection
7938 collection[idx] = reference;
7939 }
7940 } else {
7941 element.set(property.name, reference);
7942 }
7943 }
7944 }
7945
7946 function handleClose() {
7947 stack.pop().handleEnd();
7948 }
7949
7950 var PREAMBLE_START_PATTERN = /^<\?xml /i;
7951
7952 var ENCODING_PATTERN = / encoding="([^"]+)"/i;
7953
7954 var UTF_8_PATTERN = /^utf-8$/i;
7955
7956 function handleQuestion(question) {
7957
7958 if (!PREAMBLE_START_PATTERN.test(question)) {
7959 return;
7960 }
7961
7962 var match = ENCODING_PATTERN.exec(question);
7963 var encoding = match && match[1];
7964
7965 if (!encoding || UTF_8_PATTERN.test(encoding)) {
7966 return;
7967 }
7968
7969 context.addWarning({
7970 message:
7971 'unsupported document encoding <' + encoding + '>, ' +
7972 'falling back to UTF-8'
7973 });
7974 }
7975
7976 function handleOpen(node, getContext) {
7977 var handler = stack.peek();
7978
7979 try {
7980 stack.push(handler.handleNode(node));
7981 } catch (err) {
7982
7983 if (handleError(err, getContext, lax)) {
7984 stack.push(new NoopHandler());
7985 }
7986 }
7987 }
7988
7989 function handleCData(text) {
7990 stack.peek().handleText(text);
7991 }
7992
7993 function handleText(text) {
7994 // strip whitespace only nodes, i.e. before
7995 // <!CDATA[ ... ]> sections and in between tags
7996 text = text.trim();
7997
7998 if (!text) {
7999 return;
8000 }
8001
8002 stack.peek().handleText(text);
8003 }
8004
8005 var uriMap = model.getPackages().reduce(function(uriMap, p) {
8006 uriMap[p.uri] = p.prefix;
8007
8008 return uriMap;
8009 }, {});
8010
8011 parser
8012 .ns(uriMap)
8013 .on('openTag', function(obj, decodeStr, selfClosing, getContext) {
8014
8015 // gracefully handle unparsable attributes (attrs=false)
8016 var attrs = obj.attrs || {};
8017
8018 var decodedAttrs = Object.keys(attrs).reduce(function(d, key) {
8019 var value = decodeStr(attrs[key]);
8020
8021 d[key] = value;
8022
8023 return d;
8024 }, {});
8025
8026 var node = {
8027 name: obj.name,
8028 originalName: obj.originalName,
8029 attributes: decodedAttrs,
8030 ns: obj.ns
8031 };
8032
8033 handleOpen(node, getContext);
8034 })
8035 .on('question', handleQuestion)
8036 .on('closeTag', handleClose)
8037 .on('cdata', handleCData)
8038 .on('text', function(text, decodeEntities$$1) {
8039 handleText(decodeEntities$$1(text));
8040 })
8041 .on('error', handleError)
8042 .on('warn', handleWarning);
8043
8044 // deferred parse XML to make loading really ascnchronous
8045 // this ensures the execution environment (node or browser)
8046 // is kept responsive and that certain optimization strategies
8047 // can kick in
8048 defer(function() {
8049 var err;
8050
8051 try {
8052 parser.parse(xml);
8053
8054 resolveReferences();
8055 } catch (e) {
8056 err = e;
8057 }
8058
8059 var element = rootHandler.element;
8060
8061 // handle the situation that we could not extract
8062 // the desired root element from the document
8063 if (!err && !element) {
8064 err = error$1('failed to parse document as <' + rootHandler.type.$descriptor.name + '>');
8065 }
8066
8067 done(err, err ? undefined : element, context);
8068 });
8069 };
8070
8071 Reader.prototype.handler = function(name) {
8072 return new RootElementHandler(this.model, name);
8073 };
8074
8075 var XML_PREAMBLE = '<?xml version="1.0" encoding="UTF-8"?>\n';
8076
8077 var ESCAPE_ATTR_CHARS = /<|>|'|"|&|\n\r|\n/g;
8078 var ESCAPE_CHARS = /<|>|&/g;
8079
8080
8081 function Namespaces(parent) {
8082
8083 var prefixMap = {};
8084 var uriMap = {};
8085 var used = {};
8086
8087 var wellknown = [];
8088 var custom = [];
8089
8090 // API
8091
8092 this.byUri = function(uri) {
8093 return uriMap[uri] || (
8094 parent && parent.byUri(uri)
8095 );
8096 };
8097
8098 this.add = function(ns, isWellknown) {
8099
8100 uriMap[ns.uri] = ns;
8101
8102 if (isWellknown) {
8103 wellknown.push(ns);
8104 } else {
8105 custom.push(ns);
8106 }
8107
8108 this.mapPrefix(ns.prefix, ns.uri);
8109 };
8110
8111 this.uriByPrefix = function(prefix) {
8112 return prefixMap[prefix || 'xmlns'];
8113 };
8114
8115 this.mapPrefix = function(prefix, uri) {
8116 prefixMap[prefix || 'xmlns'] = uri;
8117 };
8118
8119 this.logUsed = function(ns) {
8120 var uri = ns.uri;
8121
8122 used[uri] = this.byUri(uri);
8123 };
8124
8125 this.getUsed = function(ns) {
8126
8127 function isUsed(ns) {
8128 return used[ns.uri];
8129 }
8130
8131 var allNs = [].concat(wellknown, custom);
8132
8133 return allNs.filter(isUsed);
8134 };
8135
8136 }
8137
8138 function lower(string) {
8139 return string.charAt(0).toLowerCase() + string.slice(1);
8140 }
8141
8142 function nameToAlias(name, pkg) {
8143 if (hasLowerCaseAlias(pkg)) {
8144 return lower(name);
8145 } else {
8146 return name;
8147 }
8148 }
8149
8150 function inherits(ctor, superCtor) {
8151 ctor.super_ = superCtor;
8152 ctor.prototype = Object.create(superCtor.prototype, {
8153 constructor: {
8154 value: ctor,
8155 enumerable: false,
8156 writable: true,
8157 configurable: true
8158 }
8159 });
8160 }
8161
8162 function nsName(ns) {
8163 if (isString(ns)) {
8164 return ns;
8165 } else {
8166 return (ns.prefix ? ns.prefix + ':' : '') + ns.localName;
8167 }
8168 }
8169
8170 function getNsAttrs(namespaces) {
8171
8172 return map(namespaces.getUsed(), function(ns) {
8173 var name = 'xmlns' + (ns.prefix ? ':' + ns.prefix : '');
8174 return { name: name, value: ns.uri };
8175 });
8176
8177 }
8178
8179 function getElementNs(ns, descriptor) {
8180 if (descriptor.isGeneric) {
8181 return assign({ localName: descriptor.ns.localName }, ns);
8182 } else {
8183 return assign({ localName: nameToAlias(descriptor.ns.localName, descriptor.$pkg) }, ns);
8184 }
8185 }
8186
8187 function getPropertyNs(ns, descriptor) {
8188 return assign({ localName: descriptor.ns.localName }, ns);
8189 }
8190
8191 function getSerializableProperties(element) {
8192 var descriptor = element.$descriptor;
8193
8194 return filter(descriptor.properties, function(p) {
8195 var name = p.name;
8196
8197 if (p.isVirtual) {
8198 return false;
8199 }
8200
8201 // do not serialize defaults
8202 if (!element.hasOwnProperty(name)) {
8203 return false;
8204 }
8205
8206 var value = element[name];
8207
8208 // do not serialize default equals
8209 if (value === p.default) {
8210 return false;
8211 }
8212
8213 // do not serialize null properties
8214 if (value === null) {
8215 return false;
8216 }
8217
8218 return p.isMany ? value.length : true;
8219 });
8220 }
8221
8222 var ESCAPE_ATTR_MAP = {
8223 '\n': '#10',
8224 '\n\r': '#10',
8225 '"': '#34',
8226 '\'': '#39',
8227 '<': '#60',
8228 '>': '#62',
8229 '&': '#38'
8230 };
8231
8232 var ESCAPE_MAP = {
8233 '<': 'lt',
8234 '>': 'gt',
8235 '&': 'amp'
8236 };
8237
8238 function escape$1(str, charPattern, replaceMap) {
8239
8240 // ensure we are handling strings here
8241 str = isString(str) ? str : '' + str;
8242
8243 return str.replace(charPattern, function(s) {
8244 return '&' + replaceMap[s] + ';';
8245 });
8246 }
8247
8248 /**
8249 * Escape a string attribute to not contain any bad values (line breaks, '"', ...)
8250 *
8251 * @param {String} str the string to escape
8252 * @return {String} the escaped string
8253 */
8254 function escapeAttr(str) {
8255 return escape$1(str, ESCAPE_ATTR_CHARS, ESCAPE_ATTR_MAP);
8256 }
8257
8258 function escapeBody(str) {
8259 return escape$1(str, ESCAPE_CHARS, ESCAPE_MAP);
8260 }
8261
8262 function filterAttributes(props) {
8263 return filter(props, function(p) { return p.isAttr; });
8264 }
8265
8266 function filterContained(props) {
8267 return filter(props, function(p) { return !p.isAttr; });
8268 }
8269
8270
8271 function ReferenceSerializer(tagName) {
8272 this.tagName = tagName;
8273 }
8274
8275 ReferenceSerializer.prototype.build = function(element) {
8276 this.element = element;
8277 return this;
8278 };
8279
8280 ReferenceSerializer.prototype.serializeTo = function(writer) {
8281 writer
8282 .appendIndent()
8283 .append('<' + this.tagName + '>' + this.element.id + '</' + this.tagName + '>')
8284 .appendNewLine();
8285 };
8286
8287 function BodySerializer() {}
8288
8289 BodySerializer.prototype.serializeValue =
8290 BodySerializer.prototype.serializeTo = function(writer) {
8291 writer.append(
8292 this.escape
8293 ? escapeBody(this.value)
8294 : this.value
8295 );
8296 };
8297
8298 BodySerializer.prototype.build = function(prop, value) {
8299 this.value = value;
8300
8301 if (prop.type === 'String' && value.search(ESCAPE_CHARS) !== -1) {
8302 this.escape = true;
8303 }
8304
8305 return this;
8306 };
8307
8308 function ValueSerializer(tagName) {
8309 this.tagName = tagName;
8310 }
8311
8312 inherits(ValueSerializer, BodySerializer);
8313
8314 ValueSerializer.prototype.serializeTo = function(writer) {
8315
8316 writer
8317 .appendIndent()
8318 .append('<' + this.tagName + '>');
8319
8320 this.serializeValue(writer);
8321
8322 writer
8323 .append('</' + this.tagName + '>')
8324 .appendNewLine();
8325 };
8326
8327 function ElementSerializer(parent, propertyDescriptor) {
8328 this.body = [];
8329 this.attrs = [];
8330
8331 this.parent = parent;
8332 this.propertyDescriptor = propertyDescriptor;
8333 }
8334
8335 ElementSerializer.prototype.build = function(element) {
8336 this.element = element;
8337
8338 var elementDescriptor = element.$descriptor,
8339 propertyDescriptor = this.propertyDescriptor;
8340
8341 var otherAttrs,
8342 properties;
8343
8344 var isGeneric = elementDescriptor.isGeneric;
8345
8346 if (isGeneric) {
8347 otherAttrs = this.parseGeneric(element);
8348 } else {
8349 otherAttrs = this.parseNsAttributes(element);
8350 }
8351
8352 if (propertyDescriptor) {
8353 this.ns = this.nsPropertyTagName(propertyDescriptor);
8354 } else {
8355 this.ns = this.nsTagName(elementDescriptor);
8356 }
8357
8358 // compute tag name
8359 this.tagName = this.addTagName(this.ns);
8360
8361 if (!isGeneric) {
8362 properties = getSerializableProperties(element);
8363
8364 this.parseAttributes(filterAttributes(properties));
8365 this.parseContainments(filterContained(properties));
8366 }
8367
8368 this.parseGenericAttributes(element, otherAttrs);
8369
8370 return this;
8371 };
8372
8373 ElementSerializer.prototype.nsTagName = function(descriptor) {
8374 var effectiveNs = this.logNamespaceUsed(descriptor.ns);
8375 return getElementNs(effectiveNs, descriptor);
8376 };
8377
8378 ElementSerializer.prototype.nsPropertyTagName = function(descriptor) {
8379 var effectiveNs = this.logNamespaceUsed(descriptor.ns);
8380 return getPropertyNs(effectiveNs, descriptor);
8381 };
8382
8383 ElementSerializer.prototype.isLocalNs = function(ns) {
8384 return ns.uri === this.ns.uri;
8385 };
8386
8387 /**
8388 * Get the actual ns attribute name for the given element.
8389 *
8390 * @param {Object} element
8391 * @param {Boolean} [element.inherited=false]
8392 *
8393 * @return {Object} nsName
8394 */
8395 ElementSerializer.prototype.nsAttributeName = function(element) {
8396
8397 var ns;
8398
8399 if (isString(element)) {
8400 ns = parseName(element);
8401 } else {
8402 ns = element.ns;
8403 }
8404
8405 // return just local name for inherited attributes
8406 if (element.inherited) {
8407 return { localName: ns.localName };
8408 }
8409
8410 // parse + log effective ns
8411 var effectiveNs = this.logNamespaceUsed(ns);
8412
8413 // LOG ACTUAL namespace use
8414 this.getNamespaces().logUsed(effectiveNs);
8415
8416 // strip prefix if same namespace like parent
8417 if (this.isLocalNs(effectiveNs)) {
8418 return { localName: ns.localName };
8419 } else {
8420 return assign({ localName: ns.localName }, effectiveNs);
8421 }
8422 };
8423
8424 ElementSerializer.prototype.parseGeneric = function(element) {
8425
8426 var self = this,
8427 body = this.body;
8428
8429 var attributes = [];
8430
8431 forEach(element, function(val, key) {
8432
8433 var nonNsAttr;
8434
8435 if (key === '$body') {
8436 body.push(new BodySerializer().build({ type: 'String' }, val));
8437 } else
8438 if (key === '$children') {
8439 forEach(val, function(child) {
8440 body.push(new ElementSerializer(self).build(child));
8441 });
8442 } else
8443 if (key.indexOf('$') !== 0) {
8444 nonNsAttr = self.parseNsAttribute(element, key, val);
8445
8446 if (nonNsAttr) {
8447 attributes.push({ name: key, value: val });
8448 }
8449 }
8450 });
8451
8452 return attributes;
8453 };
8454
8455 ElementSerializer.prototype.parseNsAttribute = function(element, name, value) {
8456 var model = element.$model;
8457
8458 var nameNs = parseName(name);
8459
8460 var ns;
8461
8462 // parse xmlns:foo="http://foo.bar"
8463 if (nameNs.prefix === 'xmlns') {
8464 ns = { prefix: nameNs.localName, uri: value };
8465 }
8466
8467 // parse xmlns="http://foo.bar"
8468 if (!nameNs.prefix && nameNs.localName === 'xmlns') {
8469 ns = { uri: value };
8470 }
8471
8472 if (!ns) {
8473 return {
8474 name: name,
8475 value: value
8476 };
8477 }
8478
8479 if (model && model.getPackage(value)) {
8480 // register well known namespace
8481 this.logNamespace(ns, true, true);
8482 } else {
8483 // log custom namespace directly as used
8484 var actualNs = this.logNamespaceUsed(ns, true);
8485
8486 this.getNamespaces().logUsed(actualNs);
8487 }
8488 };
8489
8490
8491 /**
8492 * Parse namespaces and return a list of left over generic attributes
8493 *
8494 * @param {Object} element
8495 * @return {Array<Object>}
8496 */
8497 ElementSerializer.prototype.parseNsAttributes = function(element, attrs) {
8498 var self = this;
8499
8500 var genericAttrs = element.$attrs;
8501
8502 var attributes = [];
8503
8504 // parse namespace attributes first
8505 // and log them. push non namespace attributes to a list
8506 // and process them later
8507 forEach(genericAttrs, function(value, name) {
8508
8509 var nonNsAttr = self.parseNsAttribute(element, name, value);
8510
8511 if (nonNsAttr) {
8512 attributes.push(nonNsAttr);
8513 }
8514 });
8515
8516 return attributes;
8517 };
8518
8519 ElementSerializer.prototype.parseGenericAttributes = function(element, attributes) {
8520
8521 var self = this;
8522
8523 forEach(attributes, function(attr) {
8524
8525 // do not serialize xsi:type attribute
8526 // it is set manually based on the actual implementation type
8527 if (attr.name === XSI_TYPE$1) {
8528 return;
8529 }
8530
8531 try {
8532 self.addAttribute(self.nsAttributeName(attr.name), attr.value);
8533 } catch (e) {
8534 console.warn(
8535 'missing namespace information for ',
8536 attr.name, '=', attr.value, 'on', element,
8537 e);
8538 }
8539 });
8540 };
8541
8542 ElementSerializer.prototype.parseContainments = function(properties) {
8543
8544 var self = this,
8545 body = this.body,
8546 element = this.element;
8547
8548 forEach(properties, function(p) {
8549 var value = element.get(p.name),
8550 isReference = p.isReference,
8551 isMany = p.isMany;
8552
8553 if (!isMany) {
8554 value = [ value ];
8555 }
8556
8557 if (p.isBody) {
8558 body.push(new BodySerializer().build(p, value[0]));
8559 } else
8560 if (isSimple(p.type)) {
8561 forEach(value, function(v) {
8562 body.push(new ValueSerializer(self.addTagName(self.nsPropertyTagName(p))).build(p, v));
8563 });
8564 } else
8565 if (isReference) {
8566 forEach(value, function(v) {
8567 body.push(new ReferenceSerializer(self.addTagName(self.nsPropertyTagName(p))).build(v));
8568 });
8569 } else {
8570 // allow serialization via type
8571 // rather than element name
8572 var asType = serializeAsType(p),
8573 asProperty = serializeAsProperty(p);
8574
8575 forEach(value, function(v) {
8576 var serializer;
8577
8578 if (asType) {
8579 serializer = new TypeSerializer(self, p);
8580 } else
8581 if (asProperty) {
8582 serializer = new ElementSerializer(self, p);
8583 } else {
8584 serializer = new ElementSerializer(self);
8585 }
8586
8587 body.push(serializer.build(v));
8588 });
8589 }
8590 });
8591 };
8592
8593 ElementSerializer.prototype.getNamespaces = function(local) {
8594
8595 var namespaces = this.namespaces,
8596 parent = this.parent,
8597 parentNamespaces;
8598
8599 if (!namespaces) {
8600 parentNamespaces = parent && parent.getNamespaces();
8601
8602 if (local || !parentNamespaces) {
8603 this.namespaces = namespaces = new Namespaces(parentNamespaces);
8604 } else {
8605 namespaces = parentNamespaces;
8606 }
8607 }
8608
8609 return namespaces;
8610 };
8611
8612 ElementSerializer.prototype.logNamespace = function(ns, wellknown, local) {
8613 var namespaces = this.getNamespaces(local);
8614
8615 var nsUri = ns.uri,
8616 nsPrefix = ns.prefix;
8617
8618 var existing = namespaces.byUri(nsUri);
8619
8620 if (!existing) {
8621 namespaces.add(ns, wellknown);
8622 }
8623
8624 namespaces.mapPrefix(nsPrefix, nsUri);
8625
8626 return ns;
8627 };
8628
8629 ElementSerializer.prototype.logNamespaceUsed = function(ns, local) {
8630 var element = this.element,
8631 model = element.$model,
8632 namespaces = this.getNamespaces(local);
8633
8634 // ns may be
8635 //
8636 // * prefix only
8637 // * prefix:uri
8638 // * localName only
8639
8640 var prefix = ns.prefix,
8641 uri = ns.uri,
8642 newPrefix, idx,
8643 wellknownUri;
8644
8645 // handle anonymous namespaces (elementForm=unqualified), cf. #23
8646 if (!prefix && !uri) {
8647 return { localName: ns.localName };
8648 }
8649
8650 wellknownUri = DEFAULT_NS_MAP[prefix] || model && (model.getPackage(prefix) || {}).uri;
8651
8652 uri = uri || wellknownUri || namespaces.uriByPrefix(prefix);
8653
8654 if (!uri) {
8655 throw new Error('no namespace uri given for prefix <' + prefix + '>');
8656 }
8657
8658 ns = namespaces.byUri(uri);
8659
8660 if (!ns) {
8661 newPrefix = prefix;
8662 idx = 1;
8663
8664 // find a prefix that is not mapped yet
8665 while (namespaces.uriByPrefix(newPrefix)) {
8666 newPrefix = prefix + '_' + idx++;
8667 }
8668
8669 ns = this.logNamespace({ prefix: newPrefix, uri: uri }, wellknownUri === uri);
8670 }
8671
8672 if (prefix) {
8673 namespaces.mapPrefix(prefix, uri);
8674 }
8675
8676 return ns;
8677 };
8678
8679 ElementSerializer.prototype.parseAttributes = function(properties) {
8680 var self = this,
8681 element = this.element;
8682
8683 forEach(properties, function(p) {
8684
8685 var value = element.get(p.name);
8686
8687 if (p.isReference) {
8688
8689 if (!p.isMany) {
8690 value = value.id;
8691 }
8692 else {
8693 var values$$1 = [];
8694 forEach(value, function(v) {
8695 values$$1.push(v.id);
8696 });
8697 // IDREFS is a whitespace-separated list of references.
8698 value = values$$1.join(' ');
8699 }
8700
8701 }
8702
8703 self.addAttribute(self.nsAttributeName(p), value);
8704 });
8705 };
8706
8707 ElementSerializer.prototype.addTagName = function(nsTagName) {
8708 var actualNs = this.logNamespaceUsed(nsTagName);
8709
8710 this.getNamespaces().logUsed(actualNs);
8711
8712 return nsName(nsTagName);
8713 };
8714
8715 ElementSerializer.prototype.addAttribute = function(name, value) {
8716 var attrs = this.attrs;
8717
8718 if (isString(value)) {
8719 value = escapeAttr(value);
8720 }
8721
8722 attrs.push({ name: name, value: value });
8723 };
8724
8725 ElementSerializer.prototype.serializeAttributes = function(writer) {
8726 var attrs = this.attrs,
8727 namespaces = this.namespaces;
8728
8729 if (namespaces) {
8730 attrs = getNsAttrs(namespaces).concat(attrs);
8731 }
8732
8733 forEach(attrs, function(a) {
8734 writer
8735 .append(' ')
8736 .append(nsName(a.name)).append('="').append(a.value).append('"');
8737 });
8738 };
8739
8740 ElementSerializer.prototype.serializeTo = function(writer) {
8741 var firstBody = this.body[0],
8742 indent = firstBody && firstBody.constructor !== BodySerializer;
8743
8744 writer
8745 .appendIndent()
8746 .append('<' + this.tagName);
8747
8748 this.serializeAttributes(writer);
8749
8750 writer.append(firstBody ? '>' : ' />');
8751
8752 if (firstBody) {
8753
8754 if (indent) {
8755 writer
8756 .appendNewLine()
8757 .indent();
8758 }
8759
8760 forEach(this.body, function(b) {
8761 b.serializeTo(writer);
8762 });
8763
8764 if (indent) {
8765 writer
8766 .unindent()
8767 .appendIndent();
8768 }
8769
8770 writer.append('</' + this.tagName + '>');
8771 }
8772
8773 writer.appendNewLine();
8774 };
8775
8776 /**
8777 * A serializer for types that handles serialization of data types
8778 */
8779 function TypeSerializer(parent, propertyDescriptor) {
8780 ElementSerializer.call(this, parent, propertyDescriptor);
8781 }
8782
8783 inherits(TypeSerializer, ElementSerializer);
8784
8785 TypeSerializer.prototype.parseNsAttributes = function(element) {
8786
8787 // extracted attributes
8788 var attributes = ElementSerializer.prototype.parseNsAttributes.call(this, element);
8789
8790 var descriptor = element.$descriptor;
8791
8792 // only serialize xsi:type if necessary
8793 if (descriptor.name === this.propertyDescriptor.type) {
8794 return attributes;
8795 }
8796
8797 var typeNs = this.typeNs = this.nsTagName(descriptor);
8798 this.getNamespaces().logUsed(this.typeNs);
8799
8800 // add xsi:type attribute to represent the elements
8801 // actual type
8802
8803 var pkg = element.$model.getPackage(typeNs.uri),
8804 typePrefix = (pkg.xml && pkg.xml.typePrefix) || '';
8805
8806 this.addAttribute(
8807 this.nsAttributeName(XSI_TYPE$1),
8808 (typeNs.prefix ? typeNs.prefix + ':' : '') + typePrefix + descriptor.ns.localName
8809 );
8810
8811 return attributes;
8812 };
8813
8814 TypeSerializer.prototype.isLocalNs = function(ns) {
8815 return ns.uri === (this.typeNs || this.ns).uri;
8816 };
8817
8818 function SavingWriter() {
8819 this.value = '';
8820
8821 this.write = function(str) {
8822 this.value += str;
8823 };
8824 }
8825
8826 function FormatingWriter(out, format) {
8827
8828 var indent = [''];
8829
8830 this.append = function(str) {
8831 out.write(str);
8832
8833 return this;
8834 };
8835
8836 this.appendNewLine = function() {
8837 if (format) {
8838 out.write('\n');
8839 }
8840
8841 return this;
8842 };
8843
8844 this.appendIndent = function() {
8845 if (format) {
8846 out.write(indent.join(' '));
8847 }
8848
8849 return this;
8850 };
8851
8852 this.indent = function() {
8853 indent.push('');
8854 return this;
8855 };
8856
8857 this.unindent = function() {
8858 indent.pop();
8859 return this;
8860 };
8861 }
8862
8863 /**
8864 * A writer for meta-model backed document trees
8865 *
8866 * @param {Object} options output options to pass into the writer
8867 */
8868 function Writer(options) {
8869
8870 options = assign({ format: false, preamble: true }, options || {});
8871
8872 function toXML(tree, writer) {
8873 var internalWriter = writer || new SavingWriter();
8874 var formatingWriter = new FormatingWriter(internalWriter, options.format);
8875
8876 if (options.preamble) {
8877 formatingWriter.append(XML_PREAMBLE);
8878 }
8879
8880 new ElementSerializer().build(tree).serializeTo(formatingWriter);
8881
8882 if (!writer) {
8883 return internalWriter.value;
8884 }
8885 }
8886
8887 return {
8888 toXML: toXML
8889 };
8890 }
8891
8892 /**
8893 * A sub class of {@link Moddle} with support for import and export of BPMN 2.0 xml files.
8894 *
8895 * @class BpmnModdle
8896 * @extends Moddle
8897 *
8898 * @param {Object|Array} packages to use for instantiating the model
8899 * @param {Object} [options] additional options to pass over
8900 */
8901 function BpmnModdle(packages, options) {
8902 Moddle.call(this, packages, options);
8903 }
8904
8905 BpmnModdle.prototype = Object.create(Moddle.prototype);
8906
8907
8908 /**
8909 * Instantiates a BPMN model tree from a given xml string.
8910 *
8911 * @param {String} xmlStr
8912 * @param {String} [typeName='bpmn:Definitions'] name of the root element
8913 * @param {Object} [options] options to pass to the underlying reader
8914 * @param {Function} done callback that is invoked with (err, result, parseContext)
8915 * once the import completes
8916 */
8917 BpmnModdle.prototype.fromXML = function(xmlStr, typeName, options, done) {
8918
8919 if (!isString(typeName)) {
8920 done = options;
8921 options = typeName;
8922 typeName = 'bpmn:Definitions';
8923 }
8924
8925 if (isFunction(options)) {
8926 done = options;
8927 options = {};
8928 }
8929
8930 var reader = new Reader(assign({ model: this, lax: true }, options));
8931 var rootHandler = reader.handler(typeName);
8932
8933 reader.fromXML(xmlStr, rootHandler, done);
8934 };
8935
8936
8937 /**
8938 * Serializes a BPMN 2.0 object tree to XML.
8939 *
8940 * @param {String} element the root element, typically an instance of `bpmn:Definitions`
8941 * @param {Object} [options] to pass to the underlying writer
8942 * @param {Function} done callback invoked with (err, xmlStr) once the import completes
8943 */
8944 BpmnModdle.prototype.toXML = function(element, options, done) {
8945
8946 if (isFunction(options)) {
8947 done = options;
8948 options = {};
8949 }
8950
8951 var writer = new Writer(options);
8952
8953 var result;
8954 var err;
8955
8956 try {
8957 result = writer.toXML(element);
8958 } catch (e) {
8959 err = e;
8960 }
8961
8962 return done(err, result);
8963 };
8964
8965 var name = "BPMN20";
8966 var uri = "http://www.omg.org/spec/BPMN/20100524/MODEL";
8967 var associations = [
8968 ];
8969 var types$1 = [
8970 {
8971 name: "Interface",
8972 superClass: [
8973 "RootElement"
8974 ],
8975 properties: [
8976 {
8977 name: "name",
8978 isAttr: true,
8979 type: "String"
8980 },
8981 {
8982 name: "operations",
8983 type: "Operation",
8984 isMany: true
8985 },
8986 {
8987 name: "implementationRef",
8988 type: "String",
8989 isAttr: true
8990 }
8991 ]
8992 },
8993 {
8994 name: "Operation",
8995 superClass: [
8996 "BaseElement"
8997 ],
8998 properties: [
8999 {
9000 name: "name",
9001 isAttr: true,
9002 type: "String"
9003 },
9004 {
9005 name: "inMessageRef",
9006 type: "Message",
9007 isReference: true
9008 },
9009 {
9010 name: "outMessageRef",
9011 type: "Message",
9012 isReference: true
9013 },
9014 {
9015 name: "errorRef",
9016 type: "Error",
9017 isMany: true,
9018 isReference: true
9019 },
9020 {
9021 name: "implementationRef",
9022 type: "String",
9023 isAttr: true
9024 }
9025 ]
9026 },
9027 {
9028 name: "EndPoint",
9029 superClass: [
9030 "RootElement"
9031 ]
9032 },
9033 {
9034 name: "Auditing",
9035 superClass: [
9036 "BaseElement"
9037 ]
9038 },
9039 {
9040 name: "GlobalTask",
9041 superClass: [
9042 "CallableElement"
9043 ],
9044 properties: [
9045 {
9046 name: "resources",
9047 type: "ResourceRole",
9048 isMany: true
9049 }
9050 ]
9051 },
9052 {
9053 name: "Monitoring",
9054 superClass: [
9055 "BaseElement"
9056 ]
9057 },
9058 {
9059 name: "Performer",
9060 superClass: [
9061 "ResourceRole"
9062 ]
9063 },
9064 {
9065 name: "Process",
9066 superClass: [
9067 "FlowElementsContainer",
9068 "CallableElement"
9069 ],
9070 properties: [
9071 {
9072 name: "processType",
9073 type: "ProcessType",
9074 isAttr: true
9075 },
9076 {
9077 name: "isClosed",
9078 isAttr: true,
9079 type: "Boolean"
9080 },
9081 {
9082 name: "auditing",
9083 type: "Auditing"
9084 },
9085 {
9086 name: "monitoring",
9087 type: "Monitoring"
9088 },
9089 {
9090 name: "properties",
9091 type: "Property",
9092 isMany: true
9093 },
9094 {
9095 name: "laneSets",
9096 type: "LaneSet",
9097 isMany: true,
9098 replaces: "FlowElementsContainer#laneSets"
9099 },
9100 {
9101 name: "flowElements",
9102 type: "FlowElement",
9103 isMany: true,
9104 replaces: "FlowElementsContainer#flowElements"
9105 },
9106 {
9107 name: "artifacts",
9108 type: "Artifact",
9109 isMany: true
9110 },
9111 {
9112 name: "resources",
9113 type: "ResourceRole",
9114 isMany: true
9115 },
9116 {
9117 name: "correlationSubscriptions",
9118 type: "CorrelationSubscription",
9119 isMany: true
9120 },
9121 {
9122 name: "supports",
9123 type: "Process",
9124 isMany: true,
9125 isReference: true
9126 },
9127 {
9128 name: "definitionalCollaborationRef",
9129 type: "Collaboration",
9130 isAttr: true,
9131 isReference: true
9132 },
9133 {
9134 name: "isExecutable",
9135 isAttr: true,
9136 type: "Boolean"
9137 }
9138 ]
9139 },
9140 {
9141 name: "LaneSet",
9142 superClass: [
9143 "BaseElement"
9144 ],
9145 properties: [
9146 {
9147 name: "lanes",
9148 type: "Lane",
9149 isMany: true
9150 },
9151 {
9152 name: "name",
9153 isAttr: true,
9154 type: "String"
9155 }
9156 ]
9157 },
9158 {
9159 name: "Lane",
9160 superClass: [
9161 "BaseElement"
9162 ],
9163 properties: [
9164 {
9165 name: "name",
9166 isAttr: true,
9167 type: "String"
9168 },
9169 {
9170 name: "partitionElementRef",
9171 type: "BaseElement",
9172 isAttr: true,
9173 isReference: true
9174 },
9175 {
9176 name: "partitionElement",
9177 type: "BaseElement"
9178 },
9179 {
9180 name: "flowNodeRef",
9181 type: "FlowNode",
9182 isMany: true,
9183 isReference: true
9184 },
9185 {
9186 name: "childLaneSet",
9187 type: "LaneSet",
9188 xml: {
9189 serialize: "xsi:type"
9190 }
9191 }
9192 ]
9193 },
9194 {
9195 name: "GlobalManualTask",
9196 superClass: [
9197 "GlobalTask"
9198 ]
9199 },
9200 {
9201 name: "ManualTask",
9202 superClass: [
9203 "Task"
9204 ]
9205 },
9206 {
9207 name: "UserTask",
9208 superClass: [
9209 "Task"
9210 ],
9211 properties: [
9212 {
9213 name: "renderings",
9214 type: "Rendering",
9215 isMany: true
9216 },
9217 {
9218 name: "implementation",
9219 isAttr: true,
9220 type: "String"
9221 }
9222 ]
9223 },
9224 {
9225 name: "Rendering",
9226 superClass: [
9227 "BaseElement"
9228 ]
9229 },
9230 {
9231 name: "HumanPerformer",
9232 superClass: [
9233 "Performer"
9234 ]
9235 },
9236 {
9237 name: "PotentialOwner",
9238 superClass: [
9239 "HumanPerformer"
9240 ]
9241 },
9242 {
9243 name: "GlobalUserTask",
9244 superClass: [
9245 "GlobalTask"
9246 ],
9247 properties: [
9248 {
9249 name: "implementation",
9250 isAttr: true,
9251 type: "String"
9252 },
9253 {
9254 name: "renderings",
9255 type: "Rendering",
9256 isMany: true
9257 }
9258 ]
9259 },
9260 {
9261 name: "Gateway",
9262 isAbstract: true,
9263 superClass: [
9264 "FlowNode"
9265 ],
9266 properties: [
9267 {
9268 name: "gatewayDirection",
9269 type: "GatewayDirection",
9270 "default": "Unspecified",
9271 isAttr: true
9272 }
9273 ]
9274 },
9275 {
9276 name: "EventBasedGateway",
9277 superClass: [
9278 "Gateway"
9279 ],
9280 properties: [
9281 {
9282 name: "instantiate",
9283 "default": false,
9284 isAttr: true,
9285 type: "Boolean"
9286 },
9287 {
9288 name: "eventGatewayType",
9289 type: "EventBasedGatewayType",
9290 isAttr: true,
9291 "default": "Exclusive"
9292 }
9293 ]
9294 },
9295 {
9296 name: "ComplexGateway",
9297 superClass: [
9298 "Gateway"
9299 ],
9300 properties: [
9301 {
9302 name: "activationCondition",
9303 type: "Expression",
9304 xml: {
9305 serialize: "xsi:type"
9306 }
9307 },
9308 {
9309 name: "default",
9310 type: "SequenceFlow",
9311 isAttr: true,
9312 isReference: true
9313 }
9314 ]
9315 },
9316 {
9317 name: "ExclusiveGateway",
9318 superClass: [
9319 "Gateway"
9320 ],
9321 properties: [
9322 {
9323 name: "default",
9324 type: "SequenceFlow",
9325 isAttr: true,
9326 isReference: true
9327 }
9328 ]
9329 },
9330 {
9331 name: "InclusiveGateway",
9332 superClass: [
9333 "Gateway"
9334 ],
9335 properties: [
9336 {
9337 name: "default",
9338 type: "SequenceFlow",
9339 isAttr: true,
9340 isReference: true
9341 }
9342 ]
9343 },
9344 {
9345 name: "ParallelGateway",
9346 superClass: [
9347 "Gateway"
9348 ]
9349 },
9350 {
9351 name: "RootElement",
9352 isAbstract: true,
9353 superClass: [
9354 "BaseElement"
9355 ]
9356 },
9357 {
9358 name: "Relationship",
9359 superClass: [
9360 "BaseElement"
9361 ],
9362 properties: [
9363 {
9364 name: "type",
9365 isAttr: true,
9366 type: "String"
9367 },
9368 {
9369 name: "direction",
9370 type: "RelationshipDirection",
9371 isAttr: true
9372 },
9373 {
9374 name: "source",
9375 isMany: true,
9376 isReference: true,
9377 type: "Element"
9378 },
9379 {
9380 name: "target",
9381 isMany: true,
9382 isReference: true,
9383 type: "Element"
9384 }
9385 ]
9386 },
9387 {
9388 name: "BaseElement",
9389 isAbstract: true,
9390 properties: [
9391 {
9392 name: "id",
9393 isAttr: true,
9394 type: "String",
9395 isId: true
9396 },
9397 {
9398 name: "documentation",
9399 type: "Documentation",
9400 isMany: true
9401 },
9402 {
9403 name: "extensionDefinitions",
9404 type: "ExtensionDefinition",
9405 isMany: true,
9406 isReference: true
9407 },
9408 {
9409 name: "extensionElements",
9410 type: "ExtensionElements"
9411 }
9412 ]
9413 },
9414 {
9415 name: "Extension",
9416 properties: [
9417 {
9418 name: "mustUnderstand",
9419 "default": false,
9420 isAttr: true,
9421 type: "Boolean"
9422 },
9423 {
9424 name: "definition",
9425 type: "ExtensionDefinition",
9426 isAttr: true,
9427 isReference: true
9428 }
9429 ]
9430 },
9431 {
9432 name: "ExtensionDefinition",
9433 properties: [
9434 {
9435 name: "name",
9436 isAttr: true,
9437 type: "String"
9438 },
9439 {
9440 name: "extensionAttributeDefinitions",
9441 type: "ExtensionAttributeDefinition",
9442 isMany: true
9443 }
9444 ]
9445 },
9446 {
9447 name: "ExtensionAttributeDefinition",
9448 properties: [
9449 {
9450 name: "name",
9451 isAttr: true,
9452 type: "String"
9453 },
9454 {
9455 name: "type",
9456 isAttr: true,
9457 type: "String"
9458 },
9459 {
9460 name: "isReference",
9461 "default": false,
9462 isAttr: true,
9463 type: "Boolean"
9464 },
9465 {
9466 name: "extensionDefinition",
9467 type: "ExtensionDefinition",
9468 isAttr: true,
9469 isReference: true
9470 }
9471 ]
9472 },
9473 {
9474 name: "ExtensionElements",
9475 properties: [
9476 {
9477 name: "valueRef",
9478 isAttr: true,
9479 isReference: true,
9480 type: "Element"
9481 },
9482 {
9483 name: "values",
9484 type: "Element",
9485 isMany: true
9486 },
9487 {
9488 name: "extensionAttributeDefinition",
9489 type: "ExtensionAttributeDefinition",
9490 isAttr: true,
9491 isReference: true
9492 }
9493 ]
9494 },
9495 {
9496 name: "Documentation",
9497 superClass: [
9498 "BaseElement"
9499 ],
9500 properties: [
9501 {
9502 name: "text",
9503 type: "String",
9504 isBody: true
9505 },
9506 {
9507 name: "textFormat",
9508 "default": "text/plain",
9509 isAttr: true,
9510 type: "String"
9511 }
9512 ]
9513 },
9514 {
9515 name: "Event",
9516 isAbstract: true,
9517 superClass: [
9518 "FlowNode",
9519 "InteractionNode"
9520 ],
9521 properties: [
9522 {
9523 name: "properties",
9524 type: "Property",
9525 isMany: true
9526 }
9527 ]
9528 },
9529 {
9530 name: "IntermediateCatchEvent",
9531 superClass: [
9532 "CatchEvent"
9533 ]
9534 },
9535 {
9536 name: "IntermediateThrowEvent",
9537 superClass: [
9538 "ThrowEvent"
9539 ]
9540 },
9541 {
9542 name: "EndEvent",
9543 superClass: [
9544 "ThrowEvent"
9545 ]
9546 },
9547 {
9548 name: "StartEvent",
9549 superClass: [
9550 "CatchEvent"
9551 ],
9552 properties: [
9553 {
9554 name: "isInterrupting",
9555 "default": true,
9556 isAttr: true,
9557 type: "Boolean"
9558 }
9559 ]
9560 },
9561 {
9562 name: "ThrowEvent",
9563 isAbstract: true,
9564 superClass: [
9565 "Event"
9566 ],
9567 properties: [
9568 {
9569 name: "dataInputs",
9570 type: "DataInput",
9571 isMany: true
9572 },
9573 {
9574 name: "dataInputAssociations",
9575 type: "DataInputAssociation",
9576 isMany: true
9577 },
9578 {
9579 name: "inputSet",
9580 type: "InputSet"
9581 },
9582 {
9583 name: "eventDefinitions",
9584 type: "EventDefinition",
9585 isMany: true
9586 },
9587 {
9588 name: "eventDefinitionRef",
9589 type: "EventDefinition",
9590 isMany: true,
9591 isReference: true
9592 }
9593 ]
9594 },
9595 {
9596 name: "CatchEvent",
9597 isAbstract: true,
9598 superClass: [
9599 "Event"
9600 ],
9601 properties: [
9602 {
9603 name: "parallelMultiple",
9604 isAttr: true,
9605 type: "Boolean",
9606 "default": false
9607 },
9608 {
9609 name: "dataOutputs",
9610 type: "DataOutput",
9611 isMany: true
9612 },
9613 {
9614 name: "dataOutputAssociations",
9615 type: "DataOutputAssociation",
9616 isMany: true
9617 },
9618 {
9619 name: "outputSet",
9620 type: "OutputSet"
9621 },
9622 {
9623 name: "eventDefinitions",
9624 type: "EventDefinition",
9625 isMany: true
9626 },
9627 {
9628 name: "eventDefinitionRef",
9629 type: "EventDefinition",
9630 isMany: true,
9631 isReference: true
9632 }
9633 ]
9634 },
9635 {
9636 name: "BoundaryEvent",
9637 superClass: [
9638 "CatchEvent"
9639 ],
9640 properties: [
9641 {
9642 name: "cancelActivity",
9643 "default": true,
9644 isAttr: true,
9645 type: "Boolean"
9646 },
9647 {
9648 name: "attachedToRef",
9649 type: "Activity",
9650 isAttr: true,
9651 isReference: true
9652 }
9653 ]
9654 },
9655 {
9656 name: "EventDefinition",
9657 isAbstract: true,
9658 superClass: [
9659 "RootElement"
9660 ]
9661 },
9662 {
9663 name: "CancelEventDefinition",
9664 superClass: [
9665 "EventDefinition"
9666 ]
9667 },
9668 {
9669 name: "ErrorEventDefinition",
9670 superClass: [
9671 "EventDefinition"
9672 ],
9673 properties: [
9674 {
9675 name: "errorRef",
9676 type: "Error",
9677 isAttr: true,
9678 isReference: true
9679 }
9680 ]
9681 },
9682 {
9683 name: "TerminateEventDefinition",
9684 superClass: [
9685 "EventDefinition"
9686 ]
9687 },
9688 {
9689 name: "EscalationEventDefinition",
9690 superClass: [
9691 "EventDefinition"
9692 ],
9693 properties: [
9694 {
9695 name: "escalationRef",
9696 type: "Escalation",
9697 isAttr: true,
9698 isReference: true
9699 }
9700 ]
9701 },
9702 {
9703 name: "Escalation",
9704 properties: [
9705 {
9706 name: "structureRef",
9707 type: "ItemDefinition",
9708 isAttr: true,
9709 isReference: true
9710 },
9711 {
9712 name: "name",
9713 isAttr: true,
9714 type: "String"
9715 },
9716 {
9717 name: "escalationCode",
9718 isAttr: true,
9719 type: "String"
9720 }
9721 ],
9722 superClass: [
9723 "RootElement"
9724 ]
9725 },
9726 {
9727 name: "CompensateEventDefinition",
9728 superClass: [
9729 "EventDefinition"
9730 ],
9731 properties: [
9732 {
9733 name: "waitForCompletion",
9734 isAttr: true,
9735 type: "Boolean",
9736 "default": true
9737 },
9738 {
9739 name: "activityRef",
9740 type: "Activity",
9741 isAttr: true,
9742 isReference: true
9743 }
9744 ]
9745 },
9746 {
9747 name: "TimerEventDefinition",
9748 superClass: [
9749 "EventDefinition"
9750 ],
9751 properties: [
9752 {
9753 name: "timeDate",
9754 type: "Expression",
9755 xml: {
9756 serialize: "xsi:type"
9757 }
9758 },
9759 {
9760 name: "timeCycle",
9761 type: "Expression",
9762 xml: {
9763 serialize: "xsi:type"
9764 }
9765 },
9766 {
9767 name: "timeDuration",
9768 type: "Expression",
9769 xml: {
9770 serialize: "xsi:type"
9771 }
9772 }
9773 ]
9774 },
9775 {
9776 name: "LinkEventDefinition",
9777 superClass: [
9778 "EventDefinition"
9779 ],
9780 properties: [
9781 {
9782 name: "name",
9783 isAttr: true,
9784 type: "String"
9785 },
9786 {
9787 name: "target",
9788 type: "LinkEventDefinition",
9789 isAttr: true,
9790 isReference: true
9791 },
9792 {
9793 name: "source",
9794 type: "LinkEventDefinition",
9795 isMany: true,
9796 isReference: true
9797 }
9798 ]
9799 },
9800 {
9801 name: "MessageEventDefinition",
9802 superClass: [
9803 "EventDefinition"
9804 ],
9805 properties: [
9806 {
9807 name: "messageRef",
9808 type: "Message",
9809 isAttr: true,
9810 isReference: true
9811 },
9812 {
9813 name: "operationRef",
9814 type: "Operation",
9815 isAttr: true,
9816 isReference: true
9817 }
9818 ]
9819 },
9820 {
9821 name: "ConditionalEventDefinition",
9822 superClass: [
9823 "EventDefinition"
9824 ],
9825 properties: [
9826 {
9827 name: "condition",
9828 type: "Expression",
9829 xml: {
9830 serialize: "xsi:type"
9831 }
9832 }
9833 ]
9834 },
9835 {
9836 name: "SignalEventDefinition",
9837 superClass: [
9838 "EventDefinition"
9839 ],
9840 properties: [
9841 {
9842 name: "signalRef",
9843 type: "Signal",
9844 isAttr: true,
9845 isReference: true
9846 }
9847 ]
9848 },
9849 {
9850 name: "Signal",
9851 superClass: [
9852 "RootElement"
9853 ],
9854 properties: [
9855 {
9856 name: "structureRef",
9857 type: "ItemDefinition",
9858 isAttr: true,
9859 isReference: true
9860 },
9861 {
9862 name: "name",
9863 isAttr: true,
9864 type: "String"
9865 }
9866 ]
9867 },
9868 {
9869 name: "ImplicitThrowEvent",
9870 superClass: [
9871 "ThrowEvent"
9872 ]
9873 },
9874 {
9875 name: "DataState",
9876 superClass: [
9877 "BaseElement"
9878 ],
9879 properties: [
9880 {
9881 name: "name",
9882 isAttr: true,
9883 type: "String"
9884 }
9885 ]
9886 },
9887 {
9888 name: "ItemAwareElement",
9889 superClass: [
9890 "BaseElement"
9891 ],
9892 properties: [
9893 {
9894 name: "itemSubjectRef",
9895 type: "ItemDefinition",
9896 isAttr: true,
9897 isReference: true
9898 },
9899 {
9900 name: "dataState",
9901 type: "DataState"
9902 }
9903 ]
9904 },
9905 {
9906 name: "DataAssociation",
9907 superClass: [
9908 "BaseElement"
9909 ],
9910 properties: [
9911 {
9912 name: "assignment",
9913 type: "Assignment",
9914 isMany: true
9915 },
9916 {
9917 name: "sourceRef",
9918 type: "ItemAwareElement",
9919 isMany: true,
9920 isReference: true
9921 },
9922 {
9923 name: "targetRef",
9924 type: "ItemAwareElement",
9925 isReference: true
9926 },
9927 {
9928 name: "transformation",
9929 type: "FormalExpression",
9930 xml: {
9931 serialize: "property"
9932 }
9933 }
9934 ]
9935 },
9936 {
9937 name: "DataInput",
9938 superClass: [
9939 "ItemAwareElement"
9940 ],
9941 properties: [
9942 {
9943 name: "name",
9944 isAttr: true,
9945 type: "String"
9946 },
9947 {
9948 name: "isCollection",
9949 "default": false,
9950 isAttr: true,
9951 type: "Boolean"
9952 },
9953 {
9954 name: "inputSetRef",
9955 type: "InputSet",
9956 isVirtual: true,
9957 isMany: true,
9958 isReference: true
9959 },
9960 {
9961 name: "inputSetWithOptional",
9962 type: "InputSet",
9963 isVirtual: true,
9964 isMany: true,
9965 isReference: true
9966 },
9967 {
9968 name: "inputSetWithWhileExecuting",
9969 type: "InputSet",
9970 isVirtual: true,
9971 isMany: true,
9972 isReference: true
9973 }
9974 ]
9975 },
9976 {
9977 name: "DataOutput",
9978 superClass: [
9979 "ItemAwareElement"
9980 ],
9981 properties: [
9982 {
9983 name: "name",
9984 isAttr: true,
9985 type: "String"
9986 },
9987 {
9988 name: "isCollection",
9989 "default": false,
9990 isAttr: true,
9991 type: "Boolean"
9992 },
9993 {
9994 name: "outputSetRef",
9995 type: "OutputSet",
9996 isVirtual: true,
9997 isMany: true,
9998 isReference: true
9999 },
10000 {
10001 name: "outputSetWithOptional",
10002 type: "OutputSet",
10003 isVirtual: true,
10004 isMany: true,
10005 isReference: true
10006 },
10007 {
10008 name: "outputSetWithWhileExecuting",
10009 type: "OutputSet",
10010 isVirtual: true,
10011 isMany: true,
10012 isReference: true
10013 }
10014 ]
10015 },
10016 {
10017 name: "InputSet",
10018 superClass: [
10019 "BaseElement"
10020 ],
10021 properties: [
10022 {
10023 name: "name",
10024 isAttr: true,
10025 type: "String"
10026 },
10027 {
10028 name: "dataInputRefs",
10029 type: "DataInput",
10030 isMany: true,
10031 isReference: true
10032 },
10033 {
10034 name: "optionalInputRefs",
10035 type: "DataInput",
10036 isMany: true,
10037 isReference: true
10038 },
10039 {
10040 name: "whileExecutingInputRefs",
10041 type: "DataInput",
10042 isMany: true,
10043 isReference: true
10044 },
10045 {
10046 name: "outputSetRefs",
10047 type: "OutputSet",
10048 isMany: true,
10049 isReference: true
10050 }
10051 ]
10052 },
10053 {
10054 name: "OutputSet",
10055 superClass: [
10056 "BaseElement"
10057 ],
10058 properties: [
10059 {
10060 name: "dataOutputRefs",
10061 type: "DataOutput",
10062 isMany: true,
10063 isReference: true
10064 },
10065 {
10066 name: "name",
10067 isAttr: true,
10068 type: "String"
10069 },
10070 {
10071 name: "inputSetRefs",
10072 type: "InputSet",
10073 isMany: true,
10074 isReference: true
10075 },
10076 {
10077 name: "optionalOutputRefs",
10078 type: "DataOutput",
10079 isMany: true,
10080 isReference: true
10081 },
10082 {
10083 name: "whileExecutingOutputRefs",
10084 type: "DataOutput",
10085 isMany: true,
10086 isReference: true
10087 }
10088 ]
10089 },
10090 {
10091 name: "Property",
10092 superClass: [
10093 "ItemAwareElement"
10094 ],
10095 properties: [
10096 {
10097 name: "name",
10098 isAttr: true,
10099 type: "String"
10100 }
10101 ]
10102 },
10103 {
10104 name: "DataInputAssociation",
10105 superClass: [
10106 "DataAssociation"
10107 ]
10108 },
10109 {
10110 name: "DataOutputAssociation",
10111 superClass: [
10112 "DataAssociation"
10113 ]
10114 },
10115 {
10116 name: "InputOutputSpecification",
10117 superClass: [
10118 "BaseElement"
10119 ],
10120 properties: [
10121 {
10122 name: "dataInputs",
10123 type: "DataInput",
10124 isMany: true
10125 },
10126 {
10127 name: "dataOutputs",
10128 type: "DataOutput",
10129 isMany: true
10130 },
10131 {
10132 name: "inputSets",
10133 type: "InputSet",
10134 isMany: true
10135 },
10136 {
10137 name: "outputSets",
10138 type: "OutputSet",
10139 isMany: true
10140 }
10141 ]
10142 },
10143 {
10144 name: "DataObject",
10145 superClass: [
10146 "FlowElement",
10147 "ItemAwareElement"
10148 ],
10149 properties: [
10150 {
10151 name: "isCollection",
10152 "default": false,
10153 isAttr: true,
10154 type: "Boolean"
10155 }
10156 ]
10157 },
10158 {
10159 name: "InputOutputBinding",
10160 properties: [
10161 {
10162 name: "inputDataRef",
10163 type: "InputSet",
10164 isAttr: true,
10165 isReference: true
10166 },
10167 {
10168 name: "outputDataRef",
10169 type: "OutputSet",
10170 isAttr: true,
10171 isReference: true
10172 },
10173 {
10174 name: "operationRef",
10175 type: "Operation",
10176 isAttr: true,
10177 isReference: true
10178 }
10179 ]
10180 },
10181 {
10182 name: "Assignment",
10183 superClass: [
10184 "BaseElement"
10185 ],
10186 properties: [
10187 {
10188 name: "from",
10189 type: "Expression",
10190 xml: {
10191 serialize: "xsi:type"
10192 }
10193 },
10194 {
10195 name: "to",
10196 type: "Expression",
10197 xml: {
10198 serialize: "xsi:type"
10199 }
10200 }
10201 ]
10202 },
10203 {
10204 name: "DataStore",
10205 superClass: [
10206 "RootElement",
10207 "ItemAwareElement"
10208 ],
10209 properties: [
10210 {
10211 name: "name",
10212 isAttr: true,
10213 type: "String"
10214 },
10215 {
10216 name: "capacity",
10217 isAttr: true,
10218 type: "Integer"
10219 },
10220 {
10221 name: "isUnlimited",
10222 "default": true,
10223 isAttr: true,
10224 type: "Boolean"
10225 }
10226 ]
10227 },
10228 {
10229 name: "DataStoreReference",
10230 superClass: [
10231 "ItemAwareElement",
10232 "FlowElement"
10233 ],
10234 properties: [
10235 {
10236 name: "dataStoreRef",
10237 type: "DataStore",
10238 isAttr: true,
10239 isReference: true
10240 }
10241 ]
10242 },
10243 {
10244 name: "DataObjectReference",
10245 superClass: [
10246 "ItemAwareElement",
10247 "FlowElement"
10248 ],
10249 properties: [
10250 {
10251 name: "dataObjectRef",
10252 type: "DataObject",
10253 isAttr: true,
10254 isReference: true
10255 }
10256 ]
10257 },
10258 {
10259 name: "ConversationLink",
10260 superClass: [
10261 "BaseElement"
10262 ],
10263 properties: [
10264 {
10265 name: "sourceRef",
10266 type: "InteractionNode",
10267 isAttr: true,
10268 isReference: true
10269 },
10270 {
10271 name: "targetRef",
10272 type: "InteractionNode",
10273 isAttr: true,
10274 isReference: true
10275 },
10276 {
10277 name: "name",
10278 isAttr: true,
10279 type: "String"
10280 }
10281 ]
10282 },
10283 {
10284 name: "ConversationAssociation",
10285 superClass: [
10286 "BaseElement"
10287 ],
10288 properties: [
10289 {
10290 name: "innerConversationNodeRef",
10291 type: "ConversationNode",
10292 isAttr: true,
10293 isReference: true
10294 },
10295 {
10296 name: "outerConversationNodeRef",
10297 type: "ConversationNode",
10298 isAttr: true,
10299 isReference: true
10300 }
10301 ]
10302 },
10303 {
10304 name: "CallConversation",
10305 superClass: [
10306 "ConversationNode"
10307 ],
10308 properties: [
10309 {
10310 name: "calledCollaborationRef",
10311 type: "Collaboration",
10312 isAttr: true,
10313 isReference: true
10314 },
10315 {
10316 name: "participantAssociations",
10317 type: "ParticipantAssociation",
10318 isMany: true
10319 }
10320 ]
10321 },
10322 {
10323 name: "Conversation",
10324 superClass: [
10325 "ConversationNode"
10326 ]
10327 },
10328 {
10329 name: "SubConversation",
10330 superClass: [
10331 "ConversationNode"
10332 ],
10333 properties: [
10334 {
10335 name: "conversationNodes",
10336 type: "ConversationNode",
10337 isMany: true
10338 }
10339 ]
10340 },
10341 {
10342 name: "ConversationNode",
10343 isAbstract: true,
10344 superClass: [
10345 "InteractionNode",
10346 "BaseElement"
10347 ],
10348 properties: [
10349 {
10350 name: "name",
10351 isAttr: true,
10352 type: "String"
10353 },
10354 {
10355 name: "participantRef",
10356 type: "Participant",
10357 isMany: true,
10358 isReference: true
10359 },
10360 {
10361 name: "messageFlowRefs",
10362 type: "MessageFlow",
10363 isMany: true,
10364 isReference: true
10365 },
10366 {
10367 name: "correlationKeys",
10368 type: "CorrelationKey",
10369 isMany: true
10370 }
10371 ]
10372 },
10373 {
10374 name: "GlobalConversation",
10375 superClass: [
10376 "Collaboration"
10377 ]
10378 },
10379 {
10380 name: "PartnerEntity",
10381 superClass: [
10382 "RootElement"
10383 ],
10384 properties: [
10385 {
10386 name: "name",
10387 isAttr: true,
10388 type: "String"
10389 },
10390 {
10391 name: "participantRef",
10392 type: "Participant",
10393 isMany: true,
10394 isReference: true
10395 }
10396 ]
10397 },
10398 {
10399 name: "PartnerRole",
10400 superClass: [
10401 "RootElement"
10402 ],
10403 properties: [
10404 {
10405 name: "name",
10406 isAttr: true,
10407 type: "String"
10408 },
10409 {
10410 name: "participantRef",
10411 type: "Participant",
10412 isMany: true,
10413 isReference: true
10414 }
10415 ]
10416 },
10417 {
10418 name: "CorrelationProperty",
10419 superClass: [
10420 "RootElement"
10421 ],
10422 properties: [
10423 {
10424 name: "correlationPropertyRetrievalExpression",
10425 type: "CorrelationPropertyRetrievalExpression",
10426 isMany: true
10427 },
10428 {
10429 name: "name",
10430 isAttr: true,
10431 type: "String"
10432 },
10433 {
10434 name: "type",
10435 type: "ItemDefinition",
10436 isAttr: true,
10437 isReference: true
10438 }
10439 ]
10440 },
10441 {
10442 name: "Error",
10443 superClass: [
10444 "RootElement"
10445 ],
10446 properties: [
10447 {
10448 name: "structureRef",
10449 type: "ItemDefinition",
10450 isAttr: true,
10451 isReference: true
10452 },
10453 {
10454 name: "name",
10455 isAttr: true,
10456 type: "String"
10457 },
10458 {
10459 name: "errorCode",
10460 isAttr: true,
10461 type: "String"
10462 }
10463 ]
10464 },
10465 {
10466 name: "CorrelationKey",
10467 superClass: [
10468 "BaseElement"
10469 ],
10470 properties: [
10471 {
10472 name: "correlationPropertyRef",
10473 type: "CorrelationProperty",
10474 isMany: true,
10475 isReference: true
10476 },
10477 {
10478 name: "name",
10479 isAttr: true,
10480 type: "String"
10481 }
10482 ]
10483 },
10484 {
10485 name: "Expression",
10486 superClass: [
10487 "BaseElement"
10488 ],
10489 isAbstract: false,
10490 properties: [
10491 {
10492 name: "body",
10493 type: "String",
10494 isBody: true
10495 }
10496 ]
10497 },
10498 {
10499 name: "FormalExpression",
10500 superClass: [
10501 "Expression"
10502 ],
10503 properties: [
10504 {
10505 name: "language",
10506 isAttr: true,
10507 type: "String"
10508 },
10509 {
10510 name: "evaluatesToTypeRef",
10511 type: "ItemDefinition",
10512 isAttr: true,
10513 isReference: true
10514 }
10515 ]
10516 },
10517 {
10518 name: "Message",
10519 superClass: [
10520 "RootElement"
10521 ],
10522 properties: [
10523 {
10524 name: "name",
10525 isAttr: true,
10526 type: "String"
10527 },
10528 {
10529 name: "itemRef",
10530 type: "ItemDefinition",
10531 isAttr: true,
10532 isReference: true
10533 }
10534 ]
10535 },
10536 {
10537 name: "ItemDefinition",
10538 superClass: [
10539 "RootElement"
10540 ],
10541 properties: [
10542 {
10543 name: "itemKind",
10544 type: "ItemKind",
10545 isAttr: true
10546 },
10547 {
10548 name: "structureRef",
10549 type: "String",
10550 isAttr: true
10551 },
10552 {
10553 name: "isCollection",
10554 "default": false,
10555 isAttr: true,
10556 type: "Boolean"
10557 },
10558 {
10559 name: "import",
10560 type: "Import",
10561 isAttr: true,
10562 isReference: true
10563 }
10564 ]
10565 },
10566 {
10567 name: "FlowElement",
10568 isAbstract: true,
10569 superClass: [
10570 "BaseElement"
10571 ],
10572 properties: [
10573 {
10574 name: "name",
10575 isAttr: true,
10576 type: "String"
10577 },
10578 {
10579 name: "auditing",
10580 type: "Auditing"
10581 },
10582 {
10583 name: "monitoring",
10584 type: "Monitoring"
10585 },
10586 {
10587 name: "categoryValueRef",
10588 type: "CategoryValue",
10589 isMany: true,
10590 isReference: true
10591 }
10592 ]
10593 },
10594 {
10595 name: "SequenceFlow",
10596 superClass: [
10597 "FlowElement"
10598 ],
10599 properties: [
10600 {
10601 name: "isImmediate",
10602 isAttr: true,
10603 type: "Boolean"
10604 },
10605 {
10606 name: "conditionExpression",
10607 type: "Expression",
10608 xml: {
10609 serialize: "xsi:type"
10610 }
10611 },
10612 {
10613 name: "sourceRef",
10614 type: "FlowNode",
10615 isAttr: true,
10616 isReference: true
10617 },
10618 {
10619 name: "targetRef",
10620 type: "FlowNode",
10621 isAttr: true,
10622 isReference: true
10623 }
10624 ]
10625 },
10626 {
10627 name: "FlowElementsContainer",
10628 isAbstract: true,
10629 superClass: [
10630 "BaseElement"
10631 ],
10632 properties: [
10633 {
10634 name: "laneSets",
10635 type: "LaneSet",
10636 isMany: true
10637 },
10638 {
10639 name: "flowElements",
10640 type: "FlowElement",
10641 isMany: true
10642 }
10643 ]
10644 },
10645 {
10646 name: "CallableElement",
10647 isAbstract: true,
10648 superClass: [
10649 "RootElement"
10650 ],
10651 properties: [
10652 {
10653 name: "name",
10654 isAttr: true,
10655 type: "String"
10656 },
10657 {
10658 name: "ioSpecification",
10659 type: "InputOutputSpecification",
10660 xml: {
10661 serialize: "property"
10662 }
10663 },
10664 {
10665 name: "supportedInterfaceRef",
10666 type: "Interface",
10667 isMany: true,
10668 isReference: true
10669 },
10670 {
10671 name: "ioBinding",
10672 type: "InputOutputBinding",
10673 isMany: true,
10674 xml: {
10675 serialize: "property"
10676 }
10677 }
10678 ]
10679 },
10680 {
10681 name: "FlowNode",
10682 isAbstract: true,
10683 superClass: [
10684 "FlowElement"
10685 ],
10686 properties: [
10687 {
10688 name: "incoming",
10689 type: "SequenceFlow",
10690 isMany: true,
10691 isReference: true
10692 },
10693 {
10694 name: "outgoing",
10695 type: "SequenceFlow",
10696 isMany: true,
10697 isReference: true
10698 },
10699 {
10700 name: "lanes",
10701 type: "Lane",
10702 isVirtual: true,
10703 isMany: true,
10704 isReference: true
10705 }
10706 ]
10707 },
10708 {
10709 name: "CorrelationPropertyRetrievalExpression",
10710 superClass: [
10711 "BaseElement"
10712 ],
10713 properties: [
10714 {
10715 name: "messagePath",
10716 type: "FormalExpression"
10717 },
10718 {
10719 name: "messageRef",
10720 type: "Message",
10721 isAttr: true,
10722 isReference: true
10723 }
10724 ]
10725 },
10726 {
10727 name: "CorrelationPropertyBinding",
10728 superClass: [
10729 "BaseElement"
10730 ],
10731 properties: [
10732 {
10733 name: "dataPath",
10734 type: "FormalExpression"
10735 },
10736 {
10737 name: "correlationPropertyRef",
10738 type: "CorrelationProperty",
10739 isAttr: true,
10740 isReference: true
10741 }
10742 ]
10743 },
10744 {
10745 name: "Resource",
10746 superClass: [
10747 "RootElement"
10748 ],
10749 properties: [
10750 {
10751 name: "name",
10752 isAttr: true,
10753 type: "String"
10754 },
10755 {
10756 name: "resourceParameters",
10757 type: "ResourceParameter",
10758 isMany: true
10759 }
10760 ]
10761 },
10762 {
10763 name: "ResourceParameter",
10764 superClass: [
10765 "BaseElement"
10766 ],
10767 properties: [
10768 {
10769 name: "name",
10770 isAttr: true,
10771 type: "String"
10772 },
10773 {
10774 name: "isRequired",
10775 isAttr: true,
10776 type: "Boolean"
10777 },
10778 {
10779 name: "type",
10780 type: "ItemDefinition",
10781 isAttr: true,
10782 isReference: true
10783 }
10784 ]
10785 },
10786 {
10787 name: "CorrelationSubscription",
10788 superClass: [
10789 "BaseElement"
10790 ],
10791 properties: [
10792 {
10793 name: "correlationKeyRef",
10794 type: "CorrelationKey",
10795 isAttr: true,
10796 isReference: true
10797 },
10798 {
10799 name: "correlationPropertyBinding",
10800 type: "CorrelationPropertyBinding",
10801 isMany: true
10802 }
10803 ]
10804 },
10805 {
10806 name: "MessageFlow",
10807 superClass: [
10808 "BaseElement"
10809 ],
10810 properties: [
10811 {
10812 name: "name",
10813 isAttr: true,
10814 type: "String"
10815 },
10816 {
10817 name: "sourceRef",
10818 type: "InteractionNode",
10819 isAttr: true,
10820 isReference: true
10821 },
10822 {
10823 name: "targetRef",
10824 type: "InteractionNode",
10825 isAttr: true,
10826 isReference: true
10827 },
10828 {
10829 name: "messageRef",
10830 type: "Message",
10831 isAttr: true,
10832 isReference: true
10833 }
10834 ]
10835 },
10836 {
10837 name: "MessageFlowAssociation",
10838 superClass: [
10839 "BaseElement"
10840 ],
10841 properties: [
10842 {
10843 name: "innerMessageFlowRef",
10844 type: "MessageFlow",
10845 isAttr: true,
10846 isReference: true
10847 },
10848 {
10849 name: "outerMessageFlowRef",
10850 type: "MessageFlow",
10851 isAttr: true,
10852 isReference: true
10853 }
10854 ]
10855 },
10856 {
10857 name: "InteractionNode",
10858 isAbstract: true,
10859 properties: [
10860 {
10861 name: "incomingConversationLinks",
10862 type: "ConversationLink",
10863 isVirtual: true,
10864 isMany: true,
10865 isReference: true
10866 },
10867 {
10868 name: "outgoingConversationLinks",
10869 type: "ConversationLink",
10870 isVirtual: true,
10871 isMany: true,
10872 isReference: true
10873 }
10874 ]
10875 },
10876 {
10877 name: "Participant",
10878 superClass: [
10879 "InteractionNode",
10880 "BaseElement"
10881 ],
10882 properties: [
10883 {
10884 name: "name",
10885 isAttr: true,
10886 type: "String"
10887 },
10888 {
10889 name: "interfaceRef",
10890 type: "Interface",
10891 isMany: true,
10892 isReference: true
10893 },
10894 {
10895 name: "participantMultiplicity",
10896 type: "ParticipantMultiplicity"
10897 },
10898 {
10899 name: "endPointRefs",
10900 type: "EndPoint",
10901 isMany: true,
10902 isReference: true
10903 },
10904 {
10905 name: "processRef",
10906 type: "Process",
10907 isAttr: true,
10908 isReference: true
10909 }
10910 ]
10911 },
10912 {
10913 name: "ParticipantAssociation",
10914 superClass: [
10915 "BaseElement"
10916 ],
10917 properties: [
10918 {
10919 name: "innerParticipantRef",
10920 type: "Participant",
10921 isAttr: true,
10922 isReference: true
10923 },
10924 {
10925 name: "outerParticipantRef",
10926 type: "Participant",
10927 isAttr: true,
10928 isReference: true
10929 }
10930 ]
10931 },
10932 {
10933 name: "ParticipantMultiplicity",
10934 properties: [
10935 {
10936 name: "minimum",
10937 "default": 0,
10938 isAttr: true,
10939 type: "Integer"
10940 },
10941 {
10942 name: "maximum",
10943 "default": 1,
10944 isAttr: true,
10945 type: "Integer"
10946 }
10947 ],
10948 superClass: [
10949 "BaseElement"
10950 ]
10951 },
10952 {
10953 name: "Collaboration",
10954 superClass: [
10955 "RootElement"
10956 ],
10957 properties: [
10958 {
10959 name: "name",
10960 isAttr: true,
10961 type: "String"
10962 },
10963 {
10964 name: "isClosed",
10965 isAttr: true,
10966 type: "Boolean"
10967 },
10968 {
10969 name: "participants",
10970 type: "Participant",
10971 isMany: true
10972 },
10973 {
10974 name: "messageFlows",
10975 type: "MessageFlow",
10976 isMany: true
10977 },
10978 {
10979 name: "artifacts",
10980 type: "Artifact",
10981 isMany: true
10982 },
10983 {
10984 name: "conversations",
10985 type: "ConversationNode",
10986 isMany: true
10987 },
10988 {
10989 name: "conversationAssociations",
10990 type: "ConversationAssociation"
10991 },
10992 {
10993 name: "participantAssociations",
10994 type: "ParticipantAssociation",
10995 isMany: true
10996 },
10997 {
10998 name: "messageFlowAssociations",
10999 type: "MessageFlowAssociation",
11000 isMany: true
11001 },
11002 {
11003 name: "correlationKeys",
11004 type: "CorrelationKey",
11005 isMany: true
11006 },
11007 {
11008 name: "choreographyRef",
11009 type: "Choreography",
11010 isMany: true,
11011 isReference: true
11012 },
11013 {
11014 name: "conversationLinks",
11015 type: "ConversationLink",
11016 isMany: true
11017 }
11018 ]
11019 },
11020 {
11021 name: "ChoreographyActivity",
11022 isAbstract: true,
11023 superClass: [
11024 "FlowNode"
11025 ],
11026 properties: [
11027 {
11028 name: "participantRef",
11029 type: "Participant",
11030 isMany: true,
11031 isReference: true
11032 },
11033 {
11034 name: "initiatingParticipantRef",
11035 type: "Participant",
11036 isAttr: true,
11037 isReference: true
11038 },
11039 {
11040 name: "correlationKeys",
11041 type: "CorrelationKey",
11042 isMany: true
11043 },
11044 {
11045 name: "loopType",
11046 type: "ChoreographyLoopType",
11047 "default": "None",
11048 isAttr: true
11049 }
11050 ]
11051 },
11052 {
11053 name: "CallChoreography",
11054 superClass: [
11055 "ChoreographyActivity"
11056 ],
11057 properties: [
11058 {
11059 name: "calledChoreographyRef",
11060 type: "Choreography",
11061 isAttr: true,
11062 isReference: true
11063 },
11064 {
11065 name: "participantAssociations",
11066 type: "ParticipantAssociation",
11067 isMany: true
11068 }
11069 ]
11070 },
11071 {
11072 name: "SubChoreography",
11073 superClass: [
11074 "ChoreographyActivity",
11075 "FlowElementsContainer"
11076 ],
11077 properties: [
11078 {
11079 name: "artifacts",
11080 type: "Artifact",
11081 isMany: true
11082 }
11083 ]
11084 },
11085 {
11086 name: "ChoreographyTask",
11087 superClass: [
11088 "ChoreographyActivity"
11089 ],
11090 properties: [
11091 {
11092 name: "messageFlowRef",
11093 type: "MessageFlow",
11094 isMany: true,
11095 isReference: true
11096 }
11097 ]
11098 },
11099 {
11100 name: "Choreography",
11101 superClass: [
11102 "Collaboration",
11103 "FlowElementsContainer"
11104 ]
11105 },
11106 {
11107 name: "GlobalChoreographyTask",
11108 superClass: [
11109 "Choreography"
11110 ],
11111 properties: [
11112 {
11113 name: "initiatingParticipantRef",
11114 type: "Participant",
11115 isAttr: true,
11116 isReference: true
11117 }
11118 ]
11119 },
11120 {
11121 name: "TextAnnotation",
11122 superClass: [
11123 "Artifact"
11124 ],
11125 properties: [
11126 {
11127 name: "text",
11128 type: "String"
11129 },
11130 {
11131 name: "textFormat",
11132 "default": "text/plain",
11133 isAttr: true,
11134 type: "String"
11135 }
11136 ]
11137 },
11138 {
11139 name: "Group",
11140 superClass: [
11141 "Artifact"
11142 ],
11143 properties: [
11144 {
11145 name: "categoryValueRef",
11146 type: "CategoryValue",
11147 isAttr: true,
11148 isReference: true
11149 }
11150 ]
11151 },
11152 {
11153 name: "Association",
11154 superClass: [
11155 "Artifact"
11156 ],
11157 properties: [
11158 {
11159 name: "associationDirection",
11160 type: "AssociationDirection",
11161 isAttr: true
11162 },
11163 {
11164 name: "sourceRef",
11165 type: "BaseElement",
11166 isAttr: true,
11167 isReference: true
11168 },
11169 {
11170 name: "targetRef",
11171 type: "BaseElement",
11172 isAttr: true,
11173 isReference: true
11174 }
11175 ]
11176 },
11177 {
11178 name: "Category",
11179 superClass: [
11180 "RootElement"
11181 ],
11182 properties: [
11183 {
11184 name: "categoryValue",
11185 type: "CategoryValue",
11186 isMany: true
11187 },
11188 {
11189 name: "name",
11190 isAttr: true,
11191 type: "String"
11192 }
11193 ]
11194 },
11195 {
11196 name: "Artifact",
11197 isAbstract: true,
11198 superClass: [
11199 "BaseElement"
11200 ]
11201 },
11202 {
11203 name: "CategoryValue",
11204 superClass: [
11205 "BaseElement"
11206 ],
11207 properties: [
11208 {
11209 name: "categorizedFlowElements",
11210 type: "FlowElement",
11211 isVirtual: true,
11212 isMany: true,
11213 isReference: true
11214 },
11215 {
11216 name: "value",
11217 isAttr: true,
11218 type: "String"
11219 }
11220 ]
11221 },
11222 {
11223 name: "Activity",
11224 isAbstract: true,
11225 superClass: [
11226 "FlowNode"
11227 ],
11228 properties: [
11229 {
11230 name: "isForCompensation",
11231 "default": false,
11232 isAttr: true,
11233 type: "Boolean"
11234 },
11235 {
11236 name: "default",
11237 type: "SequenceFlow",
11238 isAttr: true,
11239 isReference: true
11240 },
11241 {
11242 name: "ioSpecification",
11243 type: "InputOutputSpecification",
11244 xml: {
11245 serialize: "property"
11246 }
11247 },
11248 {
11249 name: "boundaryEventRefs",
11250 type: "BoundaryEvent",
11251 isMany: true,
11252 isReference: true
11253 },
11254 {
11255 name: "properties",
11256 type: "Property",
11257 isMany: true
11258 },
11259 {
11260 name: "dataInputAssociations",
11261 type: "DataInputAssociation",
11262 isMany: true
11263 },
11264 {
11265 name: "dataOutputAssociations",
11266 type: "DataOutputAssociation",
11267 isMany: true
11268 },
11269 {
11270 name: "startQuantity",
11271 "default": 1,
11272 isAttr: true,
11273 type: "Integer"
11274 },
11275 {
11276 name: "resources",
11277 type: "ResourceRole",
11278 isMany: true
11279 },
11280 {
11281 name: "completionQuantity",
11282 "default": 1,
11283 isAttr: true,
11284 type: "Integer"
11285 },
11286 {
11287 name: "loopCharacteristics",
11288 type: "LoopCharacteristics"
11289 }
11290 ]
11291 },
11292 {
11293 name: "ServiceTask",
11294 superClass: [
11295 "Task"
11296 ],
11297 properties: [
11298 {
11299 name: "implementation",
11300 isAttr: true,
11301 type: "String"
11302 },
11303 {
11304 name: "operationRef",
11305 type: "Operation",
11306 isAttr: true,
11307 isReference: true
11308 }
11309 ]
11310 },
11311 {
11312 name: "SubProcess",
11313 superClass: [
11314 "Activity",
11315 "FlowElementsContainer",
11316 "InteractionNode"
11317 ],
11318 properties: [
11319 {
11320 name: "triggeredByEvent",
11321 "default": false,
11322 isAttr: true,
11323 type: "Boolean"
11324 },
11325 {
11326 name: "artifacts",
11327 type: "Artifact",
11328 isMany: true
11329 }
11330 ]
11331 },
11332 {
11333 name: "LoopCharacteristics",
11334 isAbstract: true,
11335 superClass: [
11336 "BaseElement"
11337 ]
11338 },
11339 {
11340 name: "MultiInstanceLoopCharacteristics",
11341 superClass: [
11342 "LoopCharacteristics"
11343 ],
11344 properties: [
11345 {
11346 name: "isSequential",
11347 "default": false,
11348 isAttr: true,
11349 type: "Boolean"
11350 },
11351 {
11352 name: "behavior",
11353 type: "MultiInstanceBehavior",
11354 "default": "All",
11355 isAttr: true
11356 },
11357 {
11358 name: "loopCardinality",
11359 type: "Expression",
11360 xml: {
11361 serialize: "xsi:type"
11362 }
11363 },
11364 {
11365 name: "loopDataInputRef",
11366 type: "ItemAwareElement",
11367 isReference: true
11368 },
11369 {
11370 name: "loopDataOutputRef",
11371 type: "ItemAwareElement",
11372 isReference: true
11373 },
11374 {
11375 name: "inputDataItem",
11376 type: "DataInput",
11377 xml: {
11378 serialize: "property"
11379 }
11380 },
11381 {
11382 name: "outputDataItem",
11383 type: "DataOutput",
11384 xml: {
11385 serialize: "property"
11386 }
11387 },
11388 {
11389 name: "complexBehaviorDefinition",
11390 type: "ComplexBehaviorDefinition",
11391 isMany: true
11392 },
11393 {
11394 name: "completionCondition",
11395 type: "Expression",
11396 xml: {
11397 serialize: "xsi:type"
11398 }
11399 },
11400 {
11401 name: "oneBehaviorEventRef",
11402 type: "EventDefinition",
11403 isAttr: true,
11404 isReference: true
11405 },
11406 {
11407 name: "noneBehaviorEventRef",
11408 type: "EventDefinition",
11409 isAttr: true,
11410 isReference: true
11411 }
11412 ]
11413 },
11414 {
11415 name: "StandardLoopCharacteristics",
11416 superClass: [
11417 "LoopCharacteristics"
11418 ],
11419 properties: [
11420 {
11421 name: "testBefore",
11422 "default": false,
11423 isAttr: true,
11424 type: "Boolean"
11425 },
11426 {
11427 name: "loopCondition",
11428 type: "Expression",
11429 xml: {
11430 serialize: "xsi:type"
11431 }
11432 },
11433 {
11434 name: "loopMaximum",
11435 type: "Integer",
11436 isAttr: true
11437 }
11438 ]
11439 },
11440 {
11441 name: "CallActivity",
11442 superClass: [
11443 "Activity"
11444 ],
11445 properties: [
11446 {
11447 name: "calledElement",
11448 type: "String",
11449 isAttr: true
11450 }
11451 ]
11452 },
11453 {
11454 name: "Task",
11455 superClass: [
11456 "Activity",
11457 "InteractionNode"
11458 ]
11459 },
11460 {
11461 name: "SendTask",
11462 superClass: [
11463 "Task"
11464 ],
11465 properties: [
11466 {
11467 name: "implementation",
11468 isAttr: true,
11469 type: "String"
11470 },
11471 {
11472 name: "operationRef",
11473 type: "Operation",
11474 isAttr: true,
11475 isReference: true
11476 },
11477 {
11478 name: "messageRef",
11479 type: "Message",
11480 isAttr: true,
11481 isReference: true
11482 }
11483 ]
11484 },
11485 {
11486 name: "ReceiveTask",
11487 superClass: [
11488 "Task"
11489 ],
11490 properties: [
11491 {
11492 name: "implementation",
11493 isAttr: true,
11494 type: "String"
11495 },
11496 {
11497 name: "instantiate",
11498 "default": false,
11499 isAttr: true,
11500 type: "Boolean"
11501 },
11502 {
11503 name: "operationRef",
11504 type: "Operation",
11505 isAttr: true,
11506 isReference: true
11507 },
11508 {
11509 name: "messageRef",
11510 type: "Message",
11511 isAttr: true,
11512 isReference: true
11513 }
11514 ]
11515 },
11516 {
11517 name: "ScriptTask",
11518 superClass: [
11519 "Task"
11520 ],
11521 properties: [
11522 {
11523 name: "scriptFormat",
11524 isAttr: true,
11525 type: "String"
11526 },
11527 {
11528 name: "script",
11529 type: "String"
11530 }
11531 ]
11532 },
11533 {
11534 name: "BusinessRuleTask",
11535 superClass: [
11536 "Task"
11537 ],
11538 properties: [
11539 {
11540 name: "implementation",
11541 isAttr: true,
11542 type: "String"
11543 }
11544 ]
11545 },
11546 {
11547 name: "AdHocSubProcess",
11548 superClass: [
11549 "SubProcess"
11550 ],
11551 properties: [
11552 {
11553 name: "completionCondition",
11554 type: "Expression",
11555 xml: {
11556 serialize: "xsi:type"
11557 }
11558 },
11559 {
11560 name: "ordering",
11561 type: "AdHocOrdering",
11562 isAttr: true
11563 },
11564 {
11565 name: "cancelRemainingInstances",
11566 "default": true,
11567 isAttr: true,
11568 type: "Boolean"
11569 }
11570 ]
11571 },
11572 {
11573 name: "Transaction",
11574 superClass: [
11575 "SubProcess"
11576 ],
11577 properties: [
11578 {
11579 name: "protocol",
11580 isAttr: true,
11581 type: "String"
11582 },
11583 {
11584 name: "method",
11585 isAttr: true,
11586 type: "String"
11587 }
11588 ]
11589 },
11590 {
11591 name: "GlobalScriptTask",
11592 superClass: [
11593 "GlobalTask"
11594 ],
11595 properties: [
11596 {
11597 name: "scriptLanguage",
11598 isAttr: true,
11599 type: "String"
11600 },
11601 {
11602 name: "script",
11603 isAttr: true,
11604 type: "String"
11605 }
11606 ]
11607 },
11608 {
11609 name: "GlobalBusinessRuleTask",
11610 superClass: [
11611 "GlobalTask"
11612 ],
11613 properties: [
11614 {
11615 name: "implementation",
11616 isAttr: true,
11617 type: "String"
11618 }
11619 ]
11620 },
11621 {
11622 name: "ComplexBehaviorDefinition",
11623 superClass: [
11624 "BaseElement"
11625 ],
11626 properties: [
11627 {
11628 name: "condition",
11629 type: "FormalExpression"
11630 },
11631 {
11632 name: "event",
11633 type: "ImplicitThrowEvent"
11634 }
11635 ]
11636 },
11637 {
11638 name: "ResourceRole",
11639 superClass: [
11640 "BaseElement"
11641 ],
11642 properties: [
11643 {
11644 name: "resourceRef",
11645 type: "Resource",
11646 isReference: true
11647 },
11648 {
11649 name: "resourceParameterBindings",
11650 type: "ResourceParameterBinding",
11651 isMany: true
11652 },
11653 {
11654 name: "resourceAssignmentExpression",
11655 type: "ResourceAssignmentExpression"
11656 },
11657 {
11658 name: "name",
11659 isAttr: true,
11660 type: "String"
11661 }
11662 ]
11663 },
11664 {
11665 name: "ResourceParameterBinding",
11666 properties: [
11667 {
11668 name: "expression",
11669 type: "Expression",
11670 xml: {
11671 serialize: "xsi:type"
11672 }
11673 },
11674 {
11675 name: "parameterRef",
11676 type: "ResourceParameter",
11677 isAttr: true,
11678 isReference: true
11679 }
11680 ],
11681 superClass: [
11682 "BaseElement"
11683 ]
11684 },
11685 {
11686 name: "ResourceAssignmentExpression",
11687 properties: [
11688 {
11689 name: "expression",
11690 type: "Expression",
11691 xml: {
11692 serialize: "xsi:type"
11693 }
11694 }
11695 ],
11696 superClass: [
11697 "BaseElement"
11698 ]
11699 },
11700 {
11701 name: "Import",
11702 properties: [
11703 {
11704 name: "importType",
11705 isAttr: true,
11706 type: "String"
11707 },
11708 {
11709 name: "location",
11710 isAttr: true,
11711 type: "String"
11712 },
11713 {
11714 name: "namespace",
11715 isAttr: true,
11716 type: "String"
11717 }
11718 ]
11719 },
11720 {
11721 name: "Definitions",
11722 superClass: [
11723 "BaseElement"
11724 ],
11725 properties: [
11726 {
11727 name: "name",
11728 isAttr: true,
11729 type: "String"
11730 },
11731 {
11732 name: "targetNamespace",
11733 isAttr: true,
11734 type: "String"
11735 },
11736 {
11737 name: "expressionLanguage",
11738 "default": "http://www.w3.org/1999/XPath",
11739 isAttr: true,
11740 type: "String"
11741 },
11742 {
11743 name: "typeLanguage",
11744 "default": "http://www.w3.org/2001/XMLSchema",
11745 isAttr: true,
11746 type: "String"
11747 },
11748 {
11749 name: "imports",
11750 type: "Import",
11751 isMany: true
11752 },
11753 {
11754 name: "extensions",
11755 type: "Extension",
11756 isMany: true
11757 },
11758 {
11759 name: "rootElements",
11760 type: "RootElement",
11761 isMany: true
11762 },
11763 {
11764 name: "diagrams",
11765 isMany: true,
11766 type: "bpmndi:BPMNDiagram"
11767 },
11768 {
11769 name: "exporter",
11770 isAttr: true,
11771 type: "String"
11772 },
11773 {
11774 name: "relationships",
11775 type: "Relationship",
11776 isMany: true
11777 },
11778 {
11779 name: "exporterVersion",
11780 isAttr: true,
11781 type: "String"
11782 }
11783 ]
11784 }
11785 ];
11786 var enumerations = [
11787 {
11788 name: "ProcessType",
11789 literalValues: [
11790 {
11791 name: "None"
11792 },
11793 {
11794 name: "Public"
11795 },
11796 {
11797 name: "Private"
11798 }
11799 ]
11800 },
11801 {
11802 name: "GatewayDirection",
11803 literalValues: [
11804 {
11805 name: "Unspecified"
11806 },
11807 {
11808 name: "Converging"
11809 },
11810 {
11811 name: "Diverging"
11812 },
11813 {
11814 name: "Mixed"
11815 }
11816 ]
11817 },
11818 {
11819 name: "EventBasedGatewayType",
11820 literalValues: [
11821 {
11822 name: "Parallel"
11823 },
11824 {
11825 name: "Exclusive"
11826 }
11827 ]
11828 },
11829 {
11830 name: "RelationshipDirection",
11831 literalValues: [
11832 {
11833 name: "None"
11834 },
11835 {
11836 name: "Forward"
11837 },
11838 {
11839 name: "Backward"
11840 },
11841 {
11842 name: "Both"
11843 }
11844 ]
11845 },
11846 {
11847 name: "ItemKind",
11848 literalValues: [
11849 {
11850 name: "Physical"
11851 },
11852 {
11853 name: "Information"
11854 }
11855 ]
11856 },
11857 {
11858 name: "ChoreographyLoopType",
11859 literalValues: [
11860 {
11861 name: "None"
11862 },
11863 {
11864 name: "Standard"
11865 },
11866 {
11867 name: "MultiInstanceSequential"
11868 },
11869 {
11870 name: "MultiInstanceParallel"
11871 }
11872 ]
11873 },
11874 {
11875 name: "AssociationDirection",
11876 literalValues: [
11877 {
11878 name: "None"
11879 },
11880 {
11881 name: "One"
11882 },
11883 {
11884 name: "Both"
11885 }
11886 ]
11887 },
11888 {
11889 name: "MultiInstanceBehavior",
11890 literalValues: [
11891 {
11892 name: "None"
11893 },
11894 {
11895 name: "One"
11896 },
11897 {
11898 name: "All"
11899 },
11900 {
11901 name: "Complex"
11902 }
11903 ]
11904 },
11905 {
11906 name: "AdHocOrdering",
11907 literalValues: [
11908 {
11909 name: "Parallel"
11910 },
11911 {
11912 name: "Sequential"
11913 }
11914 ]
11915 }
11916 ];
11917 var prefix$1 = "bpmn";
11918 var xml = {
11919 tagAlias: "lowerCase",
11920 typePrefix: "t"
11921 };
11922 var BpmnPackage = {
11923 name: name,
11924 uri: uri,
11925 associations: associations,
11926 types: types$1,
11927 enumerations: enumerations,
11928 prefix: prefix$1,
11929 xml: xml
11930 };
11931
11932 var name$1 = "BPMNDI";
11933 var uri$1 = "http://www.omg.org/spec/BPMN/20100524/DI";
11934 var types$2 = [
11935 {
11936 name: "BPMNDiagram",
11937 properties: [
11938 {
11939 name: "plane",
11940 type: "BPMNPlane",
11941 redefines: "di:Diagram#rootElement"
11942 },
11943 {
11944 name: "labelStyle",
11945 type: "BPMNLabelStyle",
11946 isMany: true
11947 }
11948 ],
11949 superClass: [
11950 "di:Diagram"
11951 ]
11952 },
11953 {
11954 name: "BPMNPlane",
11955 properties: [
11956 {
11957 name: "bpmnElement",
11958 isAttr: true,
11959 isReference: true,
11960 type: "bpmn:BaseElement",
11961 redefines: "di:DiagramElement#modelElement"
11962 }
11963 ],
11964 superClass: [
11965 "di:Plane"
11966 ]
11967 },
11968 {
11969 name: "BPMNShape",
11970 properties: [
11971 {
11972 name: "bpmnElement",
11973 isAttr: true,
11974 isReference: true,
11975 type: "bpmn:BaseElement",
11976 redefines: "di:DiagramElement#modelElement"
11977 },
11978 {
11979 name: "isHorizontal",
11980 isAttr: true,
11981 type: "Boolean"
11982 },
11983 {
11984 name: "isExpanded",
11985 isAttr: true,
11986 type: "Boolean"
11987 },
11988 {
11989 name: "isMarkerVisible",
11990 isAttr: true,
11991 type: "Boolean"
11992 },
11993 {
11994 name: "label",
11995 type: "BPMNLabel"
11996 },
11997 {
11998 name: "isMessageVisible",
11999 isAttr: true,
12000 type: "Boolean"
12001 },
12002 {
12003 name: "participantBandKind",
12004 type: "ParticipantBandKind",
12005 isAttr: true
12006 },
12007 {
12008 name: "choreographyActivityShape",
12009 type: "BPMNShape",
12010 isAttr: true,
12011 isReference: true
12012 }
12013 ],
12014 superClass: [
12015 "di:LabeledShape"
12016 ]
12017 },
12018 {
12019 name: "BPMNEdge",
12020 properties: [
12021 {
12022 name: "label",
12023 type: "BPMNLabel"
12024 },
12025 {
12026 name: "bpmnElement",
12027 isAttr: true,
12028 isReference: true,
12029 type: "bpmn:BaseElement",
12030 redefines: "di:DiagramElement#modelElement"
12031 },
12032 {
12033 name: "sourceElement",
12034 isAttr: true,
12035 isReference: true,
12036 type: "di:DiagramElement",
12037 redefines: "di:Edge#source"
12038 },
12039 {
12040 name: "targetElement",
12041 isAttr: true,
12042 isReference: true,
12043 type: "di:DiagramElement",
12044 redefines: "di:Edge#target"
12045 },
12046 {
12047 name: "messageVisibleKind",
12048 type: "MessageVisibleKind",
12049 isAttr: true,
12050 "default": "initiating"
12051 }
12052 ],
12053 superClass: [
12054 "di:LabeledEdge"
12055 ]
12056 },
12057 {
12058 name: "BPMNLabel",
12059 properties: [
12060 {
12061 name: "labelStyle",
12062 type: "BPMNLabelStyle",
12063 isAttr: true,
12064 isReference: true,
12065 redefines: "di:DiagramElement#style"
12066 }
12067 ],
12068 superClass: [
12069 "di:Label"
12070 ]
12071 },
12072 {
12073 name: "BPMNLabelStyle",
12074 properties: [
12075 {
12076 name: "font",
12077 type: "dc:Font"
12078 }
12079 ],
12080 superClass: [
12081 "di:Style"
12082 ]
12083 }
12084 ];
12085 var enumerations$1 = [
12086 {
12087 name: "ParticipantBandKind",
12088 literalValues: [
12089 {
12090 name: "top_initiating"
12091 },
12092 {
12093 name: "middle_initiating"
12094 },
12095 {
12096 name: "bottom_initiating"
12097 },
12098 {
12099 name: "top_non_initiating"
12100 },
12101 {
12102 name: "middle_non_initiating"
12103 },
12104 {
12105 name: "bottom_non_initiating"
12106 }
12107 ]
12108 },
12109 {
12110 name: "MessageVisibleKind",
12111 literalValues: [
12112 {
12113 name: "initiating"
12114 },
12115 {
12116 name: "non_initiating"
12117 }
12118 ]
12119 }
12120 ];
12121 var associations$1 = [
12122 ];
12123 var prefix$2 = "bpmndi";
12124 var BpmnDiPackage = {
12125 name: name$1,
12126 uri: uri$1,
12127 types: types$2,
12128 enumerations: enumerations$1,
12129 associations: associations$1,
12130 prefix: prefix$2
12131 };
12132
12133 var name$2 = "DC";
12134 var uri$2 = "http://www.omg.org/spec/DD/20100524/DC";
12135 var types$3 = [
12136 {
12137 name: "Boolean"
12138 },
12139 {
12140 name: "Integer"
12141 },
12142 {
12143 name: "Real"
12144 },
12145 {
12146 name: "String"
12147 },
12148 {
12149 name: "Font",
12150 properties: [
12151 {
12152 name: "name",
12153 type: "String",
12154 isAttr: true
12155 },
12156 {
12157 name: "size",
12158 type: "Real",
12159 isAttr: true
12160 },
12161 {
12162 name: "isBold",
12163 type: "Boolean",
12164 isAttr: true
12165 },
12166 {
12167 name: "isItalic",
12168 type: "Boolean",
12169 isAttr: true
12170 },
12171 {
12172 name: "isUnderline",
12173 type: "Boolean",
12174 isAttr: true
12175 },
12176 {
12177 name: "isStrikeThrough",
12178 type: "Boolean",
12179 isAttr: true
12180 }
12181 ]
12182 },
12183 {
12184 name: "Point",
12185 properties: [
12186 {
12187 name: "x",
12188 type: "Real",
12189 "default": "0",
12190 isAttr: true
12191 },
12192 {
12193 name: "y",
12194 type: "Real",
12195 "default": "0",
12196 isAttr: true
12197 }
12198 ]
12199 },
12200 {
12201 name: "Bounds",
12202 properties: [
12203 {
12204 name: "x",
12205 type: "Real",
12206 "default": "0",
12207 isAttr: true
12208 },
12209 {
12210 name: "y",
12211 type: "Real",
12212 "default": "0",
12213 isAttr: true
12214 },
12215 {
12216 name: "width",
12217 type: "Real",
12218 isAttr: true
12219 },
12220 {
12221 name: "height",
12222 type: "Real",
12223 isAttr: true
12224 }
12225 ]
12226 }
12227 ];
12228 var prefix$3 = "dc";
12229 var associations$2 = [
12230 ];
12231 var DcPackage = {
12232 name: name$2,
12233 uri: uri$2,
12234 types: types$3,
12235 prefix: prefix$3,
12236 associations: associations$2
12237 };
12238
12239 var name$3 = "DI";
12240 var uri$3 = "http://www.omg.org/spec/DD/20100524/DI";
12241 var types$4 = [
12242 {
12243 name: "DiagramElement",
12244 isAbstract: true,
12245 properties: [
12246 {
12247 name: "id",
12248 type: "String",
12249 isAttr: true,
12250 isId: true
12251 },
12252 {
12253 name: "extension",
12254 type: "Extension"
12255 },
12256 {
12257 name: "owningDiagram",
12258 type: "Diagram",
12259 isReadOnly: true,
12260 isVirtual: true,
12261 isReference: true
12262 },
12263 {
12264 name: "owningElement",
12265 type: "DiagramElement",
12266 isReadOnly: true,
12267 isVirtual: true,
12268 isReference: true
12269 },
12270 {
12271 name: "modelElement",
12272 isReadOnly: true,
12273 isVirtual: true,
12274 isReference: true,
12275 type: "Element"
12276 },
12277 {
12278 name: "style",
12279 type: "Style",
12280 isReadOnly: true,
12281 isVirtual: true,
12282 isReference: true
12283 },
12284 {
12285 name: "ownedElement",
12286 type: "DiagramElement",
12287 isReadOnly: true,
12288 isVirtual: true,
12289 isMany: true
12290 }
12291 ]
12292 },
12293 {
12294 name: "Node",
12295 isAbstract: true,
12296 superClass: [
12297 "DiagramElement"
12298 ]
12299 },
12300 {
12301 name: "Edge",
12302 isAbstract: true,
12303 superClass: [
12304 "DiagramElement"
12305 ],
12306 properties: [
12307 {
12308 name: "source",
12309 type: "DiagramElement",
12310 isReadOnly: true,
12311 isVirtual: true,
12312 isReference: true
12313 },
12314 {
12315 name: "target",
12316 type: "DiagramElement",
12317 isReadOnly: true,
12318 isVirtual: true,
12319 isReference: true
12320 },
12321 {
12322 name: "waypoint",
12323 isUnique: false,
12324 isMany: true,
12325 type: "dc:Point",
12326 xml: {
12327 serialize: "xsi:type"
12328 }
12329 }
12330 ]
12331 },
12332 {
12333 name: "Diagram",
12334 isAbstract: true,
12335 properties: [
12336 {
12337 name: "id",
12338 type: "String",
12339 isAttr: true,
12340 isId: true
12341 },
12342 {
12343 name: "rootElement",
12344 type: "DiagramElement",
12345 isReadOnly: true,
12346 isVirtual: true
12347 },
12348 {
12349 name: "name",
12350 isAttr: true,
12351 type: "String"
12352 },
12353 {
12354 name: "documentation",
12355 isAttr: true,
12356 type: "String"
12357 },
12358 {
12359 name: "resolution",
12360 isAttr: true,
12361 type: "Real"
12362 },
12363 {
12364 name: "ownedStyle",
12365 type: "Style",
12366 isReadOnly: true,
12367 isVirtual: true,
12368 isMany: true
12369 }
12370 ]
12371 },
12372 {
12373 name: "Shape",
12374 isAbstract: true,
12375 superClass: [
12376 "Node"
12377 ],
12378 properties: [
12379 {
12380 name: "bounds",
12381 type: "dc:Bounds"
12382 }
12383 ]
12384 },
12385 {
12386 name: "Plane",
12387 isAbstract: true,
12388 superClass: [
12389 "Node"
12390 ],
12391 properties: [
12392 {
12393 name: "planeElement",
12394 type: "DiagramElement",
12395 subsettedProperty: "DiagramElement-ownedElement",
12396 isMany: true
12397 }
12398 ]
12399 },
12400 {
12401 name: "LabeledEdge",
12402 isAbstract: true,
12403 superClass: [
12404 "Edge"
12405 ],
12406 properties: [
12407 {
12408 name: "ownedLabel",
12409 type: "Label",
12410 isReadOnly: true,
12411 subsettedProperty: "DiagramElement-ownedElement",
12412 isVirtual: true,
12413 isMany: true
12414 }
12415 ]
12416 },
12417 {
12418 name: "LabeledShape",
12419 isAbstract: true,
12420 superClass: [
12421 "Shape"
12422 ],
12423 properties: [
12424 {
12425 name: "ownedLabel",
12426 type: "Label",
12427 isReadOnly: true,
12428 subsettedProperty: "DiagramElement-ownedElement",
12429 isVirtual: true,
12430 isMany: true
12431 }
12432 ]
12433 },
12434 {
12435 name: "Label",
12436 isAbstract: true,
12437 superClass: [
12438 "Node"
12439 ],
12440 properties: [
12441 {
12442 name: "bounds",
12443 type: "dc:Bounds"
12444 }
12445 ]
12446 },
12447 {
12448 name: "Style",
12449 isAbstract: true,
12450 properties: [
12451 {
12452 name: "id",
12453 type: "String",
12454 isAttr: true,
12455 isId: true
12456 }
12457 ]
12458 },
12459 {
12460 name: "Extension",
12461 properties: [
12462 {
12463 name: "values",
12464 type: "Element",
12465 isMany: true
12466 }
12467 ]
12468 }
12469 ];
12470 var associations$3 = [
12471 ];
12472 var prefix$4 = "di";
12473 var xml$1 = {
12474 tagAlias: "lowerCase"
12475 };
12476 var DiPackage = {
12477 name: name$3,
12478 uri: uri$3,
12479 types: types$4,
12480 associations: associations$3,
12481 prefix: prefix$4,
12482 xml: xml$1
12483 };
12484
12485 var name$4 = "bpmn.io colors for BPMN";
12486 var uri$4 = "http://bpmn.io/schema/bpmn/biocolor/1.0";
12487 var prefix$5 = "bioc";
12488 var types$5 = [
12489 {
12490 name: "ColoredShape",
12491 "extends": [
12492 "bpmndi:BPMNShape"
12493 ],
12494 properties: [
12495 {
12496 name: "stroke",
12497 isAttr: true,
12498 type: "String"
12499 },
12500 {
12501 name: "fill",
12502 isAttr: true,
12503 type: "String"
12504 }
12505 ]
12506 },
12507 {
12508 name: "ColoredEdge",
12509 "extends": [
12510 "bpmndi:BPMNEdge"
12511 ],
12512 properties: [
12513 {
12514 name: "stroke",
12515 isAttr: true,
12516 type: "String"
12517 },
12518 {
12519 name: "fill",
12520 isAttr: true,
12521 type: "String"
12522 }
12523 ]
12524 }
12525 ];
12526 var enumerations$2 = [
12527 ];
12528 var associations$4 = [
12529 ];
12530 var BiocPackage = {
12531 name: name$4,
12532 uri: uri$4,
12533 prefix: prefix$5,
12534 types: types$5,
12535 enumerations: enumerations$2,
12536 associations: associations$4
12537 };
12538
12539 var packages = {
12540 bpmn: BpmnPackage,
12541 bpmndi: BpmnDiPackage,
12542 dc: DcPackage,
12543 di: DiPackage,
12544 bioc: BiocPackage
12545 };
12546
12547 function BpmnModdle$1(additionalPackages, options) {
12548 var pks = assign({}, packages, additionalPackages);
12549
12550 return new BpmnModdle(pks, options);
12551 }
12552
12553 function elementToString(e) {
12554 if (!e) {
12555 return '<null>';
12556 }
12557
12558 return '<' + e.$type + (e.id ? ' id="' + e.id : '') + '" />';
12559 }
12560
12561 var diRefs = new objectRefs(
12562 { name: 'bpmnElement', enumerable: true },
12563 { name: 'di', configurable: true }
12564 );
12565
12566 /**
12567 * Returns true if an element has the given meta-model type
12568 *
12569 * @param {ModdleElement} element
12570 * @param {String} type
12571 *
12572 * @return {Boolean}
12573 */
12574 function is(element, type) {
12575 return element.$instanceOf(type);
12576 }
12577
12578
12579 /**
12580 * Find a suitable display candidate for definitions where the DI does not
12581 * correctly specify one.
12582 */
12583 function findDisplayCandidate(definitions) {
12584 return find(definitions.rootElements, function(e) {
12585 return is(e, 'bpmn:Process') || is(e, 'bpmn:Collaboration');
12586 });
12587 }
12588
12589
12590 function BpmnTreeWalker(handler, translate) {
12591
12592 // list of containers already walked
12593 var handledElements = {};
12594
12595 // list of elements to handle deferred to ensure
12596 // prerequisites are drawn
12597 var deferred = [];
12598
12599 // Helpers //////////////////////
12600
12601 function contextual(fn, ctx) {
12602 return function(e) {
12603 fn(e, ctx);
12604 };
12605 }
12606
12607 function handled(element) {
12608 handledElements[element.id] = element;
12609 }
12610
12611 function isHandled(element) {
12612 return handledElements[element.id];
12613 }
12614
12615 function visit(element, ctx) {
12616
12617 var gfx = element.gfx;
12618
12619 // avoid multiple rendering of elements
12620 if (gfx) {
12621 throw new Error(
12622 translate('already rendered {element}', { element: elementToString(element) })
12623 );
12624 }
12625
12626 // call handler
12627 return handler.element(element, ctx);
12628 }
12629
12630 function visitRoot(element, diagram) {
12631 return handler.root(element, diagram);
12632 }
12633
12634 function visitIfDi(element, ctx) {
12635
12636 try {
12637 var gfx = element.di && visit(element, ctx);
12638
12639 handled(element);
12640
12641 return gfx;
12642 } catch (e) {
12643 logError(e.message, { element: element, error: e });
12644
12645 console.error(translate('failed to import {element}', { element: elementToString(element) }));
12646 console.error(e);
12647 }
12648 }
12649
12650 function logError(message, context) {
12651 handler.error(message, context);
12652 }
12653
12654 // DI handling //////////////////////
12655
12656 function registerDi(di) {
12657 var bpmnElement = di.bpmnElement;
12658
12659 if (bpmnElement) {
12660 if (bpmnElement.di) {
12661 logError(
12662 translate('multiple DI elements defined for {element}', {
12663 element: elementToString(bpmnElement)
12664 }),
12665 { element: bpmnElement }
12666 );
12667 } else {
12668 diRefs.bind(bpmnElement, 'di');
12669 bpmnElement.di = di;
12670 }
12671 } else {
12672 logError(
12673 translate('no bpmnElement referenced in {element}', {
12674 element: elementToString(di)
12675 }),
12676 { element: di }
12677 );
12678 }
12679 }
12680
12681 function handleDiagram(diagram) {
12682 handlePlane(diagram.plane);
12683 }
12684
12685 function handlePlane(plane) {
12686 registerDi(plane);
12687
12688 forEach(plane.planeElement, handlePlaneElement);
12689 }
12690
12691 function handlePlaneElement(planeElement) {
12692 registerDi(planeElement);
12693 }
12694
12695
12696 // Semantic handling //////////////////////
12697
12698 /**
12699 * Handle definitions and return the rendered diagram (if any)
12700 *
12701 * @param {ModdleElement} definitions to walk and import
12702 * @param {ModdleElement} [diagram] specific diagram to import and display
12703 *
12704 * @throws {Error} if no diagram to display could be found
12705 */
12706 function handleDefinitions(definitions, diagram) {
12707 // make sure we walk the correct bpmnElement
12708
12709 var diagrams = definitions.diagrams;
12710
12711 if (diagram && diagrams.indexOf(diagram) === -1) {
12712 throw new Error(translate('diagram not part of bpmn:Definitions'));
12713 }
12714
12715 if (!diagram && diagrams && diagrams.length) {
12716 diagram = diagrams[0];
12717 }
12718
12719 // no diagram -> nothing to import
12720 if (!diagram) {
12721 throw new Error(translate('no diagram to display'));
12722 }
12723
12724 // load DI from selected diagram only
12725 handleDiagram(diagram);
12726
12727
12728 var plane = diagram.plane;
12729
12730 if (!plane) {
12731 throw new Error(translate(
12732 'no plane for {element}',
12733 { element: elementToString(diagram) }
12734 ));
12735 }
12736
12737 var rootElement = plane.bpmnElement;
12738
12739 // ensure we default to a suitable display candidate (process or collaboration),
12740 // even if non is specified in DI
12741 if (!rootElement) {
12742 rootElement = findDisplayCandidate(definitions);
12743
12744 if (!rootElement) {
12745 throw new Error(translate('no process or collaboration to display'));
12746 } else {
12747
12748 logError(
12749 translate('correcting missing bpmnElement on {plane} to {rootElement}', {
12750 plane: elementToString(plane),
12751 rootElement: elementToString(rootElement)
12752 })
12753 );
12754
12755 // correct DI on the fly
12756 plane.bpmnElement = rootElement;
12757 registerDi(plane);
12758 }
12759 }
12760
12761
12762 var ctx = visitRoot(rootElement, plane);
12763
12764 if (is(rootElement, 'bpmn:Process')) {
12765 handleProcess(rootElement, ctx);
12766 } else if (is(rootElement, 'bpmn:Collaboration')) {
12767 handleCollaboration(rootElement, ctx);
12768
12769 // force drawing of everything not yet drawn that is part of the target DI
12770 handleUnhandledProcesses(definitions.rootElements, ctx);
12771 } else {
12772 throw new Error(
12773 translate('unsupported bpmnElement for {plane}: {rootElement}', {
12774 plane: elementToString(plane),
12775 rootElement: elementToString(rootElement)
12776 })
12777 );
12778 }
12779
12780 // handle all deferred elements
12781 handleDeferred(deferred);
12782 }
12783
12784 function handleDeferred() {
12785
12786 var fn;
12787
12788 // drain deferred until empty
12789 while (deferred.length) {
12790 fn = deferred.shift();
12791
12792 fn();
12793 }
12794 }
12795
12796 function handleProcess(process, context) {
12797 handleFlowElementsContainer(process, context);
12798 handleIoSpecification(process.ioSpecification, context);
12799
12800 handleArtifacts(process.artifacts, context);
12801
12802 // log process handled
12803 handled(process);
12804 }
12805
12806 function handleUnhandledProcesses(rootElements) {
12807
12808 // walk through all processes that have not yet been drawn and draw them
12809 // if they contain lanes with DI information.
12810 // we do this to pass the free-floating lane test cases in the MIWG test suite
12811 var processes = filter(rootElements, function(e) {
12812 return !isHandled(e) && is(e, 'bpmn:Process') && e.laneSets;
12813 });
12814
12815 processes.forEach(contextual(handleProcess));
12816 }
12817
12818 function handleMessageFlow(messageFlow, context) {
12819 visitIfDi(messageFlow, context);
12820 }
12821
12822 function handleMessageFlows(messageFlows, context) {
12823 forEach(messageFlows, contextual(handleMessageFlow, context));
12824 }
12825
12826 function handleDataAssociation(association, context) {
12827 visitIfDi(association, context);
12828 }
12829
12830 function handleDataInput(dataInput, context) {
12831 visitIfDi(dataInput, context);
12832 }
12833
12834 function handleDataOutput(dataOutput, context) {
12835 visitIfDi(dataOutput, context);
12836 }
12837
12838 function handleArtifact(artifact, context) {
12839
12840 // bpmn:TextAnnotation
12841 // bpmn:Group
12842 // bpmn:Association
12843
12844 visitIfDi(artifact, context);
12845 }
12846
12847 function handleArtifacts(artifacts, context) {
12848
12849 forEach(artifacts, function(e) {
12850 if (is(e, 'bpmn:Association')) {
12851 deferred.push(function() {
12852 handleArtifact(e, context);
12853 });
12854 } else {
12855 handleArtifact(e, context);
12856 }
12857 });
12858 }
12859
12860 function handleIoSpecification(ioSpecification, context) {
12861
12862 if (!ioSpecification) {
12863 return;
12864 }
12865
12866 forEach(ioSpecification.dataInputs, contextual(handleDataInput, context));
12867 forEach(ioSpecification.dataOutputs, contextual(handleDataOutput, context));
12868 }
12869
12870 function handleSubProcess(subProcess, context) {
12871 handleFlowElementsContainer(subProcess, context);
12872 handleArtifacts(subProcess.artifacts, context);
12873 }
12874
12875 function handleFlowNode(flowNode, context) {
12876 var childCtx = visitIfDi(flowNode, context);
12877
12878 if (is(flowNode, 'bpmn:SubProcess')) {
12879 handleSubProcess(flowNode, childCtx || context);
12880 }
12881
12882 if (is(flowNode, 'bpmn:Activity')) {
12883 handleIoSpecification(flowNode.ioSpecification, context);
12884 }
12885
12886 // defer handling of associations
12887 // affected types:
12888 //
12889 // * bpmn:Activity
12890 // * bpmn:ThrowEvent
12891 // * bpmn:CatchEvent
12892 //
12893 deferred.push(function() {
12894 forEach(flowNode.dataInputAssociations, contextual(handleDataAssociation, context));
12895 forEach(flowNode.dataOutputAssociations, contextual(handleDataAssociation, context));
12896 });
12897 }
12898
12899 function handleSequenceFlow(sequenceFlow, context) {
12900 visitIfDi(sequenceFlow, context);
12901 }
12902
12903 function handleDataElement(dataObject, context) {
12904 visitIfDi(dataObject, context);
12905 }
12906
12907 function handleBoundaryEvent(dataObject, context) {
12908 visitIfDi(dataObject, context);
12909 }
12910
12911 function handleLane(lane, context) {
12912
12913 deferred.push(function() {
12914
12915 var newContext = visitIfDi(lane, context);
12916
12917 if (lane.childLaneSet) {
12918 handleLaneSet(lane.childLaneSet, newContext || context);
12919 }
12920
12921 wireFlowNodeRefs(lane);
12922 });
12923 }
12924
12925 function handleLaneSet(laneSet, context) {
12926 forEach(laneSet.lanes, contextual(handleLane, context));
12927 }
12928
12929 function handleLaneSets(laneSets, context) {
12930 forEach(laneSets, contextual(handleLaneSet, context));
12931 }
12932
12933 function handleFlowElementsContainer(container, context) {
12934 handleFlowElements(container.flowElements, context);
12935
12936 if (container.laneSets) {
12937 handleLaneSets(container.laneSets, context);
12938 }
12939 }
12940
12941 function handleFlowElements(flowElements, context) {
12942 forEach(flowElements, function(e) {
12943 if (is(e, 'bpmn:SequenceFlow')) {
12944 deferred.push(function() {
12945 handleSequenceFlow(e, context);
12946 });
12947 } else if (is(e, 'bpmn:BoundaryEvent')) {
12948 deferred.unshift(function() {
12949 handleBoundaryEvent(e, context);
12950 });
12951 } else if (is(e, 'bpmn:FlowNode')) {
12952 handleFlowNode(e, context);
12953 } else if (is(e, 'bpmn:DataObject')) ; else if (is(e, 'bpmn:DataStoreReference')) {
12954 handleDataElement(e, context);
12955 } else if (is(e, 'bpmn:DataObjectReference')) {
12956 handleDataElement(e, context);
12957 } else {
12958 logError(
12959 translate('unrecognized flowElement {element} in context {context}', {
12960 element: elementToString(e),
12961 context: (context ? elementToString(context.businessObject) : 'null')
12962 }),
12963 { element: e, context: context }
12964 );
12965 }
12966 });
12967 }
12968
12969 function handleParticipant(participant, context) {
12970 var newCtx = visitIfDi(participant, context);
12971
12972 var process = participant.processRef;
12973 if (process) {
12974 handleProcess(process, newCtx || context);
12975 }
12976 }
12977
12978 function handleCollaboration(collaboration) {
12979
12980 forEach(collaboration.participants, contextual(handleParticipant));
12981
12982 handleArtifacts(collaboration.artifacts);
12983
12984 // handle message flows latest in the process
12985 deferred.push(function() {
12986 handleMessageFlows(collaboration.messageFlows);
12987 });
12988 }
12989
12990
12991 function wireFlowNodeRefs(lane) {
12992 // wire the virtual flowNodeRefs <-> relationship
12993 forEach(lane.flowNodeRef, function(flowNode) {
12994 var lanes = flowNode.get('lanes');
12995
12996 if (lanes) {
12997 lanes.push(lane);
12998 }
12999 });
13000 }
13001
13002 // API //////////////////////
13003
13004 return {
13005 handleDeferred: handleDeferred,
13006 handleDefinitions: handleDefinitions,
13007 handleSubProcess: handleSubProcess,
13008 registerDi: registerDi
13009 };
13010 }
13011
13012 /**
13013 * Import the definitions into a diagram.
13014 *
13015 * Errors and warnings are reported through the specified callback.
13016 *
13017 * @param {Diagram} diagram
13018 * @param {ModdleElement} definitions
13019 * @param {Function} done the callback, invoked with (err, [ warning ]) once the import is done
13020 */
13021 function importBpmnDiagram(diagram, definitions, done) {
13022
13023 var importer,
13024 eventBus,
13025 translate;
13026
13027 var error,
13028 warnings = [];
13029
13030 /**
13031 * Walk the diagram semantically, importing (=drawing)
13032 * all elements you encounter.
13033 *
13034 * @param {ModdleElement} definitions
13035 */
13036 function render(definitions) {
13037
13038 var visitor = {
13039
13040 root: function(element) {
13041 return importer.add(element);
13042 },
13043
13044 element: function(element, parentShape) {
13045 return importer.add(element, parentShape);
13046 },
13047
13048 error: function(message, context) {
13049 warnings.push({ message: message, context: context });
13050 }
13051 };
13052
13053 var walker = new BpmnTreeWalker(visitor, translate);
13054
13055 // traverse BPMN 2.0 document model,
13056 // starting at definitions
13057 walker.handleDefinitions(definitions);
13058 }
13059
13060 try {
13061 importer = diagram.get('bpmnImporter');
13062 eventBus = diagram.get('eventBus');
13063 translate = diagram.get('translate');
13064
13065 eventBus.fire('import.render.start', { definitions: definitions });
13066
13067 render(definitions);
13068
13069 eventBus.fire('import.render.complete', {
13070 error: error,
13071 warnings: warnings
13072 });
13073 } catch (e) {
13074 error = e;
13075 }
13076
13077 done(error, warnings);
13078 }
13079
13080 /**
13081 * Is an element of the given BPMN type?
13082 *
13083 * @param {djs.model.Base|ModdleElement} element
13084 * @param {String} type
13085 *
13086 * @return {Boolean}
13087 */
13088 function is$1(element, type) {
13089 var bo = getBusinessObject(element);
13090
13091 return bo && (typeof bo.$instanceOf === 'function') && bo.$instanceOf(type);
13092 }
13093
13094
13095 /**
13096 * Return the business object for a given element.
13097 *
13098 * @param {djs.model.Base|ModdleElement} element
13099 *
13100 * @return {ModdleElement}
13101 */
13102 function getBusinessObject(element) {
13103 return (element && element.businessObject) || element;
13104 }
13105
13106 function isExpanded(element) {
13107
13108 if (is$1(element, 'bpmn:CallActivity')) {
13109 return false;
13110 }
13111
13112 if (is$1(element, 'bpmn:SubProcess')) {
13113 return !!getBusinessObject(element).di.isExpanded;
13114 }
13115
13116 if (is$1(element, 'bpmn:Participant')) {
13117 return !!getBusinessObject(element).processRef;
13118 }
13119
13120 return true;
13121 }
13122
13123 function isEventSubProcess(element) {
13124 return element && !!getBusinessObject(element).triggeredByEvent;
13125 }
13126
13127 // element utils //////////////////////
13128
13129 /**
13130 * Checks if eventDefinition of the given element matches with semantic type.
13131 *
13132 * @return {boolean} true if element is of the given semantic type
13133 */
13134 function isTypedEvent(event, eventDefinitionType, filter$$1) {
13135
13136 function matches(definition, filter$$1) {
13137 return every(filter$$1, function(val, key) {
13138
13139 // we want a == conversion here, to be able to catch
13140 // undefined == false and friends
13141 /* jshint -W116 */
13142 return definition[key] == val;
13143 });
13144 }
13145
13146 return some(event.eventDefinitions, function(definition) {
13147 return definition.$type === eventDefinitionType && matches(event, filter$$1);
13148 });
13149 }
13150
13151 function isThrowEvent(event) {
13152 return (event.$type === 'bpmn:IntermediateThrowEvent') || (event.$type === 'bpmn:EndEvent');
13153 }
13154
13155 function isCollection(element) {
13156 var dataObject = element.dataObjectRef;
13157
13158 return element.isCollection || (dataObject && dataObject.isCollection);
13159 }
13160
13161 function getDi(element) {
13162 return element.businessObject.di;
13163 }
13164
13165 function getSemantic(element) {
13166 return element.businessObject;
13167 }
13168
13169
13170 // color access //////////////////////
13171
13172 function getFillColor(element, defaultColor) {
13173 return getDi(element).get('bioc:fill') || defaultColor || 'white';
13174 }
13175
13176 function getStrokeColor(element, defaultColor) {
13177 return getDi(element).get('bioc:stroke') || defaultColor || 'black';
13178 }
13179
13180
13181 // cropping path customizations //////////////////////
13182
13183 function getCirclePath(shape) {
13184
13185 var cx = shape.x + shape.width / 2,
13186 cy = shape.y + shape.height / 2,
13187 radius = shape.width / 2;
13188
13189 var circlePath = [
13190 ['M', cx, cy],
13191 ['m', 0, -radius],
13192 ['a', radius, radius, 0, 1, 1, 0, 2 * radius],
13193 ['a', radius, radius, 0, 1, 1, 0, -2 * radius],
13194 ['z']
13195 ];
13196
13197 return componentsToPath(circlePath);
13198 }
13199
13200 function getRoundRectPath(shape, borderRadius) {
13201
13202 var x = shape.x,
13203 y = shape.y,
13204 width = shape.width,
13205 height = shape.height;
13206
13207 var roundRectPath = [
13208 ['M', x + borderRadius, y],
13209 ['l', width - borderRadius * 2, 0],
13210 ['a', borderRadius, borderRadius, 0, 0, 1, borderRadius, borderRadius],
13211 ['l', 0, height - borderRadius * 2],
13212 ['a', borderRadius, borderRadius, 0, 0, 1, -borderRadius, borderRadius],
13213 ['l', borderRadius * 2 - width, 0],
13214 ['a', borderRadius, borderRadius, 0, 0, 1, -borderRadius, -borderRadius],
13215 ['l', 0, borderRadius * 2 - height],
13216 ['a', borderRadius, borderRadius, 0, 0, 1, borderRadius, -borderRadius],
13217 ['z']
13218 ];
13219
13220 return componentsToPath(roundRectPath);
13221 }
13222
13223 function getDiamondPath(shape) {
13224
13225 var width = shape.width,
13226 height = shape.height,
13227 x = shape.x,
13228 y = shape.y,
13229 halfWidth = width / 2,
13230 halfHeight = height / 2;
13231
13232 var diamondPath = [
13233 ['M', x + halfWidth, y],
13234 ['l', halfWidth, halfHeight],
13235 ['l', -halfWidth, halfHeight],
13236 ['l', -halfWidth, -halfHeight],
13237 ['z']
13238 ];
13239
13240 return componentsToPath(diamondPath);
13241 }
13242
13243 function getRectPath(shape) {
13244 var x = shape.x,
13245 y = shape.y,
13246 width = shape.width,
13247 height = shape.height;
13248
13249 var rectPath = [
13250 ['M', x, y],
13251 ['l', width, 0],
13252 ['l', 0, height],
13253 ['l', -width, 0],
13254 ['z']
13255 ];
13256
13257 return componentsToPath(rectPath);
13258 }
13259
13260 var hat_1 = createCommonjsModule(function (module) {
13261 var hat = module.exports = function (bits, base) {
13262 if (!base) base = 16;
13263 if (bits === undefined) bits = 128;
13264 if (bits <= 0) return '0';
13265
13266 var digits = Math.log(Math.pow(2, bits)) / Math.log(base);
13267 for (var i = 2; digits === Infinity; i *= 2) {
13268 digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i;
13269 }
13270
13271 var rem = digits - Math.floor(digits);
13272
13273 var res = '';
13274
13275 for (var i = 0; i < Math.floor(digits); i++) {
13276 var x = Math.floor(Math.random() * base).toString(base);
13277 res = x + res;
13278 }
13279
13280 if (rem) {
13281 var b = Math.pow(base, rem);
13282 var x = Math.floor(Math.random() * b).toString(base);
13283 res = x + res;
13284 }
13285
13286 var parsed = parseInt(res, base);
13287 if (parsed !== Infinity && parsed >= Math.pow(2, bits)) {
13288 return hat(bits, base)
13289 }
13290 else return res;
13291 };
13292
13293 hat.rack = function (bits, base, expandBy) {
13294 var fn = function (data) {
13295 var iters = 0;
13296 do {
13297 if (iters ++ > 10) {
13298 if (expandBy) bits += expandBy;
13299 else throw new Error('too many ID collisions, use more bits')
13300 }
13301
13302 var id = hat(bits, base);
13303 } while (Object.hasOwnProperty.call(hats, id));
13304
13305 hats[id] = data;
13306 return id;
13307 };
13308 var hats = fn.hats = {};
13309
13310 fn.get = function (id) {
13311 return fn.hats[id];
13312 };
13313
13314 fn.set = function (id, value) {
13315 fn.hats[id] = value;
13316 return fn;
13317 };
13318
13319 fn.bits = bits || 128;
13320 fn.base = base || 16;
13321 return fn;
13322 };
13323 });
13324
13325 /**
13326 * Create a new id generator / cache instance.
13327 *
13328 * You may optionally provide a seed that is used internally.
13329 *
13330 * @param {Seed} seed
13331 */
13332 function Ids(seed) {
13333
13334 if (!(this instanceof Ids)) {
13335 return new Ids(seed);
13336 }
13337
13338 seed = seed || [ 128, 36, 1 ];
13339 this._seed = seed.length ? hat_1.rack(seed[0], seed[1], seed[2]) : seed;
13340 }
13341
13342 var ids = Ids;
13343
13344 /**
13345 * Generate a next id.
13346 *
13347 * @param {Object} [element] element to bind the id to
13348 *
13349 * @return {String} id
13350 */
13351 Ids.prototype.next = function(element) {
13352 return this._seed(element || true);
13353 };
13354
13355 /**
13356 * Generate a next id with a given prefix.
13357 *
13358 * @param {Object} [element] element to bind the id to
13359 *
13360 * @return {String} id
13361 */
13362 Ids.prototype.nextPrefixed = function(prefix, element) {
13363 var id;
13364
13365 do {
13366 id = prefix + this.next(true);
13367 } while (this.assigned(id));
13368
13369 // claim {prefix}{random}
13370 this.claim(id, element);
13371
13372 // return
13373 return id;
13374 };
13375
13376 /**
13377 * Manually claim an existing id.
13378 *
13379 * @param {String} id
13380 * @param {String} [element] element the id is claimed by
13381 */
13382 Ids.prototype.claim = function(id, element) {
13383 this._seed.set(id, element || true);
13384 };
13385
13386 /**
13387 * Returns true if the given id has already been assigned.
13388 *
13389 * @param {String} id
13390 * @return {Boolean}
13391 */
13392 Ids.prototype.assigned = function(id) {
13393 return this._seed.get(id) || false;
13394 };
13395
13396 /**
13397 * Unclaim an id.
13398 *
13399 * @param {String} id the id to unclaim
13400 */
13401 Ids.prototype.unclaim = function(id) {
13402 delete this._seed.hats[id];
13403 };
13404
13405
13406 /**
13407 * Clear all claimed ids.
13408 */
13409 Ids.prototype.clear = function() {
13410
13411 var hats = this._seed.hats,
13412 id;
13413
13414 for (id in hats) {
13415 this.unclaim(id);
13416 }
13417 };
13418
13419 var RENDERER_IDS = new ids();
13420
13421 var TASK_BORDER_RADIUS = 10;
13422 var INNER_OUTER_DIST = 3;
13423
13424 var DEFAULT_FILL_OPACITY = .95,
13425 HIGH_FILL_OPACITY = .35;
13426
13427
13428 function BpmnRenderer(
13429 config, eventBus, styles, pathMap,
13430 canvas, textRenderer, priority) {
13431
13432 BaseRenderer.call(this, eventBus, priority);
13433
13434 var defaultFillColor = config && config.defaultFillColor,
13435 defaultStrokeColor = config && config.defaultStrokeColor;
13436
13437 var rendererId = RENDERER_IDS.next();
13438
13439 var markers = {};
13440
13441 var computeStyle = styles.computeStyle;
13442
13443 function addMarker(id, options) {
13444 var attrs = assign({
13445 fill: 'black',
13446 strokeWidth: 1,
13447 strokeLinecap: 'round',
13448 strokeDasharray: 'none'
13449 }, options.attrs);
13450
13451 var ref = options.ref || { x: 0, y: 0 };
13452
13453 var scale$$1 = options.scale || 1;
13454
13455 // fix for safari / chrome / firefox bug not correctly
13456 // resetting stroke dash array
13457 if (attrs.strokeDasharray === 'none') {
13458 attrs.strokeDasharray = [10000, 1];
13459 }
13460
13461 var marker = create('marker');
13462
13463 attr$1(options.element, attrs);
13464
13465 append(marker, options.element);
13466
13467 attr$1(marker, {
13468 id: id,
13469 viewBox: '0 0 20 20',
13470 refX: ref.x,
13471 refY: ref.y,
13472 markerWidth: 20 * scale$$1,
13473 markerHeight: 20 * scale$$1,
13474 orient: 'auto'
13475 });
13476
13477 var defs = query('defs', canvas._svg);
13478
13479 if (!defs) {
13480 defs = create('defs');
13481
13482 append(canvas._svg, defs);
13483 }
13484
13485 append(defs, marker);
13486
13487 markers[id] = marker;
13488 }
13489
13490 function marker(type, fill, stroke) {
13491 var id = type + '-' + fill + '-' + stroke + '-' + rendererId;
13492
13493 if (!markers[id]) {
13494 createMarker(type, fill, stroke);
13495 }
13496
13497 return 'url(#' + id + ')';
13498 }
13499
13500 function createMarker(type, fill, stroke) {
13501 var id = type + '-' + fill + '-' + stroke + '-' + rendererId;
13502
13503 if (type === 'sequenceflow-end') {
13504 var sequenceflowEnd = create('path');
13505 attr$1(sequenceflowEnd, { d: 'M 1 5 L 11 10 L 1 15 Z' });
13506
13507 addMarker(id, {
13508 element: sequenceflowEnd,
13509 ref: { x: 11, y: 10 },
13510 scale: 0.5,
13511 attrs: {
13512 fill: stroke,
13513 stroke: stroke
13514 }
13515 });
13516 }
13517
13518 if (type === 'messageflow-start') {
13519 var messageflowStart = create('circle');
13520 attr$1(messageflowStart, { cx: 6, cy: 6, r: 3.5 });
13521
13522 addMarker(id, {
13523 element: messageflowStart,
13524 attrs: {
13525 fill: fill,
13526 stroke: stroke
13527 },
13528 ref: { x: 6, y: 6 }
13529 });
13530 }
13531
13532 if (type === 'messageflow-end') {
13533 var messageflowEnd = create('path');
13534 attr$1(messageflowEnd, { d: 'm 1 5 l 0 -3 l 7 3 l -7 3 z' });
13535
13536 addMarker(id, {
13537 element: messageflowEnd,
13538 attrs: {
13539 fill: fill,
13540 stroke: stroke,
13541 strokeLinecap: 'butt'
13542 },
13543 ref: { x: 8.5, y: 5 }
13544 });
13545 }
13546
13547 if (type === 'association-start') {
13548 var associationStart = create('path');
13549 attr$1(associationStart, { d: 'M 11 5 L 1 10 L 11 15' });
13550
13551 addMarker(id, {
13552 element: associationStart,
13553 attrs: {
13554 fill: 'none',
13555 stroke: stroke,
13556 strokeWidth: 1.5
13557 },
13558 ref: { x: 1, y: 10 },
13559 scale: 0.5
13560 });
13561 }
13562
13563 if (type === 'association-end') {
13564 var associationEnd = create('path');
13565 attr$1(associationEnd, { d: 'M 1 5 L 11 10 L 1 15' });
13566
13567 addMarker(id, {
13568 element: associationEnd,
13569 attrs: {
13570 fill: 'none',
13571 stroke: stroke,
13572 strokeWidth: 1.5
13573 },
13574 ref: { x: 12, y: 10 },
13575 scale: 0.5
13576 });
13577 }
13578
13579 if (type === 'conditional-flow-marker') {
13580 var conditionalflowMarker = create('path');
13581 attr$1(conditionalflowMarker, { d: 'M 0 10 L 8 6 L 16 10 L 8 14 Z' });
13582
13583 addMarker(id, {
13584 element: conditionalflowMarker,
13585 attrs: {
13586 fill: fill,
13587 stroke: stroke
13588 },
13589 ref: { x: -1, y: 10 },
13590 scale: 0.5
13591 });
13592 }
13593
13594 if (type === 'conditional-default-flow-marker') {
13595 var conditionaldefaultflowMarker = create('path');
13596 attr$1(conditionaldefaultflowMarker, { d: 'M 6 4 L 10 16' });
13597
13598 addMarker(id, {
13599 element: conditionaldefaultflowMarker,
13600 attrs: {
13601 stroke: stroke
13602 },
13603 ref: { x: 0, y: 10 },
13604 scale: 0.5
13605 });
13606 }
13607 }
13608
13609 function drawCircle(parentGfx, width, height, offset, attrs) {
13610
13611 if (isObject(offset)) {
13612 attrs = offset;
13613 offset = 0;
13614 }
13615
13616 offset = offset || 0;
13617
13618 attrs = computeStyle(attrs, {
13619 stroke: 'black',
13620 strokeWidth: 2,
13621 fill: 'white'
13622 });
13623
13624 if (attrs.fill === 'none') {
13625 delete attrs.fillOpacity;
13626 }
13627
13628 var cx = width / 2,
13629 cy = height / 2;
13630
13631 var circle = create('circle');
13632 attr$1(circle, {
13633 cx: cx,
13634 cy: cy,
13635 r: Math.round((width + height) / 4 - offset)
13636 });
13637 attr$1(circle, attrs);
13638
13639 append(parentGfx, circle);
13640
13641 return circle;
13642 }
13643
13644 function drawRect(parentGfx, width, height, r, offset, attrs) {
13645
13646 if (isObject(offset)) {
13647 attrs = offset;
13648 offset = 0;
13649 }
13650
13651 offset = offset || 0;
13652
13653 attrs = computeStyle(attrs, {
13654 stroke: 'black',
13655 strokeWidth: 2,
13656 fill: 'white'
13657 });
13658
13659 var rect = create('rect');
13660 attr$1(rect, {
13661 x: offset,
13662 y: offset,
13663 width: width - offset * 2,
13664 height: height - offset * 2,
13665 rx: r,
13666 ry: r
13667 });
13668 attr$1(rect, attrs);
13669
13670 append(parentGfx, rect);
13671
13672 return rect;
13673 }
13674
13675 function drawDiamond(parentGfx, width, height, attrs) {
13676
13677 var x_2 = width / 2;
13678 var y_2 = height / 2;
13679
13680 var points = [{ x: x_2, y: 0 }, { x: width, y: y_2 }, { x: x_2, y: height }, { x: 0, y: y_2 }];
13681
13682 var pointsString = points.map(function(point) {
13683 return point.x + ',' + point.y;
13684 }).join(' ');
13685
13686 attrs = computeStyle(attrs, {
13687 stroke: 'black',
13688 strokeWidth: 2,
13689 fill: 'white'
13690 });
13691
13692 var polygon = create('polygon');
13693 attr$1(polygon, {
13694 points: pointsString
13695 });
13696 attr$1(polygon, attrs);
13697
13698 append(parentGfx, polygon);
13699
13700 return polygon;
13701 }
13702
13703 function drawLine(parentGfx, waypoints, attrs) {
13704 attrs = computeStyle(attrs, [ 'no-fill' ], {
13705 stroke: 'black',
13706 strokeWidth: 2,
13707 fill: 'none'
13708 });
13709
13710 var line = createLine(waypoints, attrs);
13711
13712 append(parentGfx, line);
13713
13714 return line;
13715 }
13716
13717 function drawPath(parentGfx, d, attrs) {
13718
13719 attrs = computeStyle(attrs, [ 'no-fill' ], {
13720 strokeWidth: 2,
13721 stroke: 'black'
13722 });
13723
13724 var path = create('path');
13725 attr$1(path, { d: d });
13726 attr$1(path, attrs);
13727
13728 append(parentGfx, path);
13729
13730 return path;
13731 }
13732
13733 function drawMarker(type, parentGfx, path, attrs) {
13734 return drawPath(parentGfx, path, assign({ 'data-marker': type }, attrs));
13735 }
13736
13737 function as(type) {
13738 return function(parentGfx, element) {
13739 return handlers[type](parentGfx, element);
13740 };
13741 }
13742
13743 function renderer(type) {
13744 return handlers[type];
13745 }
13746
13747 function renderEventContent(element, parentGfx) {
13748
13749 var event = getSemantic(element);
13750 var isThrowing = isThrowEvent(event);
13751
13752 if (isTypedEvent(event, 'bpmn:MessageEventDefinition')) {
13753 return renderer('bpmn:MessageEventDefinition')(parentGfx, element, isThrowing);
13754 }
13755
13756 if (isTypedEvent(event, 'bpmn:TimerEventDefinition')) {
13757 return renderer('bpmn:TimerEventDefinition')(parentGfx, element, isThrowing);
13758 }
13759
13760 if (isTypedEvent(event, 'bpmn:ConditionalEventDefinition')) {
13761 return renderer('bpmn:ConditionalEventDefinition')(parentGfx, element);
13762 }
13763
13764 if (isTypedEvent(event, 'bpmn:SignalEventDefinition')) {
13765 return renderer('bpmn:SignalEventDefinition')(parentGfx, element, isThrowing);
13766 }
13767
13768 if (isTypedEvent(event, 'bpmn:CancelEventDefinition') &&
13769 isTypedEvent(event, 'bpmn:TerminateEventDefinition', { parallelMultiple: false })) {
13770 return renderer('bpmn:MultipleEventDefinition')(parentGfx, element, isThrowing);
13771 }
13772
13773 if (isTypedEvent(event, 'bpmn:CancelEventDefinition') &&
13774 isTypedEvent(event, 'bpmn:TerminateEventDefinition', { parallelMultiple: true })) {
13775 return renderer('bpmn:ParallelMultipleEventDefinition')(parentGfx, element, isThrowing);
13776 }
13777
13778 if (isTypedEvent(event, 'bpmn:EscalationEventDefinition')) {
13779 return renderer('bpmn:EscalationEventDefinition')(parentGfx, element, isThrowing);
13780 }
13781
13782 if (isTypedEvent(event, 'bpmn:LinkEventDefinition')) {
13783 return renderer('bpmn:LinkEventDefinition')(parentGfx, element, isThrowing);
13784 }
13785
13786 if (isTypedEvent(event, 'bpmn:ErrorEventDefinition')) {
13787 return renderer('bpmn:ErrorEventDefinition')(parentGfx, element, isThrowing);
13788 }
13789
13790 if (isTypedEvent(event, 'bpmn:CancelEventDefinition')) {
13791 return renderer('bpmn:CancelEventDefinition')(parentGfx, element, isThrowing);
13792 }
13793
13794 if (isTypedEvent(event, 'bpmn:CompensateEventDefinition')) {
13795 return renderer('bpmn:CompensateEventDefinition')(parentGfx, element, isThrowing);
13796 }
13797
13798 if (isTypedEvent(event, 'bpmn:TerminateEventDefinition')) {
13799 return renderer('bpmn:TerminateEventDefinition')(parentGfx, element, isThrowing);
13800 }
13801
13802 return null;
13803 }
13804
13805 function renderLabel(parentGfx, label, options) {
13806
13807 options = assign({
13808 size: {
13809 width: 100
13810 }
13811 }, options);
13812
13813 var text = textRenderer.createText(label || '', options);
13814
13815 classes$1(text).add('djs-label');
13816
13817 append(parentGfx, text);
13818
13819 return text;
13820 }
13821
13822 function renderEmbeddedLabel(parentGfx, element, align) {
13823 var semantic = getSemantic(element);
13824
13825 return renderLabel(parentGfx, semantic.name, {
13826 box: element,
13827 align: align,
13828 padding: 5,
13829 style: {
13830 fill: getStrokeColor(element, defaultStrokeColor)
13831 }
13832 });
13833 }
13834
13835 function renderExternalLabel(parentGfx, element) {
13836 var semantic = getSemantic(element);
13837 var box = {
13838 width: 90,
13839 height: 30,
13840 x: element.width / 2 + element.x,
13841 y: element.height / 2 + element.y
13842 };
13843
13844 return renderLabel(parentGfx, semantic.name, {
13845 box: box,
13846 fitBox: true,
13847 style: assign(
13848 {},
13849 textRenderer.getExternalStyle(),
13850 {
13851 fill: getStrokeColor(element, defaultStrokeColor)
13852 }
13853 )
13854 });
13855 }
13856
13857 function renderLaneLabel(parentGfx, text, element) {
13858 var textBox = renderLabel(parentGfx, text, {
13859 box: {
13860 height: 30,
13861 width: element.height
13862 },
13863 align: 'center-middle',
13864 style: {
13865 fill: getStrokeColor(element, defaultStrokeColor)
13866 }
13867 });
13868
13869 var top = -1 * element.height;
13870
13871 transform$1(textBox, 0, -top, 270);
13872 }
13873
13874 function createPathFromConnection(connection) {
13875 var waypoints = connection.waypoints;
13876
13877 var pathData = 'm ' + waypoints[0].x + ',' + waypoints[0].y;
13878 for (var i = 1; i < waypoints.length; i++) {
13879 pathData += 'L' + waypoints[i].x + ',' + waypoints[i].y + ' ';
13880 }
13881 return pathData;
13882 }
13883
13884 var handlers = this.handlers = {
13885 'bpmn:Event': function(parentGfx, element, attrs) {
13886
13887 if (!('fillOpacity' in attrs)) {
13888 attrs.fillOpacity = DEFAULT_FILL_OPACITY;
13889 }
13890
13891 return drawCircle(parentGfx, element.width, element.height, attrs);
13892 },
13893 'bpmn:StartEvent': function(parentGfx, element) {
13894 var attrs = {
13895 fill: getFillColor(element, defaultFillColor),
13896 stroke: getStrokeColor(element, defaultStrokeColor)
13897 };
13898
13899 var semantic = getSemantic(element);
13900
13901 if (!semantic.isInterrupting) {
13902 attrs = {
13903 strokeDasharray: '6',
13904 strokeLinecap: 'round',
13905 fill: getFillColor(element, defaultFillColor),
13906 stroke: getStrokeColor(element, defaultStrokeColor)
13907 };
13908 }
13909
13910 var circle = renderer('bpmn:Event')(parentGfx, element, attrs);
13911
13912 renderEventContent(element, parentGfx);
13913
13914 return circle;
13915 },
13916 'bpmn:MessageEventDefinition': function(parentGfx, element, isThrowing) {
13917 var pathData = pathMap.getScaledPath('EVENT_MESSAGE', {
13918 xScaleFactor: 0.9,
13919 yScaleFactor: 0.9,
13920 containerWidth: element.width,
13921 containerHeight: element.height,
13922 position: {
13923 mx: 0.235,
13924 my: 0.315
13925 }
13926 });
13927
13928 var fill = isThrowing ? getStrokeColor(element, defaultStrokeColor) : getFillColor(element, defaultFillColor);
13929 var stroke = isThrowing ? getFillColor(element, defaultFillColor) : getStrokeColor(element, defaultStrokeColor);
13930
13931 var messagePath = drawPath(parentGfx, pathData, {
13932 strokeWidth: 1,
13933 fill: fill,
13934 stroke: stroke
13935 });
13936
13937 return messagePath;
13938 },
13939 'bpmn:TimerEventDefinition': function(parentGfx, element) {
13940 var circle = drawCircle(parentGfx, element.width, element.height, 0.2 * element.height, {
13941 strokeWidth: 2,
13942 fill: getFillColor(element, defaultFillColor),
13943 stroke: getStrokeColor(element, defaultStrokeColor)
13944 });
13945
13946 var pathData = pathMap.getScaledPath('EVENT_TIMER_WH', {
13947 xScaleFactor: 0.75,
13948 yScaleFactor: 0.75,
13949 containerWidth: element.width,
13950 containerHeight: element.height,
13951 position: {
13952 mx: 0.5,
13953 my: 0.5
13954 }
13955 });
13956
13957 drawPath(parentGfx, pathData, {
13958 strokeWidth: 2,
13959 strokeLinecap: 'square',
13960 stroke: getStrokeColor(element, defaultStrokeColor)
13961 });
13962
13963 for (var i = 0;i < 12; i++) {
13964
13965 var linePathData = pathMap.getScaledPath('EVENT_TIMER_LINE', {
13966 xScaleFactor: 0.75,
13967 yScaleFactor: 0.75,
13968 containerWidth: element.width,
13969 containerHeight: element.height,
13970 position: {
13971 mx: 0.5,
13972 my: 0.5
13973 }
13974 });
13975
13976 var width = element.width / 2;
13977 var height = element.height / 2;
13978
13979 drawPath(parentGfx, linePathData, {
13980 strokeWidth: 1,
13981 strokeLinecap: 'square',
13982 transform: 'rotate(' + (i * 30) + ',' + height + ',' + width + ')',
13983 stroke: getStrokeColor(element, defaultStrokeColor)
13984 });
13985 }
13986
13987 return circle;
13988 },
13989 'bpmn:EscalationEventDefinition': function(parentGfx, event, isThrowing) {
13990 var pathData = pathMap.getScaledPath('EVENT_ESCALATION', {
13991 xScaleFactor: 1,
13992 yScaleFactor: 1,
13993 containerWidth: event.width,
13994 containerHeight: event.height,
13995 position: {
13996 mx: 0.5,
13997 my: 0.2
13998 }
13999 });
14000
14001 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
14002
14003 return drawPath(parentGfx, pathData, {
14004 strokeWidth: 1,
14005 fill: fill,
14006 stroke: getStrokeColor(event, defaultStrokeColor)
14007 });
14008 },
14009 'bpmn:ConditionalEventDefinition': function(parentGfx, event) {
14010 var pathData = pathMap.getScaledPath('EVENT_CONDITIONAL', {
14011 xScaleFactor: 1,
14012 yScaleFactor: 1,
14013 containerWidth: event.width,
14014 containerHeight: event.height,
14015 position: {
14016 mx: 0.5,
14017 my: 0.222
14018 }
14019 });
14020
14021 return drawPath(parentGfx, pathData, {
14022 strokeWidth: 1,
14023 stroke: getStrokeColor(event, defaultStrokeColor)
14024 });
14025 },
14026 'bpmn:LinkEventDefinition': function(parentGfx, event, isThrowing) {
14027 var pathData = pathMap.getScaledPath('EVENT_LINK', {
14028 xScaleFactor: 1,
14029 yScaleFactor: 1,
14030 containerWidth: event.width,
14031 containerHeight: event.height,
14032 position: {
14033 mx: 0.57,
14034 my: 0.263
14035 }
14036 });
14037
14038 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
14039
14040 return drawPath(parentGfx, pathData, {
14041 strokeWidth: 1,
14042 fill: fill,
14043 stroke: getStrokeColor(event, defaultStrokeColor)
14044 });
14045 },
14046 'bpmn:ErrorEventDefinition': function(parentGfx, event, isThrowing) {
14047 var pathData = pathMap.getScaledPath('EVENT_ERROR', {
14048 xScaleFactor: 1.1,
14049 yScaleFactor: 1.1,
14050 containerWidth: event.width,
14051 containerHeight: event.height,
14052 position: {
14053 mx: 0.2,
14054 my: 0.722
14055 }
14056 });
14057
14058 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
14059
14060 return drawPath(parentGfx, pathData, {
14061 strokeWidth: 1,
14062 fill: fill,
14063 stroke: getStrokeColor(event, defaultStrokeColor)
14064 });
14065 },
14066 'bpmn:CancelEventDefinition': function(parentGfx, event, isThrowing) {
14067 var pathData = pathMap.getScaledPath('EVENT_CANCEL_45', {
14068 xScaleFactor: 1.0,
14069 yScaleFactor: 1.0,
14070 containerWidth: event.width,
14071 containerHeight: event.height,
14072 position: {
14073 mx: 0.638,
14074 my: -0.055
14075 }
14076 });
14077
14078 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
14079
14080 var path = drawPath(parentGfx, pathData, {
14081 strokeWidth: 1,
14082 fill: fill,
14083 stroke: getStrokeColor(event, defaultStrokeColor)
14084 });
14085
14086 rotate(path, 45);
14087
14088 return path;
14089 },
14090 'bpmn:CompensateEventDefinition': function(parentGfx, event, isThrowing) {
14091 var pathData = pathMap.getScaledPath('EVENT_COMPENSATION', {
14092 xScaleFactor: 1,
14093 yScaleFactor: 1,
14094 containerWidth: event.width,
14095 containerHeight: event.height,
14096 position: {
14097 mx: 0.22,
14098 my: 0.5
14099 }
14100 });
14101
14102 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
14103
14104 return drawPath(parentGfx, pathData, {
14105 strokeWidth: 1,
14106 fill: fill,
14107 stroke: getStrokeColor(event, defaultStrokeColor)
14108 });
14109 },
14110 'bpmn:SignalEventDefinition': function(parentGfx, event, isThrowing) {
14111 var pathData = pathMap.getScaledPath('EVENT_SIGNAL', {
14112 xScaleFactor: 0.9,
14113 yScaleFactor: 0.9,
14114 containerWidth: event.width,
14115 containerHeight: event.height,
14116 position: {
14117 mx: 0.5,
14118 my: 0.2
14119 }
14120 });
14121
14122 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
14123
14124 return drawPath(parentGfx, pathData, {
14125 strokeWidth: 1,
14126 fill: fill,
14127 stroke: getStrokeColor(event, defaultStrokeColor)
14128 });
14129 },
14130 'bpmn:MultipleEventDefinition': function(parentGfx, event, isThrowing) {
14131 var pathData = pathMap.getScaledPath('EVENT_MULTIPLE', {
14132 xScaleFactor: 1.1,
14133 yScaleFactor: 1.1,
14134 containerWidth: event.width,
14135 containerHeight: event.height,
14136 position: {
14137 mx: 0.222,
14138 my: 0.36
14139 }
14140 });
14141
14142 var fill = isThrowing ? getStrokeColor(event, defaultStrokeColor) : 'none';
14143
14144 return drawPath(parentGfx, pathData, {
14145 strokeWidth: 1,
14146 fill: fill
14147 });
14148 },
14149 'bpmn:ParallelMultipleEventDefinition': function(parentGfx, event) {
14150 var pathData = pathMap.getScaledPath('EVENT_PARALLEL_MULTIPLE', {
14151 xScaleFactor: 1.2,
14152 yScaleFactor: 1.2,
14153 containerWidth: event.width,
14154 containerHeight: event.height,
14155 position: {
14156 mx: 0.458,
14157 my: 0.194
14158 }
14159 });
14160
14161 return drawPath(parentGfx, pathData, {
14162 strokeWidth: 1,
14163 fill: getStrokeColor(event, defaultStrokeColor),
14164 stroke: getStrokeColor(event, defaultStrokeColor)
14165 });
14166 },
14167 'bpmn:EndEvent': function(parentGfx, element) {
14168 var circle = renderer('bpmn:Event')(parentGfx, element, {
14169 strokeWidth: 4,
14170 fill: getFillColor(element, defaultFillColor),
14171 stroke: getStrokeColor(element, defaultStrokeColor)
14172 });
14173
14174 renderEventContent(element, parentGfx, true);
14175
14176 return circle;
14177 },
14178 'bpmn:TerminateEventDefinition': function(parentGfx, element) {
14179 var circle = drawCircle(parentGfx, element.width, element.height, 8, {
14180 strokeWidth: 4,
14181 fill: getStrokeColor(element, defaultStrokeColor),
14182 stroke: getStrokeColor(element, defaultStrokeColor)
14183 });
14184
14185 return circle;
14186 },
14187 'bpmn:IntermediateEvent': function(parentGfx, element) {
14188 var outer = renderer('bpmn:Event')(parentGfx, element, {
14189 strokeWidth: 1,
14190 fill: getFillColor(element, defaultFillColor),
14191 stroke: getStrokeColor(element, defaultStrokeColor)
14192 });
14193
14194 /* inner */
14195 drawCircle(parentGfx, element.width, element.height, INNER_OUTER_DIST, {
14196 strokeWidth: 1,
14197 fill: getFillColor(element, 'none'),
14198 stroke: getStrokeColor(element, defaultStrokeColor)
14199 });
14200
14201 renderEventContent(element, parentGfx);
14202
14203 return outer;
14204 },
14205 'bpmn:IntermediateCatchEvent': as('bpmn:IntermediateEvent'),
14206 'bpmn:IntermediateThrowEvent': as('bpmn:IntermediateEvent'),
14207
14208 'bpmn:Activity': function(parentGfx, element, attrs) {
14209
14210 attrs = attrs || {};
14211
14212 if (!('fillOpacity' in attrs)) {
14213 attrs.fillOpacity = DEFAULT_FILL_OPACITY;
14214 }
14215
14216 return drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS, attrs);
14217 },
14218
14219 'bpmn:Task': function(parentGfx, element) {
14220 var attrs = {
14221 fill: getFillColor(element, defaultFillColor),
14222 stroke: getStrokeColor(element, defaultStrokeColor)
14223 };
14224
14225 var rect = renderer('bpmn:Activity')(parentGfx, element, attrs);
14226
14227 renderEmbeddedLabel(parentGfx, element, 'center-middle');
14228 attachTaskMarkers(parentGfx, element);
14229
14230 return rect;
14231 },
14232 'bpmn:ServiceTask': function(parentGfx, element) {
14233 var task = renderer('bpmn:Task')(parentGfx, element);
14234
14235 var pathDataBG = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
14236 abspos: {
14237 x: 12,
14238 y: 18
14239 }
14240 });
14241
14242 /* service bg */ drawPath(parentGfx, pathDataBG, {
14243 strokeWidth: 1,
14244 fill: getFillColor(element, defaultFillColor),
14245 stroke: getStrokeColor(element, defaultStrokeColor)
14246 });
14247
14248 var fillPathData = pathMap.getScaledPath('TASK_TYPE_SERVICE_FILL', {
14249 abspos: {
14250 x: 17.2,
14251 y: 18
14252 }
14253 });
14254
14255 /* service fill */ drawPath(parentGfx, fillPathData, {
14256 strokeWidth: 0,
14257 fill: getFillColor(element, defaultFillColor)
14258 });
14259
14260 var pathData = pathMap.getScaledPath('TASK_TYPE_SERVICE', {
14261 abspos: {
14262 x: 17,
14263 y: 22
14264 }
14265 });
14266
14267 /* service */ drawPath(parentGfx, pathData, {
14268 strokeWidth: 1,
14269 fill: getFillColor(element, defaultFillColor),
14270 stroke: getStrokeColor(element, defaultStrokeColor)
14271 });
14272
14273 return task;
14274 },
14275 'bpmn:UserTask': function(parentGfx, element) {
14276 var task = renderer('bpmn:Task')(parentGfx, element);
14277
14278 var x = 15;
14279 var y = 12;
14280
14281 var pathData = pathMap.getScaledPath('TASK_TYPE_USER_1', {
14282 abspos: {
14283 x: x,
14284 y: y
14285 }
14286 });
14287
14288 /* user path */ drawPath(parentGfx, pathData, {
14289 strokeWidth: 0.5,
14290 fill: getFillColor(element, defaultFillColor),
14291 stroke: getStrokeColor(element, defaultStrokeColor)
14292 });
14293
14294 var pathData2 = pathMap.getScaledPath('TASK_TYPE_USER_2', {
14295 abspos: {
14296 x: x,
14297 y: y
14298 }
14299 });
14300
14301 /* user2 path */ drawPath(parentGfx, pathData2, {
14302 strokeWidth: 0.5,
14303 fill: getFillColor(element, defaultFillColor),
14304 stroke: getStrokeColor(element, defaultStrokeColor)
14305 });
14306
14307 var pathData3 = pathMap.getScaledPath('TASK_TYPE_USER_3', {
14308 abspos: {
14309 x: x,
14310 y: y
14311 }
14312 });
14313
14314 /* user3 path */ drawPath(parentGfx, pathData3, {
14315 strokeWidth: 0.5,
14316 fill: getStrokeColor(element, defaultStrokeColor),
14317 stroke: getStrokeColor(element, defaultStrokeColor)
14318 });
14319
14320 return task;
14321 },
14322 'bpmn:ManualTask': function(parentGfx, element) {
14323 var task = renderer('bpmn:Task')(parentGfx, element);
14324
14325 var pathData = pathMap.getScaledPath('TASK_TYPE_MANUAL', {
14326 abspos: {
14327 x: 17,
14328 y: 15
14329 }
14330 });
14331
14332 /* manual path */ drawPath(parentGfx, pathData, {
14333 strokeWidth: 0.5, // 0.25,
14334 fill: getFillColor(element, defaultFillColor),
14335 stroke: getStrokeColor(element, defaultStrokeColor)
14336 });
14337
14338 return task;
14339 },
14340 'bpmn:SendTask': function(parentGfx, element) {
14341 var task = renderer('bpmn:Task')(parentGfx, element);
14342
14343 var pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
14344 xScaleFactor: 1,
14345 yScaleFactor: 1,
14346 containerWidth: 21,
14347 containerHeight: 14,
14348 position: {
14349 mx: 0.285,
14350 my: 0.357
14351 }
14352 });
14353
14354 /* send path */ drawPath(parentGfx, pathData, {
14355 strokeWidth: 1,
14356 fill: getStrokeColor(element, defaultStrokeColor),
14357 stroke: getFillColor(element, defaultFillColor)
14358 });
14359
14360 return task;
14361 },
14362 'bpmn:ReceiveTask' : function(parentGfx, element) {
14363 var semantic = getSemantic(element);
14364
14365 var task = renderer('bpmn:Task')(parentGfx, element);
14366 var pathData;
14367
14368 if (semantic.instantiate) {
14369 drawCircle(parentGfx, 28, 28, 20 * 0.22, { strokeWidth: 1 });
14370
14371 pathData = pathMap.getScaledPath('TASK_TYPE_INSTANTIATING_SEND', {
14372 abspos: {
14373 x: 7.77,
14374 y: 9.52
14375 }
14376 });
14377 } else {
14378
14379 pathData = pathMap.getScaledPath('TASK_TYPE_SEND', {
14380 xScaleFactor: 0.9,
14381 yScaleFactor: 0.9,
14382 containerWidth: 21,
14383 containerHeight: 14,
14384 position: {
14385 mx: 0.3,
14386 my: 0.4
14387 }
14388 });
14389 }
14390
14391 /* receive path */ drawPath(parentGfx, pathData, {
14392 strokeWidth: 1,
14393 fill: getFillColor(element, defaultFillColor),
14394 stroke: getStrokeColor(element, defaultStrokeColor)
14395 });
14396
14397 return task;
14398 },
14399 'bpmn:ScriptTask': function(parentGfx, element) {
14400 var task = renderer('bpmn:Task')(parentGfx, element);
14401
14402 var pathData = pathMap.getScaledPath('TASK_TYPE_SCRIPT', {
14403 abspos: {
14404 x: 15,
14405 y: 20
14406 }
14407 });
14408
14409 /* script path */ drawPath(parentGfx, pathData, {
14410 strokeWidth: 1,
14411 stroke: getStrokeColor(element, defaultStrokeColor)
14412 });
14413
14414 return task;
14415 },
14416 'bpmn:BusinessRuleTask': function(parentGfx, element) {
14417 var task = renderer('bpmn:Task')(parentGfx, element);
14418
14419 var headerPathData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_HEADER', {
14420 abspos: {
14421 x: 8,
14422 y: 8
14423 }
14424 });
14425
14426 var businessHeaderPath = drawPath(parentGfx, headerPathData);
14427 attr$1(businessHeaderPath, {
14428 strokeWidth: 1,
14429 fill: getFillColor(element, '#aaaaaa'),
14430 stroke: getStrokeColor(element, defaultStrokeColor)
14431 });
14432
14433 var headerData = pathMap.getScaledPath('TASK_TYPE_BUSINESS_RULE_MAIN', {
14434 abspos: {
14435 x: 8,
14436 y: 8
14437 }
14438 });
14439
14440 var businessPath = drawPath(parentGfx, headerData);
14441 attr$1(businessPath, {
14442 strokeWidth: 1,
14443 stroke: getStrokeColor(element, defaultStrokeColor)
14444 });
14445
14446 return task;
14447 },
14448 'bpmn:SubProcess': function(parentGfx, element, attrs) {
14449 attrs = assign({
14450 fill: getFillColor(element, defaultFillColor),
14451 stroke: getStrokeColor(element, defaultStrokeColor)
14452 }, attrs);
14453
14454 var rect = renderer('bpmn:Activity')(parentGfx, element, attrs);
14455
14456 var expanded = isExpanded(element);
14457
14458 if (isEventSubProcess(element)) {
14459 attr$1(rect, {
14460 strokeDasharray: '1,2'
14461 });
14462 }
14463
14464 renderEmbeddedLabel(parentGfx, element, expanded ? 'center-top' : 'center-middle');
14465
14466 if (expanded) {
14467 attachTaskMarkers(parentGfx, element);
14468 } else {
14469 attachTaskMarkers(parentGfx, element, ['SubProcessMarker']);
14470 }
14471
14472 return rect;
14473 },
14474 'bpmn:AdHocSubProcess': function(parentGfx, element) {
14475 return renderer('bpmn:SubProcess')(parentGfx, element);
14476 },
14477 'bpmn:Transaction': function(parentGfx, element) {
14478 var outer = renderer('bpmn:SubProcess')(parentGfx, element);
14479
14480 var innerAttrs = styles.style([ 'no-fill', 'no-events' ], {
14481 stroke: getStrokeColor(element, defaultStrokeColor)
14482 });
14483
14484 /* inner path */ drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS - 2, INNER_OUTER_DIST, innerAttrs);
14485
14486 return outer;
14487 },
14488 'bpmn:CallActivity': function(parentGfx, element) {
14489 return renderer('bpmn:SubProcess')(parentGfx, element, {
14490 strokeWidth: 5
14491 });
14492 },
14493 'bpmn:Participant': function(parentGfx, element) {
14494
14495 var attrs = {
14496 fillOpacity: DEFAULT_FILL_OPACITY,
14497 fill: getFillColor(element, defaultFillColor),
14498 stroke: getStrokeColor(element, defaultStrokeColor)
14499 };
14500
14501 var lane = renderer('bpmn:Lane')(parentGfx, element, attrs);
14502
14503 var expandedPool = isExpanded(element);
14504
14505 if (expandedPool) {
14506 drawLine(parentGfx, [
14507 { x: 30, y: 0 },
14508 { x: 30, y: element.height }
14509 ], {
14510 stroke: getStrokeColor(element, defaultStrokeColor)
14511 });
14512 var text = getSemantic(element).name;
14513 renderLaneLabel(parentGfx, text, element);
14514 } else {
14515 // Collapsed pool draw text inline
14516 var text2 = getSemantic(element).name;
14517 renderLabel(parentGfx, text2, {
14518 box: element, align: 'center-middle',
14519 style: {
14520 fill: getStrokeColor(element, defaultStrokeColor)
14521 }
14522 });
14523 }
14524
14525 var participantMultiplicity = !!(getSemantic(element).participantMultiplicity);
14526
14527 if (participantMultiplicity) {
14528 renderer('ParticipantMultiplicityMarker')(parentGfx, element);
14529 }
14530
14531 return lane;
14532 },
14533 'bpmn:Lane': function(parentGfx, element, attrs) {
14534 var rect = drawRect(parentGfx, element.width, element.height, 0, assign({
14535 fill: getFillColor(element, defaultFillColor),
14536 fillOpacity: HIGH_FILL_OPACITY,
14537 stroke: getStrokeColor(element, defaultStrokeColor)
14538 }, attrs));
14539
14540 var semantic = getSemantic(element);
14541
14542 if (semantic.$type === 'bpmn:Lane') {
14543 var text = semantic.name;
14544 renderLaneLabel(parentGfx, text, element);
14545 }
14546
14547 return rect;
14548 },
14549 'bpmn:InclusiveGateway': function(parentGfx, element) {
14550 var diamond = renderer('bpmn:Gateway')(parentGfx, element);
14551
14552 /* circle path */
14553 drawCircle(parentGfx, element.width, element.height, element.height * 0.24, {
14554 strokeWidth: 2.5,
14555 fill: getFillColor(element, defaultFillColor),
14556 stroke: getStrokeColor(element, defaultStrokeColor)
14557 });
14558
14559 return diamond;
14560 },
14561 'bpmn:ExclusiveGateway': function(parentGfx, element) {
14562 var diamond = renderer('bpmn:Gateway')(parentGfx, element);
14563
14564 var pathData = pathMap.getScaledPath('GATEWAY_EXCLUSIVE', {
14565 xScaleFactor: 0.4,
14566 yScaleFactor: 0.4,
14567 containerWidth: element.width,
14568 containerHeight: element.height,
14569 position: {
14570 mx: 0.32,
14571 my: 0.3
14572 }
14573 });
14574
14575 if ((getDi(element).isMarkerVisible)) {
14576 drawPath(parentGfx, pathData, {
14577 strokeWidth: 1,
14578 fill: getStrokeColor(element, defaultStrokeColor),
14579 stroke: getStrokeColor(element, defaultStrokeColor)
14580 });
14581 }
14582
14583 return diamond;
14584 },
14585 'bpmn:ComplexGateway': function(parentGfx, element) {
14586 var diamond = renderer('bpmn:Gateway')(parentGfx, element);
14587
14588 var pathData = pathMap.getScaledPath('GATEWAY_COMPLEX', {
14589 xScaleFactor: 0.5,
14590 yScaleFactor:0.5,
14591 containerWidth: element.width,
14592 containerHeight: element.height,
14593 position: {
14594 mx: 0.46,
14595 my: 0.26
14596 }
14597 });
14598
14599 /* complex path */ drawPath(parentGfx, pathData, {
14600 strokeWidth: 1,
14601 fill: getStrokeColor(element, defaultStrokeColor),
14602 stroke: getStrokeColor(element, defaultStrokeColor)
14603 });
14604
14605 return diamond;
14606 },
14607 'bpmn:ParallelGateway': function(parentGfx, element) {
14608 var diamond = renderer('bpmn:Gateway')(parentGfx, element);
14609
14610 var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
14611 xScaleFactor: 0.6,
14612 yScaleFactor:0.6,
14613 containerWidth: element.width,
14614 containerHeight: element.height,
14615 position: {
14616 mx: 0.46,
14617 my: 0.2
14618 }
14619 });
14620
14621 /* parallel path */ drawPath(parentGfx, pathData, {
14622 strokeWidth: 1,
14623 fill: getStrokeColor(element, defaultStrokeColor),
14624 stroke: getStrokeColor(element, defaultStrokeColor)
14625 });
14626
14627 return diamond;
14628 },
14629 'bpmn:EventBasedGateway': function(parentGfx, element) {
14630
14631 var semantic = getSemantic(element);
14632
14633 var diamond = renderer('bpmn:Gateway')(parentGfx, element);
14634
14635 /* outer circle path */ drawCircle(parentGfx, element.width, element.height, element.height * 0.20, {
14636 strokeWidth: 1,
14637 fill: 'none',
14638 stroke: getStrokeColor(element, defaultStrokeColor)
14639 });
14640
14641 var type = semantic.eventGatewayType;
14642 var instantiate = !!semantic.instantiate;
14643
14644 function drawEvent() {
14645
14646 var pathData = pathMap.getScaledPath('GATEWAY_EVENT_BASED', {
14647 xScaleFactor: 0.18,
14648 yScaleFactor: 0.18,
14649 containerWidth: element.width,
14650 containerHeight: element.height,
14651 position: {
14652 mx: 0.36,
14653 my: 0.44
14654 }
14655 });
14656
14657 var attrs = {
14658 strokeWidth: 2,
14659 fill: getFillColor(element, 'none'),
14660 stroke: getStrokeColor(element, defaultStrokeColor)
14661 };
14662
14663 /* event path */ drawPath(parentGfx, pathData, attrs);
14664 }
14665
14666 if (type === 'Parallel') {
14667
14668 var pathData = pathMap.getScaledPath('GATEWAY_PARALLEL', {
14669 xScaleFactor: 0.4,
14670 yScaleFactor:0.4,
14671 containerWidth: element.width,
14672 containerHeight: element.height,
14673 position: {
14674 mx: 0.474,
14675 my: 0.296
14676 }
14677 });
14678
14679 var parallelPath = drawPath(parentGfx, pathData);
14680 attr$1(parallelPath, {
14681 strokeWidth: 1,
14682 fill: 'none'
14683 });
14684 } else if (type === 'Exclusive') {
14685
14686 if (!instantiate) {
14687 var innerCircle = drawCircle(parentGfx, element.width, element.height, element.height * 0.26);
14688 attr$1(innerCircle, {
14689 strokeWidth: 1,
14690 fill: 'none',
14691 stroke: getStrokeColor(element, defaultStrokeColor)
14692 });
14693 }
14694
14695 drawEvent();
14696 }
14697
14698
14699 return diamond;
14700 },
14701 'bpmn:Gateway': function(parentGfx, element) {
14702 var attrs = {
14703 fill: getFillColor(element, defaultFillColor),
14704 fillOpacity: DEFAULT_FILL_OPACITY,
14705 stroke: getStrokeColor(element, defaultStrokeColor)
14706 };
14707
14708 return drawDiamond(parentGfx, element.width, element.height, attrs);
14709 },
14710 'bpmn:SequenceFlow': function(parentGfx, element) {
14711 var pathData = createPathFromConnection(element);
14712
14713 var fill = getFillColor(element, defaultFillColor),
14714 stroke = getStrokeColor(element, defaultStrokeColor);
14715
14716 var attrs = {
14717 strokeLinejoin: 'round',
14718 markerEnd: marker('sequenceflow-end', fill, stroke),
14719 stroke: getStrokeColor(element, defaultStrokeColor)
14720 };
14721
14722 var path = drawPath(parentGfx, pathData, attrs);
14723
14724 var sequenceFlow = getSemantic(element);
14725
14726 var source;
14727
14728 if (element.source) {
14729 source = element.source.businessObject;
14730
14731 // conditional flow marker
14732 if (sequenceFlow.conditionExpression && source.$instanceOf('bpmn:Activity')) {
14733 attr$1(path, {
14734 markerStart: marker('conditional-flow-marker', fill, stroke)
14735 });
14736 }
14737
14738 // default marker
14739 if (source.default && (source.$instanceOf('bpmn:Gateway') || source.$instanceOf('bpmn:Activity')) &&
14740 source.default === sequenceFlow) {
14741 attr$1(path, {
14742 markerStart: marker('conditional-default-flow-marker', fill, stroke)
14743 });
14744 }
14745 }
14746
14747 return path;
14748 },
14749 'bpmn:Association': function(parentGfx, element, attrs) {
14750
14751 var semantic = getSemantic(element);
14752
14753 var fill = getFillColor(element, defaultFillColor),
14754 stroke = getStrokeColor(element, defaultStrokeColor);
14755
14756 attrs = assign({
14757 strokeDasharray: '0.5, 5',
14758 strokeLinecap: 'round',
14759 strokeLinejoin: 'round',
14760 stroke: getStrokeColor(element, defaultStrokeColor)
14761 }, attrs || {});
14762
14763 if (semantic.associationDirection === 'One' ||
14764 semantic.associationDirection === 'Both') {
14765 attrs.markerEnd = marker('association-end', fill, stroke);
14766 }
14767
14768 if (semantic.associationDirection === 'Both') {
14769 attrs.markerStart = marker('association-start', fill, stroke);
14770 }
14771
14772 return drawLine(parentGfx, element.waypoints, attrs);
14773 },
14774 'bpmn:DataInputAssociation': function(parentGfx, element) {
14775 var fill = getFillColor(element, defaultFillColor),
14776 stroke = getStrokeColor(element, defaultStrokeColor);
14777
14778 return renderer('bpmn:Association')(parentGfx, element, {
14779 markerEnd: marker('association-end', fill, stroke)
14780 });
14781 },
14782 'bpmn:DataOutputAssociation': function(parentGfx, element) {
14783 var fill = getFillColor(element, defaultFillColor),
14784 stroke = getStrokeColor(element, defaultStrokeColor);
14785
14786 return renderer('bpmn:Association')(parentGfx, element, {
14787 markerEnd: marker('association-end', fill, stroke)
14788 });
14789 },
14790 'bpmn:MessageFlow': function(parentGfx, element) {
14791
14792 var semantic = getSemantic(element),
14793 di = getDi(element);
14794
14795 var fill = getFillColor(element, defaultFillColor),
14796 stroke = getStrokeColor(element, defaultStrokeColor);
14797
14798 var pathData = createPathFromConnection(element);
14799
14800 var attrs = {
14801 markerEnd: marker('messageflow-end', fill, stroke),
14802 markerStart: marker('messageflow-start', fill, stroke),
14803 strokeDasharray: '10, 12',
14804 strokeLinecap: 'round',
14805 strokeLinejoin: 'round',
14806 strokeWidth: '1.5px',
14807 stroke: getStrokeColor(element, defaultStrokeColor)
14808 };
14809
14810 var path = drawPath(parentGfx, pathData, attrs);
14811
14812 if (semantic.messageRef) {
14813 var midPoint = path.getPointAtLength(path.getTotalLength() / 2);
14814
14815 var markerPathData = pathMap.getScaledPath('MESSAGE_FLOW_MARKER', {
14816 abspos: {
14817 x: midPoint.x,
14818 y: midPoint.y
14819 }
14820 });
14821
14822 var messageAttrs = { strokeWidth: 1 };
14823
14824 if (di.messageVisibleKind === 'initiating') {
14825 messageAttrs.fill = 'white';
14826 messageAttrs.stroke = 'black';
14827 } else {
14828 messageAttrs.fill = '#888';
14829 messageAttrs.stroke = 'white';
14830 }
14831
14832 drawPath(parentGfx, markerPathData, messageAttrs);
14833 }
14834
14835 return path;
14836 },
14837 'bpmn:DataObject': function(parentGfx, element) {
14838 var pathData = pathMap.getScaledPath('DATA_OBJECT_PATH', {
14839 xScaleFactor: 1,
14840 yScaleFactor: 1,
14841 containerWidth: element.width,
14842 containerHeight: element.height,
14843 position: {
14844 mx: 0.474,
14845 my: 0.296
14846 }
14847 });
14848
14849 var elementObject = drawPath(parentGfx, pathData, {
14850 fill: getFillColor(element, defaultFillColor),
14851 fillOpacity: DEFAULT_FILL_OPACITY,
14852 stroke: getStrokeColor(element, defaultStrokeColor)
14853 });
14854
14855 var semantic = getSemantic(element);
14856
14857 if (isCollection(semantic)) {
14858 renderDataItemCollection(parentGfx, element);
14859 }
14860
14861 return elementObject;
14862 },
14863 'bpmn:DataObjectReference': as('bpmn:DataObject'),
14864 'bpmn:DataInput': function(parentGfx, element) {
14865
14866 var arrowPathData = pathMap.getRawPath('DATA_ARROW');
14867
14868 // page
14869 var elementObject = renderer('bpmn:DataObject')(parentGfx, element);
14870
14871 /* input arrow path */ drawPath(parentGfx, arrowPathData, { strokeWidth: 1 });
14872
14873 return elementObject;
14874 },
14875 'bpmn:DataOutput': function(parentGfx, element) {
14876 var arrowPathData = pathMap.getRawPath('DATA_ARROW');
14877
14878 // page
14879 var elementObject = renderer('bpmn:DataObject')(parentGfx, element);
14880
14881 /* output arrow path */ drawPath(parentGfx, arrowPathData, {
14882 strokeWidth: 1,
14883 fill: 'black'
14884 });
14885
14886 return elementObject;
14887 },
14888 'bpmn:DataStoreReference': function(parentGfx, element) {
14889 var DATA_STORE_PATH = pathMap.getScaledPath('DATA_STORE', {
14890 xScaleFactor: 1,
14891 yScaleFactor: 1,
14892 containerWidth: element.width,
14893 containerHeight: element.height,
14894 position: {
14895 mx: 0,
14896 my: 0.133
14897 }
14898 });
14899
14900 var elementStore = drawPath(parentGfx, DATA_STORE_PATH, {
14901 strokeWidth: 2,
14902 fill: getFillColor(element, defaultFillColor),
14903 fillOpacity: DEFAULT_FILL_OPACITY,
14904 stroke: getStrokeColor(element, defaultStrokeColor)
14905 });
14906
14907 return elementStore;
14908 },
14909 'bpmn:BoundaryEvent': function(parentGfx, element) {
14910
14911 var semantic = getSemantic(element),
14912 cancel = semantic.cancelActivity;
14913
14914 var attrs = {
14915 strokeWidth: 1,
14916 fill: getFillColor(element, defaultFillColor),
14917 stroke: getStrokeColor(element, defaultStrokeColor)
14918 };
14919
14920 if (!cancel) {
14921 attrs.strokeDasharray = '6';
14922 attrs.strokeLinecap = 'round';
14923 }
14924
14925 // apply fillOpacity
14926 var outerAttrs = assign({}, attrs, {
14927 fillOpacity: 1
14928 });
14929
14930 // apply no-fill
14931 var innerAttrs = assign({}, attrs, {
14932 fill: 'none'
14933 });
14934
14935 var outer = renderer('bpmn:Event')(parentGfx, element, outerAttrs);
14936
14937 /* inner path */ drawCircle(parentGfx, element.width, element.height, INNER_OUTER_DIST, innerAttrs);
14938
14939 renderEventContent(element, parentGfx);
14940
14941 return outer;
14942 },
14943 'bpmn:Group': function(parentGfx, element) {
14944 var semantic = getSemantic(element),
14945 di = getDi(element);
14946
14947 var group = drawRect(parentGfx, element.width, element.height, TASK_BORDER_RADIUS, {
14948 strokeWidth: 1,
14949 strokeDasharray: '8,3,1,3',
14950 fill: 'none',
14951 pointerEvents: 'none'
14952 });
14953
14954 var categoryValueRef = semantic.categoryValueRef || {};
14955
14956 if (categoryValueRef.value) {
14957 var box = di.label ? di.label.bounds : element;
14958
14959 renderLabel(parentGfx, categoryValueRef.value, {
14960 box: box,
14961 style: {
14962 fill: getStrokeColor(element, defaultStrokeColor)
14963 }
14964 });
14965 }
14966
14967 return group;
14968 },
14969 'label': function(parentGfx, element) {
14970 return renderExternalLabel(parentGfx, element);
14971 },
14972 'bpmn:TextAnnotation': function(parentGfx, element) {
14973 var style = {
14974 'fill': 'none',
14975 'stroke': 'none'
14976 };
14977
14978 var textElement = drawRect(parentGfx, element.width, element.height, 0, 0, style);
14979
14980 var textPathData = pathMap.getScaledPath('TEXT_ANNOTATION', {
14981 xScaleFactor: 1,
14982 yScaleFactor: 1,
14983 containerWidth: element.width,
14984 containerHeight: element.height,
14985 position: {
14986 mx: 0.0,
14987 my: 0.0
14988 }
14989 });
14990
14991 drawPath(parentGfx, textPathData, {
14992 stroke: getStrokeColor(element, defaultStrokeColor)
14993 });
14994
14995 var text = getSemantic(element).text || '';
14996 renderLabel(parentGfx, text, {
14997 box: element,
14998 align: 'left-top',
14999 padding: 5,
15000 style: {
15001 fill: getStrokeColor(element, defaultStrokeColor)
15002 }
15003 });
15004
15005 return textElement;
15006 },
15007 'ParticipantMultiplicityMarker': function(parentGfx, element) {
15008 var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
15009 xScaleFactor: 1,
15010 yScaleFactor: 1,
15011 containerWidth: element.width,
15012 containerHeight: element.height,
15013 position: {
15014 mx: ((element.width / 2) / element.width),
15015 my: (element.height - 15) / element.height
15016 }
15017 });
15018
15019 drawMarker('participant-multiplicity', parentGfx, markerPath, {
15020 strokeWidth: 1,
15021 fill: getFillColor(element, defaultFillColor),
15022 stroke: getStrokeColor(element, defaultStrokeColor)
15023 });
15024 },
15025 'SubProcessMarker': function(parentGfx, element) {
15026 var markerRect = drawRect(parentGfx, 14, 14, 0, {
15027 strokeWidth: 1,
15028 fill: getFillColor(element, defaultFillColor),
15029 stroke: getStrokeColor(element, defaultStrokeColor)
15030 });
15031
15032 // Process marker is placed in the middle of the box
15033 // therefore fixed values can be used here
15034 translate(markerRect, element.width / 2 - 7.5, element.height - 20);
15035
15036 var markerPath = pathMap.getScaledPath('MARKER_SUB_PROCESS', {
15037 xScaleFactor: 1.5,
15038 yScaleFactor: 1.5,
15039 containerWidth: element.width,
15040 containerHeight: element.height,
15041 position: {
15042 mx: (element.width / 2 - 7.5) / element.width,
15043 my: (element.height - 20) / element.height
15044 }
15045 });
15046
15047 drawMarker('sub-process', parentGfx, markerPath, {
15048 fill: getFillColor(element, defaultFillColor),
15049 stroke: getStrokeColor(element, defaultStrokeColor)
15050 });
15051 },
15052 'ParallelMarker': function(parentGfx, element, position) {
15053 var markerPath = pathMap.getScaledPath('MARKER_PARALLEL', {
15054 xScaleFactor: 1,
15055 yScaleFactor: 1,
15056 containerWidth: element.width,
15057 containerHeight: element.height,
15058 position: {
15059 mx: ((element.width / 2 + position.parallel) / element.width),
15060 my: (element.height - 20) / element.height
15061 }
15062 });
15063
15064 drawMarker('parallel', parentGfx, markerPath, {
15065 fill: getFillColor(element, defaultFillColor),
15066 stroke: getStrokeColor(element, defaultStrokeColor)
15067 });
15068 },
15069 'SequentialMarker': function(parentGfx, element, position) {
15070 var markerPath = pathMap.getScaledPath('MARKER_SEQUENTIAL', {
15071 xScaleFactor: 1,
15072 yScaleFactor: 1,
15073 containerWidth: element.width,
15074 containerHeight: element.height,
15075 position: {
15076 mx: ((element.width / 2 + position.seq) / element.width),
15077 my: (element.height - 19) / element.height
15078 }
15079 });
15080
15081 drawMarker('sequential', parentGfx, markerPath, {
15082 fill: getFillColor(element, defaultFillColor),
15083 stroke: getStrokeColor(element, defaultStrokeColor)
15084 });
15085 },
15086 'CompensationMarker': function(parentGfx, element, position) {
15087 var markerMath = pathMap.getScaledPath('MARKER_COMPENSATION', {
15088 xScaleFactor: 1,
15089 yScaleFactor: 1,
15090 containerWidth: element.width,
15091 containerHeight: element.height,
15092 position: {
15093 mx: ((element.width / 2 + position.compensation) / element.width),
15094 my: (element.height - 13) / element.height
15095 }
15096 });
15097
15098 drawMarker('compensation', parentGfx, markerMath, {
15099 strokeWidth: 1,
15100 fill: getFillColor(element, defaultFillColor),
15101 stroke: getStrokeColor(element, defaultStrokeColor)
15102 });
15103 },
15104 'LoopMarker': function(parentGfx, element, position) {
15105 var markerPath = pathMap.getScaledPath('MARKER_LOOP', {
15106 xScaleFactor: 1,
15107 yScaleFactor: 1,
15108 containerWidth: element.width,
15109 containerHeight: element.height,
15110 position: {
15111 mx: ((element.width / 2 + position.loop) / element.width),
15112 my: (element.height - 7) / element.height
15113 }
15114 });
15115
15116 drawMarker('loop', parentGfx, markerPath, {
15117 strokeWidth: 1,
15118 fill: getFillColor(element, defaultFillColor),
15119 stroke: getStrokeColor(element, defaultStrokeColor),
15120 strokeLinecap: 'round',
15121 strokeMiterlimit: 0.5
15122 });
15123 },
15124 'AdhocMarker': function(parentGfx, element, position) {
15125 var markerPath = pathMap.getScaledPath('MARKER_ADHOC', {
15126 xScaleFactor: 1,
15127 yScaleFactor: 1,
15128 containerWidth: element.width,
15129 containerHeight: element.height,
15130 position: {
15131 mx: ((element.width / 2 + position.adhoc) / element.width),
15132 my: (element.height - 15) / element.height
15133 }
15134 });
15135
15136 drawMarker('adhoc', parentGfx, markerPath, {
15137 strokeWidth: 1,
15138 fill: getStrokeColor(element, defaultStrokeColor),
15139 stroke: getStrokeColor(element, defaultStrokeColor)
15140 });
15141 }
15142 };
15143
15144 function attachTaskMarkers(parentGfx, element, taskMarkers) {
15145 var obj = getSemantic(element);
15146
15147 var subprocess = taskMarkers && taskMarkers.indexOf('SubProcessMarker') !== -1;
15148 var position;
15149
15150 if (subprocess) {
15151 position = {
15152 seq: -21,
15153 parallel: -22,
15154 compensation: -42,
15155 loop: -18,
15156 adhoc: 10
15157 };
15158 } else {
15159 position = {
15160 seq: -3,
15161 parallel: -6,
15162 compensation: -27,
15163 loop: 0,
15164 adhoc: 10
15165 };
15166 }
15167
15168 forEach(taskMarkers, function(marker) {
15169 renderer(marker)(parentGfx, element, position);
15170 });
15171
15172 if (obj.isForCompensation) {
15173 renderer('CompensationMarker')(parentGfx, element, position);
15174 }
15175
15176 if (obj.$type === 'bpmn:AdHocSubProcess') {
15177 renderer('AdhocMarker')(parentGfx, element, position);
15178 }
15179
15180 var loopCharacteristics = obj.loopCharacteristics,
15181 isSequential = loopCharacteristics && loopCharacteristics.isSequential;
15182
15183 if (loopCharacteristics) {
15184
15185 if (isSequential === undefined) {
15186 renderer('LoopMarker')(parentGfx, element, position);
15187 }
15188
15189 if (isSequential === false) {
15190 renderer('ParallelMarker')(parentGfx, element, position);
15191 }
15192
15193 if (isSequential === true) {
15194 renderer('SequentialMarker')(parentGfx, element, position);
15195 }
15196 }
15197 }
15198
15199 function renderDataItemCollection(parentGfx, element) {
15200
15201 var yPosition = (element.height - 16) / element.height;
15202
15203 var pathData = pathMap.getScaledPath('DATA_OBJECT_COLLECTION_PATH', {
15204 xScaleFactor: 1,
15205 yScaleFactor: 1,
15206 containerWidth: element.width,
15207 containerHeight: element.height,
15208 position: {
15209 mx: 0.451,
15210 my: yPosition
15211 }
15212 });
15213
15214 /* collection path */ drawPath(parentGfx, pathData, {
15215 strokeWidth: 2
15216 });
15217 }
15218
15219
15220 // extension API, use at your own risk
15221 this._drawPath = drawPath;
15222
15223 }
15224
15225
15226 inherits_browser(BpmnRenderer, BaseRenderer);
15227
15228 BpmnRenderer.$inject = [
15229 'config.bpmnRenderer',
15230 'eventBus',
15231 'styles',
15232 'pathMap',
15233 'canvas',
15234 'textRenderer'
15235 ];
15236
15237
15238 BpmnRenderer.prototype.canRender = function(element) {
15239 return is$1(element, 'bpmn:BaseElement');
15240 };
15241
15242 BpmnRenderer.prototype.drawShape = function(parentGfx, element) {
15243 var type = element.type;
15244 var h = this.handlers[type];
15245
15246 /* jshint -W040 */
15247 return h(parentGfx, element);
15248 };
15249
15250 BpmnRenderer.prototype.drawConnection = function(parentGfx, element) {
15251 var type = element.type;
15252 var h = this.handlers[type];
15253
15254 /* jshint -W040 */
15255 return h(parentGfx, element);
15256 };
15257
15258 BpmnRenderer.prototype.getShapePath = function(element) {
15259
15260 if (is$1(element, 'bpmn:Event')) {
15261 return getCirclePath(element);
15262 }
15263
15264 if (is$1(element, 'bpmn:Activity')) {
15265 return getRoundRectPath(element, TASK_BORDER_RADIUS);
15266 }
15267
15268 if (is$1(element, 'bpmn:Gateway')) {
15269 return getDiamondPath(element);
15270 }
15271
15272 return getRectPath(element);
15273 };
15274
15275 var DEFAULT_BOX_PADDING = 0;
15276
15277 var DEFAULT_LABEL_SIZE = {
15278 width: 150,
15279 height: 50
15280 };
15281
15282
15283 function parseAlign(align) {
15284
15285 var parts = align.split('-');
15286
15287 return {
15288 horizontal: parts[0] || 'center',
15289 vertical: parts[1] || 'top'
15290 };
15291 }
15292
15293 function parsePadding(padding) {
15294
15295 if (isObject(padding)) {
15296 return assign({ top: 0, left: 0, right: 0, bottom: 0 }, padding);
15297 } else {
15298 return {
15299 top: padding,
15300 left: padding,
15301 right: padding,
15302 bottom: padding
15303 };
15304 }
15305 }
15306
15307 function getTextBBox(text, fakeText) {
15308
15309 fakeText.textContent = text;
15310
15311 var textBBox;
15312
15313 try {
15314 var bbox,
15315 emptyLine = text === '';
15316
15317 // add dummy text, when line is empty to
15318 // determine correct height
15319 fakeText.textContent = emptyLine ? 'dummy' : text;
15320
15321 textBBox = fakeText.getBBox();
15322
15323 // take text rendering related horizontal
15324 // padding into account
15325 bbox = {
15326 width: textBBox.width + textBBox.x * 2,
15327 height: textBBox.height
15328 };
15329
15330 if (emptyLine) {
15331 // correct width
15332 bbox.width = 0;
15333 }
15334
15335 return bbox;
15336 } catch (e) {
15337 return { width: 0, height: 0 };
15338 }
15339 }
15340
15341
15342 /**
15343 * Layout the next line and return the layouted element.
15344 *
15345 * Alters the lines passed.
15346 *
15347 * @param {Array<String>} lines
15348 * @return {Object} the line descriptor, an object { width, height, text }
15349 */
15350 function layoutNext(lines, maxWidth, fakeText) {
15351
15352 var originalLine = lines.shift(),
15353 fitLine = originalLine;
15354
15355 var textBBox;
15356
15357 for (;;) {
15358 textBBox = getTextBBox(fitLine, fakeText);
15359
15360 textBBox.width = fitLine ? textBBox.width : 0;
15361
15362 // try to fit
15363 if (fitLine === ' ' || fitLine === '' || textBBox.width < Math.round(maxWidth) || fitLine.length < 2) {
15364 return fit(lines, fitLine, originalLine, textBBox);
15365 }
15366
15367 fitLine = shortenLine(fitLine, textBBox.width, maxWidth);
15368 }
15369 }
15370
15371 function fit(lines, fitLine, originalLine, textBBox) {
15372 if (fitLine.length < originalLine.length) {
15373 var remainder = originalLine.slice(fitLine.length).trim();
15374
15375 lines.unshift(remainder);
15376 }
15377
15378 return {
15379 width: textBBox.width,
15380 height: textBBox.height,
15381 text: fitLine
15382 };
15383 }
15384
15385
15386 /**
15387 * Shortens a line based on spacing and hyphens.
15388 * Returns the shortened result on success.
15389 *
15390 * @param {String} line
15391 * @param {Number} maxLength the maximum characters of the string
15392 * @return {String} the shortened string
15393 */
15394 function semanticShorten(line, maxLength) {
15395 var parts = line.split(/(\s|-)/g),
15396 part,
15397 shortenedParts = [],
15398 length = 0;
15399
15400 // try to shorten via spaces + hyphens
15401 if (parts.length > 1) {
15402 while ((part = parts.shift())) {
15403 if (part.length + length < maxLength) {
15404 shortenedParts.push(part);
15405 length += part.length;
15406 } else {
15407 // remove previous part, too if hyphen does not fit anymore
15408 if (part === '-') {
15409 shortenedParts.pop();
15410 }
15411
15412 break;
15413 }
15414 }
15415 }
15416
15417 return shortenedParts.join('');
15418 }
15419
15420
15421 function shortenLine(line, width, maxWidth) {
15422 var length = Math.max(line.length * (maxWidth / width), 1);
15423
15424 // try to shorten semantically (i.e. based on spaces and hyphens)
15425 var shortenedLine = semanticShorten(line, length);
15426
15427 if (!shortenedLine) {
15428
15429 // force shorten by cutting the long word
15430 shortenedLine = line.slice(0, Math.max(Math.round(length - 1), 1));
15431 }
15432
15433 return shortenedLine;
15434 }
15435
15436
15437 function getHelperSvg() {
15438 var helperSvg = document.getElementById('helper-svg');
15439
15440 if (!helperSvg) {
15441 helperSvg = create('svg');
15442
15443 attr$1(helperSvg, {
15444 id: 'helper-svg',
15445 width: 0,
15446 height: 0,
15447 style: 'visibility: hidden; position: fixed'
15448 });
15449
15450 document.body.appendChild(helperSvg);
15451 }
15452
15453 return helperSvg;
15454 }
15455
15456
15457 /**
15458 * Creates a new label utility
15459 *
15460 * @param {Object} config
15461 * @param {Dimensions} config.size
15462 * @param {Number} config.padding
15463 * @param {Object} config.style
15464 * @param {String} config.align
15465 */
15466 function Text(config) {
15467
15468 this._config = assign({}, {
15469 size: DEFAULT_LABEL_SIZE,
15470 padding: DEFAULT_BOX_PADDING,
15471 style: {},
15472 align: 'center-top'
15473 }, config || {});
15474 }
15475
15476 /**
15477 * Returns the layouted text as an SVG element.
15478 *
15479 * @param {String} text
15480 * @param {Object} options
15481 *
15482 * @return {SVGElement}
15483 */
15484 Text.prototype.createText = function(text, options) {
15485 return this.layoutText(text, options).element;
15486 };
15487
15488 /**
15489 * Returns a labels layouted dimensions.
15490 *
15491 * @param {String} text to layout
15492 * @param {Object} options
15493 *
15494 * @return {Dimensions}
15495 */
15496 Text.prototype.getDimensions = function(text, options) {
15497 return this.layoutText(text, options).dimensions;
15498 };
15499
15500 /**
15501 * Creates and returns a label and its bounding box.
15502 *
15503 * @method Text#createText
15504 *
15505 * @param {String} text the text to render on the label
15506 * @param {Object} options
15507 * @param {String} options.align how to align in the bounding box.
15508 * Any of { 'center-middle', 'center-top' },
15509 * defaults to 'center-top'.
15510 * @param {String} options.style style to be applied to the text
15511 * @param {boolean} options.fitBox indicates if box will be recalculated to
15512 * fit text
15513 *
15514 * @return {Object} { element, dimensions }
15515 */
15516 Text.prototype.layoutText = function(text, options) {
15517 var box = assign({}, this._config.size, options.box),
15518 style = assign({}, this._config.style, options.style),
15519 align = parseAlign(options.align || this._config.align),
15520 padding = parsePadding(options.padding !== undefined ? options.padding : this._config.padding),
15521 fitBox = options.fitBox || false;
15522
15523 var lineHeight = getLineHeight(style);
15524
15525 var lines = text.split(/\r?\n/g),
15526 layouted = [];
15527
15528 var maxWidth = box.width - padding.left - padding.right;
15529
15530 // ensure correct rendering by attaching helper text node to invisible SVG
15531 var helperText = create('text');
15532 attr$1(helperText, { x: 0, y: 0 });
15533 attr$1(helperText, style);
15534
15535 var helperSvg = getHelperSvg();
15536
15537 append(helperSvg, helperText);
15538
15539 while (lines.length) {
15540 layouted.push(layoutNext(lines, maxWidth, helperText));
15541 }
15542
15543 if (align.vertical === 'middle') {
15544 padding.top = padding.bottom = 0;
15545 }
15546
15547 var totalHeight = reduce(layouted, function(sum, line, idx) {
15548 return sum + (lineHeight || line.height);
15549 }, 0) + padding.top + padding.bottom;
15550
15551 var maxLineWidth = reduce(layouted, function(sum, line, idx) {
15552 return line.width > sum ? line.width : sum;
15553 }, 0);
15554
15555 // the y position of the next line
15556 var y = padding.top;
15557
15558 if (align.vertical === 'middle') {
15559 y += (box.height - totalHeight) / 2;
15560 }
15561
15562 // magic number initial offset
15563 y -= (lineHeight || layouted[0].height) / 4;
15564
15565
15566 var textElement = create('text');
15567
15568 attr$1(textElement, style);
15569
15570 // layout each line taking into account that parent
15571 // shape might resize to fit text size
15572 forEach(layouted, function(line) {
15573
15574 var x;
15575
15576 y += (lineHeight || line.height);
15577
15578 switch (align.horizontal) {
15579 case 'left':
15580 x = padding.left;
15581 break;
15582
15583 case 'right':
15584 x = ((fitBox ? maxLineWidth : maxWidth)
15585 - padding.right - line.width);
15586 break;
15587
15588 default:
15589 // aka center
15590 x = Math.max((((fitBox ? maxLineWidth : maxWidth)
15591 - line.width) / 2 + padding.left), 0);
15592 }
15593
15594 var tspan = create('tspan');
15595 attr$1(tspan, { x: x, y: y });
15596
15597 tspan.textContent = line.text;
15598
15599 append(textElement, tspan);
15600 });
15601
15602 remove$1(helperText);
15603
15604 var dimensions = {
15605 width: maxLineWidth,
15606 height: totalHeight
15607 };
15608
15609 return {
15610 dimensions: dimensions,
15611 element: textElement
15612 };
15613 };
15614
15615
15616 function getLineHeight(style) {
15617 if ('fontSize' in style && 'lineHeight' in style) {
15618 return style.lineHeight * parseInt(style.fontSize, 10);
15619 }
15620 }
15621
15622 var DEFAULT_FONT_SIZE = 12;
15623 var LINE_HEIGHT_RATIO = 1.2;
15624
15625 var MIN_TEXT_ANNOTATION_HEIGHT = 30;
15626
15627
15628 function TextRenderer(config) {
15629
15630 var defaultStyle = assign({
15631 fontFamily: 'Arial, sans-serif',
15632 fontSize: DEFAULT_FONT_SIZE,
15633 fontWeight: 'normal',
15634 lineHeight: LINE_HEIGHT_RATIO
15635 }, config && config.defaultStyle || {});
15636
15637 var fontSize = parseInt(defaultStyle.fontSize, 10) - 1;
15638
15639 var externalStyle = assign({}, defaultStyle, {
15640 fontSize: fontSize
15641 }, config && config.externalStyle || {});
15642
15643 var textUtil = new Text({
15644 style: defaultStyle
15645 });
15646
15647 /**
15648 * Get the new bounds of an externally rendered,
15649 * layouted label.
15650 *
15651 * @param {Bounds} bounds
15652 * @param {String} text
15653 *
15654 * @return {Bounds}
15655 */
15656 this.getExternalLabelBounds = function(bounds, text) {
15657
15658 var layoutedDimensions = textUtil.getDimensions(text, {
15659 box: {
15660 width: 90,
15661 height: 30,
15662 x: bounds.width / 2 + bounds.x,
15663 y: bounds.height / 2 + bounds.y
15664 },
15665 style: externalStyle
15666 });
15667
15668 // resize label shape to fit label text
15669 return {
15670 x: Math.round(bounds.x + bounds.width / 2 - layoutedDimensions.width / 2),
15671 y: Math.round(bounds.y),
15672 width: Math.ceil(layoutedDimensions.width),
15673 height: Math.ceil(layoutedDimensions.height)
15674 };
15675
15676 };
15677
15678 /**
15679 * Get the new bounds of text annotation.
15680 *
15681 * @param {Bounds} bounds
15682 * @param {String} text
15683 *
15684 * @return {Bounds}
15685 */
15686 this.getTextAnnotationBounds = function(bounds, text) {
15687
15688 var layoutedDimensions = textUtil.getDimensions(text, {
15689 box: bounds,
15690 style: defaultStyle,
15691 align: 'left-top',
15692 padding: 5
15693 });
15694
15695 return {
15696 x: bounds.x,
15697 y: bounds.y,
15698 width: bounds.width,
15699 height: Math.max(MIN_TEXT_ANNOTATION_HEIGHT, Math.round(layoutedDimensions.height))
15700 };
15701 };
15702
15703 /**
15704 * Create a layouted text element.
15705 *
15706 * @param {String} text
15707 * @param {Object} [options]
15708 *
15709 * @return {SVGElement} rendered text
15710 */
15711 this.createText = function(text, options) {
15712 return textUtil.createText(text, options || {});
15713 };
15714
15715 /**
15716 * Get default text style.
15717 */
15718 this.getDefaultStyle = function() {
15719 return defaultStyle;
15720 };
15721
15722 /**
15723 * Get the external text style.
15724 */
15725 this.getExternalStyle = function() {
15726 return externalStyle;
15727 };
15728
15729 }
15730
15731 TextRenderer.$inject = [
15732 'config.textRenderer'
15733 ];
15734
15735 /**
15736 * Map containing SVG paths needed by BpmnRenderer.
15737 */
15738
15739 function PathMap() {
15740
15741 /**
15742 * Contains a map of path elements
15743 *
15744 * <h1>Path definition</h1>
15745 * A parameterized path is defined like this:
15746 * <pre>
15747 * 'GATEWAY_PARALLEL': {
15748 * d: 'm {mx},{my} {e.x0},0 0,{e.x1} {e.x1},0 0,{e.y0} -{e.x1},0 0,{e.y1} ' +
15749 '-{e.x0},0 0,-{e.y1} -{e.x1},0 0,-{e.y0} {e.x1},0 z',
15750 * height: 17.5,
15751 * width: 17.5,
15752 * heightElements: [2.5, 7.5],
15753 * widthElements: [2.5, 7.5]
15754 * }
15755 * </pre>
15756 * <p>It's important to specify a correct <b>height and width</b> for the path as the scaling
15757 * is based on the ratio between the specified height and width in this object and the
15758 * height and width that is set as scale target (Note x,y coordinates will be scaled with
15759 * individual ratios).</p>
15760 * <p>The '<b>heightElements</b>' and '<b>widthElements</b>' array must contain the values that will be scaled.
15761 * The scaling is based on the computed ratios.
15762 * Coordinates on the y axis should be in the <b>heightElement</b>'s array, they will be scaled using
15763 * the computed ratio coefficient.
15764 * In the parameterized path the scaled values can be accessed through the 'e' object in {} brackets.
15765 * <ul>
15766 * <li>The values for the y axis can be accessed in the path string using {e.y0}, {e.y1}, ....</li>
15767 * <li>The values for the x axis can be accessed in the path string using {e.x0}, {e.x1}, ....</li>
15768 * </ul>
15769 * The numbers x0, x1 respectively y0, y1, ... map to the corresponding array index.
15770 * </p>
15771 */
15772 this.pathMap = {
15773 'EVENT_MESSAGE': {
15774 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}',
15775 height: 36,
15776 width: 36,
15777 heightElements: [6, 14],
15778 widthElements: [10.5, 21]
15779 },
15780 'EVENT_SIGNAL': {
15781 d: 'M {mx},{my} l {e.x0},{e.y0} l -{e.x1},0 Z',
15782 height: 36,
15783 width: 36,
15784 heightElements: [18],
15785 widthElements: [10, 20]
15786 },
15787 'EVENT_ESCALATION': {
15788 d: 'M {mx},{my} l {e.x0},{e.y0} l -{e.x0},-{e.y1} l -{e.x0},{e.y1} Z',
15789 height: 36,
15790 width: 36,
15791 heightElements: [20, 7],
15792 widthElements: [8]
15793 },
15794 'EVENT_CONDITIONAL': {
15795 d: 'M {e.x0},{e.y0} l {e.x1},0 l 0,{e.y2} l -{e.x1},0 Z ' +
15796 'M {e.x2},{e.y3} l {e.x0},0 ' +
15797 'M {e.x2},{e.y4} l {e.x0},0 ' +
15798 'M {e.x2},{e.y5} l {e.x0},0 ' +
15799 'M {e.x2},{e.y6} l {e.x0},0 ' +
15800 'M {e.x2},{e.y7} l {e.x0},0 ' +
15801 'M {e.x2},{e.y8} l {e.x0},0 ',
15802 height: 36,
15803 width: 36,
15804 heightElements: [8.5, 14.5, 18, 11.5, 14.5, 17.5, 20.5, 23.5, 26.5],
15805 widthElements: [10.5, 14.5, 12.5]
15806 },
15807 'EVENT_LINK': {
15808 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',
15809 height: 36,
15810 width: 36,
15811 heightElements: [4.4375, 6.75, 7.8125],
15812 widthElements: [9.84375, 13.5]
15813 },
15814 'EVENT_ERROR': {
15815 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',
15816 height: 36,
15817 width: 36,
15818 heightElements: [0.023, 8.737, 8.151, 16.564, 10.591, 8.714],
15819 widthElements: [0.085, 6.672, 6.97, 4.273, 5.337, 6.636]
15820 },
15821 'EVENT_CANCEL_45': {
15822 d: 'm {mx},{my} -{e.x1},0 0,{e.x0} {e.x1},0 0,{e.y1} {e.x0},0 ' +
15823 '0,-{e.y1} {e.x1},0 0,-{e.y0} -{e.x1},0 0,-{e.y1} -{e.x0},0 z',
15824 height: 36,
15825 width: 36,
15826 heightElements: [4.75, 8.5],
15827 widthElements: [4.75, 8.5]
15828 },
15829 'EVENT_COMPENSATION': {
15830 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',
15831 height: 36,
15832 width: 36,
15833 heightElements: [6.5, 13, 0.4, 6.1],
15834 widthElements: [9, 9.3, 8.7]
15835 },
15836 'EVENT_TIMER_WH': {
15837 d: 'M {mx},{my} l {e.x0},-{e.y0} m -{e.x0},{e.y0} l {e.x1},{e.y1} ',
15838 height: 36,
15839 width: 36,
15840 heightElements: [10, 2],
15841 widthElements: [3, 7]
15842 },
15843 'EVENT_TIMER_LINE': {
15844 d: 'M {mx},{my} ' +
15845 'm {e.x0},{e.y0} l -{e.x1},{e.y1} ',
15846 height: 36,
15847 width: 36,
15848 heightElements: [10, 3],
15849 widthElements: [0, 0]
15850 },
15851 'EVENT_MULTIPLE': {
15852 d:'m {mx},{my} {e.x1},-{e.y0} {e.x1},{e.y0} -{e.x0},{e.y1} -{e.x2},0 z',
15853 height: 36,
15854 width: 36,
15855 heightElements: [6.28099, 12.56199],
15856 widthElements: [3.1405, 9.42149, 12.56198]
15857 },
15858 'EVENT_PARALLEL_MULTIPLE': {
15859 d:'m {mx},{my} {e.x0},0 0,{e.y1} {e.x1},0 0,{e.y0} -{e.x1},0 0,{e.y1} ' +
15860 '-{e.x0},0 0,-{e.y1} -{e.x1},0 0,-{e.y0} {e.x1},0 z',
15861 height: 36,
15862 width: 36,
15863 heightElements: [2.56228, 7.68683],
15864 widthElements: [2.56228, 7.68683]
15865 },
15866 'GATEWAY_EXCLUSIVE': {
15867 d:'m {mx},{my} {e.x0},{e.y0} {e.x1},{e.y0} {e.x2},0 {e.x4},{e.y2} ' +
15868 '{e.x4},{e.y1} {e.x2},0 {e.x1},{e.y3} {e.x0},{e.y3} ' +
15869 '{e.x3},0 {e.x5},{e.y1} {e.x5},{e.y2} {e.x3},0 z',
15870 height: 17.5,
15871 width: 17.5,
15872 heightElements: [8.5, 6.5312, -6.5312, -8.5],
15873 widthElements: [6.5, -6.5, 3, -3, 5, -5]
15874 },
15875 'GATEWAY_PARALLEL': {
15876 d:'m {mx},{my} 0,{e.y1} -{e.x1},0 0,{e.y0} {e.x1},0 0,{e.y1} {e.x0},0 ' +
15877 '0,-{e.y1} {e.x1},0 0,-{e.y0} -{e.x1},0 0,-{e.y1} -{e.x0},0 z',
15878 height: 30,
15879 width: 30,
15880 heightElements: [5, 12.5],
15881 widthElements: [5, 12.5]
15882 },
15883 'GATEWAY_EVENT_BASED': {
15884 d:'m {mx},{my} {e.x0},{e.y0} {e.x0},{e.y1} {e.x1},{e.y2} {e.x2},0 z',
15885 height: 11,
15886 width: 11,
15887 heightElements: [-6, 6, 12, -12],
15888 widthElements: [9, -3, -12]
15889 },
15890 'GATEWAY_COMPLEX': {
15891 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} ' +
15892 '{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} ' +
15893 '{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} ' +
15894 '-{e.x0},{e.y1} 0,-{e.y0} -{e.x3},0 z',
15895 height: 17.125,
15896 width: 17.125,
15897 heightElements: [4.875, 3.4375, 2.125, 3],
15898 widthElements: [3.4375, 2.125, 4.875, 3]
15899 },
15900 'DATA_OBJECT_PATH': {
15901 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',
15902 height: 61,
15903 width: 51,
15904 heightElements: [10, 50, 60],
15905 widthElements: [10, 40, 50, 60]
15906 },
15907 'DATA_OBJECT_COLLECTION_PATH': {
15908 d:'m {mx}, {my} ' +
15909 'm 0 15 l 0 -15 ' +
15910 'm 4 15 l 0 -15 ' +
15911 'm 4 15 l 0 -15 ',
15912 height: 61,
15913 width: 51,
15914 heightElements: [12],
15915 widthElements: [1, 6, 12, 15]
15916 },
15917 'DATA_ARROW': {
15918 d:'m 5,9 9,0 0,-3 5,5 -5,5 0,-3 -9,0 z',
15919 height: 61,
15920 width: 51,
15921 heightElements: [],
15922 widthElements: []
15923 },
15924 'DATA_STORE': {
15925 d:'m {mx},{my} ' +
15926 'l 0,{e.y2} ' +
15927 'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0 ' +
15928 'l 0,-{e.y2} ' +
15929 'c -{e.x0},-{e.y1} -{e.x1},-{e.y1} -{e.x2},0' +
15930 'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0 ' +
15931 'm -{e.x2},{e.y0}' +
15932 'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0' +
15933 'm -{e.x2},{e.y0}' +
15934 'c {e.x0},{e.y1} {e.x1},{e.y1} {e.x2},0',
15935 height: 61,
15936 width: 61,
15937 heightElements: [7, 10, 45],
15938 widthElements: [2, 58, 60]
15939 },
15940 'TEXT_ANNOTATION': {
15941 d: 'm {mx}, {my} m 10,0 l -10,0 l 0,{e.y0} l 10,0',
15942 height: 30,
15943 width: 10,
15944 heightElements: [30],
15945 widthElements: [10]
15946 },
15947 'MARKER_SUB_PROCESS': {
15948 d: 'm{mx},{my} m 7,2 l 0,10 m -5,-5 l 10,0',
15949 height: 10,
15950 width: 10,
15951 heightElements: [],
15952 widthElements: []
15953 },
15954 'MARKER_PARALLEL': {
15955 d: 'm{mx},{my} m 3,2 l 0,10 m 3,-10 l 0,10 m 3,-10 l 0,10',
15956 height: 10,
15957 width: 10,
15958 heightElements: [],
15959 widthElements: []
15960 },
15961 'MARKER_SEQUENTIAL': {
15962 d: 'm{mx},{my} m 0,3 l 10,0 m -10,3 l 10,0 m -10,3 l 10,0',
15963 height: 10,
15964 width: 10,
15965 heightElements: [],
15966 widthElements: []
15967 },
15968 'MARKER_COMPENSATION': {
15969 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',
15970 height: 10,
15971 width: 21,
15972 heightElements: [],
15973 widthElements: []
15974 },
15975 'MARKER_LOOP': {
15976 d: 'm {mx},{my} c 3.526979,0 6.386161,-2.829858 6.386161,-6.320661 0,-3.490806 -2.859182,-6.320661 ' +
15977 '-6.386161,-6.320661 -3.526978,0 -6.38616,2.829855 -6.38616,6.320661 0,1.745402 ' +
15978 '0.714797,3.325567 1.870463,4.469381 0.577834,0.571908 1.265885,1.034728 2.029916,1.35457 ' +
15979 'l -0.718163,-3.909793 m 0.718163,3.909793 -3.885211,0.802902',
15980 height: 13.9,
15981 width: 13.7,
15982 heightElements: [],
15983 widthElements: []
15984 },
15985 'MARKER_ADHOC': {
15986 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 ' +
15987 '3.85579,1.15803 5.76082,1.79107 1.06385,0.34139996 2.24454,0.1438 3.18759,-0.43767 0.61743,-0.33642 ' +
15988 '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 ' +
15989 '-3.6918,1.66181996 -1.24459,0.0927 -2.46671,-0.2491 -3.59505,-0.74812 -1.35789,-0.55965 ' +
15990 '-2.75133,-1.33436996 -4.27027,-1.18121996 -1.37741,0.14601 -2.41842,1.13685996 -3.44288,1.96782996 z',
15991 height: 4,
15992 width: 15,
15993 heightElements: [],
15994 widthElements: []
15995 },
15996 'TASK_TYPE_SEND': {
15997 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}',
15998 height: 14,
15999 width: 21,
16000 heightElements: [6, 14],
16001 widthElements: [10.5, 21]
16002 },
16003 'TASK_TYPE_SCRIPT': {
16004 d: 'm {mx},{my} c 9.966553,-6.27276 -8.000926,-7.91932 2.968968,-14.938 l -8.802728,0 ' +
16005 'c -10.969894,7.01868 6.997585,8.66524 -2.968967,14.938 z ' +
16006 'm -7,-12 l 5,0 ' +
16007 'm -4.5,3 l 4.5,0 ' +
16008 'm -3,3 l 5,0' +
16009 'm -4,3 l 5,0',
16010 height: 15,
16011 width: 12.6,
16012 heightElements: [6, 14],
16013 widthElements: [10.5, 21]
16014 },
16015 'TASK_TYPE_USER_1': {
16016 d: 'm {mx},{my} c 0.909,-0.845 1.594,-2.049 1.594,-3.385 0,-2.554 -1.805,-4.62199999 ' +
16017 '-4.357,-4.62199999 -2.55199998,0 -4.28799998,2.06799999 -4.28799998,4.62199999 0,1.348 ' +
16018 '0.974,2.562 1.89599998,3.405 -0.52899998,0.187 -5.669,2.097 -5.794,4.7560005 v 6.718 ' +
16019 'h 17 v -6.718 c 0,-2.2980005 -5.5279996,-4.5950005 -6.0509996,-4.7760005 z' +
16020 'm -8,6 l 0,5.5 m 11,0 l 0,-5'
16021 },
16022 'TASK_TYPE_USER_2': {
16023 d: 'm {mx},{my} m 2.162,1.009 c 0,2.4470005 -2.158,4.4310005 -4.821,4.4310005 ' +
16024 '-2.66499998,0 -4.822,-1.981 -4.822,-4.4310005 '
16025 },
16026 'TASK_TYPE_USER_3': {
16027 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 ' +
16028 '4.124,0.965 -0.098,-0.57 -0.117,-3.79099999 -4.191,-4.13599999 -3.57499998,0.001 ' +
16029 '-4.20799998,3.36699999 -4.20699998,4.34799999 z'
16030 },
16031 'TASK_TYPE_MANUAL': {
16032 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 ' +
16033 '-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 ' +
16034 '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 ' +
16035 '-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 ' +
16036 '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 ' +
16037 '-10.86,-0.003 -11.0829995,-0.003 -0.022,-0.047 -0.045,-0.094 -0.069,-0.139 0.3939995,-0.319 ' +
16038 '2.0409995,-1.626 2.4149995,-2.017 0.469,-0.4870005 0.519,-1.1650005 0.162,-1.6040005 -0.414,-0.511 ' +
16039 '-0.973,-0.5 -1.48,-0.236 -1.4609995,0.764 -6.5999995,3.6430005 -7.7329995,4.2710005 -0.9,0.499 ' +
16040 '-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 ' +
16041 '-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 ' +
16042 '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 ' +
16043 '-5.824,-0.004 -6.04,-0.004 10e-4,-0.084 0.003,-0.586 10e-4,-0.67 z'
16044 },
16045 'TASK_TYPE_INSTANTIATING_SEND': {
16046 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'
16047 },
16048 'TASK_TYPE_SERVICE': {
16049 d: 'm {mx},{my} v -1.71335 c 0.352326,-0.0705 0.703932,-0.17838 1.047628,-0.32133 ' +
16050 '0.344416,-0.14465 0.665822,-0.32133 0.966377,-0.52145 l 1.19431,1.18005 1.567487,-1.57688 ' +
16051 '-1.195028,-1.18014 c 0.403376,-0.61394 0.683079,-1.29908 0.825447,-2.01824 l 1.622133,-0.01 ' +
16052 'v -2.2196 l -1.636514,0.01 c -0.07333,-0.35153 -0.178319,-0.70024 -0.323564,-1.04372 ' +
16053 '-0.145244,-0.34406 -0.321407,-0.6644 -0.522735,-0.96217 l 1.131035,-1.13631 -1.583305,-1.56293 ' +
16054 '-1.129598,1.13589 c -0.614052,-0.40108 -1.302883,-0.68093 -2.022633,-0.82247 l 0.0093,-1.61852 ' +
16055 '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 ' +
16056 '-0.665102,0.32092 -0.9635006,0.52046 l -1.1698628,-1.15823 -1.5667691,1.5792 1.1684265,1.15669 ' +
16057 'c -0.4026573,0.61283 -0.68308,1.29797 -0.8247287,2.01713 l -1.6588041,0.003 v 2.22174 ' +
16058 'l 1.6724648,-0.006 c 0.073327,0.35077 0.1797598,0.70243 0.3242851,1.04472 0.1452428,0.34448 ' +
16059 '0.3214064,0.6644 0.5227339,0.96066 l -1.1993431,1.19723 1.5840256,1.56011 1.1964668,-1.19348 ' +
16060 'c 0.6140517,0.40346 1.3028827,0.68232 2.0233517,0.82331 l 7.19e-4,1.69892 h 2.226848 z ' +
16061 'm 0.221462,-3.9957 c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' +
16062 '0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' +
16063 '0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z'
16064 },
16065 'TASK_TYPE_SERVICE_FILL': {
16066 d: 'm {mx},{my} c -1.788948,0.7502 -3.8576,-0.0928 -4.6097055,-1.87438 -0.7521065,-1.78321 ' +
16067 '0.090598,-3.84627 1.8802645,-4.59604 1.78823,-0.74936 3.856881,0.0929 4.608987,1.87437 ' +
16068 '0.752106,1.78165 -0.0906,3.84612 -1.879546,4.59605 z'
16069 },
16070 'TASK_TYPE_BUSINESS_RULE_HEADER': {
16071 d: 'm {mx},{my} 0,4 20,0 0,-4 z'
16072 },
16073 'TASK_TYPE_BUSINESS_RULE_MAIN': {
16074 d: 'm {mx},{my} 0,12 20,0 0,-12 z' +
16075 'm 0,8 l 20,0 ' +
16076 'm -13,-4 l 0,8'
16077 },
16078 'MESSAGE_FLOW_MARKER': {
16079 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'
16080 }
16081 };
16082
16083 this.getRawPath = function getRawPath(pathId) {
16084 return this.pathMap[pathId].d;
16085 };
16086
16087 /**
16088 * Scales the path to the given height and width.
16089 * <h1>Use case</h1>
16090 * <p>Use case is to scale the content of elements (event, gateways) based
16091 * on the element bounding box's size.
16092 * </p>
16093 * <h1>Why not transform</h1>
16094 * <p>Scaling a path with transform() will also scale the stroke and IE does not support
16095 * the option 'non-scaling-stroke' to prevent this.
16096 * Also there are use cases where only some parts of a path should be
16097 * scaled.</p>
16098 *
16099 * @param {String} pathId The ID of the path.
16100 * @param {Object} param <p>
16101 * Example param object scales the path to 60% size of the container (data.width, data.height).
16102 * <pre>
16103 * {
16104 * xScaleFactor: 0.6,
16105 * yScaleFactor:0.6,
16106 * containerWidth: data.width,
16107 * containerHeight: data.height,
16108 * position: {
16109 * mx: 0.46,
16110 * my: 0.2,
16111 * }
16112 * }
16113 * </pre>
16114 * <ul>
16115 * <li>targetpathwidth = xScaleFactor * containerWidth</li>
16116 * <li>targetpathheight = yScaleFactor * containerHeight</li>
16117 * <li>Position is used to set the starting coordinate of the path. M is computed:
16118 * <ul>
16119 * <li>position.x * containerWidth</li>
16120 * <li>position.y * containerHeight</li>
16121 * </ul>
16122 * Center of the container <pre> position: {
16123 * mx: 0.5,
16124 * my: 0.5,
16125 * }</pre>
16126 * Upper left corner of the container
16127 * <pre> position: {
16128 * mx: 0.0,
16129 * my: 0.0,
16130 * }</pre>
16131 * </li>
16132 * </ul>
16133 * </p>
16134 *
16135 */
16136 this.getScaledPath = function getScaledPath(pathId, param) {
16137 var rawPath = this.pathMap[pathId];
16138
16139 // positioning
16140 // compute the start point of the path
16141 var mx, my;
16142
16143 if (param.abspos) {
16144 mx = param.abspos.x;
16145 my = param.abspos.y;
16146 } else {
16147 mx = param.containerWidth * param.position.mx;
16148 my = param.containerHeight * param.position.my;
16149 }
16150
16151 var coordinates = {}; // map for the scaled coordinates
16152 if (param.position) {
16153
16154 // path
16155 var heightRatio = (param.containerHeight / rawPath.height) * param.yScaleFactor;
16156 var widthRatio = (param.containerWidth / rawPath.width) * param.xScaleFactor;
16157
16158
16159 // Apply height ratio
16160 for (var heightIndex = 0; heightIndex < rawPath.heightElements.length; heightIndex++) {
16161 coordinates['y' + heightIndex] = rawPath.heightElements[heightIndex] * heightRatio;
16162 }
16163
16164 // Apply width ratio
16165 for (var widthIndex = 0; widthIndex < rawPath.widthElements.length; widthIndex++) {
16166 coordinates['x' + widthIndex] = rawPath.widthElements[widthIndex] * widthRatio;
16167 }
16168 }
16169
16170 // Apply value to raw path
16171 var path = format(
16172 rawPath.d, {
16173 mx: mx,
16174 my: my,
16175 e: coordinates
16176 }
16177 );
16178 return path;
16179 };
16180 }
16181
16182 // helpers //////////////////////
16183
16184 // copied from https://github.com/adobe-webplatform/Snap.svg/blob/master/src/svg.js
16185 var tokenRegex = /\{([^}]+)\}/g,
16186 objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g; // matches .xxxxx or ["xxxxx"] to run over object properties
16187
16188 function replacer(all, key, obj) {
16189 var res = obj;
16190 key.replace(objNotationRegex, function(all, name, quote, quotedName, isFunc) {
16191 name = name || quotedName;
16192 if (res) {
16193 if (name in res) {
16194 res = res[name];
16195 }
16196 typeof res == 'function' && isFunc && (res = res());
16197 }
16198 });
16199 res = (res == null || res == obj ? all : res) + '';
16200
16201 return res;
16202 }
16203
16204 function format(str, obj) {
16205 return String(str).replace(tokenRegex, function(all, key) {
16206 return replacer(all, key, obj);
16207 });
16208 }
16209
16210 var DrawModule$1 = {
16211 __init__: [ 'bpmnRenderer' ],
16212 bpmnRenderer: [ 'type', BpmnRenderer ],
16213 textRenderer: [ 'type', TextRenderer ],
16214 pathMap: [ 'type', PathMap ]
16215 };
16216
16217 /**
16218 * A simple translation stub to be used for multi-language support
16219 * in diagrams. Can be easily replaced with a more sophisticated
16220 * solution.
16221 *
16222 * @example
16223 *
16224 * // use it inside any diagram component by injecting `translate`.
16225 *
16226 * function MyService(translate) {
16227 * alert(translate('HELLO {you}', { you: 'You!' }));
16228 * }
16229 *
16230 * @param {String} template to interpolate
16231 * @param {Object} [replacements] a map with substitutes
16232 *
16233 * @return {String} the translated string
16234 */
16235 function translate$1(template, replacements) {
16236
16237 replacements = replacements || {};
16238
16239 return template.replace(/{([^}]+)}/g, function(_, key) {
16240 return replacements[key] || '{' + key + '}';
16241 });
16242 }
16243
16244 var translate$2 = {
16245 translate: [ 'value', translate$1 ]
16246 };
16247
16248 var DEFAULT_LABEL_SIZE$1 = {
16249 width: 90,
16250 height: 20
16251 };
16252
16253 var FLOW_LABEL_INDENT = 15;
16254
16255
16256 /**
16257 * Returns true if the given semantic has an external label
16258 *
16259 * @param {BpmnElement} semantic
16260 * @return {Boolean} true if has label
16261 */
16262 function isLabelExternal(semantic) {
16263 return is$1(semantic, 'bpmn:Event') ||
16264 is$1(semantic, 'bpmn:Gateway') ||
16265 is$1(semantic, 'bpmn:DataStoreReference') ||
16266 is$1(semantic, 'bpmn:DataObjectReference') ||
16267 is$1(semantic, 'bpmn:SequenceFlow') ||
16268 is$1(semantic, 'bpmn:MessageFlow');
16269 }
16270
16271 /**
16272 * Get the position for sequence flow labels
16273 *
16274 * @param {Array<Point>} waypoints
16275 * @return {Point} the label position
16276 */
16277 function getFlowLabelPosition(waypoints) {
16278
16279 // get the waypoints mid
16280 var mid = waypoints.length / 2 - 1;
16281
16282 var first = waypoints[Math.floor(mid)];
16283 var second = waypoints[Math.ceil(mid + 0.01)];
16284
16285 // get position
16286 var position = getWaypointsMid(waypoints);
16287
16288 // calculate angle
16289 var angle = Math.atan((second.y - first.y) / (second.x - first.x));
16290
16291 var x = position.x,
16292 y = position.y;
16293
16294 if (Math.abs(angle) < Math.PI / 2) {
16295 y -= FLOW_LABEL_INDENT;
16296 } else {
16297 x += FLOW_LABEL_INDENT;
16298 }
16299
16300 return { x: x, y: y };
16301 }
16302
16303
16304 /**
16305 * Get the middle of a number of waypoints
16306 *
16307 * @param {Array<Point>} waypoints
16308 * @return {Point} the mid point
16309 */
16310 function getWaypointsMid(waypoints) {
16311
16312 var mid = waypoints.length / 2 - 1;
16313
16314 var first = waypoints[Math.floor(mid)];
16315 var second = waypoints[Math.ceil(mid + 0.01)];
16316
16317 return {
16318 x: first.x + (second.x - first.x) / 2,
16319 y: first.y + (second.y - first.y) / 2
16320 };
16321 }
16322
16323
16324 function getExternalLabelMid(element) {
16325
16326 if (element.waypoints) {
16327 return getFlowLabelPosition(element.waypoints);
16328 } else {
16329 return {
16330 x: element.x + element.width / 2,
16331 y: element.y + element.height + DEFAULT_LABEL_SIZE$1.height / 2
16332 };
16333 }
16334 }
16335
16336
16337 /**
16338 * Returns the bounds of an elements label, parsed from the elements DI or
16339 * generated from its bounds.
16340 *
16341 * @param {BpmnElement} semantic
16342 * @param {djs.model.Base} element
16343 */
16344 function getExternalLabelBounds(semantic, element) {
16345
16346 var mid,
16347 size$$1,
16348 bounds,
16349 di = semantic.di,
16350 label = di.label;
16351
16352 if (label && label.bounds) {
16353 bounds = label.bounds;
16354
16355 size$$1 = {
16356 width: Math.max(DEFAULT_LABEL_SIZE$1.width, bounds.width),
16357 height: bounds.height
16358 };
16359
16360 mid = {
16361 x: bounds.x + bounds.width / 2,
16362 y: bounds.y + bounds.height / 2
16363 };
16364 } else {
16365
16366 mid = getExternalLabelMid(element);
16367
16368 size$$1 = DEFAULT_LABEL_SIZE$1;
16369 }
16370
16371 return assign({
16372 x: mid.x - size$$1.width / 2,
16373 y: mid.y - size$$1.height / 2
16374 }, size$$1);
16375 }
16376
16377 /**
16378 * Computes the distance between two points
16379 *
16380 * @param {Point} p
16381 * @param {Point} q
16382 *
16383 * @return {Number} distance
16384 */
16385
16386 /**
16387 * This file contains portions that got extraced from Snap.svg (licensed Apache-2.0).
16388 *
16389 * @see https://github.com/adobe-webplatform/Snap.svg/blob/master/src/path.js
16390 */
16391
16392 /* eslint no-fallthrough: "off" */
16393
16394 var math = Math,
16395 PI = math.PI;
16396
16397 function roundPoint(point) {
16398
16399 return {
16400 x: Math.round(point.x),
16401 y: Math.round(point.y)
16402 };
16403 }
16404
16405
16406 /**
16407 * Get the mid of the given bounds or point.
16408 *
16409 * @param {Bounds|Point} bounds
16410 *
16411 * @return {Point}
16412 */
16413 function getMid(bounds) {
16414 return roundPoint({
16415 x: bounds.x + (bounds.width || 0) / 2,
16416 y: bounds.y + (bounds.height || 0) / 2
16417 });
16418 }
16419
16420 function elementData(semantic, attrs) {
16421 return assign({
16422 id: semantic.id,
16423 type: semantic.$type,
16424 businessObject: semantic
16425 }, attrs);
16426 }
16427
16428 function collectWaypoints(waypoints) {
16429 return map(waypoints, function(p) {
16430 return { x: p.x, y: p.y };
16431 });
16432 }
16433
16434 function notYetDrawn(translate, semantic, refSemantic, property) {
16435 return new Error(translate('element {element} referenced by {referenced}#{property} not yet drawn', {
16436 element: elementToString(refSemantic),
16437 referenced: elementToString(semantic),
16438 property: property
16439 }));
16440 }
16441
16442
16443 /**
16444 * An importer that adds bpmn elements to the canvas
16445 *
16446 * @param {EventBus} eventBus
16447 * @param {Canvas} canvas
16448 * @param {ElementFactory} elementFactory
16449 * @param {ElementRegistry} elementRegistry
16450 * @param {Function} translate
16451 * @param {TextRenderer} textRenderer
16452 */
16453 function BpmnImporter(
16454 eventBus, canvas, elementFactory,
16455 elementRegistry, translate, textRenderer) {
16456
16457 this._eventBus = eventBus;
16458 this._canvas = canvas;
16459 this._elementFactory = elementFactory;
16460 this._elementRegistry = elementRegistry;
16461 this._translate = translate;
16462 this._textRenderer = textRenderer;
16463 }
16464
16465 BpmnImporter.$inject = [
16466 'eventBus',
16467 'canvas',
16468 'elementFactory',
16469 'elementRegistry',
16470 'translate',
16471 'textRenderer'
16472 ];
16473
16474
16475 /**
16476 * Add bpmn element (semantic) to the canvas onto the
16477 * specified parent shape.
16478 */
16479 BpmnImporter.prototype.add = function(semantic, parentElement) {
16480
16481 var di = semantic.di,
16482 element,
16483 translate = this._translate,
16484 hidden;
16485
16486 var parentIndex;
16487
16488 // ROOT ELEMENT
16489 // handle the special case that we deal with a
16490 // invisible root element (process or collaboration)
16491 if (is$1(di, 'bpmndi:BPMNPlane')) {
16492
16493 // add a virtual element (not being drawn)
16494 element = this._elementFactory.createRoot(elementData(semantic));
16495
16496 this._canvas.setRootElement(element);
16497 }
16498
16499 // SHAPE
16500 else if (is$1(di, 'bpmndi:BPMNShape')) {
16501
16502 var collapsed = !isExpanded(semantic);
16503 hidden = parentElement && (parentElement.hidden || parentElement.collapsed);
16504
16505 var bounds = semantic.di.bounds;
16506
16507 element = this._elementFactory.createShape(elementData(semantic, {
16508 collapsed: collapsed,
16509 hidden: hidden,
16510 x: Math.round(bounds.x),
16511 y: Math.round(bounds.y),
16512 width: Math.round(bounds.width),
16513 height: Math.round(bounds.height)
16514 }));
16515
16516 if (is$1(semantic, 'bpmn:BoundaryEvent')) {
16517 this._attachBoundary(semantic, element);
16518 }
16519
16520 // insert lanes behind other flow nodes (cf. #727)
16521 if (is$1(semantic, 'bpmn:Lane')) {
16522 parentIndex = 0;
16523 }
16524
16525 if (is$1(semantic, 'bpmn:DataStoreReference')) {
16526
16527 // check wether data store is inside our outside of its semantic parent
16528 if (!isPointInsideBBox$1(parentElement, getMid(bounds))) {
16529 parentElement = this._canvas.getRootElement();
16530 }
16531 }
16532
16533 this._canvas.addShape(element, parentElement, parentIndex);
16534 }
16535
16536 // CONNECTION
16537 else if (is$1(di, 'bpmndi:BPMNEdge')) {
16538
16539 var source = this._getSource(semantic),
16540 target = this._getTarget(semantic);
16541
16542 hidden = parentElement && (parentElement.hidden || parentElement.collapsed);
16543
16544 element = this._elementFactory.createConnection(elementData(semantic, {
16545 hidden: hidden,
16546 source: source,
16547 target: target,
16548 waypoints: collectWaypoints(semantic.di.waypoint)
16549 }));
16550
16551 if (is$1(semantic, 'bpmn:DataAssociation')) {
16552
16553 // render always on top; this ensures DataAssociations
16554 // are rendered correctly across different "hacks" people
16555 // love to model such as cross participant / sub process
16556 // associations
16557 parentElement = null;
16558 }
16559
16560 // insert sequence flows behind other flow nodes (cf. #727)
16561 if (is$1(semantic, 'bpmn:SequenceFlow')) {
16562 parentIndex = 0;
16563 }
16564
16565 this._canvas.addConnection(element, parentElement, parentIndex);
16566 } else {
16567 throw new Error(translate('unknown di {di} for element {semantic}', {
16568 di: elementToString(di),
16569 semantic: elementToString(semantic)
16570 }));
16571 }
16572 // (optional) LABEL
16573 if (isLabelExternal(semantic) && semantic.name) {
16574 this.addLabel(semantic, element);
16575 }
16576
16577
16578 this._eventBus.fire('bpmnElement.added', { element: element });
16579
16580 return element;
16581 };
16582
16583
16584 /**
16585 * Attach the boundary element to the given host
16586 *
16587 * @param {ModdleElement} boundarySemantic
16588 * @param {djs.model.Base} boundaryElement
16589 */
16590 BpmnImporter.prototype._attachBoundary = function(boundarySemantic, boundaryElement) {
16591 var translate = this._translate;
16592 var hostSemantic = boundarySemantic.attachedToRef;
16593
16594 if (!hostSemantic) {
16595 throw new Error(translate('missing {semantic}#attachedToRef', {
16596 semantic: elementToString(boundarySemantic)
16597 }));
16598 }
16599
16600 var host = this._elementRegistry.get(hostSemantic.id),
16601 attachers = host && host.attachers;
16602
16603 if (!host) {
16604 throw notYetDrawn(translate, boundarySemantic, hostSemantic, 'attachedToRef');
16605 }
16606
16607 // wire element.host <> host.attachers
16608 boundaryElement.host = host;
16609
16610 if (!attachers) {
16611 host.attachers = attachers = [];
16612 }
16613
16614 if (attachers.indexOf(boundaryElement) === -1) {
16615 attachers.push(boundaryElement);
16616 }
16617 };
16618
16619
16620 /**
16621 * add label for an element
16622 */
16623 BpmnImporter.prototype.addLabel = function(semantic, element) {
16624 var bounds,
16625 text,
16626 label;
16627
16628 bounds = getExternalLabelBounds(semantic, element);
16629
16630 text = semantic.name;
16631
16632 if (text) {
16633 // get corrected bounds from actual layouted text
16634 bounds = this._textRenderer.getExternalLabelBounds(bounds, text);
16635 }
16636
16637 label = this._elementFactory.createLabel(elementData(semantic, {
16638 id: semantic.id + '_label',
16639 labelTarget: element,
16640 type: 'label',
16641 hidden: element.hidden || !semantic.name,
16642 x: Math.round(bounds.x),
16643 y: Math.round(bounds.y),
16644 width: Math.round(bounds.width),
16645 height: Math.round(bounds.height)
16646 }));
16647
16648 return this._canvas.addShape(label, element.parent);
16649 };
16650
16651 /**
16652 * Return the drawn connection end based on the given side.
16653 *
16654 * @throws {Error} if the end is not yet drawn
16655 */
16656 BpmnImporter.prototype._getEnd = function(semantic, side) {
16657
16658 var element,
16659 refSemantic,
16660 type = semantic.$type,
16661 translate = this._translate;
16662
16663 refSemantic = semantic[side + 'Ref'];
16664
16665 // handle mysterious isMany DataAssociation#sourceRef
16666 if (side === 'source' && type === 'bpmn:DataInputAssociation') {
16667 refSemantic = refSemantic && refSemantic[0];
16668 }
16669
16670 // fix source / target for DataInputAssociation / DataOutputAssociation
16671 if (side === 'source' && type === 'bpmn:DataOutputAssociation' ||
16672 side === 'target' && type === 'bpmn:DataInputAssociation') {
16673
16674 refSemantic = semantic.$parent;
16675 }
16676
16677 element = refSemantic && this._getElement(refSemantic);
16678
16679 if (element) {
16680 return element;
16681 }
16682
16683 if (refSemantic) {
16684 throw notYetDrawn(translate, semantic, refSemantic, side + 'Ref');
16685 } else {
16686 throw new Error(translate('{semantic}#{side} Ref not specified', {
16687 semantic: elementToString(semantic),
16688 side: side
16689 }));
16690 }
16691 };
16692
16693 BpmnImporter.prototype._getSource = function(semantic) {
16694 return this._getEnd(semantic, 'source');
16695 };
16696
16697 BpmnImporter.prototype._getTarget = function(semantic) {
16698 return this._getEnd(semantic, 'target');
16699 };
16700
16701
16702 BpmnImporter.prototype._getElement = function(semantic) {
16703 return this._elementRegistry.get(semantic.id);
16704 };
16705
16706
16707 // helpers ////////////////////
16708
16709 function isPointInsideBBox$1(bbox, point) {
16710 var x = point.x,
16711 y = point.y;
16712
16713 return x >= bbox.x &&
16714 x <= bbox.x + bbox.width &&
16715 y >= bbox.y &&
16716 y <= bbox.y + bbox.height;
16717 }
16718
16719 var ImportModule = {
16720 __depends__: [
16721 translate$2
16722 ],
16723 bpmnImporter: [ 'type', BpmnImporter ]
16724 };
16725
16726 var CoreModule$1 = {
16727 __depends__: [
16728 DrawModule$1,
16729 ImportModule
16730 ]
16731 };
16732
16733 function getOriginal(event) {
16734 return event.originalEvent || event.srcEvent;
16735 }
16736
16737
16738 function toPoint(event) {
16739
16740 if (event.pointers && event.pointers.length) {
16741 event = event.pointers[0];
16742 }
16743
16744 if (event.touches && event.touches.length) {
16745 event = event.touches[0];
16746 }
16747
16748 return event ? {
16749 x: event.clientX,
16750 y: event.clientY
16751 } : null;
16752 }
16753
16754 function isMac() {
16755 return (/mac/i).test(navigator.platform);
16756 }
16757
16758 function isPrimaryButton(event) {
16759 // button === 0 -> left áka primary mouse button
16760 return !(getOriginal(event) || event).button;
16761 }
16762
16763 function hasPrimaryModifier(event) {
16764 var originalEvent = getOriginal(event) || event;
16765
16766 if (!isPrimaryButton(event)) {
16767 return false;
16768 }
16769
16770 // Use alt as primary modifier key for mac OS
16771 if (isMac()) {
16772 return originalEvent.metaKey;
16773 } else {
16774 return originalEvent.ctrlKey;
16775 }
16776 }
16777
16778 function allowAll(e) { return true; }
16779
16780 var LOW_PRIORITY = 500;
16781
16782 /**
16783 * A plugin that provides interaction events for diagram elements.
16784 *
16785 * It emits the following events:
16786 *
16787 * * element.hover
16788 * * element.out
16789 * * element.click
16790 * * element.dblclick
16791 * * element.mousedown
16792 * * element.contextmenu
16793 *
16794 * Each event is a tuple { element, gfx, originalEvent }.
16795 *
16796 * Canceling the event via Event#preventDefault()
16797 * prevents the original DOM operation.
16798 *
16799 * @param {EventBus} eventBus
16800 */
16801 function InteractionEvents(eventBus, elementRegistry, styles) {
16802
16803 var HIT_STYLE = styles.cls('djs-hit', [ 'no-fill', 'no-border' ], {
16804 stroke: 'white',
16805 strokeWidth: 15
16806 });
16807
16808 /**
16809 * Fire an interaction event.
16810 *
16811 * @param {String} type local event name, e.g. element.click.
16812 * @param {DOMEvent} event native event
16813 * @param {djs.model.Base} [element] the diagram element to emit the event on;
16814 * defaults to the event target
16815 */
16816 function fire(type, event, element) {
16817
16818 if (isIgnored(type, event)) {
16819 return;
16820 }
16821
16822 var target, gfx, returnValue;
16823
16824 if (!element) {
16825 target = event.delegateTarget || event.target;
16826
16827 if (target) {
16828 gfx = target;
16829 element = elementRegistry.get(gfx);
16830 }
16831 } else {
16832 gfx = elementRegistry.getGraphics(element);
16833 }
16834
16835 if (!gfx || !element) {
16836 return;
16837 }
16838
16839 returnValue = eventBus.fire(type, {
16840 element: element,
16841 gfx: gfx,
16842 originalEvent: event
16843 });
16844
16845 if (returnValue === false) {
16846 event.stopPropagation();
16847 event.preventDefault();
16848 }
16849 }
16850
16851 // TODO(nikku): document this
16852 var handlers = {};
16853
16854 function mouseHandler(localEventName) {
16855 return handlers[localEventName];
16856 }
16857
16858 function isIgnored(localEventName, event) {
16859
16860 var filter$$1 = ignoredFilters[localEventName] || isPrimaryButton;
16861
16862 // only react on left mouse button interactions
16863 // except for interaction events that are enabled
16864 // for secundary mouse button
16865 return !filter$$1(event);
16866 }
16867
16868 var bindings = {
16869 mouseover: 'element.hover',
16870 mouseout: 'element.out',
16871 click: 'element.click',
16872 dblclick: 'element.dblclick',
16873 mousedown: 'element.mousedown',
16874 mouseup: 'element.mouseup',
16875 contextmenu: 'element.contextmenu'
16876 };
16877
16878 var ignoredFilters = {
16879 'element.contextmenu': allowAll
16880 };
16881
16882
16883 // manual event trigger
16884
16885 /**
16886 * Trigger an interaction event (based on a native dom event)
16887 * on the target shape or connection.
16888 *
16889 * @param {String} eventName the name of the triggered DOM event
16890 * @param {MouseEvent} event
16891 * @param {djs.model.Base} targetElement
16892 */
16893 function triggerMouseEvent(eventName, event, targetElement) {
16894
16895 // i.e. element.mousedown...
16896 var localEventName = bindings[eventName];
16897
16898 if (!localEventName) {
16899 throw new Error('unmapped DOM event name <' + eventName + '>');
16900 }
16901
16902 return fire(localEventName, event, targetElement);
16903 }
16904
16905
16906 var elementSelector = 'svg, .djs-element';
16907
16908 // event registration
16909
16910 function registerEvent(node, event, localEvent, ignoredFilter) {
16911
16912 var handler = handlers[localEvent] = function(event) {
16913 fire(localEvent, event);
16914 };
16915
16916 if (ignoredFilter) {
16917 ignoredFilters[localEvent] = ignoredFilter;
16918 }
16919
16920 handler.$delegate = delegateEvents.bind(node, elementSelector, event, handler);
16921 }
16922
16923 function unregisterEvent(node, event, localEvent) {
16924
16925 var handler = mouseHandler(localEvent);
16926
16927 if (!handler) {
16928 return;
16929 }
16930
16931 delegateEvents.unbind(node, event, handler.$delegate);
16932 }
16933
16934 function registerEvents(svg) {
16935 forEach(bindings, function(val, key) {
16936 registerEvent(svg, key, val);
16937 });
16938 }
16939
16940 function unregisterEvents(svg) {
16941 forEach(bindings, function(val, key) {
16942 unregisterEvent(svg, key, val);
16943 });
16944 }
16945
16946 eventBus.on('canvas.destroy', function(event) {
16947 unregisterEvents(event.svg);
16948 });
16949
16950 eventBus.on('canvas.init', function(event) {
16951 registerEvents(event.svg);
16952 });
16953
16954
16955 eventBus.on([ 'shape.added', 'connection.added' ], function(event) {
16956 var element = event.element,
16957 gfx = event.gfx,
16958 hit;
16959
16960 if (element.waypoints) {
16961 hit = createLine(element.waypoints);
16962 } else {
16963 hit = create('rect');
16964 attr$1(hit, {
16965 x: 0,
16966 y: 0,
16967 width: element.width,
16968 height: element.height
16969 });
16970 }
16971
16972 attr$1(hit, HIT_STYLE);
16973
16974 append(gfx, hit);
16975 });
16976
16977 // Update djs-hit on change.
16978 // A low priortity is necessary, because djs-hit of labels has to be updated
16979 // after the label bounds have been updated in the renderer.
16980 eventBus.on('shape.changed', LOW_PRIORITY, function(event) {
16981
16982 var element = event.element,
16983 gfx = event.gfx,
16984 hit = query('.djs-hit', gfx);
16985
16986 attr$1(hit, {
16987 width: element.width,
16988 height: element.height
16989 });
16990 });
16991
16992 eventBus.on('connection.changed', function(event) {
16993
16994 var element = event.element,
16995 gfx = event.gfx,
16996 hit = query('.djs-hit', gfx);
16997
16998 updateLine(hit, element.waypoints);
16999 });
17000
17001
17002 // API
17003
17004 this.fire = fire;
17005
17006 this.triggerMouseEvent = triggerMouseEvent;
17007
17008 this.mouseHandler = mouseHandler;
17009
17010 this.registerEvent = registerEvent;
17011 this.unregisterEvent = unregisterEvent;
17012 }
17013
17014
17015 InteractionEvents.$inject = [
17016 'eventBus',
17017 'elementRegistry',
17018 'styles'
17019 ];
17020
17021
17022 /**
17023 * An event indicating that the mouse hovered over an element
17024 *
17025 * @event element.hover
17026 *
17027 * @type {Object}
17028 * @property {djs.model.Base} element
17029 * @property {SVGElement} gfx
17030 * @property {Event} originalEvent
17031 */
17032
17033 /**
17034 * An event indicating that the mouse has left an element
17035 *
17036 * @event element.out
17037 *
17038 * @type {Object}
17039 * @property {djs.model.Base} element
17040 * @property {SVGElement} gfx
17041 * @property {Event} originalEvent
17042 */
17043
17044 /**
17045 * An event indicating that the mouse has clicked an element
17046 *
17047 * @event element.click
17048 *
17049 * @type {Object}
17050 * @property {djs.model.Base} element
17051 * @property {SVGElement} gfx
17052 * @property {Event} originalEvent
17053 */
17054
17055 /**
17056 * An event indicating that the mouse has double clicked an element
17057 *
17058 * @event element.dblclick
17059 *
17060 * @type {Object}
17061 * @property {djs.model.Base} element
17062 * @property {SVGElement} gfx
17063 * @property {Event} originalEvent
17064 */
17065
17066 /**
17067 * An event indicating that the mouse has gone down on an element.
17068 *
17069 * @event element.mousedown
17070 *
17071 * @type {Object}
17072 * @property {djs.model.Base} element
17073 * @property {SVGElement} gfx
17074 * @property {Event} originalEvent
17075 */
17076
17077 /**
17078 * An event indicating that the mouse has gone up on an element.
17079 *
17080 * @event element.mouseup
17081 *
17082 * @type {Object}
17083 * @property {djs.model.Base} element
17084 * @property {SVGElement} gfx
17085 * @property {Event} originalEvent
17086 */
17087
17088 /**
17089 * An event indicating that the context menu action is triggered
17090 * via mouse or touch controls.
17091 *
17092 * @event element.contextmenu
17093 *
17094 * @type {Object}
17095 * @property {djs.model.Base} element
17096 * @property {SVGElement} gfx
17097 * @property {Event} originalEvent
17098 */
17099
17100 var InteractionEventsModule = {
17101 __init__: [ 'interactionEvents' ],
17102 interactionEvents: [ 'type', InteractionEvents ]
17103 };
17104
17105 var LOW_PRIORITY$1 = 500;
17106
17107
17108 /**
17109 * @class
17110 *
17111 * A plugin that adds an outline to shapes and connections that may be activated and styled
17112 * via CSS classes.
17113 *
17114 * @param {EventBus} eventBus
17115 * @param {Styles} styles
17116 * @param {ElementRegistry} elementRegistry
17117 */
17118 function Outline(eventBus, styles, elementRegistry) {
17119
17120 this.offset = 6;
17121
17122 var OUTLINE_STYLE = styles.cls('djs-outline', [ 'no-fill' ]);
17123
17124 var self = this;
17125
17126 function createOutline(gfx, bounds) {
17127 var outline = create('rect');
17128
17129 attr$1(outline, assign({
17130 x: 10,
17131 y: 10,
17132 width: 100,
17133 height: 100
17134 }, OUTLINE_STYLE));
17135
17136 append(gfx, outline);
17137
17138 return outline;
17139 }
17140
17141 // A low priortity is necessary, because outlines of labels have to be updated
17142 // after the label bounds have been updated in the renderer.
17143 eventBus.on([ 'shape.added', 'shape.changed' ], LOW_PRIORITY$1, function(event) {
17144 var element = event.element,
17145 gfx = event.gfx;
17146
17147 var outline = query('.djs-outline', gfx);
17148
17149 if (!outline) {
17150 outline = createOutline(gfx, element);
17151 }
17152
17153 self.updateShapeOutline(outline, element);
17154 });
17155
17156 eventBus.on([ 'connection.added', 'connection.changed' ], function(event) {
17157 var element = event.element,
17158 gfx = event.gfx;
17159
17160 var outline = query('.djs-outline', gfx);
17161
17162 if (!outline) {
17163 outline = createOutline(gfx, element);
17164 }
17165
17166 self.updateConnectionOutline(outline, element);
17167 });
17168 }
17169
17170
17171 /**
17172 * Updates the outline of a shape respecting the dimension of the
17173 * element and an outline offset.
17174 *
17175 * @param {SVGElement} outline
17176 * @param {djs.model.Base} element
17177 */
17178 Outline.prototype.updateShapeOutline = function(outline, element) {
17179
17180 attr$1(outline, {
17181 x: -this.offset,
17182 y: -this.offset,
17183 width: element.width + this.offset * 2,
17184 height: element.height + this.offset * 2
17185 });
17186
17187 };
17188
17189
17190 /**
17191 * Updates the outline of a connection respecting the bounding box of
17192 * the connection and an outline offset.
17193 *
17194 * @param {SVGElement} outline
17195 * @param {djs.model.Base} element
17196 */
17197 Outline.prototype.updateConnectionOutline = function(outline, connection) {
17198
17199 var bbox = getBBox(connection);
17200
17201 attr$1(outline, {
17202 x: bbox.x - this.offset,
17203 y: bbox.y - this.offset,
17204 width: bbox.width + this.offset * 2,
17205 height: bbox.height + this.offset * 2
17206 });
17207
17208 };
17209
17210
17211 Outline.$inject = ['eventBus', 'styles', 'elementRegistry'];
17212
17213 var OutlineModule = {
17214 __init__: [ 'outline' ],
17215 outline: [ 'type', Outline ]
17216 };
17217
17218 /**
17219 * A service that offers the current selection in a diagram.
17220 * Offers the api to control the selection, too.
17221 *
17222 * @class
17223 *
17224 * @param {EventBus} eventBus the event bus
17225 */
17226 function Selection(eventBus) {
17227
17228 this._eventBus = eventBus;
17229
17230 this._selectedElements = [];
17231
17232 var self = this;
17233
17234 eventBus.on([ 'shape.remove', 'connection.remove' ], function(e) {
17235 var element = e.element;
17236 self.deselect(element);
17237 });
17238
17239 eventBus.on([ 'diagram.clear' ], function(e) {
17240 self.select(null);
17241 });
17242 }
17243
17244 Selection.$inject = [ 'eventBus' ];
17245
17246
17247 Selection.prototype.deselect = function(element) {
17248 var selectedElements = this._selectedElements;
17249
17250 var idx = selectedElements.indexOf(element);
17251
17252 if (idx !== -1) {
17253 var oldSelection = selectedElements.slice();
17254
17255 selectedElements.splice(idx, 1);
17256
17257 this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: selectedElements });
17258 }
17259 };
17260
17261
17262 Selection.prototype.get = function() {
17263 return this._selectedElements;
17264 };
17265
17266 Selection.prototype.isSelected = function(element) {
17267 return this._selectedElements.indexOf(element) !== -1;
17268 };
17269
17270
17271 /**
17272 * This method selects one or more elements on the diagram.
17273 *
17274 * By passing an additional add parameter you can decide whether or not the element(s)
17275 * should be added to the already existing selection or not.
17276 *
17277 * @method Selection#select
17278 *
17279 * @param {Object|Object[]} elements element or array of elements to be selected
17280 * @param {boolean} [add] whether the element(s) should be appended to the current selection, defaults to false
17281 */
17282 Selection.prototype.select = function(elements, add) {
17283 var selectedElements = this._selectedElements,
17284 oldSelection = selectedElements.slice();
17285
17286 if (!isArray(elements)) {
17287 elements = elements ? [ elements ] : [];
17288 }
17289
17290 // selection may be cleared by passing an empty array or null
17291 // to the method
17292 if (add) {
17293 forEach(elements, function(element) {
17294 if (selectedElements.indexOf(element) !== -1) {
17295 // already selected
17296 return;
17297 } else {
17298 selectedElements.push(element);
17299 }
17300 });
17301 } else {
17302 this._selectedElements = selectedElements = elements.slice();
17303 }
17304
17305 this._eventBus.fire('selection.changed', { oldSelection: oldSelection, newSelection: selectedElements });
17306 };
17307
17308 var MARKER_HOVER = 'hover',
17309 MARKER_SELECTED = 'selected';
17310
17311
17312 /**
17313 * A plugin that adds a visible selection UI to shapes and connections
17314 * by appending the <code>hover</code> and <code>selected</code> classes to them.
17315 *
17316 * @class
17317 *
17318 * Makes elements selectable, too.
17319 *
17320 * @param {EventBus} events
17321 * @param {SelectionService} selection
17322 * @param {Canvas} canvas
17323 */
17324 function SelectionVisuals(events, canvas, selection, styles) {
17325
17326 this._multiSelectionBox = null;
17327
17328 function addMarker(e, cls) {
17329 canvas.addMarker(e, cls);
17330 }
17331
17332 function removeMarker(e, cls) {
17333 canvas.removeMarker(e, cls);
17334 }
17335
17336 events.on('element.hover', function(event) {
17337 addMarker(event.element, MARKER_HOVER);
17338 });
17339
17340 events.on('element.out', function(event) {
17341 removeMarker(event.element, MARKER_HOVER);
17342 });
17343
17344 events.on('selection.changed', function(event) {
17345
17346 function deselect(s) {
17347 removeMarker(s, MARKER_SELECTED);
17348 }
17349
17350 function select(s) {
17351 addMarker(s, MARKER_SELECTED);
17352 }
17353
17354 var oldSelection = event.oldSelection,
17355 newSelection = event.newSelection;
17356
17357 forEach(oldSelection, function(e) {
17358 if (newSelection.indexOf(e) === -1) {
17359 deselect(e);
17360 }
17361 });
17362
17363 forEach(newSelection, function(e) {
17364 if (oldSelection.indexOf(e) === -1) {
17365 select(e);
17366 }
17367 });
17368 });
17369 }
17370
17371 SelectionVisuals.$inject = [
17372 'eventBus',
17373 'canvas',
17374 'selection',
17375 'styles'
17376 ];
17377
17378 function SelectionBehavior(
17379 eventBus, selection, canvas,
17380 elementRegistry) {
17381
17382 eventBus.on('create.end', 500, function(e) {
17383
17384 // select the created shape after a
17385 // successful create operation
17386 if (e.context.canExecute) {
17387 selection.select(e.context.shape);
17388 }
17389 });
17390
17391 eventBus.on('connect.end', 500, function(e) {
17392
17393 // select the connect end target
17394 // after a connect operation
17395 if (e.context.canExecute && e.context.target) {
17396 selection.select(e.context.target);
17397 }
17398 });
17399
17400 eventBus.on('shape.move.end', 500, function(e) {
17401 var previousSelection = e.previousSelection || [];
17402
17403 var shape = elementRegistry.get(e.context.shape.id);
17404
17405 // make sure at least the main moved element is being
17406 // selected after a move operation
17407 var inSelection = find(previousSelection, function(selectedShape) {
17408 return shape.id === selectedShape.id;
17409 });
17410
17411 if (!inSelection) {
17412 selection.select(shape);
17413 }
17414 });
17415
17416 // Shift + click selection
17417 eventBus.on('element.click', function(event) {
17418
17419 var element = event.element;
17420
17421 // do not select the root element
17422 // or connections
17423 if (element === canvas.getRootElement()) {
17424 element = null;
17425 }
17426
17427 var isSelected = selection.isSelected(element),
17428 isMultiSelect = selection.get().length > 1;
17429
17430 // mouse-event: SELECTION_KEY
17431 var add = hasPrimaryModifier(event);
17432
17433 // select OR deselect element in multi selection
17434 if (isSelected && isMultiSelect) {
17435 if (add) {
17436 return selection.deselect(element);
17437 } else {
17438 return selection.select(element);
17439 }
17440 } else
17441 if (!isSelected) {
17442 selection.select(element, add);
17443 } else {
17444 selection.deselect(element);
17445 }
17446 });
17447 }
17448
17449 SelectionBehavior.$inject = [
17450 'eventBus',
17451 'selection',
17452 'canvas',
17453 'elementRegistry'
17454 ];
17455
17456 var SelectionModule = {
17457 __init__: [ 'selectionVisuals', 'selectionBehavior' ],
17458 __depends__: [
17459 InteractionEventsModule,
17460 OutlineModule
17461 ],
17462 selection: [ 'type', Selection ],
17463 selectionVisuals: [ 'type', SelectionVisuals ],
17464 selectionBehavior: [ 'type', SelectionBehavior ]
17465 };
17466
17467 /**
17468 * Util that provides unique IDs.
17469 *
17470 * @class djs.util.IdGenerator
17471 * @constructor
17472 * @memberOf djs.util
17473 *
17474 * The ids can be customized via a given prefix and contain a random value to avoid collisions.
17475 *
17476 * @param {String} prefix a prefix to prepend to generated ids (for better readability)
17477 */
17478 function IdGenerator(prefix) {
17479
17480 this._counter = 0;
17481 this._prefix = (prefix ? prefix + '-' : '') + Math.floor(Math.random() * 1000000000) + '-';
17482 }
17483
17484 /**
17485 * Returns a next unique ID.
17486 *
17487 * @method djs.util.IdGenerator#next
17488 *
17489 * @returns {String} the id
17490 */
17491 IdGenerator.prototype.next = function() {
17492 return this._prefix + (++this._counter);
17493 };
17494
17495 // document wide unique overlay ids
17496 var ids$1 = new IdGenerator('ov');
17497
17498 var LOW_PRIORITY$2 = 500;
17499
17500
17501 /**
17502 * A service that allows users to attach overlays to diagram elements.
17503 *
17504 * The overlay service will take care of overlay positioning during updates.
17505 *
17506 * @example
17507 *
17508 * // add a pink badge on the top left of the shape
17509 * overlays.add(someShape, {
17510 * position: {
17511 * top: -5,
17512 * left: -5
17513 * },
17514 * html: '<div style="width: 10px; background: fuchsia; color: white;">0</div>'
17515 * });
17516 *
17517 * // or add via shape id
17518 *
17519 * overlays.add('some-element-id', {
17520 * position: {
17521 * top: -5,
17522 * left: -5
17523 * }
17524 * html: '<div style="width: 10px; background: fuchsia; color: white;">0</div>'
17525 * });
17526 *
17527 * // or add with optional type
17528 *
17529 * overlays.add(someShape, 'badge', {
17530 * position: {
17531 * top: -5,
17532 * left: -5
17533 * }
17534 * html: '<div style="width: 10px; background: fuchsia; color: white;">0</div>'
17535 * });
17536 *
17537 *
17538 * // remove an overlay
17539 *
17540 * var id = overlays.add(...);
17541 * overlays.remove(id);
17542 *
17543 *
17544 * You may configure overlay defaults during tool by providing a `config` module
17545 * with `overlays.defaults` as an entry:
17546 *
17547 * {
17548 * overlays: {
17549 * defaults: {
17550 * show: {
17551 * minZoom: 0.7,
17552 * maxZoom: 5.0
17553 * },
17554 * scale: {
17555 * min: 1
17556 * }
17557 * }
17558 * }
17559 *
17560 * @param {Object} config
17561 * @param {EventBus} eventBus
17562 * @param {Canvas} canvas
17563 * @param {ElementRegistry} elementRegistry
17564 */
17565 function Overlays(config, eventBus, canvas, elementRegistry) {
17566
17567 this._eventBus = eventBus;
17568 this._canvas = canvas;
17569 this._elementRegistry = elementRegistry;
17570
17571 this._ids = ids$1;
17572
17573 this._overlayDefaults = assign({
17574 // no show constraints
17575 show: null,
17576
17577 // always scale
17578 scale: true
17579 }, config && config.defaults);
17580
17581 /**
17582 * Mapping overlayId -> overlay
17583 */
17584 this._overlays = {};
17585
17586 /**
17587 * Mapping elementId -> overlay container
17588 */
17589 this._overlayContainers = [];
17590
17591 // root html element for all overlays
17592 this._overlayRoot = createRoot(canvas.getContainer());
17593
17594 this._init();
17595 }
17596
17597
17598 Overlays.$inject = [
17599 'config.overlays',
17600 'eventBus',
17601 'canvas',
17602 'elementRegistry'
17603 ];
17604
17605
17606 /**
17607 * Returns the overlay with the specified id or a list of overlays
17608 * for an element with a given type.
17609 *
17610 * @example
17611 *
17612 * // return the single overlay with the given id
17613 * overlays.get('some-id');
17614 *
17615 * // return all overlays for the shape
17616 * overlays.get({ element: someShape });
17617 *
17618 * // return all overlays on shape with type 'badge'
17619 * overlays.get({ element: someShape, type: 'badge' });
17620 *
17621 * // shape can also be specified as id
17622 * overlays.get({ element: 'element-id', type: 'badge' });
17623 *
17624 *
17625 * @param {Object} search
17626 * @param {String} [search.id]
17627 * @param {String|djs.model.Base} [search.element]
17628 * @param {String} [search.type]
17629 *
17630 * @return {Object|Array<Object>} the overlay(s)
17631 */
17632 Overlays.prototype.get = function(search) {
17633
17634 if (isString(search)) {
17635 search = { id: search };
17636 }
17637
17638 if (isString(search.element)) {
17639 search.element = this._elementRegistry.get(search.element);
17640 }
17641
17642 if (search.element) {
17643 var container = this._getOverlayContainer(search.element, true);
17644
17645 // return a list of overlays when searching by element (+type)
17646 if (container) {
17647 return search.type ? filter(container.overlays, matchPattern({ type: search.type })) : container.overlays.slice();
17648 } else {
17649 return [];
17650 }
17651 } else
17652 if (search.type) {
17653 return filter(this._overlays, matchPattern({ type: search.type }));
17654 } else {
17655 // return single element when searching by id
17656 return search.id ? this._overlays[search.id] : null;
17657 }
17658 };
17659
17660 /**
17661 * Adds a HTML overlay to an element.
17662 *
17663 * @param {String|djs.model.Base} element attach overlay to this shape
17664 * @param {String} [type] optional type to assign to the overlay
17665 * @param {Object} overlay the overlay configuration
17666 *
17667 * @param {String|DOMElement} overlay.html html element to use as an overlay
17668 * @param {Object} [overlay.show] show configuration
17669 * @param {Number} [overlay.show.minZoom] minimal zoom level to show the overlay
17670 * @param {Number} [overlay.show.maxZoom] maximum zoom level to show the overlay
17671 * @param {Object} overlay.position where to attach the overlay
17672 * @param {Number} [overlay.position.left] relative to element bbox left attachment
17673 * @param {Number} [overlay.position.top] relative to element bbox top attachment
17674 * @param {Number} [overlay.position.bottom] relative to element bbox bottom attachment
17675 * @param {Number} [overlay.position.right] relative to element bbox right attachment
17676 * @param {Boolean|Object} [overlay.scale=true] false to preserve the same size regardless of
17677 * diagram zoom
17678 * @param {Number} [overlay.scale.min]
17679 * @param {Number} [overlay.scale.max]
17680 *
17681 * @return {String} id that may be used to reference the overlay for update or removal
17682 */
17683 Overlays.prototype.add = function(element, type, overlay) {
17684
17685 if (isObject(type)) {
17686 overlay = type;
17687 type = null;
17688 }
17689
17690 if (!element.id) {
17691 element = this._elementRegistry.get(element);
17692 }
17693
17694 if (!overlay.position) {
17695 throw new Error('must specifiy overlay position');
17696 }
17697
17698 if (!overlay.html) {
17699 throw new Error('must specifiy overlay html');
17700 }
17701
17702 if (!element) {
17703 throw new Error('invalid element specified');
17704 }
17705
17706 var id = this._ids.next();
17707
17708 overlay = assign({}, this._overlayDefaults, overlay, {
17709 id: id,
17710 type: type,
17711 element: element,
17712 html: overlay.html
17713 });
17714
17715 this._addOverlay(overlay);
17716
17717 return id;
17718 };
17719
17720
17721 /**
17722 * Remove an overlay with the given id or all overlays matching the given filter.
17723 *
17724 * @see Overlays#get for filter options.
17725 *
17726 * @param {String} [id]
17727 * @param {Object} [filter]
17728 */
17729 Overlays.prototype.remove = function(filter$$1) {
17730
17731 var overlays = this.get(filter$$1) || [];
17732
17733 if (!isArray(overlays)) {
17734 overlays = [ overlays ];
17735 }
17736
17737 var self = this;
17738
17739 forEach(overlays, function(overlay) {
17740
17741 var container = self._getOverlayContainer(overlay.element, true);
17742
17743 if (overlay) {
17744 remove(overlay.html);
17745 remove(overlay.htmlContainer);
17746
17747 delete overlay.htmlContainer;
17748 delete overlay.element;
17749
17750 delete self._overlays[overlay.id];
17751 }
17752
17753 if (container) {
17754 var idx = container.overlays.indexOf(overlay);
17755 if (idx !== -1) {
17756 container.overlays.splice(idx, 1);
17757 }
17758 }
17759 });
17760
17761 };
17762
17763
17764 Overlays.prototype.show = function() {
17765 setVisible(this._overlayRoot);
17766 };
17767
17768
17769 Overlays.prototype.hide = function() {
17770 setVisible(this._overlayRoot, false);
17771 };
17772
17773 Overlays.prototype.clear = function() {
17774 this._overlays = {};
17775
17776 this._overlayContainers = [];
17777
17778 clear(this._overlayRoot);
17779 };
17780
17781 Overlays.prototype._updateOverlayContainer = function(container) {
17782 var element = container.element,
17783 html = container.html;
17784
17785 // update container left,top according to the elements x,y coordinates
17786 // this ensures we can attach child elements relative to this container
17787
17788 var x = element.x,
17789 y = element.y;
17790
17791 if (element.waypoints) {
17792 var bbox = getBBox(element);
17793 x = bbox.x;
17794 y = bbox.y;
17795 }
17796
17797 setPosition(html, x, y);
17798
17799 attr(container.html, 'data-container-id', element.id);
17800 };
17801
17802
17803 Overlays.prototype._updateOverlay = function(overlay) {
17804
17805 var position = overlay.position,
17806 htmlContainer = overlay.htmlContainer,
17807 element = overlay.element;
17808
17809 // update overlay html relative to shape because
17810 // it is already positioned on the element
17811
17812 // update relative
17813 var left = position.left,
17814 top = position.top;
17815
17816 if (position.right !== undefined) {
17817
17818 var width;
17819
17820 if (element.waypoints) {
17821 width = getBBox(element).width;
17822 } else {
17823 width = element.width;
17824 }
17825
17826 left = position.right * -1 + width;
17827 }
17828
17829 if (position.bottom !== undefined) {
17830
17831 var height;
17832
17833 if (element.waypoints) {
17834 height = getBBox(element).height;
17835 } else {
17836 height = element.height;
17837 }
17838
17839 top = position.bottom * -1 + height;
17840 }
17841
17842 setPosition(htmlContainer, left || 0, top || 0);
17843 };
17844
17845
17846 Overlays.prototype._createOverlayContainer = function(element) {
17847 var html = domify('<div class="djs-overlays" style="position: absolute" />');
17848
17849 this._overlayRoot.appendChild(html);
17850
17851 var container = {
17852 html: html,
17853 element: element,
17854 overlays: []
17855 };
17856
17857 this._updateOverlayContainer(container);
17858
17859 this._overlayContainers.push(container);
17860
17861 return container;
17862 };
17863
17864
17865 Overlays.prototype._updateRoot = function(viewbox) {
17866 var scale = viewbox.scale || 1;
17867
17868 var matrix = 'matrix(' +
17869 [
17870 scale,
17871 0,
17872 0,
17873 scale,
17874 -1 * viewbox.x * scale,
17875 -1 * viewbox.y * scale
17876 ].join(',') +
17877 ')';
17878
17879 setTransform(this._overlayRoot, matrix);
17880 };
17881
17882
17883 Overlays.prototype._getOverlayContainer = function(element, raw) {
17884 var container = find(this._overlayContainers, function(c) {
17885 return c.element === element;
17886 });
17887
17888
17889 if (!container && !raw) {
17890 return this._createOverlayContainer(element);
17891 }
17892
17893 return container;
17894 };
17895
17896
17897 Overlays.prototype._addOverlay = function(overlay) {
17898
17899 var id = overlay.id,
17900 element = overlay.element,
17901 html = overlay.html,
17902 htmlContainer,
17903 overlayContainer;
17904
17905 // unwrap jquery (for those who need it)
17906 if (html.get && html.constructor.prototype.jquery) {
17907 html = html.get(0);
17908 }
17909
17910 // create proper html elements from
17911 // overlay HTML strings
17912 if (isString(html)) {
17913 html = domify(html);
17914 }
17915
17916 overlayContainer = this._getOverlayContainer(element);
17917
17918 htmlContainer = domify('<div class="djs-overlay" data-overlay-id="' + id + '" style="position: absolute">');
17919
17920 htmlContainer.appendChild(html);
17921
17922 if (overlay.type) {
17923 classes(htmlContainer).add('djs-overlay-' + overlay.type);
17924 }
17925
17926 overlay.htmlContainer = htmlContainer;
17927
17928 overlayContainer.overlays.push(overlay);
17929 overlayContainer.html.appendChild(htmlContainer);
17930
17931 this._overlays[id] = overlay;
17932
17933 this._updateOverlay(overlay);
17934 this._updateOverlayVisibilty(overlay, this._canvas.viewbox());
17935 };
17936
17937
17938 Overlays.prototype._updateOverlayVisibilty = function(overlay, viewbox) {
17939 var show = overlay.show,
17940 minZoom = show && show.minZoom,
17941 maxZoom = show && show.maxZoom,
17942 htmlContainer = overlay.htmlContainer,
17943 visible = true;
17944
17945 if (show) {
17946 if (
17947 (isDefined(minZoom) && minZoom > viewbox.scale) ||
17948 (isDefined(maxZoom) && maxZoom < viewbox.scale)
17949 ) {
17950 visible = false;
17951 }
17952
17953 setVisible(htmlContainer, visible);
17954 }
17955
17956 this._updateOverlayScale(overlay, viewbox);
17957 };
17958
17959
17960 Overlays.prototype._updateOverlayScale = function(overlay, viewbox) {
17961 var shouldScale = overlay.scale,
17962 minScale,
17963 maxScale,
17964 htmlContainer = overlay.htmlContainer;
17965
17966 var scale, transform = '';
17967
17968 if (shouldScale !== true) {
17969
17970 if (shouldScale === false) {
17971 minScale = 1;
17972 maxScale = 1;
17973 } else {
17974 minScale = shouldScale.min;
17975 maxScale = shouldScale.max;
17976 }
17977
17978 if (isDefined(minScale) && viewbox.scale < minScale) {
17979 scale = (1 / viewbox.scale || 1) * minScale;
17980 }
17981
17982 if (isDefined(maxScale) && viewbox.scale > maxScale) {
17983 scale = (1 / viewbox.scale || 1) * maxScale;
17984 }
17985 }
17986
17987 if (isDefined(scale)) {
17988 transform = 'scale(' + scale + ',' + scale + ')';
17989 }
17990
17991 setTransform(htmlContainer, transform);
17992 };
17993
17994
17995 Overlays.prototype._updateOverlaysVisibilty = function(viewbox) {
17996
17997 var self = this;
17998
17999 forEach(this._overlays, function(overlay) {
18000 self._updateOverlayVisibilty(overlay, viewbox);
18001 });
18002 };
18003
18004
18005 Overlays.prototype._init = function() {
18006
18007 var eventBus = this._eventBus;
18008
18009 var self = this;
18010
18011
18012 // scroll/zoom integration
18013
18014 function updateViewbox(viewbox) {
18015 self._updateRoot(viewbox);
18016 self._updateOverlaysVisibilty(viewbox);
18017
18018 self.show();
18019 }
18020
18021 eventBus.on('canvas.viewbox.changing', function(event) {
18022 self.hide();
18023 });
18024
18025 eventBus.on('canvas.viewbox.changed', function(event) {
18026 updateViewbox(event.viewbox);
18027 });
18028
18029
18030 // remove integration
18031
18032 eventBus.on([ 'shape.remove', 'connection.remove' ], function(e) {
18033 var element = e.element;
18034 var overlays = self.get({ element: element });
18035
18036 forEach(overlays, function(o) {
18037 self.remove(o.id);
18038 });
18039
18040 var container = self._getOverlayContainer(element);
18041
18042 if (container) {
18043 remove(container.html);
18044 var i = self._overlayContainers.indexOf(container);
18045 if (i !== -1) {
18046 self._overlayContainers.splice(i, 1);
18047 }
18048 }
18049 });
18050
18051
18052 // move integration
18053
18054 eventBus.on('element.changed', LOW_PRIORITY$2, function(e) {
18055 var element = e.element;
18056
18057 var container = self._getOverlayContainer(element, true);
18058
18059 if (container) {
18060 forEach(container.overlays, function(overlay) {
18061 self._updateOverlay(overlay);
18062 });
18063
18064 self._updateOverlayContainer(container);
18065 }
18066 });
18067
18068
18069 // marker integration, simply add them on the overlays as classes, too.
18070
18071 eventBus.on('element.marker.update', function(e) {
18072 var container = self._getOverlayContainer(e.element, true);
18073 if (container) {
18074 classes(container.html)[e.add ? 'add' : 'remove'](e.marker);
18075 }
18076 });
18077
18078
18079 // clear overlays with diagram
18080
18081 eventBus.on('diagram.clear', this.clear, this);
18082 };
18083
18084
18085
18086 // helpers /////////////////////////////
18087
18088 function createRoot(parent) {
18089 var root = domify('<div class="djs-overlay-container" style="position: absolute; width: 0; height: 0;" />');
18090 parent.insertBefore(root, parent.firstChild);
18091
18092 return root;
18093 }
18094
18095 function setPosition(el, x, y) {
18096 assign(el.style, { left: x + 'px', top: y + 'px' });
18097 }
18098
18099 function setVisible(el, visible) {
18100 el.style.display = visible === false ? 'none' : '';
18101 }
18102
18103 function setTransform(el, transform) {
18104
18105 el.style['transform-origin'] = 'top left';
18106
18107 [ '', '-ms-', '-webkit-' ].forEach(function(prefix) {
18108 el.style[prefix + 'transform'] = transform;
18109 });
18110 }
18111
18112 var OverlaysModule = {
18113 __init__: [ 'overlays' ],
18114 overlays: [ 'type', Overlays ]
18115 };
18116
18117 /**
18118 * This file must not be changed or exchanged.
18119 *
18120 * @see http://bpmn.io/license for more information.
18121 */
18122
18123
18124 // inlined ../../resources/logo.svg
18125 var BPMNIO_LOGO_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 960"><path fill="#fff" d="M960 60v839c0 33-27 61-60 61H60c-33 0-60-27-60-60V60C0 27 27 0 60 0h839c34 0 61 27 61 60z"/><path fill="#52b415" d="M217 548a205 205 0 0 0-144 58 202 202 0 0 0-4 286 202 202 0 0 0 285 3 200 200 0 0 0 48-219 203 203 0 0 0-185-128zM752 6a206 206 0 0 0-192 285 206 206 0 0 0 269 111 207 207 0 0 0 111-260A204 204 0 0 0 752 6zM62 0A62 62 0 0 0 0 62v398l60 46a259 259 0 0 1 89-36c5-28 10-57 14-85l99 2 12 85a246 246 0 0 1 88 38l70-52 69 71-52 68c17 30 29 58 35 90l86 14-2 100-86 12a240 240 0 0 1-38 89l43 58h413c37 0 60-27 60-61V407a220 220 0 0 1-44 40l21 85-93 39-45-76a258 258 0 0 1-98 1l-45 76-94-39 22-85a298 298 0 0 1-70-69l-86 22-38-94 76-45a258 258 0 0 1-1-98l-76-45 40-94 85 22a271 271 0 0 1 41-47z"/></svg>';
18126
18127 var BPMNIO_LOGO_URL = 'data:image/svg+xml,' + encodeURIComponent(BPMNIO_LOGO_SVG);
18128
18129 var BPMNIO_IMG = '<img width="52" height="52" src="' + BPMNIO_LOGO_URL + '" />';
18130
18131 function css(attrs) {
18132 return attrs.join(';');
18133 }
18134
18135 var LIGHTBOX_STYLES = css([
18136 'z-index: 1001',
18137 'position: fixed',
18138 'top: 0',
18139 'left: 0',
18140 'right: 0',
18141 'bottom: 0'
18142 ]);
18143
18144 var BACKDROP_STYLES = css([
18145 'width: 100%',
18146 'height: 100%',
18147 'background: rgba(0,0,0,0.2)'
18148 ]);
18149
18150 var NOTICE_STYLES = css([
18151 'position: absolute',
18152 'left: 50%',
18153 'top: 40%',
18154 'margin: 0 -130px',
18155 'width: 260px',
18156 'padding: 10px',
18157 'background: white',
18158 'border: solid 1px #AAA',
18159 'border-radius: 3px',
18160 'font-family: Helvetica, Arial, sans-serif',
18161 'font-size: 14px',
18162 'line-height: 1.2em'
18163 ]);
18164
18165 var LIGHTBOX_MARKUP =
18166 '<div class="bjs-powered-by-lightbox" style="' + LIGHTBOX_STYLES + '">' +
18167 '<div class="backdrop" style="' + BACKDROP_STYLES + '"></div>' +
18168 '<div class="notice" style="' + NOTICE_STYLES + '">' +
18169 '<a href="http://bpmn.io" target="_blank" style="float: left; margin-right: 10px">' +
18170 BPMNIO_IMG +
18171 '</a>' +
18172 'Web-based tooling for BPMN, DMN and CMMN diagrams ' +
18173 'powered by <a href="http://bpmn.io" target="_blank">bpmn.io</a>.' +
18174 '</div>' +
18175 '</div>';
18176
18177
18178 var lightbox;
18179
18180 function open() {
18181
18182 if (!lightbox) {
18183 lightbox = domify(LIGHTBOX_MARKUP);
18184
18185 delegateEvents.bind(lightbox, '.backdrop', 'click', function(event) {
18186 document.body.removeChild(lightbox);
18187 });
18188 }
18189
18190 document.body.appendChild(lightbox);
18191 }
18192
18193 /**
18194 * The code in the <project-logo></project-logo> area
18195 * must not be changed.
18196 *
18197 * @see http://bpmn.io/license for more information.
18198 */
18199
18200
18201 function checkValidationError(err) {
18202
18203 // check if we can help the user by indicating wrong BPMN 2.0 xml
18204 // (in case he or the exporting tool did not get that right)
18205
18206 var pattern = /unparsable content <([^>]+)> detected([\s\S]*)$/;
18207 var match = pattern.exec(err.message);
18208
18209 if (match) {
18210 err.message =
18211 'unparsable content <' + match[1] + '> detected; ' +
18212 'this may indicate an invalid BPMN 2.0 diagram file' + match[2];
18213 }
18214
18215 return err;
18216 }
18217
18218 var DEFAULT_OPTIONS = {
18219 width: '100%',
18220 height: '100%',
18221 position: 'relative'
18222 };
18223
18224
18225 /**
18226 * Ensure the passed argument is a proper unit (defaulting to px)
18227 */
18228 function ensureUnit(val) {
18229 return val + (isNumber(val) ? 'px' : '');
18230 }
18231
18232 /**
18233 * A viewer for BPMN 2.0 diagrams.
18234 *
18235 * Have a look at {@link NavigatedViewer} or {@link Modeler} for bundles that include
18236 * additional features.
18237 *
18238 *
18239 * ## Extending the Viewer
18240 *
18241 * In order to extend the viewer pass extension modules to bootstrap via the
18242 * `additionalModules` option. An extension module is an object that exposes
18243 * named services.
18244 *
18245 * The following example depicts the integration of a simple
18246 * logging component that integrates with interaction events:
18247 *
18248 *
18249 * ```javascript
18250 *
18251 * // logging component
18252 * function InteractionLogger(eventBus) {
18253 * eventBus.on('element.hover', function(event) {
18254 * console.log()
18255 * })
18256 * }
18257 *
18258 * InteractionLogger.$inject = [ 'eventBus' ]; // minification save
18259 *
18260 * // extension module
18261 * var extensionModule = {
18262 * __init__: [ 'interactionLogger' ],
18263 * interactionLogger: [ 'type', InteractionLogger ]
18264 * };
18265 *
18266 * // extend the viewer
18267 * var bpmnViewer = new Viewer({ additionalModules: [ extensionModule ] });
18268 * bpmnViewer.importXML(...);
18269 * ```
18270 *
18271 * @param {Object} [options] configuration options to pass to the viewer
18272 * @param {DOMElement} [options.container] the container to render the viewer in, defaults to body.
18273 * @param {String|Number} [options.width] the width of the viewer
18274 * @param {String|Number} [options.height] the height of the viewer
18275 * @param {Object} [options.moddleExtensions] extension packages to provide
18276 * @param {Array<didi.Module>} [options.modules] a list of modules to override the default modules
18277 * @param {Array<didi.Module>} [options.additionalModules] a list of modules to use with the default modules
18278 */
18279 function Viewer(options) {
18280
18281 options = assign({}, DEFAULT_OPTIONS, options);
18282
18283 this._moddle = this._createModdle(options);
18284
18285 this._container = this._createContainer(options);
18286
18287 /* <project-logo> */
18288
18289 addProjectLogo(this._container);
18290
18291 /* </project-logo> */
18292
18293 this._init(this._container, this._moddle, options);
18294 }
18295
18296 inherits_browser(Viewer, diagramJs);
18297
18298
18299 /**
18300 * Parse and render a BPMN 2.0 diagram.
18301 *
18302 * Once finished the viewer reports back the result to the
18303 * provided callback function with (err, warnings).
18304 *
18305 * ## Life-Cycle Events
18306 *
18307 * During import the viewer will fire life-cycle events:
18308 *
18309 * * import.parse.start (about to read model from xml)
18310 * * import.parse.complete (model read; may have worked or not)
18311 * * import.render.start (graphical import start)
18312 * * import.render.complete (graphical import finished)
18313 * * import.done (everything done)
18314 *
18315 * You can use these events to hook into the life-cycle.
18316 *
18317 * @param {String} xml the BPMN 2.0 xml
18318 * @param {Function} [done] invoked with (err, warnings=[])
18319 */
18320 Viewer.prototype.importXML = function(xml, done) {
18321
18322 // done is optional
18323 done = done || function() {};
18324
18325 var self = this;
18326
18327 // hook in pre-parse listeners +
18328 // allow xml manipulation
18329 xml = this._emit('import.parse.start', { xml: xml }) || xml;
18330
18331 this._moddle.fromXML(xml, 'bpmn:Definitions', function(err, definitions, context) {
18332
18333 // hook in post parse listeners +
18334 // allow definitions manipulation
18335 definitions = self._emit('import.parse.complete', {
18336 error: err,
18337 definitions: definitions,
18338 context: context
18339 }) || definitions;
18340
18341 var parseWarnings = context.warnings;
18342
18343 if (err) {
18344 err = checkValidationError(err);
18345
18346 self._emit('import.done', { error: err, warnings: parseWarnings });
18347
18348 return done(err, parseWarnings);
18349 }
18350
18351 self.importDefinitions(definitions, function(err, importWarnings) {
18352 var allWarnings = [].concat(parseWarnings, importWarnings || []);
18353
18354 self._emit('import.done', { error: err, warnings: allWarnings });
18355
18356 done(err, allWarnings);
18357 });
18358 });
18359 };
18360
18361 /**
18362 * Export the currently displayed BPMN 2.0 diagram as
18363 * a BPMN 2.0 XML document.
18364 *
18365 * ## Life-Cycle Events
18366 *
18367 * During XML saving the viewer will fire life-cycle events:
18368 *
18369 * * saveXML.start (before serialization)
18370 * * saveXML.serialized (after xml generation)
18371 * * saveXML.done (everything done)
18372 *
18373 * You can use these events to hook into the life-cycle.
18374 *
18375 * @param {Object} [options] export options
18376 * @param {Boolean} [options.format=false] output formated XML
18377 * @param {Boolean} [options.preamble=true] output preamble
18378 *
18379 * @param {Function} done invoked with (err, xml)
18380 */
18381 Viewer.prototype.saveXML = function(options, done) {
18382
18383 if (!done) {
18384 done = options;
18385 options = {};
18386 }
18387
18388 var self = this;
18389
18390 var definitions = this._definitions;
18391
18392 if (!definitions) {
18393 return done(new Error('no definitions loaded'));
18394 }
18395
18396 // allow to fiddle around with definitions
18397 definitions = this._emit('saveXML.start', {
18398 definitions: definitions
18399 }) || definitions;
18400
18401 this._moddle.toXML(definitions, options, function(err, xml) {
18402
18403 try {
18404 xml = self._emit('saveXML.serialized', {
18405 error: err,
18406 xml: xml
18407 }) || xml;
18408
18409 self._emit('saveXML.done', {
18410 error: err,
18411 xml: xml
18412 });
18413 } catch (e) {
18414 console.error('error in saveXML life-cycle listener', e);
18415 }
18416
18417 done(err, xml);
18418 });
18419 };
18420
18421 /**
18422 * Export the currently displayed BPMN 2.0 diagram as
18423 * an SVG image.
18424 *
18425 * ## Life-Cycle Events
18426 *
18427 * During SVG saving the viewer will fire life-cycle events:
18428 *
18429 * * saveSVG.start (before serialization)
18430 * * saveSVG.done (everything done)
18431 *
18432 * You can use these events to hook into the life-cycle.
18433 *
18434 * @param {Object} [options]
18435 * @param {Function} done invoked with (err, svgStr)
18436 */
18437 Viewer.prototype.saveSVG = function(options, done) {
18438
18439 if (!done) {
18440 done = options;
18441 options = {};
18442 }
18443
18444 this._emit('saveSVG.start');
18445
18446 var svg, err;
18447
18448 try {
18449 var canvas = this.get('canvas');
18450
18451 var contentNode = canvas.getDefaultLayer(),
18452 defsNode = query('defs', canvas._svg);
18453
18454 var contents = innerSVG(contentNode),
18455 defs = defsNode ? '<defs>' + innerSVG(defsNode) + '</defs>' : '';
18456
18457 var bbox = contentNode.getBBox();
18458
18459 svg =
18460 '<?xml version="1.0" encoding="utf-8"?>\n' +
18461 '<!-- created with bpmn-js / http://bpmn.io -->\n' +
18462 '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' +
18463 '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ' +
18464 'width="' + bbox.width + '" height="' + bbox.height + '" ' +
18465 'viewBox="' + bbox.x + ' ' + bbox.y + ' ' + bbox.width + ' ' + bbox.height + '" version="1.1">' +
18466 defs + contents +
18467 '</svg>';
18468 } catch (e) {
18469 err = e;
18470 }
18471
18472 this._emit('saveSVG.done', {
18473 error: err,
18474 svg: svg
18475 });
18476
18477 done(err, svg);
18478 };
18479
18480 /**
18481 * Get a named diagram service.
18482 *
18483 * @example
18484 *
18485 * var elementRegistry = viewer.get('elementRegistry');
18486 * var startEventShape = elementRegistry.get('StartEvent_1');
18487 *
18488 * @param {String} name
18489 *
18490 * @return {Object} diagram service instance
18491 *
18492 * @method Viewer#get
18493 */
18494
18495 /**
18496 * Invoke a function in the context of this viewer.
18497 *
18498 * @example
18499 *
18500 * viewer.invoke(function(elementRegistry) {
18501 * var startEventShape = elementRegistry.get('StartEvent_1');
18502 * });
18503 *
18504 * @param {Function} fn to be invoked
18505 *
18506 * @return {Object} the functions return value
18507 *
18508 * @method Viewer#invoke
18509 */
18510
18511 /**
18512 * Remove all drawn elements from the viewer.
18513 *
18514 * After calling this method the viewer can still
18515 * be reused for opening another diagram.
18516 *
18517 * @method Viewer#clear
18518 */
18519
18520 Viewer.prototype.importDefinitions = function(definitions, done) {
18521
18522 // catch synchronous exceptions during #clear()
18523 try {
18524 if (this._definitions) {
18525 // clear existing rendered diagram
18526 this.clear();
18527 }
18528
18529 // update definitions
18530 this._definitions = definitions;
18531 } catch (e) {
18532 return done(e);
18533 }
18534
18535 // perform graphical import
18536 return importBpmnDiagram(this, definitions, done);
18537 };
18538
18539 Viewer.prototype.getModules = function() {
18540 return this._modules;
18541 };
18542
18543 /**
18544 * Destroy the viewer instance and remove all its
18545 * remainders from the document tree.
18546 */
18547 Viewer.prototype.destroy = function() {
18548
18549 // diagram destroy
18550 diagramJs.prototype.destroy.call(this);
18551
18552 // dom detach
18553 remove(this._container);
18554 };
18555
18556 /**
18557 * Register an event listener
18558 *
18559 * Remove a previously added listener via {@link #off(event, callback)}.
18560 *
18561 * @param {String} event
18562 * @param {Number} [priority]
18563 * @param {Function} callback
18564 * @param {Object} [that]
18565 */
18566 Viewer.prototype.on = function(event$$1, priority, callback, target) {
18567 return this.get('eventBus').on(event$$1, priority, callback, target);
18568 };
18569
18570 /**
18571 * De-register an event listener
18572 *
18573 * @param {String} event
18574 * @param {Function} callback
18575 */
18576 Viewer.prototype.off = function(event$$1, callback) {
18577 this.get('eventBus').off(event$$1, callback);
18578 };
18579
18580 Viewer.prototype.attachTo = function(parentNode) {
18581
18582 if (!parentNode) {
18583 throw new Error('parentNode required');
18584 }
18585
18586 // ensure we detach from the
18587 // previous, old parent
18588 this.detach();
18589
18590 // unwrap jQuery if provided
18591 if (parentNode.get && parentNode.constructor.prototype.jquery) {
18592 parentNode = parentNode.get(0);
18593 }
18594
18595 if (typeof parentNode === 'string') {
18596 parentNode = query(parentNode);
18597 }
18598
18599 parentNode.appendChild(this._container);
18600
18601 this._emit('attach', {});
18602
18603 this.get('canvas').resized();
18604 };
18605
18606 Viewer.prototype.getDefinitions = function() {
18607 return this._definitions;
18608 };
18609
18610 Viewer.prototype.detach = function() {
18611
18612 var container = this._container,
18613 parentNode = container.parentNode;
18614
18615 if (!parentNode) {
18616 return;
18617 }
18618
18619 this._emit('detach', {});
18620
18621 parentNode.removeChild(container);
18622 };
18623
18624 Viewer.prototype._init = function(container, moddle, options) {
18625
18626 var baseModules = options.modules || this.getModules(),
18627 additionalModules = options.additionalModules || [],
18628 staticModules = [
18629 {
18630 bpmnjs: [ 'value', this ],
18631 moddle: [ 'value', moddle ]
18632 }
18633 ];
18634
18635 var diagramModules = [].concat(staticModules, baseModules, additionalModules);
18636
18637 var diagramOptions = assign(omit(options, [ 'additionalModules' ]), {
18638 canvas: assign({}, options.canvas, { container: container }),
18639 modules: diagramModules
18640 });
18641
18642 // invoke diagram constructor
18643 diagramJs.call(this, diagramOptions);
18644
18645 if (options && options.container) {
18646 this.attachTo(options.container);
18647 }
18648 };
18649
18650 /**
18651 * Emit an event on the underlying {@link EventBus}
18652 *
18653 * @param {String} type
18654 * @param {Object} event
18655 *
18656 * @return {Object} event processing result (if any)
18657 */
18658 Viewer.prototype._emit = function(type, event$$1) {
18659 return this.get('eventBus').fire(type, event$$1);
18660 };
18661
18662 Viewer.prototype._createContainer = function(options) {
18663
18664 var container = domify('<div class="bjs-container"></div>');
18665
18666 assign(container.style, {
18667 width: ensureUnit(options.width),
18668 height: ensureUnit(options.height),
18669 position: options.position
18670 });
18671
18672 return container;
18673 };
18674
18675 Viewer.prototype._createModdle = function(options) {
18676 var moddleOptions = assign({}, this._moddleExtensions, options.moddleExtensions);
18677
18678 return new BpmnModdle$1(moddleOptions);
18679 };
18680
18681 // modules the viewer is composed of
18682 Viewer.prototype._modules = [
18683 CoreModule$1,
18684 translate$2,
18685 SelectionModule,
18686 OverlaysModule
18687 ];
18688
18689 // default moddle extensions the viewer is composed of
18690 Viewer.prototype._moddleExtensions = {};
18691
18692 /**
18693 * Adds the project logo to the diagram container as
18694 * required by the bpmn.io license.
18695 *
18696 * @see http://bpmn.io/license
18697 *
18698 * @param {Element} container
18699 */
18700 function addProjectLogo(container) {
18701 var img = BPMNIO_IMG;
18702
18703 var linkMarkup =
18704 '<a href="http://bpmn.io" ' +
18705 'target="_blank" ' +
18706 'class="bjs-powered-by" ' +
18707 'title="Powered by bpmn.io" ' +
18708 'style="position: absolute; bottom: 15px; right: 15px; z-index: 100">' +
18709 img +
18710 '</a>';
18711
18712 var linkElement = domify(linkMarkup);
18713
18714 container.appendChild(linkElement);
18715
18716 componentEvent.bind(linkElement, 'click', function(event$$1) {
18717 open();
18718
18719 event$$1.preventDefault();
18720 });
18721 }
18722
18723 /* </project-logo> */
18724
18725 /**
18726 * Returns true if event was triggered with any modifier
18727 * @param {KeyboardEvent} event
18728 */
18729 function hasModifier(event) {
18730 return (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey);
18731 }
18732
18733 /**
18734 * @param {KeyboardEvent} event
18735 */
18736 function isCmd(event) {
18737
18738 // ensure we don't react to AltGr
18739 // (mapped to CTRL + ALT)
18740 if (event.altKey) {
18741 return false;
18742 }
18743
18744 return event.ctrlKey || event.metaKey;
18745 }
18746
18747 /**
18748 * Checks if key pressed is one of provided keys.
18749 *
18750 * @param {String|String[]} keys
18751 * @param {KeyboardEvent} event
18752 */
18753 function isKey(keys$$1, event) {
18754 keys$$1 = isArray(keys$$1) ? keys$$1 : [ keys$$1 ];
18755
18756 return keys$$1.indexOf(event.key) > -1;
18757 }
18758
18759 /**
18760 * @param {KeyboardEvent} event
18761 */
18762 function isShift(event) {
18763 return event.shiftKey;
18764 }
18765
18766 var KEYDOWN_EVENT = 'keyboard.keydown';
18767
18768 var DEFAULT_PRIORITY$1 = 1000;
18769
18770
18771 /**
18772 * A keyboard abstraction that may be activated and
18773 * deactivated by users at will, consuming key events
18774 * and triggering diagram actions.
18775 *
18776 * For keys pressed down, keyboard fires `keyboard.keydown` event.
18777 * The event context contains one field which is `KeyboardEvent` event.
18778 *
18779 * The implementation fires the following key events that allow
18780 * other components to hook into key handling:
18781 *
18782 * - keyboard.bind
18783 * - keyboard.unbind
18784 * - keyboard.init
18785 * - keyboard.destroy
18786 *
18787 * All events contain one field which is node.
18788 *
18789 * A default binding for the keyboard may be specified via the
18790 * `keyboard.bindTo` configuration option.
18791 *
18792 * @param {Config} config
18793 * @param {EventBus} eventBus
18794 */
18795 function Keyboard(config, eventBus) {
18796 var self = this;
18797
18798 this._config = config || {};
18799 this._eventBus = eventBus;
18800
18801 this._keyHandler = this._keyHandler.bind(this);
18802
18803 // properly clean dom registrations
18804 eventBus.on('diagram.destroy', function() {
18805 self._fire('destroy');
18806
18807 self.unbind();
18808 });
18809
18810 eventBus.on('diagram.init', function() {
18811 self._fire('init');
18812 });
18813
18814 eventBus.on('attach', function() {
18815 if (config && config.bindTo) {
18816 self.bind(config.bindTo);
18817 }
18818 });
18819
18820 eventBus.on('detach', function() {
18821 self.unbind();
18822 });
18823 }
18824
18825 Keyboard.$inject = [
18826 'config.keyboard',
18827 'eventBus'
18828 ];
18829
18830 Keyboard.prototype._keyHandler = function(event$$1) {
18831
18832 var target = event$$1.target,
18833 eventBusResult;
18834
18835 if (isInput(target)) {
18836 return;
18837 }
18838
18839 var context = {
18840 keyEvent: event$$1
18841 };
18842
18843 eventBusResult = this._eventBus.fire(KEYDOWN_EVENT, context);
18844
18845 if (eventBusResult) {
18846 event$$1.preventDefault();
18847 }
18848 };
18849
18850 Keyboard.prototype.bind = function(node) {
18851
18852 // make sure that the keyboard is only bound once to the DOM
18853 this.unbind();
18854
18855 this._node = node;
18856
18857 // bind key events
18858 componentEvent.bind(node, 'keydown', this._keyHandler, true);
18859
18860 this._fire('bind');
18861 };
18862
18863 Keyboard.prototype.getBinding = function() {
18864 return this._node;
18865 };
18866
18867 Keyboard.prototype.unbind = function() {
18868 var node = this._node;
18869
18870 if (node) {
18871 this._fire('unbind');
18872
18873 // unbind key events
18874 componentEvent.unbind(node, 'keydown', this._keyHandler, true);
18875 }
18876
18877 this._node = null;
18878 };
18879
18880 Keyboard.prototype._fire = function(event$$1) {
18881 this._eventBus.fire('keyboard.' + event$$1, { node: this._node });
18882 };
18883
18884 /**
18885 * Add a listener function that is notified with `KeyboardEvent` whenever
18886 * the keyboard is bound and the user presses a key. If no priority is
18887 * provided, the default value of 1000 is used.
18888 *
18889 * @param {Number} priority
18890 * @param {Function} listener
18891 */
18892 Keyboard.prototype.addListener = function(priority, listener) {
18893 if (isFunction(priority)) {
18894 listener = priority;
18895 priority = DEFAULT_PRIORITY$1;
18896 }
18897
18898 this._eventBus.on(KEYDOWN_EVENT, priority, listener);
18899 };
18900
18901 Keyboard.prototype.hasModifier = hasModifier;
18902 Keyboard.prototype.isCmd = isCmd;
18903 Keyboard.prototype.isShift = isShift;
18904 Keyboard.prototype.isKey = isKey;
18905
18906
18907
18908 // helpers ///////
18909
18910 function isInput(target) {
18911 return target && (matchesSelector$1(target, 'input, textarea') || target.contentEditable === 'true');
18912 }
18913
18914 var LOW_PRIORITY$3 = 500;
18915
18916
18917 /**
18918 * Adds default keyboard bindings.
18919 *
18920 * This does not pull in any features will bind only actions that
18921 * have previously been registered against the editorActions component.
18922 *
18923 * @param {EventBus} eventBus
18924 * @param {Keyboard} keyboard
18925 */
18926 function KeyboardBindings(eventBus, keyboard) {
18927
18928 var self = this;
18929
18930 eventBus.on('editorActions.init', LOW_PRIORITY$3, function(event) {
18931
18932 var editorActions = event.editorActions;
18933
18934 self.registerBindings(keyboard, editorActions);
18935 });
18936 }
18937
18938 KeyboardBindings.$inject = [
18939 'eventBus',
18940 'keyboard'
18941 ];
18942
18943
18944 /**
18945 * Register available keyboard bindings.
18946 *
18947 * @param {Keyboard} keyboard
18948 * @param {EditorActions} editorActions
18949 */
18950 KeyboardBindings.prototype.registerBindings = function(keyboard, editorActions) {
18951
18952 /**
18953 * Add keyboard binding if respective editor action
18954 * is registered.
18955 *
18956 * @param {String} action name
18957 * @param {Function} fn that implements the key binding
18958 */
18959 function addListener(action, fn) {
18960
18961 if (editorActions.isRegistered(action)) {
18962 keyboard.addListener(fn);
18963 }
18964 }
18965
18966
18967 // undo
18968 // (CTRL|CMD) + Z
18969 addListener('undo', function(context) {
18970
18971 var event = context.keyEvent;
18972
18973 if (isCmd(event) && !isShift(event) && isKey(['z', 'Z'], event)) {
18974 editorActions.trigger('undo');
18975
18976 return true;
18977 }
18978 });
18979
18980 // redo
18981 // CTRL + Y
18982 // CMD + SHIFT + Z
18983 addListener('redo', function(context) {
18984
18985 var event = context.keyEvent;
18986
18987 if (isCmd(event) && (isKey(['y', 'Y'], event) || (isKey(['z', 'Z'], event) && isShift(event)))) {
18988 editorActions.trigger('redo');
18989
18990 return true;
18991 }
18992 });
18993
18994 // copy
18995 // CTRL/CMD + C
18996 addListener('copy', function(context) {
18997
18998 var event = context.keyEvent;
18999
19000 if (isCmd(event) && isKey(['c', 'C'], event)) {
19001 editorActions.trigger('copy');
19002
19003 return true;
19004 }
19005 });
19006
19007 // paste
19008 // CTRL/CMD + V
19009 addListener('paste', function(context) {
19010
19011 var event = context.keyEvent;
19012
19013 if (isCmd(event) && isKey(['v', 'V'], event)) {
19014 editorActions.trigger('paste');
19015
19016 return true;
19017 }
19018 });
19019
19020 // zoom in one step
19021 // CTRL/CMD + +
19022 addListener('stepZoom', function(context) {
19023
19024 var event = context.keyEvent;
19025
19026 if (isKey([ '+', 'Add' ], event) && isCmd(event)) {
19027 editorActions.trigger('stepZoom', { value: 1 });
19028
19029 return true;
19030 }
19031 });
19032
19033 // zoom out one step
19034 // CTRL + -
19035 addListener('stepZoom', function(context) {
19036
19037 var event = context.keyEvent;
19038
19039 if (isKey([ '-', 'Subtract' ], event) && isCmd(event)) {
19040 editorActions.trigger('stepZoom', { value: -1 });
19041
19042 return true;
19043 }
19044 });
19045
19046 // zoom to the default level
19047 // CTRL + 0
19048 addListener('zoom', function(context) {
19049
19050 var event = context.keyEvent;
19051
19052 if (isKey('0', event) && isCmd(event)) {
19053 editorActions.trigger('zoom', { value: 1 });
19054
19055 return true;
19056 }
19057 });
19058
19059 // delete selected element
19060 // DEL
19061 addListener('removeSelection', function(context) {
19062
19063 var event = context.keyEvent;
19064
19065 if (isKey([ 'Delete', 'Del' ], event)) {
19066 editorActions.trigger('removeSelection');
19067
19068 return true;
19069 }
19070 });
19071 };
19072
19073 var KeyboardModule = {
19074 __init__: [ 'keyboard', 'keyboardBindings' ],
19075 keyboard: [ 'type', Keyboard ],
19076 keyboardBindings: [ 'type', KeyboardBindings ]
19077 };
19078
19079 var DEFAULT_CONFIG = {
19080 moveSpeed: 50,
19081 moveSpeedAccelerated: 200
19082 };
19083
19084
19085 /**
19086 * A feature that allows users to move the canvas using the keyboard.
19087 *
19088 * @param {Object} config
19089 * @param {Number} [config.moveSpeed=50]
19090 * @param {Number} [config.moveSpeedAccelerated=200]
19091 * @param {Keyboard} keyboard
19092 * @param {Canvas} canvas
19093 */
19094 function KeyboardMove(
19095 config,
19096 keyboard,
19097 canvas
19098 ) {
19099
19100 var self = this;
19101
19102 this._config = assign({}, DEFAULT_CONFIG, config || {});
19103
19104 keyboard.addListener(arrowsListener);
19105
19106
19107 function arrowsListener(context) {
19108
19109 var event = context.keyEvent,
19110 config = self._config;
19111
19112 if (!keyboard.isCmd(event)) {
19113 return;
19114 }
19115
19116 if (keyboard.isKey([
19117 'ArrowLeft', 'Left',
19118 'ArrowUp', 'Up',
19119 'ArrowDown', 'Down',
19120 'ArrowRight', 'Right'
19121 ], event)) {
19122
19123 var speed = (
19124 keyboard.isShift(event) ?
19125 config.moveSpeedAccelerated :
19126 config.moveSpeed
19127 );
19128
19129 var direction;
19130
19131 switch (event.key) {
19132 case 'ArrowLeft':
19133 case 'Left':
19134 direction = 'left';
19135 break;
19136 case 'ArrowUp':
19137 case 'Up':
19138 direction = 'up';
19139 break;
19140 case 'ArrowRight':
19141 case 'Right':
19142 direction = 'right';
19143 break;
19144 case 'ArrowDown':
19145 case 'Down':
19146 direction = 'down';
19147 break;
19148 }
19149
19150 self.moveCanvas({
19151 speed: speed,
19152 direction: direction
19153 });
19154
19155 return true;
19156 }
19157 }
19158
19159 this.moveCanvas = function(opts) {
19160
19161 var dx = 0,
19162 dy = 0,
19163 speed = opts.speed;
19164
19165 var actualSpeed = speed / Math.min(Math.sqrt(canvas.viewbox().scale), 1);
19166
19167 switch (opts.direction) {
19168 case 'left': // Left
19169 dx = actualSpeed;
19170 break;
19171 case 'up': // Up
19172 dy = actualSpeed;
19173 break;
19174 case 'right': // Right
19175 dx = -actualSpeed;
19176 break;
19177 case 'down': // Down
19178 dy = -actualSpeed;
19179 break;
19180 }
19181
19182 canvas.scroll({
19183 dx: dx,
19184 dy: dy
19185 });
19186 };
19187
19188 }
19189
19190
19191 KeyboardMove.$inject = [
19192 'config.keyboardMove',
19193 'keyboard',
19194 'canvas'
19195 ];
19196
19197 var KeyboardMoveModule = {
19198 __depends__: [
19199 KeyboardModule
19200 ],
19201 __init__: [ 'keyboardMove' ],
19202 keyboardMove: [ 'type', KeyboardMove ]
19203 };
19204
19205 var CURSOR_CLS_PATTERN = /^djs-cursor-.*$/;
19206
19207
19208 function set$1(mode) {
19209 var classes$$1 = classes(document.body);
19210
19211 classes$$1.removeMatching(CURSOR_CLS_PATTERN);
19212
19213 if (mode) {
19214 classes$$1.add('djs-cursor-' + mode);
19215 }
19216 }
19217
19218 function unset() {
19219 set$1(null);
19220 }
19221
19222 var TRAP_PRIORITY = 5000;
19223
19224 /**
19225 * Installs a click trap that prevents a ghost click following a dragging operation.
19226 *
19227 * @return {Function} a function to immediately remove the installed trap.
19228 */
19229 function install(eventBus, eventName) {
19230
19231 eventName = eventName || 'element.click';
19232
19233 function trap() {
19234 return false;
19235 }
19236
19237 eventBus.once(eventName, TRAP_PRIORITY, trap);
19238
19239 return function() {
19240 eventBus.off(eventName, trap);
19241 };
19242 }
19243
19244 function delta(a, b) {
19245 return {
19246 x: a.x - b.x,
19247 y: a.y - b.y
19248 };
19249 }
19250
19251 var THRESHOLD = 15;
19252
19253
19254 /**
19255 * Move the canvas via mouse.
19256 *
19257 * @param {EventBus} eventBus
19258 * @param {Canvas} canvas
19259 */
19260 function MoveCanvas(eventBus, canvas) {
19261
19262 var context;
19263
19264
19265 // listen for move on element mouse down;
19266 // allow others to hook into the event before us though
19267 // (dragging / element moving will do this)
19268 eventBus.on('element.mousedown', 500, function(e) {
19269 return handleStart(e.originalEvent);
19270 });
19271
19272
19273 function handleMove(event$$1) {
19274
19275 var start = context.start,
19276 position = toPoint(event$$1),
19277 delta$$1 = delta(position, start);
19278
19279 if (!context.dragging && length(delta$$1) > THRESHOLD) {
19280 context.dragging = true;
19281
19282 install(eventBus);
19283
19284 set$1('grab');
19285 }
19286
19287 if (context.dragging) {
19288
19289 var lastPosition = context.last || context.start;
19290
19291 delta$$1 = delta(position, lastPosition);
19292
19293 canvas.scroll({
19294 dx: delta$$1.x,
19295 dy: delta$$1.y
19296 });
19297
19298 context.last = position;
19299 }
19300
19301 // prevent select
19302 event$$1.preventDefault();
19303 }
19304
19305
19306 function handleEnd(event$$1) {
19307 componentEvent.unbind(document, 'mousemove', handleMove);
19308 componentEvent.unbind(document, 'mouseup', handleEnd);
19309
19310 context = null;
19311
19312 unset();
19313 }
19314
19315 function handleStart(event$$1) {
19316 // event is already handled by '.djs-draggable'
19317 if (closest(event$$1.target, '.djs-draggable')) {
19318 return;
19319 }
19320
19321
19322 // reject non-left left mouse button or modifier key
19323 if (event$$1.button || event$$1.ctrlKey || event$$1.shiftKey || event$$1.altKey) {
19324 return;
19325 }
19326
19327 context = {
19328 start: toPoint(event$$1)
19329 };
19330
19331 componentEvent.bind(document, 'mousemove', handleMove);
19332 componentEvent.bind(document, 'mouseup', handleEnd);
19333
19334 // we've handled the event
19335 return true;
19336 }
19337 }
19338
19339
19340 MoveCanvas.$inject = [
19341 'eventBus',
19342 'canvas'
19343 ];
19344
19345
19346
19347 // helpers ///////
19348
19349 function length(point) {
19350 return Math.sqrt(Math.pow(point.x, 2) + Math.pow(point.y, 2));
19351 }
19352
19353 var MoveCanvasModule = {
19354 __init__: [ 'moveCanvas' ],
19355 moveCanvas: [ 'type', MoveCanvas ]
19356 };
19357
19358 /**
19359 * Get the logarithm of x with base 10
19360 * @param {Integer} value
19361 */
19362 function log10(x) {
19363 return Math.log(x) / Math.log(10);
19364 }
19365
19366 /**
19367 * Get step size for given range and number of steps.
19368 *
19369 * @param {Object} range - Range.
19370 * @param {number} range.min - Range minimum.
19371 * @param {number} range.max - Range maximum.
19372 */
19373 function getStepSize(range, steps) {
19374
19375 var minLinearRange = log10(range.min),
19376 maxLinearRange = log10(range.max);
19377
19378 var absoluteLinearRange = Math.abs(minLinearRange) + Math.abs(maxLinearRange);
19379
19380 return absoluteLinearRange / steps;
19381 }
19382
19383 function cap(range, scale) {
19384 return Math.max(range.min, Math.min(range.max, scale));
19385 }
19386
19387 var sign = Math.sign || function(n) {
19388 return n >= 0 ? 1 : -1;
19389 };
19390
19391 var RANGE = { min: 0.2, max: 4 },
19392 NUM_STEPS = 10;
19393
19394 var DELTA_THRESHOLD = 0.1;
19395
19396 var DEFAULT_SCALE = 0.75;
19397
19398 /**
19399 * An implementation of zooming and scrolling within the
19400 * {@link Canvas} via the mouse wheel.
19401 *
19402 * Mouse wheel zooming / scrolling may be disabled using
19403 * the {@link toggle(enabled)} method.
19404 *
19405 * @param {Object} [config]
19406 * @param {Boolean} [config.enabled=true] default enabled state
19407 * @param {Number} [config.scale=.75] scroll sensivity
19408 * @param {EventBus} eventBus
19409 * @param {Canvas} canvas
19410 */
19411 function ZoomScroll(config, eventBus, canvas) {
19412
19413 config = config || {};
19414
19415 this._enabled = false;
19416
19417 this._canvas = canvas;
19418 this._container = canvas._container;
19419
19420 this._handleWheel = bind(this._handleWheel, this);
19421
19422 this._totalDelta = 0;
19423 this._scale = config.scale || DEFAULT_SCALE;
19424
19425 var self = this;
19426
19427 eventBus.on('canvas.init', function(e) {
19428 self._init(config.enabled !== false);
19429 });
19430 }
19431
19432 ZoomScroll.$inject = [
19433 'config.zoomScroll',
19434 'eventBus',
19435 'canvas'
19436 ];
19437
19438 ZoomScroll.prototype.scroll = function scroll(delta$$1) {
19439 this._canvas.scroll(delta$$1);
19440 };
19441
19442
19443 ZoomScroll.prototype.reset = function reset() {
19444 this._canvas.zoom('fit-viewport');
19445 };
19446
19447 /**
19448 * Zoom depending on delta.
19449 *
19450 * @param {number} delta - Zoom delta.
19451 * @param {Object} position - Zoom position.
19452 */
19453 ZoomScroll.prototype.zoom = function zoom(delta$$1, position) {
19454
19455 // zoom with half the step size of stepZoom
19456 var stepSize = getStepSize(RANGE, NUM_STEPS * 2);
19457
19458 // add until threshold reached
19459 this._totalDelta += delta$$1;
19460
19461 if (Math.abs(this._totalDelta) > DELTA_THRESHOLD) {
19462 this._zoom(delta$$1, position, stepSize);
19463
19464 // reset
19465 this._totalDelta = 0;
19466 }
19467 };
19468
19469
19470 ZoomScroll.prototype._handleWheel = function handleWheel(event$$1) {
19471 // event is already handled by '.djs-scrollable'
19472 if (closest(event$$1.target, '.djs-scrollable', true)) {
19473 return;
19474 }
19475
19476 var element = this._container;
19477
19478 event$$1.preventDefault();
19479
19480 // pinch to zoom is mapped to wheel + ctrlKey = true
19481 // in modern browsers (!)
19482
19483 var isZoom = event$$1.ctrlKey;
19484
19485 var isHorizontalScroll = event$$1.shiftKey;
19486
19487 var factor = -1 * this._scale,
19488 delta$$1;
19489
19490 if (isZoom) {
19491 factor *= event$$1.deltaMode === 0 ? 0.020 : 0.32;
19492 } else {
19493 factor *= event$$1.deltaMode === 0 ? 1.0 : 16.0;
19494 }
19495
19496 if (isZoom) {
19497 var elementRect = element.getBoundingClientRect();
19498
19499 var offset = {
19500 x: event$$1.clientX - elementRect.left,
19501 y: event$$1.clientY - elementRect.top
19502 };
19503
19504 delta$$1 = (
19505 Math.sqrt(
19506 Math.pow(event$$1.deltaY, 2) +
19507 Math.pow(event$$1.deltaX, 2)
19508 ) * sign(event$$1.deltaY) * factor
19509 );
19510
19511 // zoom in relative to diagram {x,y} coordinates
19512 this.zoom(delta$$1, offset);
19513 } else {
19514
19515 if (isHorizontalScroll) {
19516 delta$$1 = {
19517 dx: factor * event$$1.deltaY,
19518 dy: 0
19519 };
19520 } else {
19521 delta$$1 = {
19522 dx: factor * event$$1.deltaX,
19523 dy: factor * event$$1.deltaY
19524 };
19525 }
19526
19527 this.scroll(delta$$1);
19528 }
19529 };
19530
19531 /**
19532 * Zoom with fixed step size.
19533 *
19534 * @param {number} delta - Zoom delta (1 for zooming in, -1 for out).
19535 * @param {Object} position - Zoom position.
19536 */
19537 ZoomScroll.prototype.stepZoom = function stepZoom(delta$$1, position) {
19538
19539 var stepSize = getStepSize(RANGE, NUM_STEPS);
19540
19541 this._zoom(delta$$1, position, stepSize);
19542 };
19543
19544
19545 /**
19546 * Zoom in/out given a step size.
19547 *
19548 * @param {number} delta - Zoom delta. Can be positive or negative.
19549 * @param {Object} position - Zoom position.
19550 * @param {number} stepSize - Step size.
19551 */
19552 ZoomScroll.prototype._zoom = function(delta$$1, position, stepSize) {
19553 var canvas = this._canvas;
19554
19555 var direction = delta$$1 > 0 ? 1 : -1;
19556
19557 var currentLinearZoomLevel = log10(canvas.zoom());
19558
19559 // snap to a proximate zoom step
19560 var newLinearZoomLevel = Math.round(currentLinearZoomLevel / stepSize) * stepSize;
19561
19562 // increase or decrease one zoom step in the given direction
19563 newLinearZoomLevel += stepSize * direction;
19564
19565 // calculate the absolute logarithmic zoom level based on the linear zoom level
19566 // (e.g. 2 for an absolute x2 zoom)
19567 var newLogZoomLevel = Math.pow(10, newLinearZoomLevel);
19568
19569 canvas.zoom(cap(RANGE, newLogZoomLevel), position);
19570 };
19571
19572
19573 /**
19574 * Toggle the zoom scroll ability via mouse wheel.
19575 *
19576 * @param {Boolean} [newEnabled] new enabled state
19577 */
19578 ZoomScroll.prototype.toggle = function toggle(newEnabled) {
19579
19580 var element = this._container;
19581 var handleWheel = this._handleWheel;
19582
19583 var oldEnabled = this._enabled;
19584
19585 if (typeof newEnabled === 'undefined') {
19586 newEnabled = !oldEnabled;
19587 }
19588
19589 // only react on actual changes
19590 if (oldEnabled !== newEnabled) {
19591
19592 // add or remove wheel listener based on
19593 // changed enabled state
19594 componentEvent[newEnabled ? 'bind' : 'unbind'](element, 'wheel', handleWheel, false);
19595 }
19596
19597 this._enabled = newEnabled;
19598
19599 return newEnabled;
19600 };
19601
19602
19603 ZoomScroll.prototype._init = function(newEnabled) {
19604 this.toggle(newEnabled);
19605 };
19606
19607 var ZoomScrollModule = {
19608 __init__: [ 'zoomScroll' ],
19609 zoomScroll: [ 'type', ZoomScroll ]
19610 };
19611
19612 /**
19613 * A viewer that includes mouse navigation facilities
19614 *
19615 * @param {Object} options
19616 */
19617 function NavigatedViewer(options) {
19618 Viewer.call(this, options);
19619 }
19620
19621 inherits_browser(NavigatedViewer, Viewer);
19622
19623 NavigatedViewer.prototype._navigationModules = [
19624 KeyboardMoveModule,
19625 MoveCanvasModule,
19626 ZoomScrollModule
19627 ];
19628
19629 NavigatedViewer.prototype._modules = [].concat(
19630 NavigatedViewer.prototype._modules,
19631 NavigatedViewer.prototype._navigationModules);
19632
19633 return NavigatedViewer;
19634
19635})));