1/*!
2 * bpmn-js - bpmn-modeler v8.8.2
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: 2021-10-20
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 = typeof globalThis !== 'undefined' ? globalThis : global || self, global.BpmnJS = factory());
17}(this, (function () { 'use strict';
18
19	var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
20
21	var inherits_browser = {exports: {}};
22
23	if (typeof Object.create === 'function') {
24	  // implementation from standard node.js 'util' module
25	  inherits_browser.exports = function inherits(ctor, superCtor) {
26	    if (superCtor) {
27	      ctor.super_ = superCtor;
28	      ctor.prototype = Object.create(superCtor.prototype, {
29	        constructor: {
30	          value: ctor,
31	          enumerable: false,
32	          writable: true,
33	          configurable: true
34	        }
35	      });
36	    }
37	  };
38	} else {
39	  // old school shim for old browsers
40	  inherits_browser.exports = function inherits(ctor, superCtor) {
41	    if (superCtor) {
42	      ctor.super_ = superCtor;
43	      var TempCtor = function () {};
44	      TempCtor.prototype = superCtor.prototype;
45	      ctor.prototype = new TempCtor();
46	      ctor.prototype.constructor = ctor;
47	    }
48	  };
49	}
50
51	var inherits$1 = inherits_browser.exports;
52
53	function createCommonjsModule(fn, module) {
54		return module = { exports: {} }, fn(module, module.exports), module.exports;
55	}
56
57	var hat_1 = createCommonjsModule(function (module) {
58	var hat = module.exports = function (bits, base) {
59	    if (!base) base = 16;
60	    if (bits === undefined) bits = 128;
61	    if (bits <= 0) return '0';
62
63	    var digits = Math.log(Math.pow(2, bits)) / Math.log(base);
64	    for (var i = 2; digits === Infinity; i *= 2) {
65	        digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i;
66	    }
67
68	    var rem = digits - Math.floor(digits);
69
70	    var res = '';
71
72	    for (var i = 0; i < Math.floor(digits); i++) {
73	        var x = Math.floor(Math.random() * base).toString(base);
74	        res = x + res;
75	    }
76
77	    if (rem) {
78	        var b = Math.pow(base, rem);
79	        var x = Math.floor(Math.random() * b).toString(base);
80	        res = x + res;
81	    }
82
83	    var parsed = parseInt(res, base);
84	    if (parsed !== Infinity && parsed >= Math.pow(2, bits)) {
85	        return hat(bits, base)
86	    }
87	    else return res;
88	};
89
90	hat.rack = function (bits, base, expandBy) {
91	    var fn = function (data) {
92	        var iters = 0;
93	        do {
94	            if (iters ++ > 10) {
95	                if (expandBy) bits += expandBy;
96	                else throw new Error('too many ID collisions, use more bits')
97	            }
98
99	            var id = hat(bits, base);
100	        } while (Object.hasOwnProperty.call(hats, id));
101
102	        hats[id] = data;
103	        return id;
104	    };
105	    var hats = fn.hats = {};
106
107	    fn.get = function (id) {
108	        return fn.hats[id];
109	    };
110
111	    fn.set = function (id, value) {
112	        fn.hats[id] = value;
113	        return fn;
114	    };
115
116	    fn.bits = bits || 128;
117	    fn.base = base || 16;
118	    return fn;
119	};
120	});
121
122	/**
123	 * Create a new id generator / cache instance.
124	 *
125	 * You may optionally provide a seed that is used internally.
126	 *
127	 * @param {Seed} seed
128	 */
129
130	function Ids(seed) {
131	  if (!(this instanceof Ids)) {
132	    return new Ids(seed);
133	  }
134
135	  seed = seed || [128, 36, 1];
136	  this._seed = seed.length ? hat_1.rack(seed[0], seed[1], seed[2]) : seed;
137	}
138	/**
139	 * Generate a next id.
140	 *
141	 * @param {Object} [element] element to bind the id to
142	 *
143	 * @return {String} id
144	 */
145
146	Ids.prototype.next = function (element) {
147	  return this._seed(element || true);
148	};
149	/**
150	 * Generate a next id with a given prefix.
151	 *
152	 * @param {Object} [element] element to bind the id to
153	 *
154	 * @return {String} id
155	 */
156
157
158	Ids.prototype.nextPrefixed = function (prefix, element) {
159	  var id;
160
161	  do {
162	    id = prefix + this.next(true);
163	  } while (this.assigned(id)); // claim {prefix}{random}
164
165
166	  this.claim(id, element); // return
167
168	  return id;
169	};
170	/**
171	 * Manually claim an existing id.
172	 *
173	 * @param {String} id
174	 * @param {String} [element] element the id is claimed by
175	 */
176
177
178	Ids.prototype.claim = function (id, element) {
179	  this._seed.set(id, element || true);
180	};
181	/**
182	 * Returns true if the given id has already been assigned.
183	 *
184	 * @param  {String} id
185	 * @return {Boolean}
186	 */
187
188
189	Ids.prototype.assigned = function (id) {
190	  return this._seed.get(id) || false;
191	};
192	/**
193	 * Unclaim an id.
194	 *
195	 * @param  {String} id the id to unclaim
196	 */
197
198
199	Ids.prototype.unclaim = function (id) {
200	  delete this._seed.hats[id];
201	};
202	/**
203	 * Clear all claimed ids.
204	 */
205
206
207	Ids.prototype.clear = function () {
208	  var hats = this._seed.hats,
209	      id;
210
211	  for (id in hats) {
212	    this.unclaim(id);
213	  }
214	};
215
216	/**
217	 * Flatten array, one level deep.
218	 *
219	 * @param {Array<?>} arr
220	 *
221	 * @return {Array<?>}
222	 */
223	function flatten(arr) {
224	  return Array.prototype.concat.apply([], arr);
225	}
226
227	var nativeToString = Object.prototype.toString;
228	var nativeHasOwnProperty = Object.prototype.hasOwnProperty;
229	function isUndefined$1(obj) {
230	  return obj === undefined;
231	}
232	function isDefined(obj) {
233	  return obj !== undefined;
234	}
235	function isNil(obj) {
236	  return obj == null;
237	}
238	function isArray$2(obj) {
239	  return nativeToString.call(obj) === '[object Array]';
240	}
241	function isObject(obj) {
242	  return nativeToString.call(obj) === '[object Object]';
243	}
244	function isNumber(obj) {
245	  return nativeToString.call(obj) === '[object Number]';
246	}
247	function isFunction(obj) {
248	  var tag = nativeToString.call(obj);
249	  return tag === '[object Function]' || tag === '[object AsyncFunction]' || tag === '[object GeneratorFunction]' || tag === '[object AsyncGeneratorFunction]' || tag === '[object Proxy]';
250	}
251	function isString(obj) {
252	  return nativeToString.call(obj) === '[object String]';
253	}
254	/**
255	 * Ensure collection is an array.
256	 *
257	 * @param {Object} obj
258	 */
259
260	function ensureArray(obj) {
261	  if (isArray$2(obj)) {
262	    return;
263	  }
264
265	  throw new Error('must supply array');
266	}
267	/**
268	 * Return true, if target owns a property with the given key.
269	 *
270	 * @param {Object} target
271	 * @param {String} key
272	 *
273	 * @return {Boolean}
274	 */
275
276	function has(target, key) {
277	  return nativeHasOwnProperty.call(target, key);
278	}
279
280	/**
281	 * Find element in collection.
282	 *
283	 * @param  {Array|Object} collection
284	 * @param  {Function|Object} matcher
285	 *
286	 * @return {Object}
287	 */
288
289	function find(collection, matcher) {
290	  matcher = toMatcher(matcher);
291	  var match;
292	  forEach(collection, function (val, key) {
293	    if (matcher(val, key)) {
294	      match = val;
295	      return false;
296	    }
297	  });
298	  return match;
299	}
300	/**
301	 * Find element index in collection.
302	 *
303	 * @param  {Array|Object} collection
304	 * @param  {Function} matcher
305	 *
306	 * @return {Object}
307	 */
308
309	function findIndex(collection, matcher) {
310	  matcher = toMatcher(matcher);
311	  var idx = isArray$2(collection) ? -1 : undefined;
312	  forEach(collection, function (val, key) {
313	    if (matcher(val, key)) {
314	      idx = key;
315	      return false;
316	    }
317	  });
318	  return idx;
319	}
320	/**
321	 * Find element in collection.
322	 *
323	 * @param  {Array|Object} collection
324	 * @param  {Function} matcher
325	 *
326	 * @return {Array} result
327	 */
328
329	function filter(collection, matcher) {
330	  var result = [];
331	  forEach(collection, function (val, key) {
332	    if (matcher(val, key)) {
333	      result.push(val);
334	    }
335	  });
336	  return result;
337	}
338	/**
339	 * Iterate over collection; returning something
340	 * (non-undefined) will stop iteration.
341	 *
342	 * @param  {Array|Object} collection
343	 * @param  {Function} iterator
344	 *
345	 * @return {Object} return result that stopped the iteration
346	 */
347
348	function forEach(collection, iterator) {
349	  var val, result;
350
351	  if (isUndefined$1(collection)) {
352	    return;
353	  }
354
355	  var convertKey = isArray$2(collection) ? toNum : identity;
356
357	  for (var key in collection) {
358	    if (has(collection, key)) {
359	      val = collection[key];
360	      result = iterator(val, convertKey(key));
361
362	      if (result === false) {
363	        return val;
364	      }
365	    }
366	  }
367	}
368	/**
369	 * Return collection without element.
370	 *
371	 * @param  {Array} arr
372	 * @param  {Function} matcher
373	 *
374	 * @return {Array}
375	 */
376
377	function without(arr, matcher) {
378	  if (isUndefined$1(arr)) {
379	    return [];
380	  }
381
382	  ensureArray(arr);
383	  matcher = toMatcher(matcher);
384	  return arr.filter(function (el, idx) {
385	    return !matcher(el, idx);
386	  });
387	}
388	/**
389	 * Reduce collection, returning a single result.
390	 *
391	 * @param  {Object|Array} collection
392	 * @param  {Function} iterator
393	 * @param  {Any} result
394	 *
395	 * @return {Any} result returned from last iterator
396	 */
397
398	function reduce(collection, iterator, result) {
399	  forEach(collection, function (value, idx) {
400	    result = iterator(result, value, idx);
401	  });
402	  return result;
403	}
404	/**
405	 * Return true if every element in the collection
406	 * matches the criteria.
407	 *
408	 * @param  {Object|Array} collection
409	 * @param  {Function} matcher
410	 *
411	 * @return {Boolean}
412	 */
413
414	function every(collection, matcher) {
415	  return !!reduce(collection, function (matches, val, key) {
416	    return matches && matcher(val, key);
417	  }, true);
418	}
419	/**
420	 * Return true if some elements in the collection
421	 * match the criteria.
422	 *
423	 * @param  {Object|Array} collection
424	 * @param  {Function} matcher
425	 *
426	 * @return {Boolean}
427	 */
428
429	function some(collection, matcher) {
430	  return !!find(collection, matcher);
431	}
432	/**
433	 * Transform a collection into another collection
434	 * by piping each member through the given fn.
435	 *
436	 * @param  {Object|Array}   collection
437	 * @param  {Function} fn
438	 *
439	 * @return {Array} transformed collection
440	 */
441
442	function map$1(collection, fn) {
443	  var result = [];
444	  forEach(collection, function (val, key) {
445	    result.push(fn(val, key));
446	  });
447	  return result;
448	}
449	/**
450	 * Get the collections keys.
451	 *
452	 * @param  {Object|Array} collection
453	 *
454	 * @return {Array}
455	 */
456
457	function keys(collection) {
458	  return collection && Object.keys(collection) || [];
459	}
460	/**
461	 * Shorthand for `keys(o).length`.
462	 *
463	 * @param  {Object|Array} collection
464	 *
465	 * @return {Number}
466	 */
467
468	function size(collection) {
469	  return keys(collection).length;
470	}
471	/**
472	 * Get the values in the collection.
473	 *
474	 * @param  {Object|Array} collection
475	 *
476	 * @return {Array}
477	 */
478
479	function values(collection) {
480	  return map$1(collection, function (val) {
481	    return val;
482	  });
483	}
484	/**
485	 * Group collection members by attribute.
486	 *
487	 * @param  {Object|Array} collection
488	 * @param  {Function} extractor
489	 *
490	 * @return {Object} map with { attrValue => [ a, b, c ] }
491	 */
492
493	function groupBy(collection, extractor) {
494	  var grouped = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
495	  extractor = toExtractor(extractor);
496	  forEach(collection, function (val) {
497	    var discriminator = extractor(val) || '_';
498	    var group = grouped[discriminator];
499
500	    if (!group) {
501	      group = grouped[discriminator] = [];
502	    }
503
504	    group.push(val);
505	  });
506	  return grouped;
507	}
508	function uniqueBy(extractor) {
509	  extractor = toExtractor(extractor);
510	  var grouped = {};
511
512	  for (var _len = arguments.length, collections = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
513	    collections[_key - 1] = arguments[_key];
514	  }
515
516	  forEach(collections, function (c) {
517	    return groupBy(c, extractor, grouped);
518	  });
519	  var result = map$1(grouped, function (val, key) {
520	    return val[0];
521	  });
522	  return result;
523	}
524	var unionBy = uniqueBy;
525	/**
526	 * Sort collection by criteria.
527	 *
528	 * @param  {Object|Array} collection
529	 * @param  {String|Function} extractor
530	 *
531	 * @return {Array}
532	 */
533
534	function sortBy(collection, extractor) {
535	  extractor = toExtractor(extractor);
536	  var sorted = [];
537	  forEach(collection, function (value, key) {
538	    var disc = extractor(value, key);
539	    var entry = {
540	      d: disc,
541	      v: value
542	    };
543
544	    for (var idx = 0; idx < sorted.length; idx++) {
545	      var d = sorted[idx].d;
546
547	      if (disc < d) {
548	        sorted.splice(idx, 0, entry);
549	        return;
550	      }
551	    } // not inserted, append (!)
552
553
554	    sorted.push(entry);
555	  });
556	  return map$1(sorted, function (e) {
557	    return e.v;
558	  });
559	}
560	/**
561	 * Create an object pattern matcher.
562	 *
563	 * @example
564	 *
565	 * const matcher = matchPattern({ id: 1 });
566	 *
567	 * var element = find(elements, matcher);
568	 *
569	 * @param  {Object} pattern
570	 *
571	 * @return {Function} matcherFn
572	 */
573
574	function matchPattern(pattern) {
575	  return function (el) {
576	    return every(pattern, function (val, key) {
577	      return el[key] === val;
578	    });
579	  };
580	}
581
582	function toExtractor(extractor) {
583	  return isFunction(extractor) ? extractor : function (e) {
584	    return e[extractor];
585	  };
586	}
587
588	function toMatcher(matcher) {
589	  return isFunction(matcher) ? matcher : function (e) {
590	    return e === matcher;
591	  };
592	}
593
594	function identity(arg) {
595	  return arg;
596	}
597
598	function toNum(arg) {
599	  return Number(arg);
600	}
601
602	/**
603	 * Debounce fn, calling it only once if
604	 * the given time elapsed between calls.
605	 *
606	 * @param  {Function} fn
607	 * @param  {Number} timeout
608	 *
609	 * @return {Function} debounced function
610	 */
611	function debounce(fn, timeout) {
612	  var timer;
613	  var lastArgs;
614	  var lastThis;
615	  var lastNow;
616
617	  function fire() {
618	    var now = Date.now();
619	    var scheduledDiff = lastNow + timeout - now;
620
621	    if (scheduledDiff > 0) {
622	      return schedule(scheduledDiff);
623	    }
624
625	    fn.apply(lastThis, lastArgs);
626	    timer = lastNow = lastArgs = lastThis = undefined;
627	  }
628
629	  function schedule(timeout) {
630	    timer = setTimeout(fire, timeout);
631	  }
632
633	  return function () {
634	    lastNow = Date.now();
635
636	    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
637	      args[_key] = arguments[_key];
638	    }
639
640	    lastArgs = args;
641	    lastThis = this; // ensure an execution is scheduled
642
643	    if (!timer) {
644	      schedule(timeout);
645	    }
646	  };
647	}
648	/**
649	 * Bind function against target <this>.
650	 *
651	 * @param  {Function} fn
652	 * @param  {Object}   target
653	 *
654	 * @return {Function} bound function
655	 */
656
657	function bind$2(fn, target) {
658	  return fn.bind(target);
659	}
660
661	function _extends() {
662	  _extends = Object.assign || function (target) {
663	    for (var i = 1; i < arguments.length; i++) {
664	      var source = arguments[i];
665
666	      for (var key in source) {
667	        if (Object.prototype.hasOwnProperty.call(source, key)) {
668	          target[key] = source[key];
669	        }
670	      }
671	    }
672
673	    return target;
674	  };
675
676	  return _extends.apply(this, arguments);
677	}
678
679	/**
680	 * Convenience wrapper for `Object.assign`.
681	 *
682	 * @param {Object} target
683	 * @param {...Object} others
684	 *
685	 * @return {Object} the target
686	 */
687
688	function assign(target) {
689	  for (var _len = arguments.length, others = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
690	    others[_key - 1] = arguments[_key];
691	  }
692
693	  return _extends.apply(void 0, [target].concat(others));
694	}
695	/**
696	 * Pick given properties from the target object.
697	 *
698	 * @param {Object} target
699	 * @param {Array} properties
700	 *
701	 * @return {Object} target
702	 */
703
704	function pick(target, properties) {
705	  var result = {};
706	  var obj = Object(target);
707	  forEach(properties, function (prop) {
708	    if (prop in obj) {
709	      result[prop] = target[prop];
710	    }
711	  });
712	  return result;
713	}
714	/**
715	 * Pick all target properties, excluding the given ones.
716	 *
717	 * @param {Object} target
718	 * @param {Array} properties
719	 *
720	 * @return {Object} target
721	 */
722
723	function omit(target, properties) {
724	  var result = {};
725	  var obj = Object(target);
726	  forEach(obj, function (prop, key) {
727	    if (properties.indexOf(key) === -1) {
728	      result[key] = prop;
729	    }
730	  });
731	  return result;
732	}
733
734	/**
735	 * Set attribute `name` to `val`, or get attr `name`.
736	 *
737	 * @param {Element} el
738	 * @param {String} name
739	 * @param {String} [val]
740	 * @api public
741	 */
742	function attr$1(el, name, val) {
743	  // get
744	  if (arguments.length == 2) {
745	    return el.getAttribute(name);
746	  }
747
748	  // remove
749	  if (val === null) {
750	    return el.removeAttribute(name);
751	  }
752
753	  // set
754	  el.setAttribute(name, val);
755
756	  return el;
757	}
758
759	var indexOf$1 = [].indexOf;
760
761	var indexof = function(arr, obj){
762	  if (indexOf$1) return arr.indexOf(obj);
763	  for (var i = 0; i < arr.length; ++i) {
764	    if (arr[i] === obj) return i;
765	  }
766	  return -1;
767	};
768
769	/**
770	 * Taken from https://github.com/component/classes
771	 *
772	 * Without the component bits.
773	 */
774
775	/**
776	 * Whitespace regexp.
777	 */
778
779	var re$1 = /\s+/;
780
781	/**
782	 * toString reference.
783	 */
784
785	var toString$1 = Object.prototype.toString;
786
787	/**
788	 * Wrap `el` in a `ClassList`.
789	 *
790	 * @param {Element} el
791	 * @return {ClassList}
792	 * @api public
793	 */
794
795	function classes$1(el) {
796	  return new ClassList$1(el);
797	}
798
799	/**
800	 * Initialize a new ClassList for `el`.
801	 *
802	 * @param {Element} el
803	 * @api private
804	 */
805
806	function ClassList$1(el) {
807	  if (!el || !el.nodeType) {
808	    throw new Error('A DOM element reference is required');
809	  }
810	  this.el = el;
811	  this.list = el.classList;
812	}
813
814	/**
815	 * Add class `name` if not already present.
816	 *
817	 * @param {String} name
818	 * @return {ClassList}
819	 * @api public
820	 */
821
822	ClassList$1.prototype.add = function (name) {
823	  // classList
824	  if (this.list) {
825	    this.list.add(name);
826	    return this;
827	  }
828
829	  // fallback
830	  var arr = this.array();
831	  var i = indexof(arr, name);
832	  if (!~i) arr.push(name);
833	  this.el.className = arr.join(' ');
834	  return this;
835	};
836
837	/**
838	 * Remove class `name` when present, or
839	 * pass a regular expression to remove
840	 * any which match.
841	 *
842	 * @param {String|RegExp} name
843	 * @return {ClassList}
844	 * @api public
845	 */
846
847	ClassList$1.prototype.remove = function (name) {
848	  if ('[object RegExp]' == toString$1.call(name)) {
849	    return this.removeMatching(name);
850	  }
851
852	  // classList
853	  if (this.list) {
854	    this.list.remove(name);
855	    return this;
856	  }
857
858	  // fallback
859	  var arr = this.array();
860	  var i = indexof(arr, name);
861	  if (~i) arr.splice(i, 1);
862	  this.el.className = arr.join(' ');
863	  return this;
864	};
865
866	/**
867	 * Remove all classes matching `re`.
868	 *
869	 * @param {RegExp} re
870	 * @return {ClassList}
871	 * @api private
872	 */
873
874	ClassList$1.prototype.removeMatching = function (re) {
875	  var arr = this.array();
876	  for (var i = 0; i < arr.length; i++) {
877	    if (re.test(arr[i])) {
878	      this.remove(arr[i]);
879	    }
880	  }
881	  return this;
882	};
883
884	/**
885	 * Toggle class `name`, can force state via `force`.
886	 *
887	 * For browsers that support classList, but do not support `force` yet,
888	 * the mistake will be detected and corrected.
889	 *
890	 * @param {String} name
891	 * @param {Boolean} force
892	 * @return {ClassList}
893	 * @api public
894	 */
895
896	ClassList$1.prototype.toggle = function (name, force) {
897	  // classList
898	  if (this.list) {
899	    if ('undefined' !== typeof force) {
900	      if (force !== this.list.toggle(name, force)) {
901	        this.list.toggle(name); // toggle again to correct
902	      }
903	    } else {
904	      this.list.toggle(name);
905	    }
906	    return this;
907	  }
908
909	  // fallback
910	  if ('undefined' !== typeof force) {
911	    if (!force) {
912	      this.remove(name);
913	    } else {
914	      this.add(name);
915	    }
916	  } else {
917	    if (this.has(name)) {
918	      this.remove(name);
919	    } else {
920	      this.add(name);
921	    }
922	  }
923
924	  return this;
925	};
926
927	/**
928	 * Return an array of classes.
929	 *
930	 * @return {Array}
931	 * @api public
932	 */
933
934	ClassList$1.prototype.array = function () {
935	  var className = this.el.getAttribute('class') || '';
936	  var str = className.replace(/^\s+|\s+$/g, '');
937	  var arr = str.split(re$1);
938	  if ('' === arr[0]) arr.shift();
939	  return arr;
940	};
941
942	/**
943	 * Check if class `name` is present.
944	 *
945	 * @param {String} name
946	 * @return {ClassList}
947	 * @api public
948	 */
949
950	ClassList$1.prototype.has = ClassList$1.prototype.contains = function (name) {
951	  return this.list ? this.list.contains(name) : !!~indexof(this.array(), name);
952	};
953
954	/**
955	 * Remove all children from the given element.
956	 */
957	function clear$1(el) {
958
959	  var c;
960
961	  while (el.childNodes.length) {
962	    c = el.childNodes[0];
963	    el.removeChild(c);
964	  }
965
966	  return el;
967	}
968
969	var proto = typeof Element !== 'undefined' ? Element.prototype : {};
970	var vendor = proto.matches
971	  || proto.matchesSelector
972	  || proto.webkitMatchesSelector
973	  || proto.mozMatchesSelector
974	  || proto.msMatchesSelector
975	  || proto.oMatchesSelector;
976
977	var matchesSelector = match;
978
979	/**
980	 * Match `el` to `selector`.
981	 *
982	 * @param {Element} el
983	 * @param {String} selector
984	 * @return {Boolean}
985	 * @api public
986	 */
987
988	function match(el, selector) {
989	  if (!el || el.nodeType !== 1) return false;
990	  if (vendor) return vendor.call(el, selector);
991	  var nodes = el.parentNode.querySelectorAll(selector);
992	  for (var i = 0; i < nodes.length; i++) {
993	    if (nodes[i] == el) return true;
994	  }
995	  return false;
996	}
997
998	/**
999	 * Closest
1000	 *
1001	 * @param {Element} el
1002	 * @param {String} selector
1003	 * @param {Boolean} checkYourSelf (optional)
1004	 */
1005	function closest (element, selector, checkYourSelf) {
1006	  var currentElem = checkYourSelf ? element : element.parentNode;
1007
1008	  while (currentElem && currentElem.nodeType !== document.DOCUMENT_NODE && currentElem.nodeType !== document.DOCUMENT_FRAGMENT_NODE) {
1009
1010	    if (matchesSelector(currentElem, selector)) {
1011	      return currentElem;
1012	    }
1013
1014	    currentElem = currentElem.parentNode;
1015	  }
1016
1017	  return matchesSelector(currentElem, selector) ? currentElem : null;
1018	}
1019
1020	var bind = window.addEventListener ? 'addEventListener' : 'attachEvent',
1021	    unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent',
1022	    prefix$6 = bind !== 'addEventListener' ? 'on' : '';
1023
1024	/**
1025	 * Bind `el` event `type` to `fn`.
1026	 *
1027	 * @param {Element} el
1028	 * @param {String} type
1029	 * @param {Function} fn
1030	 * @param {Boolean} capture
1031	 * @return {Function}
1032	 * @api public
1033	 */
1034
1035	var bind_1 = function(el, type, fn, capture){
1036	  el[bind](prefix$6 + type, fn, capture || false);
1037	  return fn;
1038	};
1039
1040	/**
1041	 * Unbind `el` event `type`'s callback `fn`.
1042	 *
1043	 * @param {Element} el
1044	 * @param {String} type
1045	 * @param {Function} fn
1046	 * @param {Boolean} capture
1047	 * @return {Function}
1048	 * @api public
1049	 */
1050
1051	var unbind_1 = function(el, type, fn, capture){
1052	  el[unbind](prefix$6 + type, fn, capture || false);
1053	  return fn;
1054	};
1055
1056	var componentEvent = {
1057		bind: bind_1,
1058		unbind: unbind_1
1059	};
1060
1061	/**
1062	 * Module dependencies.
1063	 */
1064
1065	/**
1066	 * Delegate event `type` to `selector`
1067	 * and invoke `fn(e)`. A callback function
1068	 * is returned which may be passed to `.unbind()`.
1069	 *
1070	 * @param {Element} el
1071	 * @param {String} selector
1072	 * @param {String} type
1073	 * @param {Function} fn
1074	 * @param {Boolean} capture
1075	 * @return {Function}
1076	 * @api public
1077	 */
1078
1079	// Some events don't bubble, so we want to bind to the capture phase instead
1080	// when delegating.
1081	var forceCaptureEvents = ['focus', 'blur'];
1082
1083	function bind$1(el, selector, type, fn, capture) {
1084	  if (forceCaptureEvents.indexOf(type) !== -1) {
1085	    capture = true;
1086	  }
1087
1088	  return componentEvent.bind(el, type, function (e) {
1089	    var target = e.target || e.srcElement;
1090	    e.delegateTarget = closest(target, selector, true);
1091	    if (e.delegateTarget) {
1092	      fn.call(el, e);
1093	    }
1094	  }, capture);
1095	}
1096
1097	/**
1098	 * Unbind event `type`'s callback `fn`.
1099	 *
1100	 * @param {Element} el
1101	 * @param {String} type
1102	 * @param {Function} fn
1103	 * @param {Boolean} capture
1104	 * @api public
1105	 */
1106	function unbind$1(el, type, fn, capture) {
1107	  if (forceCaptureEvents.indexOf(type) !== -1) {
1108	    capture = true;
1109	  }
1110
1111	  return componentEvent.unbind(el, type, fn, capture);
1112	}
1113
1114	var delegate = {
1115	  bind: bind$1,
1116	  unbind: unbind$1
1117	};
1118
1119	/**
1120	 * Expose `parse`.
1121	 */
1122
1123	var domify = parse$1;
1124
1125	/**
1126	 * Tests for browser support.
1127	 */
1128
1129	var innerHTMLBug = false;
1130	var bugTestDiv;
1131	if (typeof document !== 'undefined') {
1132	  bugTestDiv = document.createElement('div');
1133	  // Setup
1134	  bugTestDiv.innerHTML = '  <link/><table></table><a href="/a">a</a><input type="checkbox"/>';
1135	  // Make sure that link elements get serialized correctly by innerHTML
1136	  // This requires a wrapper element in IE
1137	  innerHTMLBug = !bugTestDiv.getElementsByTagName('link').length;
1138	  bugTestDiv = undefined;
1139	}
1140
1141	/**
1142	 * Wrap map from jquery.
1143	 */
1144
1145	var map = {
1146	  legend: [1, '<fieldset>', '</fieldset>'],
1147	  tr: [2, '<table><tbody>', '</tbody></table>'],
1148	  col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
1149	  // for script/link/style tags to work in IE6-8, you have to wrap
1150	  // in a div with a non-whitespace character in front, ha!
1151	  _default: innerHTMLBug ? [1, 'X<div>', '</div>'] : [0, '', '']
1152	};
1153
1154	map.td =
1155	map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
1156
1157	map.option =
1158	map.optgroup = [1, '<select multiple="multiple">', '</select>'];
1159
1160	map.thead =
1161	map.tbody =
1162	map.colgroup =
1163	map.caption =
1164	map.tfoot = [1, '<table>', '</table>'];
1165
1166	map.polyline =
1167	map.ellipse =
1168	map.polygon =
1169	map.circle =
1170	map.text =
1171	map.line =
1172	map.path =
1173	map.rect =
1174	map.g = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'];
1175
1176	/**
1177	 * Parse `html` and return a DOM Node instance, which could be a TextNode,
1178	 * HTML DOM Node of some kind (<div> for example), or a DocumentFragment
1179	 * instance, depending on the contents of the `html` string.
1180	 *
1181	 * @param {String} html - HTML string to "domify"
1182	 * @param {Document} doc - The `document` instance to create the Node for
1183	 * @return {DOMNode} the TextNode, DOM Node, or DocumentFragment instance
1184	 * @api private
1185	 */
1186
1187	function parse$1(html, doc) {
1188	  if ('string' != typeof html) throw new TypeError('String expected');
1189
1190	  // default to the global `document` object
1191	  if (!doc) doc = document;
1192
1193	  // tag name
1194	  var m = /<([\w:]+)/.exec(html);
1195	  if (!m) return doc.createTextNode(html);
1196
1197	  html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace
1198
1199	  var tag = m[1];
1200
1201	  // body support
1202	  if (tag == 'body') {
1203	    var el = doc.createElement('html');
1204	    el.innerHTML = html;
1205	    return el.removeChild(el.lastChild);
1206	  }
1207
1208	  // wrap map
1209	  var wrap = map[tag] || map._default;
1210	  var depth = wrap[0];
1211	  var prefix = wrap[1];
1212	  var suffix = wrap[2];
1213	  var el = doc.createElement('div');
1214	  el.innerHTML = prefix + html + suffix;
1215	  while (depth--) el = el.lastChild;
1216
1217	  // one element
1218	  if (el.firstChild == el.lastChild) {
1219	    return el.removeChild(el.firstChild);
1220	  }
1221
1222	  // several elements
1223	  var fragment = doc.createDocumentFragment();
1224	  while (el.firstChild) {
1225	    fragment.appendChild(el.removeChild(el.firstChild));
1226	  }
1227
1228	  return fragment;
1229	}
1230
1231	function query(selector, el) {
1232	  el = el || document;
1233
1234	  return el.querySelector(selector);
1235	}
1236
1237	function all(selector, el) {
1238	  el = el || document;
1239
1240	  return el.querySelectorAll(selector);
1241	}
1242
1243	function remove$2(el) {
1244	  el.parentNode && el.parentNode.removeChild(el);
1245	}
1246
1247	function ensureImported(element, target) {
1248
1249	  if (element.ownerDocument !== target.ownerDocument) {
1250	    try {
1251	      // may fail on webkit
1252	      return target.ownerDocument.importNode(element, true);
1253	    } catch (e) {
1254	      // ignore
1255	    }
1256	  }
1257
1258	  return element;
1259	}
1260
1261	/**
1262	 * appendTo utility
1263	 */
1264
1265	/**
1266	 * Append a node to a target element and return the appended node.
1267	 *
1268	 * @param  {SVGElement} element
1269	 * @param  {SVGElement} target
1270	 *
1271	 * @return {SVGElement} the appended node
1272	 */
1273	function appendTo(element, target) {
1274	  return target.appendChild(ensureImported(element, target));
1275	}
1276
1277	/**
1278	 * append utility
1279	 */
1280
1281	/**
1282	 * Append a node to an element
1283	 *
1284	 * @param  {SVGElement} element
1285	 * @param  {SVGElement} node
1286	 *
1287	 * @return {SVGElement} the element
1288	 */
1289	function append(target, node) {
1290	  appendTo(node, target);
1291	  return target;
1292	}
1293
1294	/**
1295	 * attribute accessor utility
1296	 */
1297
1298	var LENGTH_ATTR = 2;
1299
1300	var CSS_PROPERTIES = {
1301	  'alignment-baseline': 1,
1302	  'baseline-shift': 1,
1303	  'clip': 1,
1304	  'clip-path': 1,
1305	  'clip-rule': 1,
1306	  'color': 1,
1307	  'color-interpolation': 1,
1308	  'color-interpolation-filters': 1,
1309	  'color-profile': 1,
1310	  'color-rendering': 1,
1311	  'cursor': 1,
1312	  'direction': 1,
1313	  'display': 1,
1314	  'dominant-baseline': 1,
1315	  'enable-background': 1,
1316	  'fill': 1,
1317	  'fill-opacity': 1,
1318	  'fill-rule': 1,
1319	  'filter': 1,
1320	  'flood-color': 1,
1321	  'flood-opacity': 1,
1322	  'font': 1,
1323	  'font-family': 1,
1324	  'font-size': LENGTH_ATTR,
1325	  'font-size-adjust': 1,
1326	  'font-stretch': 1,
1327	  'font-style': 1,
1328	  'font-variant': 1,
1329	  'font-weight': 1,
1330	  'glyph-orientation-horizontal': 1,
1331	  'glyph-orientation-vertical': 1,
1332	  'image-rendering': 1,
1333	  'kerning': 1,
1334	  'letter-spacing': 1,
1335	  'lighting-color': 1,
1336	  'marker': 1,
1337	  'marker-end': 1,
1338	  'marker-mid': 1,
1339	  'marker-start': 1,
1340	  'mask': 1,
1341	  'opacity': 1,
1342	  'overflow': 1,
1343	  'pointer-events': 1,
1344	  'shape-rendering': 1,
1345	  'stop-color': 1,
1346	  'stop-opacity': 1,
1347	  'stroke': 1,
1348	  'stroke-dasharray': 1,
1349	  'stroke-dashoffset': 1,
1350	  'stroke-linecap': 1,
1351	  'stroke-linejoin': 1,
1352	  'stroke-miterlimit': 1,
1353	  'stroke-opacity': 1,
1354	  'stroke-width': LENGTH_ATTR,
1355	  'text-anchor': 1,
1356	  'text-decoration': 1,
1357	  'text-rendering': 1,
1358	  'unicode-bidi': 1,
1359	  'visibility': 1,
1360	  'word-spacing': 1,
1361	  'writing-mode': 1
1362	};
1363
1364
1365	function getAttribute(node, name) {
1366	  if (CSS_PROPERTIES[name]) {
1367	    return node.style[name];
1368	  } else {
1369	    return node.getAttributeNS(null, name);
1370	  }
1371	}
1372
1373	function setAttribute(node, name, value) {
1374	  var hyphenated = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
1375
1376	  var type = CSS_PROPERTIES[hyphenated];
1377
1378	  if (type) {
1379	    // append pixel unit, unless present
1380	    if (type === LENGTH_ATTR && typeof value === 'number') {
1381	      value = String(value) + 'px';
1382	    }
1383
1384	    node.style[hyphenated] = value;
1385	  } else {
1386	    node.setAttributeNS(null, name, value);
1387	  }
1388	}
1389
1390	function setAttributes(node, attrs) {
1391
1392	  var names = Object.keys(attrs), i, name;
1393
1394	  for (i = 0, name; (name = names[i]); i++) {
1395	    setAttribute(node, name, attrs[name]);
1396	  }
1397	}
1398
1399	/**
1400	 * Gets or sets raw attributes on a node.
1401	 *
1402	 * @param  {SVGElement} node
1403	 * @param  {Object} [attrs]
1404	 * @param  {String} [name]
1405	 * @param  {String} [value]
1406	 *
1407	 * @return {String}
1408	 */
1409	function attr(node, name, value) {
1410	  if (typeof name === 'string') {
1411	    if (value !== undefined) {
1412	      setAttribute(node, name, value);
1413	    } else {
1414	      return getAttribute(node, name);
1415	    }
1416	  } else {
1417	    setAttributes(node, name);
1418	  }
1419
1420	  return node;
1421	}
1422
1423	/**
1424	 * Clear utility
1425	 */
1426	function index(arr, obj) {
1427	  if (arr.indexOf) {
1428	    return arr.indexOf(obj);
1429	  }
1430
1431
1432	  for (var i = 0; i < arr.length; ++i) {
1433	    if (arr[i] === obj) {
1434	      return i;
1435	    }
1436	  }
1437
1438	  return -1;
1439	}
1440
1441	var re = /\s+/;
1442
1443	var toString = Object.prototype.toString;
1444
1445	function defined(o) {
1446	  return typeof o !== 'undefined';
1447	}
1448
1449	/**
1450	 * Wrap `el` in a `ClassList`.
1451	 *
1452	 * @param {Element} el
1453	 * @return {ClassList}
1454	 * @api public
1455	 */
1456
1457	function classes(el) {
1458	  return new ClassList(el);
1459	}
1460
1461	function ClassList(el) {
1462	  if (!el || !el.nodeType) {
1463	    throw new Error('A DOM element reference is required');
1464	  }
1465	  this.el = el;
1466	  this.list = el.classList;
1467	}
1468
1469	/**
1470	 * Add class `name` if not already present.
1471	 *
1472	 * @param {String} name
1473	 * @return {ClassList}
1474	 * @api public
1475	 */
1476
1477	ClassList.prototype.add = function(name) {
1478
1479	  // classList
1480	  if (this.list) {
1481	    this.list.add(name);
1482	    return this;
1483	  }
1484
1485	  // fallback
1486	  var arr = this.array();
1487	  var i = index(arr, name);
1488	  if (!~i) {
1489	    arr.push(name);
1490	  }
1491
1492	  if (defined(this.el.className.baseVal)) {
1493	    this.el.className.baseVal = arr.join(' ');
1494	  } else {
1495	    this.el.className = arr.join(' ');
1496	  }
1497
1498	  return this;
1499	};
1500
1501	/**
1502	 * Remove class `name` when present, or
1503	 * pass a regular expression to remove
1504	 * any which match.
1505	 *
1506	 * @param {String|RegExp} name
1507	 * @return {ClassList}
1508	 * @api public
1509	 */
1510
1511	ClassList.prototype.remove = function(name) {
1512	  if ('[object RegExp]' === toString.call(name)) {
1513	    return this.removeMatching(name);
1514	  }
1515
1516	  // classList
1517	  if (this.list) {
1518	    this.list.remove(name);
1519	    return this;
1520	  }
1521
1522	  // fallback
1523	  var arr = this.array();
1524	  var i = index(arr, name);
1525	  if (~i) {
1526	    arr.splice(i, 1);
1527	  }
1528	  this.el.className.baseVal = arr.join(' ');
1529	  return this;
1530	};
1531
1532	/**
1533	 * Remove all classes matching `re`.
1534	 *
1535	 * @param {RegExp} re
1536	 * @return {ClassList}
1537	 * @api private
1538	 */
1539
1540	ClassList.prototype.removeMatching = function(re) {
1541	  var arr = this.array();
1542	  for (var i = 0; i < arr.length; i++) {
1543	    if (re.test(arr[i])) {
1544	      this.remove(arr[i]);
1545	    }
1546	  }
1547	  return this;
1548	};
1549
1550	/**
1551	 * Toggle class `name`, can force state via `force`.
1552	 *
1553	 * For browsers that support classList, but do not support `force` yet,
1554	 * the mistake will be detected and corrected.
1555	 *
1556	 * @param {String} name
1557	 * @param {Boolean} force
1558	 * @return {ClassList}
1559	 * @api public
1560	 */
1561
1562	ClassList.prototype.toggle = function(name, force) {
1563	  // classList
1564	  if (this.list) {
1565	    if (defined(force)) {
1566	      if (force !== this.list.toggle(name, force)) {
1567	        this.list.toggle(name); // toggle again to correct
1568	      }
1569	    } else {
1570	      this.list.toggle(name);
1571	    }
1572	    return this;
1573	  }
1574
1575	  // fallback
1576	  if (defined(force)) {
1577	    if (!force) {
1578	      this.remove(name);
1579	    } else {
1580	      this.add(name);
1581	    }
1582	  } else {
1583	    if (this.has(name)) {
1584	      this.remove(name);
1585	    } else {
1586	      this.add(name);
1587	    }
1588	  }
1589
1590	  return this;
1591	};
1592
1593	/**
1594	 * Return an array of classes.
1595	 *
1596	 * @return {Array}
1597	 * @api public
1598	 */
1599
1600	ClassList.prototype.array = function() {
1601	  var className = this.el.getAttribute('class') || '';
1602	  var str = className.replace(/^\s+|\s+$/g, '');
1603	  var arr = str.split(re);
1604	  if ('' === arr[0]) {
1605	    arr.shift();
1606	  }
1607	  return arr;
1608	};
1609
1610	/**
1611	 * Check if class `name` is present.
1612	 *
1613	 * @param {String} name
1614	 * @return {ClassList}
1615	 * @api public
1616	 */
1617
1618	ClassList.prototype.has =
1619	ClassList.prototype.contains = function(name) {
1620	  return (
1621	    this.list ?
1622	      this.list.contains(name) :
1623	      !! ~index(this.array(), name)
1624	  );
1625	};
1626
1627	function remove$1(element) {
1628	  var parent = element.parentNode;
1629
1630	  if (parent) {
1631	    parent.removeChild(element);
1632	  }
1633
1634	  return element;
1635	}
1636
1637	/**
1638	 * Clear utility
1639	 */
1640
1641	/**
1642	 * Removes all children from the given element
1643	 *
1644	 * @param  {DOMElement} element
1645	 * @return {DOMElement} the element (for chaining)
1646	 */
1647	function clear(element) {
1648	  var child;
1649
1650	  while ((child = element.firstChild)) {
1651	    remove$1(child);
1652	  }
1653
1654	  return element;
1655	}
1656
1657	function clone$1(element) {
1658	  return element.cloneNode(true);
1659	}
1660
1661	var ns = {
1662	  svg: 'http://www.w3.org/2000/svg'
1663	};
1664
1665	/**
1666	 * DOM parsing utility
1667	 */
1668
1669	var SVG_START = '<svg xmlns="' + ns.svg + '"';
1670
1671	function parse(svg) {
1672
1673	  var unwrap = false;
1674
1675	  // ensure we import a valid svg document
1676	  if (svg.substring(0, 4) === '<svg') {
1677	    if (svg.indexOf(ns.svg) === -1) {
1678	      svg = SVG_START + svg.substring(4);
1679	    }
1680	  } else {
1681	    // namespace svg
1682	    svg = SVG_START + '>' + svg + '</svg>';
1683	    unwrap = true;
1684	  }
1685
1686	  var parsed = parseDocument(svg);
1687
1688	  if (!unwrap) {
1689	    return parsed;
1690	  }
1691
1692	  var fragment = document.createDocumentFragment();
1693
1694	  var parent = parsed.firstChild;
1695
1696	  while (parent.firstChild) {
1697	    fragment.appendChild(parent.firstChild);
1698	  }
1699
1700	  return fragment;
1701	}
1702
1703	function parseDocument(svg) {
1704
1705	  var parser;
1706
1707	  // parse
1708	  parser = new DOMParser();
1709	  parser.async = false;
1710
1711	  return parser.parseFromString(svg, 'text/xml');
1712	}
1713
1714	/**
1715	 * Create utility for SVG elements
1716	 */
1717
1718
1719	/**
1720	 * Create a specific type from name or SVG markup.
1721	 *
1722	 * @param {String} name the name or markup of the element
1723	 * @param {Object} [attrs] attributes to set on the element
1724	 *
1725	 * @returns {SVGElement}
1726	 */
1727	function create$1(name, attrs) {
1728	  var element;
1729
1730	  if (name.charAt(0) === '<') {
1731	    element = parse(name).firstChild;
1732	    element = document.importNode(element, true);
1733	  } else {
1734	    element = document.createElementNS(ns.svg, name);
1735	  }
1736
1737	  if (attrs) {
1738	    attr(element, attrs);
1739	  }
1740
1741	  return element;
1742	}
1743
1744	/**
1745	 * Geometry helpers
1746	 */
1747
1748	// fake node used to instantiate svg geometry elements
1749	var node = create$1('svg');
1750
1751	function extend$1(object, props) {
1752	  var i, k, keys = Object.keys(props);
1753
1754	  for (i = 0; (k = keys[i]); i++) {
1755	    object[k] = props[k];
1756	  }
1757
1758	  return object;
1759	}
1760
1761	/**
1762	 * Create matrix via args.
1763	 *
1764	 * @example
1765	 *
1766	 * createMatrix({ a: 1, b: 1 });
1767	 * createMatrix();
1768	 * createMatrix(1, 2, 0, 0, 30, 20);
1769	 *
1770	 * @return {SVGMatrix}
1771	 */
1772	function createMatrix(a, b, c, d, e, f) {
1773	  var matrix = node.createSVGMatrix();
1774
1775	  switch (arguments.length) {
1776	  case 0:
1777	    return matrix;
1778	  case 1:
1779	    return extend$1(matrix, a);
1780	  case 6:
1781	    return extend$1(matrix, {
1782	      a: a,
1783	      b: b,
1784	      c: c,
1785	      d: d,
1786	      e: e,
1787	      f: f
1788	    });
1789	  }
1790	}
1791
1792	function createTransform(matrix) {
1793	  if (matrix) {
1794	    return node.createSVGTransformFromMatrix(matrix);
1795	  } else {
1796	    return node.createSVGTransform();
1797	  }
1798	}
1799
1800	/**
1801	 * Serialization util
1802	 */
1803
1804	var TEXT_ENTITIES = /([&<>]{1})/g;
1805	var ATTR_ENTITIES = /([\n\r"]{1})/g;
1806
1807	var ENTITY_REPLACEMENT = {
1808	  '&': '&amp;',
1809	  '<': '&lt;',
1810	  '>': '&gt;',
1811	  '"': '\''
1812	};
1813
1814	function escape$1(str, pattern) {
1815
1816	  function replaceFn(match, entity) {
1817	    return ENTITY_REPLACEMENT[entity] || entity;
1818	  }
1819
1820	  return str.replace(pattern, replaceFn);
1821	}
1822
1823	function serialize(node, output) {
1824
1825	  var i, len, attrMap, attrNode, childNodes;
1826
1827	  switch (node.nodeType) {
1828	  // TEXT
1829	  case 3:
1830	    // replace special XML characters
1831	    output.push(escape$1(node.textContent, TEXT_ENTITIES));
1832	    break;
1833
1834	  // ELEMENT
1835	  case 1:
1836	    output.push('<', node.tagName);
1837
1838	    if (node.hasAttributes()) {
1839	      attrMap = node.attributes;
1840	      for (i = 0, len = attrMap.length; i < len; ++i) {
1841	        attrNode = attrMap.item(i);
1842	        output.push(' ', attrNode.name, '="', escape$1(attrNode.value, ATTR_ENTITIES), '"');
1843	      }
1844	    }
1845
1846	    if (node.hasChildNodes()) {
1847	      output.push('>');
1848	      childNodes = node.childNodes;
1849	      for (i = 0, len = childNodes.length; i < len; ++i) {
1850	        serialize(childNodes.item(i), output);
1851	      }
1852	      output.push('</', node.tagName, '>');
1853	    } else {
1854	      output.push('/>');
1855	    }
1856	    break;
1857
1858	  // COMMENT
1859	  case 8:
1860	    output.push('<!--', escape$1(node.nodeValue, TEXT_ENTITIES), '-->');
1861	    break;
1862
1863	  // CDATA
1864	  case 4:
1865	    output.push('<![CDATA[', node.nodeValue, ']]>');
1866	    break;
1867
1868	  default:
1869	    throw new Error('unable to handle node ' + node.nodeType);
1870	  }
1871
1872	  return output;
1873	}
1874
1875	/**
1876	 * innerHTML like functionality for SVG elements.
1877	 * based on innerSVG (https://code.google.com/p/innersvg)
1878	 */
1879
1880
1881	function set$1(element, svg) {
1882
1883	  var parsed = parse(svg);
1884
1885	  // clear element contents
1886	  clear(element);
1887
1888	  if (!svg) {
1889	    return;
1890	  }
1891
1892	  if (!isFragment(parsed)) {
1893	    // extract <svg> from parsed document
1894	    parsed = parsed.documentElement;
1895	  }
1896
1897	  var nodes = slice$1(parsed.childNodes);
1898
1899	  // import + append each node
1900	  for (var i = 0; i < nodes.length; i++) {
1901	    appendTo(nodes[i], element);
1902	  }
1903
1904	}
1905
1906	function get$1(element) {
1907	  var child = element.firstChild,
1908	      output = [];
1909
1910	  while (child) {
1911	    serialize(child, output);
1912	    child = child.nextSibling;
1913	  }
1914
1915	  return output.join('');
1916	}
1917
1918	function isFragment(node) {
1919	  return node.nodeName === '#document-fragment';
1920	}
1921
1922	function innerSVG(element, svg) {
1923
1924	  if (svg !== undefined) {
1925
1926	    try {
1927	      set$1(element, svg);
1928	    } catch (e) {
1929	      throw new Error('error parsing SVG: ' + e.message);
1930	    }
1931
1932	    return element;
1933	  } else {
1934	    return get$1(element);
1935	  }
1936	}
1937
1938
1939	function slice$1(arr) {
1940	  return Array.prototype.slice.call(arr);
1941	}
1942
1943	/**
1944	 * transform accessor utility
1945	 */
1946
1947	function wrapMatrix(transformList, transform) {
1948	  if (transform instanceof SVGMatrix) {
1949	    return transformList.createSVGTransformFromMatrix(transform);
1950	  }
1951
1952	  return transform;
1953	}
1954
1955
1956	function setTransforms(transformList, transforms) {
1957	  var i, t;
1958
1959	  transformList.clear();
1960
1961	  for (i = 0; (t = transforms[i]); i++) {
1962	    transformList.appendItem(wrapMatrix(transformList, t));
1963	  }
1964	}
1965
1966	/**
1967	 * Get or set the transforms on the given node.
1968	 *
1969	 * @param {SVGElement} node
1970	 * @param  {SVGTransform|SVGMatrix|Array<SVGTransform|SVGMatrix>} [transforms]
1971	 *
1972	 * @return {SVGTransform} the consolidated transform
1973	 */
1974	function transform$1(node, transforms) {
1975	  var transformList = node.transform.baseVal;
1976
1977	  if (transforms) {
1978
1979	    if (!Array.isArray(transforms)) {
1980	      transforms = [ transforms ];
1981	    }
1982
1983	    setTransforms(transformList, transforms);
1984	  }
1985
1986	  return transformList.consolidate();
1987	}
1988
1989	var CLASS_PATTERN = /^class /;
1990
1991	function isClass(fn) {
1992	  return CLASS_PATTERN.test(fn.toString());
1993	}
1994
1995	function isArray$1(obj) {
1996	  return Object.prototype.toString.call(obj) === '[object Array]';
1997	}
1998
1999	function hasOwnProp(obj, prop) {
2000	  return Object.prototype.hasOwnProperty.call(obj, prop);
2001	}
2002
2003	function annotate() {
2004	  var args = Array.prototype.slice.call(arguments);
2005
2006	  if (args.length === 1 && isArray$1(args[0])) {
2007	    args = args[0];
2008	  }
2009
2010	  var fn = args.pop();
2011
2012	  fn.$inject = args;
2013
2014	  return fn;
2015	}
2016
2017
2018	// Current limitations:
2019	// - can't put into "function arg" comments
2020	// function /* (no parenthesis like this) */ (){}
2021	// function abc( /* xx (no parenthesis like this) */ a, b) {}
2022	//
2023	// Just put the comment before function or inside:
2024	// /* (((this is fine))) */ function(a, b) {}
2025	// function abc(a) { /* (((this is fine))) */}
2026	//
2027	// - can't reliably auto-annotate constructor; we'll match the
2028	// first constructor(...) pattern found which may be the one
2029	// of a nested class, too.
2030
2031	var CONSTRUCTOR_ARGS = /constructor\s*[^(]*\(\s*([^)]*)\)/m;
2032	var FN_ARGS = /^(?:async )?(?:function\s*)?[^(]*\(\s*([^)]*)\)/m;
2033	var FN_ARG = /\/\*([^*]*)\*\//m;
2034
2035	function parseAnnotations(fn) {
2036
2037	  if (typeof fn !== 'function') {
2038	    throw new Error('Cannot annotate "' + fn + '". Expected a function!');
2039	  }
2040
2041	  var match = fn.toString().match(isClass(fn) ? CONSTRUCTOR_ARGS : FN_ARGS);
2042
2043	  // may parse class without constructor
2044	  if (!match) {
2045	    return [];
2046	  }
2047
2048	  return match[1] && match[1].split(',').map(function(arg) {
2049	    match = arg.match(FN_ARG);
2050	    return match ? match[1].trim() : arg.trim();
2051	  }) || [];
2052	}
2053
2054	function Module() {
2055	  var providers = [];
2056
2057	  this.factory = function(name, factory) {
2058	    providers.push([name, 'factory', factory]);
2059	    return this;
2060	  };
2061
2062	  this.value = function(name, value) {
2063	    providers.push([name, 'value', value]);
2064	    return this;
2065	  };
2066
2067	  this.type = function(name, type) {
2068	    providers.push([name, 'type', type]);
2069	    return this;
2070	  };
2071
2072	  this.forEach = function(iterator) {
2073	    providers.forEach(iterator);
2074	  };
2075
2076	}
2077
2078	function Injector(modules, parent) {
2079	  parent = parent || {
2080	    get: function(name, strict) {
2081	      currentlyResolving.push(name);
2082
2083	      if (strict === false) {
2084	        return null;
2085	      } else {
2086	        throw error('No provider for "' + name + '"!');
2087	      }
2088	    }
2089	  };
2090
2091	  var currentlyResolving = [];
2092	  var providers = this._providers = Object.create(parent._providers || null);
2093	  var instances = this._instances = Object.create(null);
2094
2095	  var self = instances.injector = this;
2096
2097	  var error = function(msg) {
2098	    var stack = currentlyResolving.join(' -> ');
2099	    currentlyResolving.length = 0;
2100	    return new Error(stack ? msg + ' (Resolving: ' + stack + ')' : msg);
2101	  };
2102
2103	  /**
2104	   * Return a named service.
2105	   *
2106	   * @param {String} name
2107	   * @param {Boolean} [strict=true] if false, resolve missing services to null
2108	   *
2109	   * @return {Object}
2110	   */
2111	  var get = function(name, strict) {
2112	    if (!providers[name] && name.indexOf('.') !== -1) {
2113	      var parts = name.split('.');
2114	      var pivot = get(parts.shift());
2115
2116	      while (parts.length) {
2117	        pivot = pivot[parts.shift()];
2118	      }
2119
2120	      return pivot;
2121	    }
2122
2123	    if (hasOwnProp(instances, name)) {
2124	      return instances[name];
2125	    }
2126
2127	    if (hasOwnProp(providers, name)) {
2128	      if (currentlyResolving.indexOf(name) !== -1) {
2129	        currentlyResolving.push(name);
2130	        throw error('Cannot resolve circular dependency!');
2131	      }
2132
2133	      currentlyResolving.push(name);
2134	      instances[name] = providers[name][0](providers[name][1]);
2135	      currentlyResolving.pop();
2136
2137	      return instances[name];
2138	    }
2139
2140	    return parent.get(name, strict);
2141	  };
2142
2143	  var fnDef = function(fn, locals) {
2144
2145	    if (typeof locals === 'undefined') {
2146	      locals = {};
2147	    }
2148
2149	    if (typeof fn !== 'function') {
2150	      if (isArray$1(fn)) {
2151	        fn = annotate(fn.slice());
2152	      } else {
2153	        throw new Error('Cannot invoke "' + fn + '". Expected a function!');
2154	      }
2155	    }
2156
2157	    var inject = fn.$inject || parseAnnotations(fn);
2158	    var dependencies = inject.map(function(dep) {
2159	      if (hasOwnProp(locals, dep)) {
2160	        return locals[dep];
2161	      } else {
2162	        return get(dep);
2163	      }
2164	    });
2165
2166	    return {
2167	      fn: fn,
2168	      dependencies: dependencies
2169	    };
2170	  };
2171
2172	  var instantiate = function(Type) {
2173	    var def = fnDef(Type);
2174
2175	    var fn = def.fn,
2176	        dependencies = def.dependencies;
2177
2178	    // instantiate var args constructor
2179	    var Constructor = Function.prototype.bind.apply(fn, [ null ].concat(dependencies));
2180
2181	    return new Constructor();
2182	  };
2183
2184	  var invoke = function(func, context, locals) {
2185	    var def = fnDef(func, locals);
2186
2187	    var fn = def.fn,
2188	        dependencies = def.dependencies;
2189
2190	    return fn.apply(context, dependencies);
2191	  };
2192
2193
2194	  var createPrivateInjectorFactory = function(privateChildInjector) {
2195	    return annotate(function(key) {
2196	      return privateChildInjector.get(key);
2197	    });
2198	  };
2199
2200	  var createChild = function(modules, forceNewInstances) {
2201	    if (forceNewInstances && forceNewInstances.length) {
2202	      var fromParentModule = Object.create(null);
2203	      var matchedScopes = Object.create(null);
2204
2205	      var privateInjectorsCache = [];
2206	      var privateChildInjectors = [];
2207	      var privateChildFactories = [];
2208
2209	      var provider;
2210	      var cacheIdx;
2211	      var privateChildInjector;
2212	      var privateChildInjectorFactory;
2213	      for (var name in providers) {
2214	        provider = providers[name];
2215
2216	        if (forceNewInstances.indexOf(name) !== -1) {
2217	          if (provider[2] === 'private') {
2218	            cacheIdx = privateInjectorsCache.indexOf(provider[3]);
2219	            if (cacheIdx === -1) {
2220	              privateChildInjector = provider[3].createChild([], forceNewInstances);
2221	              privateChildInjectorFactory = createPrivateInjectorFactory(privateChildInjector);
2222	              privateInjectorsCache.push(provider[3]);
2223	              privateChildInjectors.push(privateChildInjector);
2224	              privateChildFactories.push(privateChildInjectorFactory);
2225	              fromParentModule[name] = [privateChildInjectorFactory, name, 'private', privateChildInjector];
2226	            } else {
2227	              fromParentModule[name] = [privateChildFactories[cacheIdx], name, 'private', privateChildInjectors[cacheIdx]];
2228	            }
2229	          } else {
2230	            fromParentModule[name] = [provider[2], provider[1]];
2231	          }
2232	          matchedScopes[name] = true;
2233	        }
2234
2235	        if ((provider[2] === 'factory' || provider[2] === 'type') && provider[1].$scope) {
2236	          /* jshint -W083 */
2237	          forceNewInstances.forEach(function(scope) {
2238	            if (provider[1].$scope.indexOf(scope) !== -1) {
2239	              fromParentModule[name] = [provider[2], provider[1]];
2240	              matchedScopes[scope] = true;
2241	            }
2242	          });
2243	        }
2244	      }
2245
2246	      forceNewInstances.forEach(function(scope) {
2247	        if (!matchedScopes[scope]) {
2248	          throw new Error('No provider for "' + scope + '". Cannot use provider from the parent!');
2249	        }
2250	      });
2251
2252	      modules.unshift(fromParentModule);
2253	    }
2254
2255	    return new Injector(modules, self);
2256	  };
2257
2258	  var factoryMap = {
2259	    factory: invoke,
2260	    type: instantiate,
2261	    value: function(value) {
2262	      return value;
2263	    }
2264	  };
2265
2266	  modules.forEach(function(module) {
2267
2268	    function arrayUnwrap(type, value) {
2269	      if (type !== 'value' && isArray$1(value)) {
2270	        value = annotate(value.slice());
2271	      }
2272
2273	      return value;
2274	    }
2275
2276	    // TODO(vojta): handle wrong inputs (modules)
2277	    if (module instanceof Module) {
2278	      module.forEach(function(provider) {
2279	        var name = provider[0];
2280	        var type = provider[1];
2281	        var value = provider[2];
2282
2283	        providers[name] = [factoryMap[type], arrayUnwrap(type, value), type];
2284	      });
2285	    } else if (typeof module === 'object') {
2286	      if (module.__exports__) {
2287	        var clonedModule = Object.keys(module).reduce(function(m, key) {
2288	          if (key.substring(0, 2) !== '__') {
2289	            m[key] = module[key];
2290	          }
2291	          return m;
2292	        }, Object.create(null));
2293
2294	        var privateInjector = new Injector((module.__modules__ || []).concat([clonedModule]), self);
2295	        var getFromPrivateInjector = annotate(function(key) {
2296	          return privateInjector.get(key);
2297	        });
2298	        module.__exports__.forEach(function(key) {
2299	          providers[key] = [getFromPrivateInjector, key, 'private', privateInjector];
2300	        });
2301	      } else {
2302	        Object.keys(module).forEach(function(name) {
2303	          if (module[name][2] === 'private') {
2304	            providers[name] = module[name];
2305	            return;
2306	          }
2307
2308	          var type = module[name][0];
2309	          var value = module[name][1];
2310
2311	          providers[name] = [factoryMap[type], arrayUnwrap(type, value), type];
2312	        });
2313	      }
2314	    }
2315	  });
2316
2317	  // public API
2318	  this.get = get;
2319	  this.invoke = invoke;
2320	  this.instantiate = instantiate;
2321	  this.createChild = createChild;
2322	}
2323
2324	var DEFAULT_RENDER_PRIORITY$1 = 1000;
2325
2326	/**
2327	 * The base implementation of shape and connection renderers.
2328	 *
2329	 * @param {EventBus} eventBus
2330	 * @param {number} [renderPriority=1000]
2331	 */
2332	function BaseRenderer(eventBus, renderPriority) {
2333	  var self = this;
2334
2335	  renderPriority = renderPriority || DEFAULT_RENDER_PRIORITY$1;
2336
2337	  eventBus.on([ 'render.shape', 'render.connection' ], renderPriority, function(evt, context) {
2338	    var type = evt.type,
2339	        element = context.element,
2340	        visuals = context.gfx;
2341
2342	    if (self.canRender(element)) {
2343	      if (type === 'render.shape') {
2344	        return self.drawShape(visuals, element);
2345	      } else {
2346	        return self.drawConnection(visuals, element);
2347	      }
2348	    }
2349	  });
2350
2351	  eventBus.on([ 'render.getShapePath', 'render.getConnectionPath'], renderPriority, function(evt, element) {
2352	    if (self.canRender(element)) {
2353	      if (evt.type === 'render.getShapePath') {
2354	        return self.getShapePath(element);
2355	      } else {
2356	        return self.getConnectionPath(element);
2357	      }
2358	    }
2359	  });
2360	}
2361
2362	/**
2363	 * Should check whether *this* renderer can render
2364	 * the element/connection.
2365	 *
2366	 * @param {element} element
2367	 *
2368	 * @returns {boolean}
2369	 */
2370	BaseRenderer.prototype.canRender = function() {};
2371
2372	/**
2373	 * Provides the shape's snap svg element to be drawn on the `canvas`.
2374	 *
2375	 * @param {djs.Graphics} visuals
2376	 * @param {Shape} shape
2377	 *
2378	 * @returns {Snap.svg} [returns a Snap.svg paper element ]
2379	 */
2380	BaseRenderer.prototype.drawShape = function() {};
2381
2382	/**
2383	 * Provides the shape's snap svg element to be drawn on the `canvas`.
2384	 *
2385	 * @param {djs.Graphics} visuals
2386	 * @param {Connection} connection
2387	 *
2388	 * @returns {Snap.svg} [returns a Snap.svg paper element ]
2389	 */
2390	BaseRenderer.prototype.drawConnection = function() {};
2391
2392	/**
2393	 * Gets the SVG path of a shape that represents it's visual bounds.
2394	 *
2395	 * @param {Shape} shape
2396	 *
2397	 * @return {string} svg path
2398	 */
2399	BaseRenderer.prototype.getShapePath = function() {};
2400
2401	/**
2402	 * Gets the SVG path of a connection that represents it's visual bounds.
2403	 *
2404	 * @param {Connection} connection
2405	 *
2406	 * @return {string} svg path
2407	 */
2408	BaseRenderer.prototype.getConnectionPath = function() {};
2409
2410	function componentsToPath(elements) {
2411	  return elements.join(',').replace(/,?([A-z]),?/g, '$1');
2412	}
2413
2414	function toSVGPoints(points) {
2415	  var result = '';
2416
2417	  for (var i = 0, p; (p = points[i]); i++) {
2418	    result += p.x + ',' + p.y + ' ';
2419	  }
2420
2421	  return result;
2422	}
2423
2424	function createLine(points, attrs) {
2425
2426	  var line = create$1('polyline');
2427	  attr(line, { points: toSVGPoints(points) });
2428
2429	  if (attrs) {
2430	    attr(line, attrs);
2431	  }
2432
2433	  return line;
2434	}
2435
2436	function updateLine(gfx, points) {
2437	  attr(gfx, { points: toSVGPoints(points) });
2438
2439	  return gfx;
2440	}
2441
2442	/**
2443	 * Get parent elements.
2444	 *
2445	 * @param {Array<djs.model.base>} elements
2446	 *
2447	 * @returns {Array<djs.model.Base>}
2448	 */
2449	function getParents$1(elements) {
2450
2451	  // find elements that are not children of any other elements
2452	  return filter(elements, function(element) {
2453	    return !find(elements, function(e) {
2454	      return e !== element && getParent$1(element, e);
2455	    });
2456	  });
2457	}
2458
2459
2460	function getParent$1(element, parent) {
2461	  if (!parent) {
2462	    return;
2463	  }
2464
2465	  if (element === parent) {
2466	    return parent;
2467	  }
2468
2469	  if (!element.parent) {
2470	    return;
2471	  }
2472
2473	  return getParent$1(element.parent, parent);
2474	}
2475
2476
2477	/**
2478	 * Adds an element to a collection and returns true if the
2479	 * element was added.
2480	 *
2481	 * @param {Array<Object>} elements
2482	 * @param {Object} e
2483	 * @param {boolean} unique
2484	 */
2485	function add$1(elements, e, unique) {
2486	  var canAdd = !unique || elements.indexOf(e) === -1;
2487
2488	  if (canAdd) {
2489	    elements.push(e);
2490	  }
2491
2492	  return canAdd;
2493	}
2494
2495
2496	/**
2497	 * Iterate over each element in a collection, calling the iterator function `fn`
2498	 * with (element, index, recursionDepth).
2499	 *
2500	 * Recurse into all elements that are returned by `fn`.
2501	 *
2502	 * @param  {Object|Array<Object>} elements
2503	 * @param  {Function} fn iterator function called with (element, index, recursionDepth)
2504	 * @param  {number} [depth] maximum recursion depth
2505	 */
2506	function eachElement(elements, fn, depth) {
2507
2508	  depth = depth || 0;
2509
2510	  if (!isArray$2(elements)) {
2511	    elements = [ elements ];
2512	  }
2513
2514	  forEach(elements, function(s, i) {
2515	    var filter = fn(s, i, depth);
2516
2517	    if (isArray$2(filter) && filter.length) {
2518	      eachElement(filter, fn, depth + 1);
2519	    }
2520	  });
2521	}
2522
2523
2524	/**
2525	 * Collects self + child elements up to a given depth from a list of elements.
2526	 *
2527	 * @param  {djs.model.Base|Array<djs.model.Base>} elements the elements to select the children from
2528	 * @param  {boolean} unique whether to return a unique result set (no duplicates)
2529	 * @param  {number} maxDepth the depth to search through or -1 for infinite
2530	 *
2531	 * @return {Array<djs.model.Base>} found elements
2532	 */
2533	function selfAndChildren(elements, unique, maxDepth) {
2534	  var result = [],
2535	      processedChildren = [];
2536
2537	  eachElement(elements, function(element, i, depth) {
2538	    add$1(result, element, unique);
2539
2540	    var children = element.children;
2541
2542	    // max traversal depth not reached yet
2543	    if (maxDepth === -1 || depth < maxDepth) {
2544
2545	      // children exist && children not yet processed
2546	      if (children && add$1(processedChildren, children, unique)) {
2547	        return children;
2548	      }
2549	    }
2550	  });
2551
2552	  return result;
2553	}
2554
2555
2556	/**
2557	 * Return self + ALL children for a number of elements
2558	 *
2559	 * @param  {Array<djs.model.Base>} elements to query
2560	 * @param  {boolean} allowDuplicates to allow duplicates in the result set
2561	 *
2562	 * @return {Array<djs.model.Base>} the collected elements
2563	 */
2564	function selfAndAllChildren(elements, allowDuplicates) {
2565	  return selfAndChildren(elements, !allowDuplicates, -1);
2566	}
2567
2568
2569	/**
2570	 * Gets the the closure for all selected elements,
2571	 * their enclosed children and connections.
2572	 *
2573	 * @param {Array<djs.model.Base>} elements
2574	 * @param {boolean} [isTopLevel=true]
2575	 * @param {Object} [existingClosure]
2576	 *
2577	 * @return {Object} newClosure
2578	 */
2579	function getClosure(elements, isTopLevel, closure) {
2580
2581	  if (isUndefined$1(isTopLevel)) {
2582	    isTopLevel = true;
2583	  }
2584
2585	  if (isObject(isTopLevel)) {
2586	    closure = isTopLevel;
2587	    isTopLevel = true;
2588	  }
2589
2590
2591	  closure = closure || {};
2592
2593	  var allShapes = copyObject(closure.allShapes),
2594	      allConnections = copyObject(closure.allConnections),
2595	      enclosedElements = copyObject(closure.enclosedElements),
2596	      enclosedConnections = copyObject(closure.enclosedConnections);
2597
2598	  var topLevel = copyObject(
2599	    closure.topLevel,
2600	    isTopLevel && groupBy(elements, function(e) { return e.id; })
2601	  );
2602
2603
2604	  function handleConnection(c) {
2605	    if (topLevel[c.source.id] && topLevel[c.target.id]) {
2606	      topLevel[c.id] = [ c ];
2607	    }
2608
2609	    // not enclosed as a child, but maybe logically
2610	    // (connecting two moved elements?)
2611	    if (allShapes[c.source.id] && allShapes[c.target.id]) {
2612	      enclosedConnections[c.id] = enclosedElements[c.id] = c;
2613	    }
2614
2615	    allConnections[c.id] = c;
2616	  }
2617
2618	  function handleElement(element) {
2619
2620	    enclosedElements[element.id] = element;
2621
2622	    if (element.waypoints) {
2623
2624	      // remember connection
2625	      enclosedConnections[element.id] = allConnections[element.id] = element;
2626	    } else {
2627
2628	      // remember shape
2629	      allShapes[element.id] = element;
2630
2631	      // remember all connections
2632	      forEach(element.incoming, handleConnection);
2633
2634	      forEach(element.outgoing, handleConnection);
2635
2636	      // recurse into children
2637	      return element.children;
2638	    }
2639	  }
2640
2641	  eachElement(elements, handleElement);
2642
2643	  return {
2644	    allShapes: allShapes,
2645	    allConnections: allConnections,
2646	    topLevel: topLevel,
2647	    enclosedConnections: enclosedConnections,
2648	    enclosedElements: enclosedElements
2649	  };
2650	}
2651
2652	/**
2653	 * Returns the surrounding bbox for all elements in
2654	 * the array or the element primitive.
2655	 *
2656	 * @param {Array<djs.model.Shape>|djs.model.Shape} elements
2657	 * @param {boolean} stopRecursion
2658	 */
2659	function getBBox(elements, stopRecursion) {
2660
2661	  stopRecursion = !!stopRecursion;
2662	  if (!isArray$2(elements)) {
2663	    elements = [elements];
2664	  }
2665
2666	  var minX,
2667	      minY,
2668	      maxX,
2669	      maxY;
2670
2671	  forEach(elements, function(element) {
2672
2673	    // If element is a connection the bbox must be computed first
2674	    var bbox = element;
2675	    if (element.waypoints && !stopRecursion) {
2676	      bbox = getBBox(element.waypoints, true);
2677	    }
2678
2679	    var x = bbox.x,
2680	        y = bbox.y,
2681	        height = bbox.height || 0,
2682	        width = bbox.width || 0;
2683
2684	    if (x < minX || minX === undefined) {
2685	      minX = x;
2686	    }
2687	    if (y < minY || minY === undefined) {
2688	      minY = y;
2689	    }
2690
2691	    if ((x + width) > maxX || maxX === undefined) {
2692	      maxX = x + width;
2693	    }
2694	    if ((y + height) > maxY || maxY === undefined) {
2695	      maxY = y + height;
2696	    }
2697	  });
2698
2699	  return {
2700	    x: minX,
2701	    y: minY,
2702	    height: maxY - minY,
2703	    width: maxX - minX
2704	  };
2705	}
2706
2707
2708	/**
2709	 * Returns all elements that are enclosed from the bounding box.
2710	 *
2711	 *   * If bbox.(width|height) is not specified the method returns
2712	 *     all elements with element.x/y > bbox.x/y
2713	 *   * If only bbox.x or bbox.y is specified, method return all elements with
2714	 *     e.x > bbox.x or e.y > bbox.y
2715	 *
2716	 * @param {Array<djs.model.Shape>} elements List of Elements to search through
2717	 * @param {djs.model.Shape} bbox the enclosing bbox.
2718	 *
2719	 * @return {Array<djs.model.Shape>} enclosed elements
2720	 */
2721	function getEnclosedElements(elements, bbox) {
2722
2723	  var filteredElements = {};
2724
2725	  forEach(elements, function(element) {
2726
2727	    var e = element;
2728
2729	    if (e.waypoints) {
2730	      e = getBBox(e);
2731	    }
2732
2733	    if (!isNumber(bbox.y) && (e.x > bbox.x)) {
2734	      filteredElements[element.id] = element;
2735	    }
2736	    if (!isNumber(bbox.x) && (e.y > bbox.y)) {
2737	      filteredElements[element.id] = element;
2738	    }
2739	    if (e.x > bbox.x && e.y > bbox.y) {
2740	      if (isNumber(bbox.width) && isNumber(bbox.height) &&
2741	          e.width + e.x < bbox.width + bbox.x &&
2742	          e.height + e.y < bbox.height + bbox.y) {
2743
2744	        filteredElements[element.id] = element;
2745	      } else if (!isNumber(bbox.width) || !isNumber(bbox.height)) {
2746	        filteredElements[element.id] = element;
2747	      }
2748	    }
2749	  });
2750
2751	  return filteredElements;
2752	}
2753
2754
2755	function getType(element) {
2756
2757	  if ('waypoints' in element) {
2758	    return 'connection';
2759	  }
2760
2761	  if ('x' in element) {
2762	    return 'shape';
2763	  }
2764
2765	  return 'root';
2766	}
2767
2768	function isFrameElement$1(element) {
2769
2770	  return !!(element && element.isFrame);
2771	}
2772
2773	// helpers ///////////////////////////////
2774
2775	function copyObject(src1, src2) {
2776	  return assign({}, src1 || {}, src2 || {});
2777	}
2778
2779	// apply default renderer with lowest possible priority
2780	// so that it only kicks in if noone else could render
2781	var DEFAULT_RENDER_PRIORITY = 1;
2782
2783	/**
2784	 * The default renderer used for shapes and connections.
2785	 *
2786	 * @param {EventBus} eventBus
2787	 * @param {Styles} styles
2788	 */
2789	function DefaultRenderer(eventBus, styles) {
2790
2791	  //
2792	  BaseRenderer.call(this, eventBus, DEFAULT_RENDER_PRIORITY);
2793
2794	  this.CONNECTION_STYLE = styles.style([ 'no-fill' ], { strokeWidth: 5, stroke: 'fuchsia' });
2795	  this.SHAPE_STYLE = styles.style({ fill: 'white', stroke: 'fuchsia', strokeWidth: 2 });
2796	  this.FRAME_STYLE = styles.style([ 'no-fill' ], { stroke: 'fuchsia', strokeDasharray: 4, strokeWidth: 2 });
2797	}
2798
2799	inherits$1(DefaultRenderer, BaseRenderer);
2800
2801
2802	DefaultRenderer.prototype.canRender = function() {
2803	  return true;
2804	};
2805
2806	DefaultRenderer.prototype.drawShape = function drawShape(visuals, element) {
2807	  var rect = create$1('rect');
2808
2809	  attr(rect, {
2810	    x: 0,
2811	    y: 0,
2812	    width: element.width || 0,
2813	    height: element.height || 0
2814	  });
2815
2816	  if (isFrameElement$1(element)) {
2817	    attr(rect, this.FRAME_STYLE);
2818	  } else {
2819	    attr(rect, this.SHAPE_STYLE);
2820	  }
2821
2822	  append(visuals, rect);
2823
2824	  return rect;
2825	};
2826
2827	DefaultRenderer.prototype.drawConnection = function drawConnection(visuals, connection) {
2828
2829	  var line = createLine(connection.waypoints, this.CONNECTION_STYLE);
2830	  append(visuals, line);
2831
2832	  return line;
2833	};
2834
2835	DefaultRenderer.prototype.getShapePath = function getShapePath(shape) {
2836
2837	  var x = shape.x,
2838	      y = shape.y,
2839	      width = shape.width,
2840	      height = shape.height;
2841
2842	  var shapePath = [
2843	    ['M', x, y],
2844	    ['l', width, 0],
2845	    ['l', 0, height],
2846	    ['l', -width, 0],
2847	    ['z']
2848	  ];
2849
2850	  return componentsToPath(shapePath);
2851	};
2852
2853	DefaultRenderer.prototype.getConnectionPath = function getConnectionPath(connection) {
2854	  var waypoints = connection.waypoints;
2855
2856	  var idx, point, connectionPath = [];
2857
2858	  for (idx = 0; (point = waypoints[idx]); idx++) {
2859
2860	    // take invisible docking into account
2861	    // when creating the path
2862	    point = point.original || point;
2863
2864	    connectionPath.push([ idx === 0 ? 'M' : 'L', point.x, point.y ]);
2865	  }
2866
2867	  return componentsToPath(connectionPath);
2868	};
2869
2870
2871	DefaultRenderer.$inject = [ 'eventBus', 'styles' ];
2872
2873	/**
2874	 * A component that manages shape styles
2875	 */
2876	function Styles() {
2877
2878	  var defaultTraits = {
2879
2880	    'no-fill': {
2881	      fill: 'none'
2882	    },
2883	    'no-border': {
2884	      strokeOpacity: 0.0
2885	    },
2886	    'no-events': {
2887	      pointerEvents: 'none'
2888	    }
2889	  };
2890
2891	  var self = this;
2892
2893	  /**
2894	   * Builds a style definition from a className, a list of traits and an object of additional attributes.
2895	   *
2896	   * @param  {string} className
2897	   * @param  {Array<string>} traits
2898	   * @param  {Object} additionalAttrs
2899	   *
2900	   * @return {Object} the style defintion
2901	   */
2902	  this.cls = function(className, traits, additionalAttrs) {
2903	    var attrs = this.style(traits, additionalAttrs);
2904
2905	    return assign(attrs, { 'class': className });
2906	  };
2907
2908	  /**
2909	   * Builds a style definition from a list of traits and an object of additional attributes.
2910	   *
2911	   * @param  {Array<string>} traits
2912	   * @param  {Object} additionalAttrs
2913	   *
2914	   * @return {Object} the style defintion
2915	   */
2916	  this.style = function(traits, additionalAttrs) {
2917
2918	    if (!isArray$2(traits) && !additionalAttrs) {
2919	      additionalAttrs = traits;
2920	      traits = [];
2921	    }
2922
2923	    var attrs = reduce(traits, function(attrs, t) {
2924	      return assign(attrs, defaultTraits[t] || {});
2925	    }, {});
2926
2927	    return additionalAttrs ? assign(attrs, additionalAttrs) : attrs;
2928	  };
2929
2930	  this.computeStyle = function(custom, traits, defaultStyles) {
2931	    if (!isArray$2(traits)) {
2932	      defaultStyles = traits;
2933	      traits = [];
2934	    }
2935
2936	    return self.style(traits || [], assign({}, defaultStyles, custom || {}));
2937	  };
2938	}
2939
2940	var DrawModule$1 = {
2941	  __init__: [ 'defaultRenderer' ],
2942	  defaultRenderer: [ 'type', DefaultRenderer ],
2943	  styles: [ 'type', Styles ]
2944	};
2945
2946	/**
2947	 * Failsafe remove an element from a collection
2948	 *
2949	 * @param  {Array<Object>} [collection]
2950	 * @param  {Object} [element]
2951	 *
2952	 * @return {number} the previous index of the element
2953	 */
2954	function remove(collection, element) {
2955
2956	  if (!collection || !element) {
2957	    return -1;
2958	  }
2959
2960	  var idx = collection.indexOf(element);
2961
2962	  if (idx !== -1) {
2963	    collection.splice(idx, 1);
2964	  }
2965
2966	  return idx;
2967	}
2968
2969	/**
2970	 * Fail save add an element to the given connection, ensuring
2971	 * it does not yet exist.
2972	 *
2973	 * @param {Array<Object>} collection
2974	 * @param {Object} element
2975	 * @param {number} idx
2976	 */
2977	function add(collection, element, idx) {
2978
2979	  if (!collection || !element) {
2980	    return;
2981	  }
2982
2983	  if (typeof idx !== 'number') {
2984	    idx = -1;
2985	  }
2986
2987	  var currentIdx = collection.indexOf(element);
2988
2989	  if (currentIdx !== -1) {
2990
2991	    if (currentIdx === idx) {
2992
2993	      // nothing to do, position has not changed
2994	      return;
2995	    } else {
2996
2997	      if (idx !== -1) {
2998
2999	        // remove from current position
3000	        collection.splice(currentIdx, 1);
3001	      } else {
3002
3003	        // already exists in collection
3004	        return;
3005	      }
3006	    }
3007	  }
3008
3009	  if (idx !== -1) {
3010
3011	    // insert at specified position
3012	    collection.splice(idx, 0, element);
3013	  } else {
3014
3015	    // push to end
3016	    collection.push(element);
3017	  }
3018	}
3019
3020
3021	/**
3022	 * Fail save get the index of an element in a collection.
3023	 *
3024	 * @param {Array<Object>} collection
3025	 * @param {Object} element
3026	 *
3027	 * @return {number} the index or -1 if collection or element do
3028	 *                  not exist or the element is not contained.
3029	 */
3030	function indexOf(collection, element) {
3031
3032	  if (!collection || !element) {
3033	    return -1;
3034	  }
3035
3036	  return collection.indexOf(element);
3037	}
3038
3039	/**
3040	 * Computes the distance between two points
3041	 *
3042	 * @param  {Point}  p
3043	 * @param  {Point}  q
3044	 *
3045	 * @return {number}  distance
3046	 */
3047	function pointDistance(a, b) {
3048	  if (!a || !b) {
3049	    return -1;
3050	  }
3051
3052	  return Math.sqrt(
3053	    Math.pow(a.x - b.x, 2) +
3054	    Math.pow(a.y - b.y, 2)
3055	  );
3056	}
3057
3058
3059	/**
3060	 * Returns true if the point r is on the line between p and q
3061	 *
3062	 * @param  {Point}  p
3063	 * @param  {Point}  q
3064	 * @param  {Point}  r
3065	 * @param  {number} [accuracy=5] accuracy for points on line check (lower is better)
3066	 *
3067	 * @return {boolean}
3068	 */
3069	function pointsOnLine(p, q, r, accuracy) {
3070
3071	  if (typeof accuracy === 'undefined') {
3072	    accuracy = 5;
3073	  }
3074
3075	  if (!p || !q || !r) {
3076	    return false;
3077	  }
3078
3079	  var val = (q.x - p.x) * (r.y - p.y) - (q.y - p.y) * (r.x - p.x),
3080	      dist = pointDistance(p, q);
3081
3082	  // @see http://stackoverflow.com/a/907491/412190
3083	  return Math.abs(val / dist) <= accuracy;
3084	}
3085
3086
3087	var ALIGNED_THRESHOLD = 2;
3088
3089	/**
3090	 * Check whether two points are horizontally or vertically aligned.
3091	 *
3092	 * @param {Array<Point>|Point}
3093	 * @param {Point}
3094	 *
3095	 * @return {string|boolean}
3096	 */
3097	function pointsAligned(a, b) {
3098	  var points;
3099
3100	  if (isArray$2(a)) {
3101	    points = a;
3102	  } else {
3103	    points = [ a, b ];
3104	  }
3105
3106	  if (pointsAlignedHorizontally(points)) {
3107	    return 'h';
3108	  }
3109
3110	  if (pointsAlignedVertically(points)) {
3111	    return 'v';
3112	  }
3113
3114	  return false;
3115	}
3116
3117	function pointsAlignedHorizontally(a, b) {
3118	  var points;
3119
3120	  if (isArray$2(a)) {
3121	    points = a;
3122	  } else {
3123	    points = [ a, b ];
3124	  }
3125
3126	  var firstPoint = points.slice().shift();
3127
3128	  return every(points, function(point) {
3129	    return Math.abs(firstPoint.y - point.y) <= ALIGNED_THRESHOLD;
3130	  });
3131	}
3132
3133	function pointsAlignedVertically(a, b) {
3134	  var points;
3135
3136	  if (isArray$2(a)) {
3137	    points = a;
3138	  } else {
3139	    points = [ a, b ];
3140	  }
3141
3142	  var firstPoint = points.slice().shift();
3143
3144	  return every(points, function(point) {
3145	    return Math.abs(firstPoint.x - point.x) <= ALIGNED_THRESHOLD;
3146	  });
3147	}
3148
3149
3150
3151	/**
3152	 * Returns true if the point p is inside the rectangle rect
3153	 *
3154	 * @param  {Point}  p
3155	 * @param  {Rect} rect
3156	 * @param  {number} tolerance
3157	 *
3158	 * @return {boolean}
3159	 */
3160	function pointInRect(p, rect, tolerance) {
3161	  tolerance = tolerance || 0;
3162
3163	  return p.x > rect.x - tolerance &&
3164	         p.y > rect.y - tolerance &&
3165	         p.x < rect.x + rect.width + tolerance &&
3166	         p.y < rect.y + rect.height + tolerance;
3167	}
3168
3169	/**
3170	 * Returns a point in the middle of points p and q
3171	 *
3172	 * @param  {Point}  p
3173	 * @param  {Point}  q
3174	 *
3175	 * @return {Point} middle point
3176	 */
3177	function getMidPoint(p, q) {
3178	  return {
3179	    x: Math.round(p.x + ((q.x - p.x) / 2.0)),
3180	    y: Math.round(p.y + ((q.y - p.y) / 2.0))
3181	  };
3182	}
3183
3184	/**
3185	 * This file contains source code adapted from Snap.svg (licensed Apache-2.0).
3186	 *
3187	 * @see https://github.com/adobe-webplatform/Snap.svg/blob/master/src/path.js
3188	 */
3189
3190	/* eslint no-fallthrough: "off" */
3191
3192	var p2s = /,?([a-z]),?/gi,
3193	    toFloat = parseFloat,
3194	    math = Math,
3195	    PI = math.PI,
3196	    mmin = math.min,
3197	    mmax = math.max,
3198	    pow = math.pow,
3199	    abs$7 = math.abs,
3200	    pathCommand = /([a-z])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?[\s]*,?[\s]*)+)/ig,
3201	    pathValues = /(-?\d*\.?\d*(?:e[-+]?\d+)?)[\s]*,?[\s]*/ig;
3202
3203	var isArray = Array.isArray || function(o) { return o instanceof Array; };
3204
3205	function hasProperty(obj, property) {
3206	  return Object.prototype.hasOwnProperty.call(obj, property);
3207	}
3208
3209	function clone(obj) {
3210
3211	  if (typeof obj == 'function' || Object(obj) !== obj) {
3212	    return obj;
3213	  }
3214
3215	  var res = new obj.constructor;
3216
3217	  for (var key in obj) {
3218	    if (hasProperty(obj, key)) {
3219	      res[key] = clone(obj[key]);
3220	    }
3221	  }
3222
3223	  return res;
3224	}
3225
3226	function repush(array, item) {
3227	  for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {
3228	    return array.push(array.splice(i, 1)[0]);
3229	  }
3230	}
3231
3232	function cacher(f) {
3233
3234	  function newf() {
3235
3236	    var arg = Array.prototype.slice.call(arguments, 0),
3237	        args = arg.join('\u2400'),
3238	        cache = newf.cache = newf.cache || {},
3239	        count = newf.count = newf.count || [];
3240
3241	    if (hasProperty(cache, args)) {
3242	      repush(count, args);
3243	      return cache[args];
3244	    }
3245
3246	    count.length >= 1e3 && delete cache[count.shift()];
3247	    count.push(args);
3248	    cache[args] = f.apply(0, arg);
3249
3250	    return cache[args];
3251	  }
3252	  return newf;
3253	}
3254
3255	function parsePathString(pathString) {
3256
3257	  if (!pathString) {
3258	    return null;
3259	  }
3260
3261	  var pth = paths(pathString);
3262
3263	  if (pth.arr) {
3264	    return clone(pth.arr);
3265	  }
3266
3267	  var paramCounts = { a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0 },
3268	      data = [];
3269
3270	  if (isArray(pathString) && isArray(pathString[0])) { // rough assumption
3271	    data = clone(pathString);
3272	  }
3273
3274	  if (!data.length) {
3275
3276	    String(pathString).replace(pathCommand, function(a, b, c) {
3277	      var params = [],
3278	          name = b.toLowerCase();
3279
3280	      c.replace(pathValues, function(a, b) {
3281	        b && params.push(+b);
3282	      });
3283
3284	      if (name == 'm' && params.length > 2) {
3285	        data.push([b].concat(params.splice(0, 2)));
3286	        name = 'l';
3287	        b = b == 'm' ? 'l' : 'L';
3288	      }
3289
3290	      while (params.length >= paramCounts[name]) {
3291	        data.push([b].concat(params.splice(0, paramCounts[name])));
3292	        if (!paramCounts[name]) {
3293	          break;
3294	        }
3295	      }
3296	    });
3297	  }
3298
3299	  data.toString = paths.toString;
3300	  pth.arr = clone(data);
3301
3302	  return data;
3303	}
3304
3305	function paths(ps) {
3306	  var p = paths.ps = paths.ps || {};
3307
3308	  if (p[ps]) {
3309	    p[ps].sleep = 100;
3310	  } else {
3311	    p[ps] = {
3312	      sleep: 100
3313	    };
3314	  }
3315
3316	  setTimeout(function() {
3317	    for (var key in p) {
3318	      if (hasProperty(p, key) && key != ps) {
3319	        p[key].sleep--;
3320	        !p[key].sleep && delete p[key];
3321	      }
3322	    }
3323	  });
3324
3325	  return p[ps];
3326	}
3327
3328	function rectBBox(x, y, width, height) {
3329
3330	  if (arguments.length === 1) {
3331	    y = x.y;
3332	    width = x.width;
3333	    height = x.height;
3334	    x = x.x;
3335	  }
3336
3337	  return {
3338	    x: x,
3339	    y: y,
3340	    width: width,
3341	    height: height,
3342	    x2: x + width,
3343	    y2: y + height
3344	  };
3345	}
3346
3347	function pathToString() {
3348	  return this.join(',').replace(p2s, '$1');
3349	}
3350
3351	function pathClone(pathArray) {
3352	  var res = clone(pathArray);
3353	  res.toString = pathToString;
3354	  return res;
3355	}
3356
3357	function findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
3358	  var t1 = 1 - t,
3359	      t13 = pow(t1, 3),
3360	      t12 = pow(t1, 2),
3361	      t2 = t * t,
3362	      t3 = t2 * t,
3363	      x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,
3364	      y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y;
3365
3366	  return {
3367	    x: fixError(x),
3368	    y: fixError(y)
3369	  };
3370	}
3371
3372	function bezierBBox(points) {
3373
3374	  var bbox = curveBBox.apply(null, points);
3375
3376	  return rectBBox(
3377	    bbox.x0,
3378	    bbox.y0,
3379	    bbox.x1 - bbox.x0,
3380	    bbox.y1 - bbox.y0
3381	  );
3382	}
3383
3384	function isPointInsideBBox$2(bbox, x, y) {
3385	  return x >= bbox.x &&
3386	    x <= bbox.x + bbox.width &&
3387	    y >= bbox.y &&
3388	    y <= bbox.y + bbox.height;
3389	}
3390
3391	function isBBoxIntersect(bbox1, bbox2) {
3392	  bbox1 = rectBBox(bbox1);
3393	  bbox2 = rectBBox(bbox2);
3394	  return isPointInsideBBox$2(bbox2, bbox1.x, bbox1.y)
3395	    || isPointInsideBBox$2(bbox2, bbox1.x2, bbox1.y)
3396	    || isPointInsideBBox$2(bbox2, bbox1.x, bbox1.y2)
3397	    || isPointInsideBBox$2(bbox2, bbox1.x2, bbox1.y2)
3398	    || isPointInsideBBox$2(bbox1, bbox2.x, bbox2.y)
3399	    || isPointInsideBBox$2(bbox1, bbox2.x2, bbox2.y)
3400	    || isPointInsideBBox$2(bbox1, bbox2.x, bbox2.y2)
3401	    || isPointInsideBBox$2(bbox1, bbox2.x2, bbox2.y2)
3402	    || (bbox1.x < bbox2.x2 && bbox1.x > bbox2.x
3403	        || bbox2.x < bbox1.x2 && bbox2.x > bbox1.x)
3404	    && (bbox1.y < bbox2.y2 && bbox1.y > bbox2.y
3405	        || bbox2.y < bbox1.y2 && bbox2.y > bbox1.y);
3406	}
3407
3408	function base3(t, p1, p2, p3, p4) {
3409	  var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,
3410	      t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;
3411	  return t * t2 - 3 * p1 + 3 * p2;
3412	}
3413
3414	function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {
3415
3416	  if (z == null) {
3417	    z = 1;
3418	  }
3419
3420	  z = z > 1 ? 1 : z < 0 ? 0 : z;
3421
3422	  var z2 = z / 2,
3423	      n = 12,
3424	      Tvalues = [-.1252,.1252,-.3678,.3678,-.5873,.5873,-.7699,.7699,-.9041,.9041,-.9816,.9816],
3425	      Cvalues = [0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472],
3426	      sum = 0;
3427
3428	  for (var i = 0; i < n; i++) {
3429	    var ct = z2 * Tvalues[i] + z2,
3430	        xbase = base3(ct, x1, x2, x3, x4),
3431	        ybase = base3(ct, y1, y2, y3, y4),
3432	        comb = xbase * xbase + ybase * ybase;
3433
3434	    sum += Cvalues[i] * math.sqrt(comb);
3435	  }
3436
3437	  return z2 * sum;
3438	}
3439
3440
3441	function intersectLines(x1, y1, x2, y2, x3, y3, x4, y4) {
3442
3443	  if (
3444	    mmax(x1, x2) < mmin(x3, x4) ||
3445	      mmin(x1, x2) > mmax(x3, x4) ||
3446	      mmax(y1, y2) < mmin(y3, y4) ||
3447	      mmin(y1, y2) > mmax(y3, y4)
3448	  ) {
3449	    return;
3450	  }
3451
3452	  var nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4),
3453	      ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4),
3454	      denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
3455
3456	  if (!denominator) {
3457	    return;
3458	  }
3459
3460	  var px = fixError(nx / denominator),
3461	      py = fixError(ny / denominator),
3462	      px2 = +px.toFixed(2),
3463	      py2 = +py.toFixed(2);
3464
3465	  if (
3466	    px2 < +mmin(x1, x2).toFixed(2) ||
3467	      px2 > +mmax(x1, x2).toFixed(2) ||
3468	      px2 < +mmin(x3, x4).toFixed(2) ||
3469	      px2 > +mmax(x3, x4).toFixed(2) ||
3470	      py2 < +mmin(y1, y2).toFixed(2) ||
3471	      py2 > +mmax(y1, y2).toFixed(2) ||
3472	      py2 < +mmin(y3, y4).toFixed(2) ||
3473	      py2 > +mmax(y3, y4).toFixed(2)
3474	  ) {
3475	    return;
3476	  }
3477
3478	  return { x: px, y: py };
3479	}
3480
3481	function fixError(number) {
3482	  return Math.round(number * 100000000000) / 100000000000;
3483	}
3484
3485	function findBezierIntersections(bez1, bez2, justCount) {
3486	  var bbox1 = bezierBBox(bez1),
3487	      bbox2 = bezierBBox(bez2);
3488
3489	  if (!isBBoxIntersect(bbox1, bbox2)) {
3490	    return justCount ? 0 : [];
3491	  }
3492
3493	  // As an optimization, lines will have only 1 segment
3494
3495	  var l1 = bezlen.apply(0, bez1),
3496	      l2 = bezlen.apply(0, bez2),
3497	      n1 = isLine(bez1) ? 1 : ~~(l1 / 5) || 1,
3498	      n2 = isLine(bez2) ? 1 : ~~(l2 / 5) || 1,
3499	      dots1 = [],
3500	      dots2 = [],
3501	      xy = {},
3502	      res = justCount ? 0 : [];
3503
3504	  for (var i = 0; i < n1 + 1; i++) {
3505	    var p = findDotsAtSegment.apply(0, bez1.concat(i / n1));
3506	    dots1.push({ x: p.x, y: p.y, t: i / n1 });
3507	  }
3508
3509	  for (i = 0; i < n2 + 1; i++) {
3510	    p = findDotsAtSegment.apply(0, bez2.concat(i / n2));
3511	    dots2.push({ x: p.x, y: p.y, t: i / n2 });
3512	  }
3513
3514	  for (i = 0; i < n1; i++) {
3515
3516	    for (var j = 0; j < n2; j++) {
3517	      var di = dots1[i],
3518	          di1 = dots1[i + 1],
3519	          dj = dots2[j],
3520	          dj1 = dots2[j + 1],
3521	          ci = abs$7(di1.x - di.x) < .01 ? 'y' : 'x',
3522	          cj = abs$7(dj1.x - dj.x) < .01 ? 'y' : 'x',
3523	          is = intersectLines(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y),
3524	          key;
3525
3526	      if (is) {
3527	        key = is.x.toFixed(9) + '#' + is.y.toFixed(9);
3528
3529	        if (xy[key]) {
3530	          continue;
3531	        }
3532
3533	        xy[key] = true;
3534
3535	        var t1 = di.t + abs$7((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t),
3536	            t2 = dj.t + abs$7((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t);
3537
3538	        if (t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1) {
3539
3540	          if (justCount) {
3541	            res++;
3542	          } else {
3543	            res.push({
3544	              x: is.x,
3545	              y: is.y,
3546	              t1: t1,
3547	              t2: t2
3548	            });
3549	          }
3550	        }
3551	      }
3552	    }
3553	  }
3554
3555	  return res;
3556	}
3557
3558
3559	/**
3560	 * Find or counts the intersections between two SVG paths.
3561	 *
3562	 * Returns a number in counting mode and a list of intersections otherwise.
3563	 *
3564	 * A single intersection entry contains the intersection coordinates (x, y)
3565	 * as well as additional information regarding the intersecting segments
3566	 * on each path (segment1, segment2) and the relative location of the
3567	 * intersection on these segments (t1, t2).
3568	 *
3569	 * The path may be an SVG path string or a list of path components
3570	 * such as `[ [ 'M', 0, 10 ], [ 'L', 20, 0 ] ]`.
3571	 *
3572	 * @example
3573	 *
3574	 * var intersections = findPathIntersections(
3575	 *   'M0,0L100,100',
3576	 *   [ [ 'M', 0, 100 ], [ 'L', 100, 0 ] ]
3577	 * );
3578	 *
3579	 * // intersections = [
3580	 * //   { x: 50, y: 50, segment1: 1, segment2: 1, t1: 0.5, t2: 0.5 }
3581	 * // ]
3582	 *
3583	 * @param {String|Array<PathDef>} path1
3584	 * @param {String|Array<PathDef>} path2
3585	 * @param {Boolean} [justCount=false]
3586	 *
3587	 * @return {Array<Intersection>|Number}
3588	 */
3589	function findPathIntersections(path1, path2, justCount) {
3590	  path1 = pathToCurve(path1);
3591	  path2 = pathToCurve(path2);
3592
3593	  var x1, y1, x2, y2, x1m, y1m, x2m, y2m, bez1, bez2,
3594	      res = justCount ? 0 : [];
3595
3596	  for (var i = 0, ii = path1.length; i < ii; i++) {
3597	    var pi = path1[i];
3598
3599	    if (pi[0] == 'M') {
3600	      x1 = x1m = pi[1];
3601	      y1 = y1m = pi[2];
3602	    } else {
3603
3604	      if (pi[0] == 'C') {
3605	        bez1 = [x1, y1].concat(pi.slice(1));
3606	        x1 = bez1[6];
3607	        y1 = bez1[7];
3608	      } else {
3609	        bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m];
3610	        x1 = x1m;
3611	        y1 = y1m;
3612	      }
3613
3614	      for (var j = 0, jj = path2.length; j < jj; j++) {
3615	        var pj = path2[j];
3616
3617	        if (pj[0] == 'M') {
3618	          x2 = x2m = pj[1];
3619	          y2 = y2m = pj[2];
3620	        } else {
3621
3622	          if (pj[0] == 'C') {
3623	            bez2 = [x2, y2].concat(pj.slice(1));
3624	            x2 = bez2[6];
3625	            y2 = bez2[7];
3626	          } else {
3627	            bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m];
3628	            x2 = x2m;
3629	            y2 = y2m;
3630	          }
3631
3632	          var intr = findBezierIntersections(bez1, bez2, justCount);
3633
3634	          if (justCount) {
3635	            res += intr;
3636	          } else {
3637
3638	            for (var k = 0, kk = intr.length; k < kk; k++) {
3639	              intr[k].segment1 = i;
3640	              intr[k].segment2 = j;
3641	              intr[k].bez1 = bez1;
3642	              intr[k].bez2 = bez2;
3643	            }
3644
3645	            res = res.concat(intr);
3646	          }
3647	        }
3648	      }
3649	    }
3650	  }
3651
3652	  return res;
3653	}
3654
3655
3656	function pathToAbsolute(pathArray) {
3657	  var pth = paths(pathArray);
3658
3659	  if (pth.abs) {
3660	    return pathClone(pth.abs);
3661	  }
3662
3663	  if (!isArray(pathArray) || !isArray(pathArray && pathArray[0])) { // rough assumption
3664	    pathArray = parsePathString(pathArray);
3665	  }
3666
3667	  if (!pathArray || !pathArray.length) {
3668	    return [['M', 0, 0]];
3669	  }
3670
3671	  var res = [],
3672	      x = 0,
3673	      y = 0,
3674	      mx = 0,
3675	      my = 0,
3676	      start = 0,
3677	      pa0;
3678
3679	  if (pathArray[0][0] == 'M') {
3680	    x = +pathArray[0][1];
3681	    y = +pathArray[0][2];
3682	    mx = x;
3683	    my = y;
3684	    start++;
3685	    res[0] = ['M', x, y];
3686	  }
3687
3688	  for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
3689	    res.push(r = []);
3690	    pa = pathArray[i];
3691	    pa0 = pa[0];
3692
3693	    if (pa0 != pa0.toUpperCase()) {
3694	      r[0] = pa0.toUpperCase();
3695
3696	      switch (r[0]) {
3697	      case 'A':
3698	        r[1] = pa[1];
3699	        r[2] = pa[2];
3700	        r[3] = pa[3];
3701	        r[4] = pa[4];
3702	        r[5] = pa[5];
3703	        r[6] = +pa[6] + x;
3704	        r[7] = +pa[7] + y;
3705	        break;
3706	      case 'V':
3707	        r[1] = +pa[1] + y;
3708	        break;
3709	      case 'H':
3710	        r[1] = +pa[1] + x;
3711	        break;
3712	      case 'M':
3713	        mx = +pa[1] + x;
3714	        my = +pa[2] + y;
3715	      default:
3716	        for (var j = 1, jj = pa.length; j < jj; j++) {
3717	          r[j] = +pa[j] + ((j % 2) ? x : y);
3718	        }
3719	      }
3720	    } else {
3721	      for (var k = 0, kk = pa.length; k < kk; k++) {
3722	        r[k] = pa[k];
3723	      }
3724	    }
3725	    pa0 = pa0.toUpperCase();
3726
3727	    switch (r[0]) {
3728	    case 'Z':
3729	      x = +mx;
3730	      y = +my;
3731	      break;
3732	    case 'H':
3733	      x = r[1];
3734	      break;
3735	    case 'V':
3736	      y = r[1];
3737	      break;
3738	    case 'M':
3739	      mx = r[r.length - 2];
3740	      my = r[r.length - 1];
3741	    default:
3742	      x = r[r.length - 2];
3743	      y = r[r.length - 1];
3744	    }
3745	  }
3746
3747	  res.toString = pathToString;
3748	  pth.abs = pathClone(res);
3749
3750	  return res;
3751	}
3752
3753	function isLine(bez) {
3754	  return (
3755	    bez[0] === bez[2] &&
3756	    bez[1] === bez[3] &&
3757	    bez[4] === bez[6] &&
3758	    bez[5] === bez[7]
3759	  );
3760	}
3761
3762	function lineToCurve(x1, y1, x2, y2) {
3763	  return [
3764	    x1, y1, x2,
3765	    y2, x2, y2
3766	  ];
3767	}
3768
3769	function qubicToCurve(x1, y1, ax, ay, x2, y2) {
3770	  var _13 = 1 / 3,
3771	      _23 = 2 / 3;
3772
3773	  return [
3774	    _13 * x1 + _23 * ax,
3775	    _13 * y1 + _23 * ay,
3776	    _13 * x2 + _23 * ax,
3777	    _13 * y2 + _23 * ay,
3778	    x2,
3779	    y2
3780	  ];
3781	}
3782
3783	function arcToCurve(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
3784
3785	  // for more information of where this math came from visit:
3786	  // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
3787	  var _120 = PI * 120 / 180,
3788	      rad = PI / 180 * (+angle || 0),
3789	      res = [],
3790	      xy,
3791	      rotate = cacher(function(x, y, rad) {
3792	        var X = x * math.cos(rad) - y * math.sin(rad),
3793	            Y = x * math.sin(rad) + y * math.cos(rad);
3794
3795	        return { x: X, y: Y };
3796	      });
3797
3798	  if (!recursive) {
3799	    xy = rotate(x1, y1, -rad);
3800	    x1 = xy.x;
3801	    y1 = xy.y;
3802	    xy = rotate(x2, y2, -rad);
3803	    x2 = xy.x;
3804	    y2 = xy.y;
3805
3806	    var x = (x1 - x2) / 2,
3807	        y = (y1 - y2) / 2;
3808
3809	    var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
3810
3811	    if (h > 1) {
3812	      h = math.sqrt(h);
3813	      rx = h * rx;
3814	      ry = h * ry;
3815	    }
3816
3817	    var rx2 = rx * rx,
3818	        ry2 = ry * ry,
3819	        k = (large_arc_flag == sweep_flag ? -1 : 1) *
3820	            math.sqrt(abs$7((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),
3821	        cx = k * rx * y / ry + (x1 + x2) / 2,
3822	        cy = k * -ry * x / rx + (y1 + y2) / 2,
3823	        f1 = math.asin(((y1 - cy) / ry).toFixed(9)),
3824	        f2 = math.asin(((y2 - cy) / ry).toFixed(9));
3825
3826	    f1 = x1 < cx ? PI - f1 : f1;
3827	    f2 = x2 < cx ? PI - f2 : f2;
3828	    f1 < 0 && (f1 = PI * 2 + f1);
3829	    f2 < 0 && (f2 = PI * 2 + f2);
3830
3831	    if (sweep_flag && f1 > f2) {
3832	      f1 = f1 - PI * 2;
3833	    }
3834	    if (!sweep_flag && f2 > f1) {
3835	      f2 = f2 - PI * 2;
3836	    }
3837	  } else {
3838	    f1 = recursive[0];
3839	    f2 = recursive[1];
3840	    cx = recursive[2];
3841	    cy = recursive[3];
3842	  }
3843
3844	  var df = f2 - f1;
3845
3846	  if (abs$7(df) > _120) {
3847	    var f2old = f2,
3848	        x2old = x2,
3849	        y2old = y2;
3850
3851	    f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
3852	    x2 = cx + rx * math.cos(f2);
3853	    y2 = cy + ry * math.sin(f2);
3854	    res = arcToCurve(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
3855	  }
3856
3857	  df = f2 - f1;
3858
3859	  var c1 = math.cos(f1),
3860	      s1 = math.sin(f1),
3861	      c2 = math.cos(f2),
3862	      s2 = math.sin(f2),
3863	      t = math.tan(df / 4),
3864	      hx = 4 / 3 * rx * t,
3865	      hy = 4 / 3 * ry * t,
3866	      m1 = [x1, y1],
3867	      m2 = [x1 + hx * s1, y1 - hy * c1],
3868	      m3 = [x2 + hx * s2, y2 - hy * c2],
3869	      m4 = [x2, y2];
3870
3871	  m2[0] = 2 * m1[0] - m2[0];
3872	  m2[1] = 2 * m1[1] - m2[1];
3873
3874	  if (recursive) {
3875	    return [m2, m3, m4].concat(res);
3876	  } else {
3877	    res = [m2, m3, m4].concat(res).join().split(',');
3878	    var newres = [];
3879
3880	    for (var i = 0, ii = res.length; i < ii; i++) {
3881	      newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;
3882	    }
3883
3884	    return newres;
3885	  }
3886	}
3887
3888	// Returns bounding box of cubic bezier curve.
3889	// Source: http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
3890	// Original version: NISHIO Hirokazu
3891	// Modifications: https://github.com/timo22345
3892	function curveBBox(x0, y0, x1, y1, x2, y2, x3, y3) {
3893	  var tvalues = [],
3894	      bounds = [[], []],
3895	      a, b, c, t, t1, t2, b2ac, sqrtb2ac;
3896
3897	  for (var i = 0; i < 2; ++i) {
3898
3899	    if (i == 0) {
3900	      b = 6 * x0 - 12 * x1 + 6 * x2;
3901	      a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;
3902	      c = 3 * x1 - 3 * x0;
3903	    } else {
3904	      b = 6 * y0 - 12 * y1 + 6 * y2;
3905	      a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;
3906	      c = 3 * y1 - 3 * y0;
3907	    }
3908
3909	    if (abs$7(a) < 1e-12) {
3910
3911	      if (abs$7(b) < 1e-12) {
3912	        continue;
3913	      }
3914
3915	      t = -c / b;
3916
3917	      if (0 < t && t < 1) {
3918	        tvalues.push(t);
3919	      }
3920
3921	      continue;
3922	    }
3923
3924	    b2ac = b * b - 4 * c * a;
3925	    sqrtb2ac = math.sqrt(b2ac);
3926
3927	    if (b2ac < 0) {
3928	      continue;
3929	    }
3930
3931	    t1 = (-b + sqrtb2ac) / (2 * a);
3932
3933	    if (0 < t1 && t1 < 1) {
3934	      tvalues.push(t1);
3935	    }
3936
3937	    t2 = (-b - sqrtb2ac) / (2 * a);
3938
3939	    if (0 < t2 && t2 < 1) {
3940	      tvalues.push(t2);
3941	    }
3942	  }
3943
3944	  var j = tvalues.length,
3945	      jlen = j,
3946	      mt;
3947
3948	  while (j--) {
3949	    t = tvalues[j];
3950	    mt = 1 - t;
3951	    bounds[0][j] = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3);
3952	    bounds[1][j] = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3);
3953	  }
3954
3955	  bounds[0][jlen] = x0;
3956	  bounds[1][jlen] = y0;
3957	  bounds[0][jlen + 1] = x3;
3958	  bounds[1][jlen + 1] = y3;
3959	  bounds[0].length = bounds[1].length = jlen + 2;
3960
3961	  return {
3962	    x0: mmin.apply(0, bounds[0]),
3963	    y0: mmin.apply(0, bounds[1]),
3964	    x1: mmax.apply(0, bounds[0]),
3965	    y1: mmax.apply(0, bounds[1])
3966	  };
3967	}
3968
3969	function pathToCurve(path) {
3970
3971	  var pth = paths(path);
3972
3973	  // return cached curve, if existing
3974	  if (pth.curve) {
3975	    return pathClone(pth.curve);
3976	  }
3977
3978	  var curvedPath = pathToAbsolute(path),
3979	      attrs = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null },
3980	      processPath = function(path, d, pathCommand) {
3981	        var nx, ny;
3982
3983	        if (!path) {
3984	          return ['C', d.x, d.y, d.x, d.y, d.x, d.y];
3985	        }
3986
3987	        !(path[0] in { T: 1, Q: 1 }) && (d.qx = d.qy = null);
3988
3989	        switch (path[0]) {
3990	        case 'M':
3991	          d.X = path[1];
3992	          d.Y = path[2];
3993	          break;
3994	        case 'A':
3995	          path = ['C'].concat(arcToCurve.apply(0, [d.x, d.y].concat(path.slice(1))));
3996	          break;
3997	        case 'S':
3998	          if (pathCommand == 'C' || pathCommand == 'S') {
3999
4000	            // In 'S' case we have to take into account, if the previous command is C/S.
4001	            nx = d.x * 2 - d.bx;
4002
4003	            // And reflect the previous
4004	            ny = d.y * 2 - d.by;
4005
4006	            // command's control point relative to the current point.
4007	          }
4008	          else {
4009
4010	            // or some else or nothing
4011	            nx = d.x;
4012	            ny = d.y;
4013	          }
4014	          path = ['C', nx, ny].concat(path.slice(1));
4015	          break;
4016	        case 'T':
4017	          if (pathCommand == 'Q' || pathCommand == 'T') {
4018
4019	            // In 'T' case we have to take into account, if the previous command is Q/T.
4020	            d.qx = d.x * 2 - d.qx;
4021
4022	            // And make a reflection similar
4023	            d.qy = d.y * 2 - d.qy;
4024
4025	            // to case 'S'.
4026	          }
4027	          else {
4028
4029	            // or something else or nothing
4030	            d.qx = d.x;
4031	            d.qy = d.y;
4032	          }
4033	          path = ['C'].concat(qubicToCurve(d.x, d.y, d.qx, d.qy, path[1], path[2]));
4034	          break;
4035	        case 'Q':
4036	          d.qx = path[1];
4037	          d.qy = path[2];
4038	          path = ['C'].concat(qubicToCurve(d.x, d.y, path[1], path[2], path[3], path[4]));
4039	          break;
4040	        case 'L':
4041	          path = ['C'].concat(lineToCurve(d.x, d.y, path[1], path[2]));
4042	          break;
4043	        case 'H':
4044	          path = ['C'].concat(lineToCurve(d.x, d.y, path[1], d.y));
4045	          break;
4046	        case 'V':
4047	          path = ['C'].concat(lineToCurve(d.x, d.y, d.x, path[1]));
4048	          break;
4049	        case 'Z':
4050	          path = ['C'].concat(lineToCurve(d.x, d.y, d.X, d.Y));
4051	          break;
4052	        }
4053
4054	        return path;
4055	      },
4056
4057	      fixArc = function(pp, i) {
4058
4059	        if (pp[i].length > 7) {
4060	          pp[i].shift();
4061	          var pi = pp[i];
4062
4063	          while (pi.length) {
4064	            pathCommands[i] = 'A'; // if created multiple C:s, their original seg is saved
4065	            pp.splice(i++, 0, ['C'].concat(pi.splice(0, 6)));
4066	          }
4067
4068	          pp.splice(i, 1);
4069	          ii = curvedPath.length;
4070	        }
4071	      },
4072
4073	      pathCommands = [], // path commands of original path p
4074	      pfirst = '', // temporary holder for original path command
4075	      pathCommand = ''; // holder for previous path command of original path
4076
4077	  for (var i = 0, ii = curvedPath.length; i < ii; i++) {
4078	    curvedPath[i] && (pfirst = curvedPath[i][0]); // save current path command
4079
4080	    if (pfirst != 'C') // C is not saved yet, because it may be result of conversion
4081	    {
4082	      pathCommands[i] = pfirst; // Save current path command
4083	      i && (pathCommand = pathCommands[i - 1]); // Get previous path command pathCommand
4084	    }
4085	    curvedPath[i] = processPath(curvedPath[i], attrs, pathCommand); // Previous path command is inputted to processPath
4086
4087	    if (pathCommands[i] != 'A' && pfirst == 'C') pathCommands[i] = 'C'; // A is the only command
4088	    // which may produce multiple C:s
4089	    // so we have to make sure that C is also C in original path
4090
4091	    fixArc(curvedPath, i); // fixArc adds also the right amount of A:s to pathCommands