bpmn-js
Version:
A bpmn 2.0 toolkit and web modeler
2,314 lines (1,889 loc) • 1.15 MB
JavaScript
/*!
* bpmn-js - bpmn-modeler v1.1.0
*
* Copyright (c) 2014-present, camunda Services GmbH
*
* Released under the bpmn.io license
* http://bpmn.io/license
*
* Source Code: https://github.com/bpmn-io/bpmn-js
*
* Date: 2018-04-01
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.BpmnJS = factory());
}(this, (function () { 'use strict';
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var inherits_browser = createCommonjsModule(function (module) {
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor;
var TempCtor = function () {};
TempCtor.prototype = superCtor.prototype;
ctor.prototype = new TempCtor();
ctor.prototype.constructor = ctor;
};
}
});
var hat_1 = createCommonjsModule(function (module) {
var hat = module.exports = function (bits, base) {
if (!base) base = 16;
if (bits === undefined) bits = 128;
if (bits <= 0) return '0';
var digits = Math.log(Math.pow(2, bits)) / Math.log(base);
for (var i = 2; digits === Infinity; i *= 2) {
digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i;
}
var rem = digits - Math.floor(digits);
var res = '';
for (var i = 0; i < Math.floor(digits); i++) {
var x = Math.floor(Math.random() * base).toString(base);
res = x + res;
}
if (rem) {
var b = Math.pow(base, rem);
var x = Math.floor(Math.random() * b).toString(base);
res = x + res;
}
var parsed = parseInt(res, base);
if (parsed !== Infinity && parsed >= Math.pow(2, bits)) {
return hat(bits, base)
}
else return res;
};
hat.rack = function (bits, base, expandBy) {
var fn = function (data) {
var iters = 0;
do {
if (iters ++ > 10) {
if (expandBy) bits += expandBy;
else throw new Error('too many ID collisions, use more bits')
}
var id = hat(bits, base);
} while (Object.hasOwnProperty.call(hats, id));
hats[id] = data;
return id;
};
var hats = fn.hats = {};
fn.get = function (id) {
return fn.hats[id];
};
fn.set = function (id, value) {
fn.hats[id] = value;
return fn;
};
fn.bits = bits || 128;
fn.base = base || 16;
return fn;
};
});
/**
* Create a new id generator / cache instance.
*
* You may optionally provide a seed that is used internally.
*
* @param {Seed} seed
*/
function Ids(seed) {
if (!(this instanceof Ids)) {
return new Ids(seed);
}
seed = seed || [ 128, 36, 1 ];
this._seed = seed.length ? hat_1.rack(seed[0], seed[1], seed[2]) : seed;
}
var ids = Ids;
/**
* Generate a next id.
*
* @param {Object} [element] element to bind the id to
*
* @return {String} id
*/
Ids.prototype.next = function(element) {
return this._seed(element || true);
};
/**
* Generate a next id with a given prefix.
*
* @param {Object} [element] element to bind the id to
*
* @return {String} id
*/
Ids.prototype.nextPrefixed = function(prefix, element) {
var id;
do {
id = prefix + this.next(true);
} while (this.assigned(id));
// claim {prefix}{random}
this.claim(id, element);
// return
return id;
};
/**
* Manually claim an existing id.
*
* @param {String} id
* @param {String} [element] element the id is claimed by
*/
Ids.prototype.claim = function(id, element) {
this._seed.set(id, element || true);
};
/**
* Returns true if the given id has already been assigned.
*
* @param {String} id
* @return {Boolean}
*/
Ids.prototype.assigned = function(id) {
return this._seed.get(id) || false;
};
/**
* Unclaim an id.
*
* @param {String} id the id to unclaim
*/
Ids.prototype.unclaim = function(id) {
delete this._seed.hats[id];
};
/**
* Clear all claimed ids.
*/
Ids.prototype.clear = function() {
var hats = this._seed.hats,
id;
for (id in hats) {
this.unclaim(id);
}
};
/**
* Flatten array, one level deep.
*
* @param {Array<?>} arr
*
* @return {Array<?>}
*/
function flatten(arr) {
return Array.prototype.concat.apply([], arr);
}
var nativeToString = Object.prototype.toString;
var nativeHasOwnProperty = Object.prototype.hasOwnProperty;
function isUndefined(obj) {
return obj === null || obj === undefined;
}
function isArray(obj) {
return nativeToString.call(obj) === '[object Array]';
}
function isObject(obj) {
return nativeToString.call(obj) === '[object Object]';
}
function isNumber(obj) {
return nativeToString.call(obj) === '[object Number]';
}
function isFunction(obj) {
return nativeToString.call(obj) === '[object Function]';
}
function isString(obj) {
return nativeToString.call(obj) === '[object String]';
}
/**
* Ensure collection is an array.
*
* @param {Object} obj
*/
function ensureArray(obj) {
if (isArray(obj)) {
return;
}
throw new Error('must supply array');
}
/**
* Return true, if target owns a property with the given key.
*
* @param {Object} target
* @param {String} key
*
* @return {Boolean}
*/
function has(target, key) {
return nativeHasOwnProperty.call(target, key);
}
/**
* Find element in collection.
*
* @param {Array|Object} collection
* @param {Function|Object} matcher
*
* @return {Object}
*/
function find(collection, matcher) {
matcher = toMatcher(matcher);
var match;
forEach(collection, function (val, key) {
if (matcher(val, key)) {
match = val;
return false;
}
});
return match;
}
/**
* Find element index in collection.
*
* @param {Array|Object} collection
* @param {Function} matcher
*
* @return {Object}
*/
function findIndex(collection, matcher) {
matcher = toMatcher(matcher);
var idx = isArray(collection) ? -1 : undefined;
forEach(collection, function (val, key) {
if (matcher(val, key)) {
idx = key;
return false;
}
});
return idx;
}
/**
* Find element in collection.
*
* @param {Array|Object} collection
* @param {Function} matcher
*
* @return {Array} result
*/
function filter(collection, matcher) {
var result = [];
forEach(collection, function (val, key) {
if (matcher(val, key)) {
result.push(val);
}
});
return result;
}
/**
* Iterate over collection; returning something
* (non-undefined) will stop iteration.
*
* @param {Array|Object} collection
* @param {Function} iterator
*
* @return {Object} return result that stopped the iteration
*/
function forEach(collection, iterator) {
if (isUndefined(collection)) {
return;
}
var convertKey = isArray(collection) ? toNum : identity;
for (var key in collection) {
if (has(collection, key)) {
var val = collection[key];
var result = iterator(val, convertKey(key));
if (result === false) {
return;
}
}
}
}
/**
* Return collection without element.
*
* @param {Array} arr
* @param {Function} matcher
*
* @return {Array}
*/
function without(arr, matcher) {
if (isUndefined(arr)) {
return [];
}
ensureArray(arr);
matcher = toMatcher(matcher);
return arr.filter(function (el, idx) {
return !matcher(el, idx);
});
}
/**
* Reduce collection, returning a single result.
*
* @param {Object|Array} collection
* @param {Function} iterator
* @param {Any} result
*
* @return {Any} result returned from last iterator
*/
function reduce(collection, iterator, result) {
forEach(collection, function (value, idx) {
result = iterator(result, value, idx);
});
return result;
}
/**
* Return true if every element in the collection
* matches the criteria.
*
* @param {Object|Array} collection
* @param {Function} matcher
*
* @return {Boolean}
*/
function every(collection, matcher) {
return reduce(collection, function (matches, val, key) {
return matches && matcher(val, key);
}, true);
}
/**
* Return true if some elements in the collection
* match the criteria.
*
* @param {Object|Array} collection
* @param {Function} matcher
*
* @return {Boolean}
*/
function some(collection, matcher) {
return !!find(collection, matcher);
}
/**
* Transform a collection into another collection
* by piping each member through the given fn.
*
* @param {Object|Array} collection
* @param {Function} fn
*
* @return {Array} transformed collection
*/
function map(collection, fn) {
var result = [];
forEach(collection, function (val, key) {
result.push(fn(val, key));
});
return result;
}
/**
* Get the collections keys.
*
* @param {Object|Array} collection
*
* @return {Array}
*/
function keys(collection) {
return collection && Object.keys(collection) || [];
}
/**
* Shorthand for `keys(o).length`.
*
* @param {Object|Array} collection
*
* @return {Number}
*/
function size(collection) {
return keys(collection).length;
}
/**
* Get the values in the collection.
*
* @param {Object|Array} collection
*
* @return {Array}
*/
function values(collection) {
return map(collection, function (val) {
return val;
});
}
/**
* Group collection members by attribute.
*
* @param {Object|Array} collection
* @param {Function} extractor
*
* @return {Object} map with { attrValue => [ a, b, c ] }
*/
function groupBy(collection, extractor) {
var grouped = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
extractor = toExtractor(extractor);
forEach(collection, function (val) {
var discriminator = extractor(val) || '_';
var group = grouped[discriminator];
if (!group) {
group = grouped[discriminator] = [];
}
group.push(val);
});
return grouped;
}
function uniqueBy(extractor) {
extractor = toExtractor(extractor);
var grouped = {};
for (var _len = arguments.length, collections = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
collections[_key - 1] = arguments[_key];
}
forEach(collections, function (c) {
return groupBy(c, extractor, grouped);
});
var result = map(grouped, function (val, key) {
return val[0];
});
return result;
}
var unionBy = uniqueBy;
/**
* Sort collection by criteria.
*
* @param {Object|Array} collection
* @param {String|Function} extractor
*
* @return {Array}
*/
function sortBy(collection, extractor) {
extractor = toExtractor(extractor);
var sorted = [];
forEach(collection, function (value, key) {
var disc = extractor(value, key);
var entry = {
d: disc,
v: value
};
for (var idx = 0; idx < sorted.length; idx++) {
var d = sorted[idx].d;
if (disc < d) {
sorted.splice(idx, 0, entry);
return;
}
}
// not inserted, append (!)
sorted.push(entry);
});
return map(sorted, function (e) {
return e.v;
});
}
/**
* Create an object pattern matcher.
*
* @example
*
* const matcher = matchPattern({ id: 1 });
*
* var element = find(elements, matcher);
*
* @param {Object} pattern
*
* @return {Function} matcherFn
*/
function matchPattern(pattern) {
return function (el) {
return every(pattern, function (val, key) {
return el[key] === val;
});
};
}
function toExtractor(extractor) {
return isFunction(extractor) ? extractor : function (e) {
return e[extractor];
};
}
function toMatcher(matcher) {
return isFunction(matcher) ? matcher : function (e) {
return e === matcher;
};
}
function identity(arg) {
return arg;
}
function toNum(arg) {
return Number(arg);
}
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
var slice = Array.prototype.slice;
/**
* Debounce fn, calling it only once if
* the given time elapsed between calls.
*
* @param {Function} fn
* @param {Number} timeout
*
* @return {Function} debounced function
*/
function debounce(fn, timeout) {
var timer;
return function () {
var args = slice.call(arguments);
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
fn.apply(undefined, _toConsumableArray(args));
}, timeout);
};
}
/**
* Bind function against target <this>.
*
* @param {Function} fn
* @param {Object} target
*
* @return {Function} bound function
*/
function bind(fn, target) {
return fn.bind(target);
}
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
/**
* Convenience wrapper for `Object.assign`.
*
* @param {Object} target
* @param {...Object} others
*
* @return {Object} the target
*/
function assign(target) {
for (var _len = arguments.length, others = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
others[_key - 1] = arguments[_key];
}
return _extends.apply(undefined, [target].concat(others));
}
/**
* Pick given properties from the target object.
*
* @param {Object} target
* @param {Array} properties
*
* @return {Object} target
*/
function pick(target, properties) {
var result = {};
var obj = Object(target);
forEach(properties, function (prop) {
if (prop in obj) {
result[prop] = target[prop];
}
});
return result;
}
/**
* Pick all target properties, excluding the given ones.
*
* @param {Object} target
* @param {Array} properties
*
* @return {Object} target
*/
function omit(target, properties) {
var result = {};
var obj = Object(target);
forEach(obj, function (prop, key) {
if (properties.indexOf(key) === -1) {
result[key] = prop;
}
});
return result;
}
/**
* Set attribute `name` to `val`, or get attr `name`.
*
* @param {Element} el
* @param {String} name
* @param {String} [val]
* @api public
*/
function attr(el, name, val) {
// get
if (arguments.length == 2) {
return el.getAttribute(name);
}
// remove
if (val === null) {
return el.removeAttribute(name);
}
// set
el.setAttribute(name, val);
return el;
}
var indexOf = [].indexOf;
var indexof = function(arr, obj){
if (indexOf) return arr.indexOf(obj);
for (var i = 0; i < arr.length; ++i) {
if (arr[i] === obj) return i;
}
return -1;
};
/**
* Taken from https://github.com/component/classes
*
* Without the component bits.
*/
/**
* Whitespace regexp.
*/
var re = /\s+/;
/**
* toString reference.
*/
var toString = Object.prototype.toString;
/**
* Wrap `el` in a `ClassList`.
*
* @param {Element} el
* @return {ClassList}
* @api public
*/
function classes(el) {
return new ClassList(el);
}
/**
* Initialize a new ClassList for `el`.
*
* @param {Element} el
* @api private
*/
function ClassList(el) {
if (!el || !el.nodeType) {
throw new Error('A DOM element reference is required');
}
this.el = el;
this.list = el.classList;
}
/**
* Add class `name` if not already present.
*
* @param {String} name
* @return {ClassList}
* @api public
*/
ClassList.prototype.add = function (name) {
// classList
if (this.list) {
this.list.add(name);
return this;
}
// fallback
var arr = this.array();
var i = indexof(arr, name);
if (!~i) arr.push(name);
this.el.className = arr.join(' ');
return this;
};
/**
* Remove class `name` when present, or
* pass a regular expression to remove
* any which match.
*
* @param {String|RegExp} name
* @return {ClassList}
* @api public
*/
ClassList.prototype.remove = function (name) {
if ('[object RegExp]' == toString.call(name)) {
return this.removeMatching(name);
}
// classList
if (this.list) {
this.list.remove(name);
return this;
}
// fallback
var arr = this.array();
var i = indexof(arr, name);
if (~i) arr.splice(i, 1);
this.el.className = arr.join(' ');
return this;
};
/**
* Remove all classes matching `re`.
*
* @param {RegExp} re
* @return {ClassList}
* @api private
*/
ClassList.prototype.removeMatching = function (re) {
var arr = this.array();
for (var i = 0; i < arr.length; i++) {
if (re.test(arr[i])) {
this.remove(arr[i]);
}
}
return this;
};
/**
* Toggle class `name`, can force state via `force`.
*
* For browsers that support classList, but do not support `force` yet,
* the mistake will be detected and corrected.
*
* @param {String} name
* @param {Boolean} force
* @return {ClassList}
* @api public
*/
ClassList.prototype.toggle = function (name, force) {
// classList
if (this.list) {
if ('undefined' !== typeof force) {
if (force !== this.list.toggle(name, force)) {
this.list.toggle(name); // toggle again to correct
}
} else {
this.list.toggle(name);
}
return this;
}
// fallback
if ('undefined' !== typeof force) {
if (!force) {
this.remove(name);
} else {
this.add(name);
}
} else {
if (this.has(name)) {
this.remove(name);
} else {
this.add(name);
}
}
return this;
};
/**
* Return an array of classes.
*
* @return {Array}
* @api public
*/
ClassList.prototype.array = function () {
var className = this.el.getAttribute('class') || '';
var str = className.replace(/^\s+|\s+$/g, '');
var arr = str.split(re);
if ('' === arr[0]) arr.shift();
return arr;
};
/**
* Check if class `name` is present.
*
* @param {String} name
* @return {ClassList}
* @api public
*/
ClassList.prototype.has = ClassList.prototype.contains = function (name) {
return this.list ? this.list.contains(name) : !!~indexof(this.array(), name);
};
/**
* Remove all children from the given element.
*/
function clear(el) {
var c;
while (el.childNodes.length) {
c = el.childNodes[0];
el.removeChild(c);
}
return el;
}
/**
* Element prototype.
*/
var proto = Element.prototype;
/**
* Vendor function.
*/
var vendor = proto.matchesSelector
|| proto.webkitMatchesSelector
|| proto.mozMatchesSelector
|| proto.msMatchesSelector
|| proto.oMatchesSelector;
/**
* Expose `match()`.
*/
var matchesSelector = match;
/**
* Match `el` to `selector`.
*
* @param {Element} el
* @param {String} selector
* @return {Boolean}
* @api public
*/
function match(el, selector) {
if (vendor) return vendor.call(el, selector);
var nodes = el.parentNode.querySelectorAll(selector);
for (var i = 0; i < nodes.length; ++i) {
if (nodes[i] == el) return true;
}
return false;
}
var closest = function (element, selector, checkYoSelf) {
var parent = checkYoSelf ? element : element.parentNode;
while (parent && parent !== document) {
if (matchesSelector(parent, selector)) return parent;
parent = parent.parentNode;
}
};
var bind$1 = window.addEventListener ? 'addEventListener' : 'attachEvent',
unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent',
prefix = bind$1 !== 'addEventListener' ? 'on' : '';
/**
* Bind `el` event `type` to `fn`.
*
* @param {Element} el
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
* @return {Function}
* @api public
*/
var bind_1 = function(el, type, fn, capture){
el[bind$1](prefix + type, fn, capture || false);
return fn;
};
/**
* Unbind `el` event `type`'s callback `fn`.
*
* @param {Element} el
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
* @return {Function}
* @api public
*/
var unbind_1 = function(el, type, fn, capture){
el[unbind](prefix + type, fn, capture || false);
return fn;
};
var componentEvent = {
bind: bind_1,
unbind: unbind_1
};
/**
* Module dependencies.
*/
/**
* Delegate event `type` to `selector`
* and invoke `fn(e)`. A callback function
* is returned which may be passed to `.unbind()`.
*
* @param {Element} el
* @param {String} selector
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
* @return {Function}
* @api public
*/
// Some events don't bubble, so we want to bind to the capture phase instead
// when delegating.
var forceCaptureEvents = ['focus', 'blur'];
var bind$1$1 = function(el, selector, type, fn, capture){
if (forceCaptureEvents.indexOf(type) !== -1) capture = true;
return componentEvent.bind(el, type, function(e){
var target = e.target || e.srcElement;
e.delegateTarget = closest(target, selector, true, el);
if (e.delegateTarget) fn.call(el, e);
}, capture);
};
/**
* Unbind event `type`'s callback `fn`.
*
* @param {Element} el
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
* @api public
*/
var unbind$1 = function(el, type, fn, capture){
if (forceCaptureEvents.indexOf(type) !== -1) capture = true;
componentEvent.unbind(el, type, fn, capture);
};
var delegateEvents = {
bind: bind$1$1,
unbind: unbind$1
};
/**
* Expose `parse`.
*/
var domify = parse;
/**
* Tests for browser support.
*/
var innerHTMLBug = false;
var bugTestDiv;
if (typeof document !== 'undefined') {
bugTestDiv = document.createElement('div');
// Setup
bugTestDiv.innerHTML = ' <link/><table></table><a href="/a">a</a><input type="checkbox"/>';
// Make sure that link elements get serialized correctly by innerHTML
// This requires a wrapper element in IE
innerHTMLBug = !bugTestDiv.getElementsByTagName('link').length;
bugTestDiv = undefined;
}
/**
* Wrap map from jquery.
*/
var map$1 = {
legend: [1, '<fieldset>', '</fieldset>'],
tr: [2, '<table><tbody>', '</tbody></table>'],
col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
// for script/link/style tags to work in IE6-8, you have to wrap
// in a div with a non-whitespace character in front, ha!
_default: innerHTMLBug ? [1, 'X<div>', '</div>'] : [0, '', '']
};
map$1.td =
map$1.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
map$1.option =
map$1.optgroup = [1, '<select multiple="multiple">', '</select>'];
map$1.thead =
map$1.tbody =
map$1.colgroup =
map$1.caption =
map$1.tfoot = [1, '<table>', '</table>'];
map$1.polyline =
map$1.ellipse =
map$1.polygon =
map$1.circle =
map$1.text =
map$1.line =
map$1.path =
map$1.rect =
map$1.g = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'];
/**
* Parse `html` and return a DOM Node instance, which could be a TextNode,
* HTML DOM Node of some kind (<div> for example), or a DocumentFragment
* instance, depending on the contents of the `html` string.
*
* @param {String} html - HTML string to "domify"
* @param {Document} doc - The `document` instance to create the Node for
* @return {DOMNode} the TextNode, DOM Node, or DocumentFragment instance
* @api private
*/
function parse(html, doc) {
if ('string' != typeof html) throw new TypeError('String expected');
// default to the global `document` object
if (!doc) doc = document;
// tag name
var m = /<([\w:]+)/.exec(html);
if (!m) return doc.createTextNode(html);
html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace
var tag = m[1];
// body support
if (tag == 'body') {
var el = doc.createElement('html');
el.innerHTML = html;
return el.removeChild(el.lastChild);
}
// wrap map
var wrap = map$1[tag] || map$1._default;
var depth = wrap[0];
var prefix = wrap[1];
var suffix = wrap[2];
var el = doc.createElement('div');
el.innerHTML = prefix + html + suffix;
while (depth--) el = el.lastChild;
// one element
if (el.firstChild == el.lastChild) {
return el.removeChild(el.firstChild);
}
// several elements
var fragment = doc.createDocumentFragment();
while (el.firstChild) {
fragment.appendChild(el.removeChild(el.firstChild));
}
return fragment;
}
var proto$1 = typeof Element !== 'undefined' ? Element.prototype : {};
var vendor$1 = proto$1.matches
|| proto$1.matchesSelector
|| proto$1.webkitMatchesSelector
|| proto$1.mozMatchesSelector
|| proto$1.msMatchesSelector
|| proto$1.oMatchesSelector;
var matchesSelector$1 = match$1;
/**
* Match `el` to `selector`.
*
* @param {Element} el
* @param {String} selector
* @return {Boolean}
* @api public
*/
function match$1(el, selector) {
if (!el || el.nodeType !== 1) return false;
if (vendor$1) return vendor$1.call(el, selector);
var nodes = el.parentNode.querySelectorAll(selector);
for (var i = 0; i < nodes.length; i++) {
if (nodes[i] == el) return true;
}
return false;
}
function query(selector, el) {
el = el || document;
return el.querySelector(selector);
}
function all(selector, el) {
el = el || document;
return el.querySelectorAll(selector);
}
function remove(el) {
el.parentNode && el.parentNode.removeChild(el);
}
function ensureImported(element, target) {
if (element.ownerDocument !== target.ownerDocument) {
try {
// may fail on webkit
return target.ownerDocument.importNode(element, true);
} catch (e) {
// ignore
}
}
return element;
}
/**
* appendTo utility
*/
/**
* Append a node to a target element and return the appended node.
*
* @param {SVGElement} element
* @param {SVGElement} node
*
* @return {SVGElement} the appended node
*/
function appendTo(element, target) {
target.appendChild(ensureImported(element, target));
return element;
}
/**
* append utility
*/
/**
* Append a node to an element
*
* @param {SVGElement} element
* @param {SVGElement} node
*
* @return {SVGElement} the element
*/
function append(element, node) {
appendTo(node, element);
return element;
}
/**
* attribute accessor utility
*/
var LENGTH_ATTR = 2;
var CSS_PROPERTIES = {
'alignment-baseline': 1,
'baseline-shift': 1,
'clip': 1,
'clip-path': 1,
'clip-rule': 1,
'color': 1,
'color-interpolation': 1,
'color-interpolation-filters': 1,
'color-profile': 1,
'color-rendering': 1,
'cursor': 1,
'direction': 1,
'display': 1,
'dominant-baseline': 1,
'enable-background': 1,
'fill': 1,
'fill-opacity': 1,
'fill-rule': 1,
'filter': 1,
'flood-color': 1,
'flood-opacity': 1,
'font': 1,
'font-family': 1,
'font-size': LENGTH_ATTR,
'font-size-adjust': 1,
'font-stretch': 1,
'font-style': 1,
'font-variant': 1,
'font-weight': 1,
'glyph-orientation-horizontal': 1,
'glyph-orientation-vertical': 1,
'image-rendering': 1,
'kerning': 1,
'letter-spacing': 1,
'lighting-color': 1,
'marker': 1,
'marker-end': 1,
'marker-mid': 1,
'marker-start': 1,
'mask': 1,
'opacity': 1,
'overflow': 1,
'pointer-events': 1,
'shape-rendering': 1,
'stop-color': 1,
'stop-opacity': 1,
'stroke': 1,
'stroke-dasharray': 1,
'stroke-dashoffset': 1,
'stroke-linecap': 1,
'stroke-linejoin': 1,
'stroke-miterlimit': 1,
'stroke-opacity': 1,
'stroke-width': LENGTH_ATTR,
'text-anchor': 1,
'text-decoration': 1,
'text-rendering': 1,
'unicode-bidi': 1,
'visibility': 1,
'word-spacing': 1,
'writing-mode': 1
};
function getAttribute(node, name) {
if (CSS_PROPERTIES[name]) {
return node.style[name];
} else {
return node.getAttributeNS(null, name);
}
}
function setAttribute(node, name, value) {
var hyphenated = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
var type = CSS_PROPERTIES[hyphenated];
if (type) {
// append pixel unit, unless present
if (type === LENGTH_ATTR && typeof value === 'number') {
value = String(value) + 'px';
}
node.style[hyphenated] = value;
} else {
node.setAttributeNS(null, name, value);
}
}
function setAttributes(node, attrs) {
var names = Object.keys(attrs), i, name;
for (i = 0, name; (name = names[i]); i++) {
setAttribute(node, name, attrs[name]);
}
}
/**
* Gets or sets raw attributes on a node.
*
* @param {SVGElement} node
* @param {Object} [attrs]
* @param {String} [name]
* @param {String} [value]
*
* @return {String}
*/
function attr$1(node, name, value) {
if (typeof name === 'string') {
if (value !== undefined) {
setAttribute(node, name, value);
} else {
return getAttribute(node, name);
}
} else {
setAttributes(node, name);
}
return node;
}
/**
* Clear utility
*/
function index(arr, obj) {
if (arr.indexOf) {
return arr.indexOf(obj);
}
for (var i = 0; i < arr.length; ++i) {
if (arr[i] === obj) {
return i;
}
}
return -1;
}
var re$1 = /\s+/;
var toString$1 = Object.prototype.toString;
function defined(o) {
return typeof o !== 'undefined';
}
/**
* Wrap `el` in a `ClassList`.
*
* @param {Element} el
* @return {ClassList}
* @api public
*/
function classes$1(el) {
return new ClassList$1(el);
}
function ClassList$1(el) {
if (!el || !el.nodeType) {
throw new Error('A DOM element reference is required');
}
this.el = el;
this.list = el.classList;
}
/**
* Add class `name` if not already present.
*
* @param {String} name
* @return {ClassList}
* @api public
*/
ClassList$1.prototype.add = function(name) {
// classList
if (this.list) {
this.list.add(name);
return this;
}
// fallback
var arr = this.array();
var i = index(arr, name);
if (!~i) {
arr.push(name);
}
if (defined(this.el.className.baseVal)) {
this.el.className.baseVal = arr.join(' ');
} else {
this.el.className = arr.join(' ');
}
return this;
};
/**
* Remove class `name` when present, or
* pass a regular expression to remove
* any which match.
*
* @param {String|RegExp} name
* @return {ClassList}
* @api public
*/
ClassList$1.prototype.remove = function(name) {
if ('[object RegExp]' === toString$1.call(name)) {
return this.removeMatching(name);
}
// classList
if (this.list) {
this.list.remove(name);
return this;
}
// fallback
var arr = this.array();
var i = index(arr, name);
if (~i) {
arr.splice(i, 1);
}
this.el.className.baseVal = arr.join(' ');
return this;
};
/**
* Remove all classes matching `re`.
*
* @param {RegExp} re
* @return {ClassList}
* @api private
*/
ClassList$1.prototype.removeMatching = function(re) {
var arr = this.array();
for (var i = 0; i < arr.length; i++) {
if (re.test(arr[i])) {
this.remove(arr[i]);
}
}
return this;
};
/**
* Toggle class `name`, can force state via `force`.
*
* For browsers that support classList, but do not support `force` yet,
* the mistake will be detected and corrected.
*
* @param {String} name
* @param {Boolean} force
* @return {ClassList}
* @api public
*/
ClassList$1.prototype.toggle = function(name, force) {
// classList
if (this.list) {
if (defined(force)) {
if (force !== this.list.toggle(name, force)) {
this.list.toggle(name); // toggle again to correct
}
} else {
this.list.toggle(name);
}
return this;
}
// fallback
if (defined(force)) {
if (!force) {
this.remove(name);
} else {
this.add(name);
}
} else {
if (this.has(name)) {
this.remove(name);
} else {
this.add(name);
}
}
return this;
};
/**
* Return an array of classes.
*
* @return {Array}
* @api public
*/
ClassList$1.prototype.array = function() {
var className = this.el.getAttribute('class') || '';
var str = className.replace(/^\s+|\s+$/g, '');
var arr = str.split(re$1);
if ('' === arr[0]) {
arr.shift();
}
return arr;
};
/**
* Check if class `name` is present.
*
* @param {String} name
* @return {ClassList}
* @api public
*/
ClassList$1.prototype.has =
ClassList$1.prototype.contains = function(name) {
return (
this.list ?
this.list.contains(name) :
!! ~index(this.array(), name)
);
};
function remove$1(element) {
var parent = element.parentNode;
if (parent) {
parent.removeChild(element);
}
return element;
}
/**
* Clear utility
*/
/**
* Removes all children from the given element
*
* @param {DOMElement} element
* @return {DOMElement} the element (for chaining)
*/
function clear$1(element) {
var child;
while ((child = element.firstChild)) {
remove$1(child);
}
return element;
}
function clone(element) {
return element.cloneNode(true);
}
var ns = {
svg: 'http://www.w3.org/2000/svg'
};
/**
* DOM parsing utility
*/
var SVG_START = '<svg xmlns="' + ns.svg + '"';
function parse$1(svg) {
// ensure we import a valid svg document
if (svg.substring(0, 4) === '<svg') {
if (svg.indexOf(ns.svg) === -1) {
svg = SVG_START + svg.substring(4);
}
} else {
// namespace svg
svg = SVG_START + '>' + svg + '</svg>';
}
return parseDocument(svg);
}
function parseDocument(svg) {
var parser;
// parse
parser = new DOMParser();
parser.async = false;
return parser.parseFromString(svg, 'text/xml');
}
/**
* Create utility for SVG elements
*/
/**
* Create a specific type from name or SVG markup.
*
* @param {String} name the name or markup of the element
* @param {Object} [attrs] attributes to set on the element
*
* @returns {SVGElement}
*/
function create(name, attrs) {
var element;
if (name.charAt(0) === '<') {
element = parse$1(name).firstChild;
element = document.importNode(element, true);
} else {
element = document.createElementNS(ns.svg, name);
}
if (attrs) {
attr$1(element, attrs);
}
return element;
}
/**
* Geometry helpers
*/
// fake node used to instantiate svg geometry elements
var node = create('svg');
function extend(object, props) {
var i, k, keys = Object.keys(props);
for (i = 0; (k = keys[i]); i++) {
object[k] = props[k];
}
return object;
}
function createMatrix(a, b, c, d, e, f) {
var matrix = node.createSVGMatrix();
switch (arguments.length) {
case 0:
return matrix;
case 6:
a = {
a: a,
b: b,
c: c,
d: d,
e: e,
f: f
};
break;
}
return extend(matrix, a);
}
function createTransform(matrix) {
if (matrix) {
return node.createSVGTransformFromMatrix(matrix);
} else {
return node.createSVGTransform();
}
}
/**
* Serialization util
*/
var TEXT_ENTITIES = /([&<>]{1})/g;
var ATTR_ENTITIES = /([\n\r"]{1})/g;
var ENTITY_REPLACEMENT = {
'&': '&',
'<': '<',
'>': '>',
'"': '\''
};
function escape(str, pattern) {
function replaceFn(match, entity) {
return ENTITY_REPLACEMENT[entity] || entity;
}
return str.replace(pattern, replaceFn);
}
function serialize(node, output) {
var i, len, attrMap, attrNode, childNodes;
switch (node.nodeType) {
// TEXT
case 3:
// replace special XML characters
output.push(escape(node.textContent, TEXT_ENTITIES));
break;
// ELEMENT
case 1:
output.push('<', node.tagName);
if (node.hasAttributes()) {
attrMap = node.attributes;
for (i = 0, len = attrMap.length; i < len; ++i) {
attrNode = attrMap.item(i);
output.push(' ', attrNode.name, '="', escape(attrNode.value, ATTR_ENTITIES), '"');
}
}
if (node.hasChildNodes()) {
output.push('>');
childNodes = node.childNodes;
for (i = 0, len = childNodes.length; i < len; ++i) {
serialize(childNodes.item(i), output);
}
output.push('</', node.tagName, '>');
} else {
output.push('/>');
}
break;
// COMMENT
case 8:
output.push('<!--', escape(node.nodeValue, TEXT_ENTITIES), '-->');
break;
// CDATA
case 4:
output.push('<![CDATA[', node.nodeValue, ']]>');
break;
default:
throw new Error('unable to handle node ' + node.nodeType);
}
return output;
}
/**
* innerHTML like functionality for SVG elements.
* based on innerSVG (https://code.google.com/p/innersvg)
*/
function set(element, svg) {
var node,
documentElement = parse$1(svg).documentElement;
// clear element contents
clear$1(element);
if (!svg) {
return;
}
// import + append each node
node = documentElement.firstChild;
while (node) {
appendTo(node, element);
node = node.nextSibling;
}
}
function get(element) {
var child = element.firstChild,
output = [];
while (child) {
serialize(child, output);
child = child.nextSibling;
}
return output.join('');
}
function innerSVG(element, svg) {
if (svg !== undefined) {
try {
set(element, svg);
} catch (e) {
throw new Error('error parsing SVG: ' + e.message);
}
return element;
} else {
return get(element);
}
}
/**
* transform accessor utility
*/
function wrapMatrix(transformList, transform) {
if (transform instanceof SVGMatrix) {
return transformList.createSVGTransformFromMatrix(transform);
} else {
return transform;
}
}
function setTransforms(transformList, transforms) {
var i, t;
transformList.clear();
for (i = 0; (t = transforms[i]); i++) {
transformList.appendItem(wrapMatrix(transformList, t));
}
transformList.consolidate();
}
function transform(node, transforms) {
var transformList = node.transform.baseVal;
if (arguments.length === 1) {
return transformList.consolidate();
} else {
if (transforms.length) {
setTransforms(transformList, transforms);
} else {
transformList.initialize(wrapMatrix(transformList, transforms));
}
}
}
var CLASS_PATTERN = /^class /;
function isClass(fn) {
return CLASS_PATTERN.test(fn.toString());
}
function isArray$1(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
function annotate() {
var args = Array.prototype.slice.call(arguments);
if (args.length === 1 && isArray$1(args[0])) {
args = args[0];
}
var fn = args.pop();
fn.$inject = args;
return fn;
}
// Current limitations:
// - can't put into "function arg" comments
// function /* (no parenthesis like this) */ (){}
// function abc( /* xx (no parenthesis like this) */ a, b) {}
//
// Just put the comment before function or inside:
// /* (((this is fine))) */ function(a, b) {}
// function abc(a) { /* (((this is fine))) */}
//
// - can't reliably auto-annotate constructor; we'll match the
// first constructor(...) pattern found which may be the one
// of a nested class, too.
var CONSTRUCTOR_ARGS = /constructor\s*[^(]*\(\s*([^)]*)\)/m;
var FN_ARGS = /^function\s*[^(]*\(\s*([^)]*)\)/m;
var FN_ARG = /\/\*([^*]*)\*\//m;
function parse$2(fn) {
if (typeof fn !== 'function') {
throw new Error('Cannot annotate "' + fn + '". Expected a function!');
}
var match = fn.toString().match(isClass(fn) ? CONSTRUCTOR_ARGS : FN_ARGS);
// may parse class without constructor
if (!match) {
return [];
}
return match[1] && match[1].split(',').map(function (arg) {
match = arg.match(FN_ARG);
return match ? match[1].trim() : arg.trim();
}) || [];
}
function Module() {
var providers = [];
this.factory = function (name, factory) {
providers.push([name, 'factory', factory]);
return this;
};
this.value = function (name, value) {
providers.push([name, 'value', value]);
return this;
};
this.type = function (name, type) {
providers.push([name, 'type', type]);
return this;
};
this.forEach = function (iterator) {
providers.forEach(iterator);
};
}
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
function _toConsumableArray$1(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function Injector(modules, parent) {
parent = parent || {
get: function get(name, strict) {
currentlyResolving.push(name);
if (strict === false) {
return null;
} else {
throw error('No provider for "' + name + '"!');
}
}
};
var currentlyResolving = [];
var providers = this._providers = Object.create(parent._providers || null);
var instances = this._instances = Object.create(null);
var self = instances.injector = this;
var error = function error(msg) {
var stack = currentlyResolving.join(' -> ');
currentlyResolving.length = 0;
return new Error(stack ? msg + ' (Resolving: ' + stack + ')' : msg);
};
/**
* Return a named service.
*
* @param {String} name
* @param {Boolean} [strict=true] if false, resolve missing services to null
*
* @return {Object}
*/
var get = function get(name, strict) {
if (!providers[name] && name.indexOf('.') !== -1) {
var parts = name.split('.');
var pivot = get(parts.shift());
while (parts.length) {
pivot = pivot[parts.shift()];
}
return pivot;
}
if (hasProp(instances, name)) {
return instances[name];
}
if (hasProp(providers, name)) {
if (currentlyResolving.indexOf(name) !== -1) {
currentlyResolving.push(name);
throw error('Cannot resolve circular dependency!');
}
currentlyResolving.push(name);
instances[name] = providers[name][0](providers[name][1]);
currentlyResolving.pop();
return instances[name];
}
return parent.get(name, strict);
};
var fnDef = function fnDef(fn) {
var locals = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (typeof fn !== 'function') {
if (isArray$1(fn)) {
fn = annotate(fn.slice());
} else {
throw new Error('Cannot invoke "' + fn + '". Expected a function!');
}
}
var inject = fn.$inject || parse$2(fn);
var dependencies = inject.map(function (dep) {
if (hasProp(locals, dep)) {
return locals[dep];
} else {
return get(dep);
}
});
return {
fn: fn,
dependencies: dependencies
};
};
var instantiate = function instantiate(Type) {
var _fnDef = fnDef(Type),
dependencies = _fnDef.dependencies,
fn = _fnDef.fn;
return new (Function.prototype.bind.apply(fn, [null].concat(_toConsumableArray$1(dependencies))))();
};
var invoke = function invoke(func, context, locals) {
var _fnDef2 = fnDef(func, locals),
dependencies = _fnDef2.dependencies,
fn = _fnDef2.fn;
return fn.call.apply(fn, [context].concat(_toConsumableArray$1(dependencies)));
};
var createPrivateInjectorFactory = function createPrivateInjectorFactory(privateChildInjector) {
return annotate(function (key) {
return privateChildInjector.get(key);
});
};
var createChild = function createChild(modules, forceNewInstances) {
if (forceNewInstances && forceNewInstances.length) {
var fromParentModule = Object.create(null);
var matchedScopes = Object.create(null);
var privateInjectorsCache = [];
var privateChildInjectors = [];
var privateChildFactories = [];
var provider;
var cacheIdx;
var privateChildInjector;
var privateChildInjectorFactory;
for (var name in providers) {
provider = providers[name];
if (forceNewInstances.indexOf(name) !== -1) {
if (provider[2] === 'private') {
cacheIdx = privateInjectorsCache.indexOf(provider[3]);
if (cacheIdx === -1) {
privateChildInjector = provider[3].createChild([], forceNewInstances);
privateChildInjectorFactory = createPrivateInjectorFactory(privateChildInjector);
privateInjectorsCache.push(provider[3]);
privateChildInjectors.push(privateChildInjector);
privateChildFactories.push(privateChildInjectorFactory);
fromParentModule[name] = [privateChildInjectorFactory, name, 'private', privateChildInjector];
} else {
fromParentModule[name] = [privateChildFactories[cacheIdx], name, 'private', privateChildInjectors[cacheIdx]];
}
} else {
fromParentModule[name] = [provider[2], provider[1]];
}
matchedScopes[name] = true;
}
if ((provider[2] === 'factory' || provider[2] === 'type') && provider[1].$scope) {
/* jshint -W083 */
forceNewInstances.forEach(function (scope) {
if (provider[1].$scope.indexOf(scope) !== -1) {
fromParentModule[name] = [provider[2], provider[1]];
matchedScopes[scope] = true;
}
});
}
}
forceNewInstances.forEach(function (scope) {
if (!matchedScopes[scope]) {
throw new Error('No provider for "' + scope + '". Cannot use provider from the parent!');
}
});
modules.unshift(fromParentModule);
}
return new Injector(modules, self);
};
var factoryMap = {
factory: invoke,
type: instantiate,
value: function value(_value) {
return _value;
}
};
modules.forEach(function (module) {
function arrayUnwrap(type, value) {
if (type !== 'value' && isArray$1(value)) {
value = annotate(value.slice());
}
return value;
}
// TODO(vojta): handle wrong inputs (modules)
if (module instanceof Module) {
module.forEach(function (provider) {
var name = provider[0];
var type = provider[1];
var value = provider[2];
providers[name] = [factoryMap[type], arrayUnwrap(type, value), type];
});
} else if ((typeof module === 'undefined' ? 'undefined' : _typeof(module)) === 'object') {
if (module.__exports__) {
var clonedModule = Object.keys(module).reduce(function (m, key) {
if (key.substring(0, 2) !== '__') {
m[key] = module[key];
}
return m;
}, Object.create(null));
var privateInjector = new Injector((module.__modules__ || []).concat([clonedModule]), self);
var getFromPrivateInjector = annotate(function (key) {
return privateInjector.get(key);
});
module.__exports__.forEach(function (key) {
providers[key] = [getFromPrivateInjector, key, 'private', privateInjector];
});
} else {
Object.keys(module).forEach(function (name) {
if (module[name][2] === 'private') {
providers[name] = module[name];
return;
}
var type = module[name][0];
var value = module[name][1];
providers[name] = [factoryMap[type], arrayUnwrap(type, value), type];
});
}
}
});
// public API
this.get = get;
this.invoke = invoke;
this.instantiate = instantiate;
this.createChild = createChild;
}
// helpers /////////////////
function hasProp(obj, prop) {
return Object.hasOwnProperty.call(obj, prop);
}
var DEFAULT_RENDER_PRIORITY = 1000;
/**
* The base implementation of shape and connection renderers.
*
* @pa