UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

1,300 lines (1,111 loc) 206 kB
module.exports = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ({ /***/ 0: /***/ (function(module, exports, __webpack_require__) { module.exports = __webpack_require__(867); /***/ }), /***/ 3: /***/ (function(module, exports) { module.exports = function() { throw new Error("define cannot be used indirect"); }; /***/ }), /***/ 856: /***/ (function(module, exports) { module.exports = require("../../kendo.data"); /***/ }), /***/ 857: /***/ (function(module, exports) { module.exports = require("../../kendo.dataviz.core"); /***/ }), /***/ 858: /***/ (function(module, exports) { module.exports = require("../../kendo.dataviz.themes"); /***/ }), /***/ 867: /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (f, define) { !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(856), __webpack_require__(869), __webpack_require__(870), __webpack_require__(871), __webpack_require__(872), __webpack_require__(868), __webpack_require__(857), __webpack_require__(858), __webpack_require__(873), __webpack_require__(874), __webpack_require__(875) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); })(function () { (function ($, undefined) { // Imports ================================================================ var dataviz = kendo.dataviz, draw = kendo.drawing, geom = kendo.geometry, diagram = dataviz.diagram, Widget = kendo.ui.Widget, Class = kendo.Class, proxy = $.proxy, deepExtend = kendo.deepExtend, outerWidth = kendo._outerWidth, outerHeight = kendo._outerHeight, extend = $.extend, HierarchicalDataSource = kendo.data.HierarchicalDataSource, Canvas = diagram.Canvas, Group = diagram.Group, Rectangle = diagram.Rectangle, Circle = diagram.Circle, CompositeTransform = diagram.CompositeTransform, Rect = diagram.Rect, Path = diagram.Path, DeleteShapeUnit = diagram.DeleteShapeUnit, DeleteConnectionUnit = diagram.DeleteConnectionUnit, TextBlock = diagram.TextBlock, Image = diagram.Image, Point = diagram.Point, Intersect = diagram.Intersect, ConnectionEditAdorner = diagram.ConnectionEditAdorner, UndoRedoService = diagram.UndoRedoService, ToolService = diagram.ToolService, Selector = diagram.Selector, ResizingAdorner = diagram.ResizingAdorner, ConnectorsAdorner = diagram.ConnectorsAdorner, Cursors = diagram.Cursors, Utils = diagram.Utils, Observable = kendo.Observable, ToBackUnit = diagram.ToBackUnit, ToFrontUnit = diagram.ToFrontUnit, PolylineRouter = diagram.PolylineRouter, CascadingRouter = diagram.CascadingRouter, isUndefined = Utils.isUndefined, isDefined = Utils.isDefined, defined = draw.util.defined, isArray = $.isArray, isFunction = kendo.isFunction, isString = Utils.isString, isPlainObject = $.isPlainObject, math = Math; // Constants ============================================================== var NS = ".kendoDiagram", CASCADING = "cascading", ITEMBOUNDSCHANGE = "itemBoundsChange", CHANGE = "change", CLICK = "click", DRAG = "drag", DRAG_END = "dragEnd", DRAG_START = "dragStart", MOUSE_ENTER = "mouseEnter", MOUSE_LEAVE = "mouseLeave", ERROR = "error", AUTO = "Auto", TOP = "Top", RIGHT = "Right", LEFT = "Left", BOTTOM = "Bottom", MAXINT = 9007199254740992, SELECT = "select", ITEMROTATE = "itemRotate", PAN = "pan", ZOOM_START = "zoomStart", ZOOM_END = "zoomEnd", NONE = "none", DEFAULT_CANVAS_WIDTH = 600, DEFAULT_CANVAS_HEIGHT = 600, DEFAULT_SHAPE_TYPE = "rectangle", DEFAULT_SHAPE_WIDTH = 100, DEFAULT_SHAPE_HEIGHT = 100, DEFAULT_SHAPE_MINWIDTH = 20, DEFAULT_SHAPE_MINHEIGHT = 20, DEFAULT_SHAPE_POSITION = 0, DEFAULT_CONNECTION_BACKGROUND = "Yellow", MAX_VALUE = Number.MAX_VALUE, MIN_VALUE = -Number.MAX_VALUE, ABSOLUTE = "absolute", TRANSFORMED = "transformed", ROTATED = "rotated", TRANSPARENT = "transparent", WIDTH = "width", HEIGHT = "height", X = "x", Y = "y", MOUSEWHEEL_NS = "DOMMouseScroll" + NS + " mousewheel" + NS, MOBILE_ZOOM_RATE = 0.05, MOBILE_PAN_DISTANCE = 5, BUTTON_TEMPLATE = '<a class="k-button k-button-icontext #=className#" href="\\#"><span class="#=iconClass# #=imageClass#"></span>#=text#</a>', CONNECTION_CONTENT_OFFSET = 5; diagram.DefaultConnectors = [{ name: TOP }, { name: BOTTOM }, { name: LEFT }, { name: RIGHT }, { name: AUTO, position: function (shape) { return shape.getPosition("center"); } }]; var defaultButtons = { cancel: { text: "Cancel", imageClass: "k-i-cancel", className: "k-diagram-cancel", iconClass: "k-icon" }, update: { text: "Update", imageClass: "k-i-checkmark", className: "k-diagram-update", iconClass: "k-icon" } }; diagram.shapeDefaults = function(extra) { var defaults = { type: DEFAULT_SHAPE_TYPE, path: "", autoSize: true, visual: null, x: DEFAULT_SHAPE_POSITION, y: DEFAULT_SHAPE_POSITION, minWidth: DEFAULT_SHAPE_MINWIDTH, minHeight: DEFAULT_SHAPE_MINHEIGHT, width: DEFAULT_SHAPE_WIDTH, height: DEFAULT_SHAPE_HEIGHT, hover: {}, editable: { connect: true, tools: [] }, connectors: diagram.DefaultConnectors, rotation: { angle: 0 } }; Utils.simpleExtend(defaults, extra); return defaults; }; function mwDelta(e) { var origEvent = e.originalEvent, delta = 0; if (origEvent.wheelDelta) { delta = -origEvent.wheelDelta / 40; delta = delta > 0 ? math.ceil(delta) : math.floor(delta); } else if (origEvent.detail) { delta = origEvent.detail; } return delta; } function isAutoConnector(connector) { return connector.options.name.toLowerCase() === AUTO.toLowerCase(); } function closestConnector(point, connectors) { var minimumDistance = MAXINT, resCtr, connector; for (var i = 0; i < connectors.length; i++) { connector = connectors[i]; if (!isAutoConnector(connector)) { var dist = point.distanceTo(connector.position()); if (dist < minimumDistance) { minimumDistance = dist; resCtr = connector; } } } return resCtr; } function indicesOfItems(group, visuals) { var i, indices = [], visual; var children = group.drawingContainer().children; var length = children.length; for (i = 0; i < visuals.length; i++) { visual = visuals[i]; for (var j = 0; j < length; j++) { if (children[j] == visual.drawingContainer()) { indices.push(j); break; } } } return indices; } var DiagramElement = Observable.extend({ init: function (options) { var that = this; that.dataItem = (options || {}).dataItem; Observable.fn.init.call(that); that.options = deepExtend({ id: diagram.randomId() }, that.options, options); that.isSelected = false; that.visual = new Group({ id: that.options.id, autoSize: that.options.autoSize }); that.id = that.options.id; that._template(); }, options: { hover: {}, cursor: Cursors.grip, content: { align: "center middle" }, selectable: true, serializable: true, enable: true }, _getCursor: function (point) { if (this.adorner) { return this.adorner._getCursor(point); } return this.options.cursor; }, visible: function (value) { if (isUndefined(value)) { return this.visual.visible(); } else { this.visual.visible(value); } }, bounds: function () { }, refresh: function () { this.visual.redraw(); }, position: function (point) { this.options.x = point.x; this.options.y = point.y; this.visual.position(point); }, toString: function () { return this.options.id; }, serialize: function () { // the options json object describes the shape perfectly. So this object can serve as shape serialization. var json = deepExtend({}, {options: this.options}); if (this.dataItem) { json.dataItem = this.dataItem.toString(); } return json; }, _content: function (content) { if (content !== undefined) { var options = this.options; if (diagram.Utils.isString(content)) { options.content.text = content; } else { deepExtend(options.content, content); } var contentOptions = options.content; var contentVisual = this._contentVisual; if (!contentVisual) { this._createContentVisual(contentOptions); } else { this._updateContentVisual(contentOptions); } } return this.options.content.text; }, _createContentVisual: function(options) { if (options.text) { this._contentVisual = new TextBlock(options); this._contentVisual._includeInBBox = false; this.visual.append(this._contentVisual); } }, _updateContentVisual: function(options) { this._contentVisual.redraw(options); }, _hitTest: function (point) { var bounds = this.bounds(); return this.visible() && bounds.contains(point) && this.options.enable; }, _template: function () { var that = this; if (that.options.content.template) { var data = that.dataItem || {}, elementTemplate = kendo.template(that.options.content.template, { paramName: "dataItem" }); that.options.content.text = elementTemplate(data); } }, _canSelect: function () { return this.options.selectable !== false; }, toJSON: function() { return { id: this.options.id }; } }); var Connector = Class.extend({ init: function (shape, options) { this.options = deepExtend({}, this.options, options); this.connections = []; this.shape = shape; }, options: { width: 7, height: 7, fill: { color: DEFAULT_CONNECTION_BACKGROUND }, hover: {} }, position: function () { if (this.options.position) { return this.options.position(this.shape); } else { return this.shape.getPosition(this.options.name); } }, toJSON: function () { return { shapeId: this.shape.toString(), connector: this.options.name }; } }); Connector.parse = function (diagram, str) { var tempStr = str.split(":"), id = tempStr[0], name = tempStr[1] || AUTO; for (var i = 0; i < diagram.shapes.length; i++) { var shape = diagram.shapes[i]; if (shape.options.id == id) { return shape.getConnector(name.trim()); } } }; var Shape = DiagramElement.extend({ init: function (options, diagram) { var that = this; DiagramElement.fn.init.call(that, options); this.diagram = diagram; this.updateOptionsFromModel(); options = that.options; that.connectors = []; that.type = options.type; that.createShapeVisual(); that.updateBounds(); that.content(that.content()); that._createConnectors(); }, options: diagram.shapeDefaults(), _setOptionsFromModel: function(model) { var modelOptions = filterShapeDataItem(model || this.dataItem); this.options = deepExtend({}, this.options, modelOptions); this.redrawVisual(); }, updateOptionsFromModel: function(model, field) { if (this.diagram && this.diagram._isEditable) { var modelOptions = filterShapeDataItem(model || this.dataItem); if (model && field) { if (!dataviz.inArray(field, ["x", "y", "width", "height"])) { if (this.options.visual) { this._redrawVisual(); } else if (modelOptions.type) { this.options = deepExtend({}, this.options, modelOptions); this._redrawVisual(); } if (this.options.content) { this._template(); this.content(this.options.content); } } else { var bounds = this.bounds(); bounds[field] = model[field]; this.bounds(bounds); } } else { this.options = deepExtend({}, this.options, modelOptions); } } }, _redrawVisual: function() { this.visual.clear(); this._contentVisual = null; this.options.dataItem = this.dataItem; this.createShapeVisual(); this.updateBounds(); }, redrawVisual: function() { this._redrawVisual(); if (this.options.content) { this._template(); this.content(this.options.content); } }, updateModel: function(syncChanges) { var diagram = this.diagram; if (diagram && diagram._isEditable) { var bounds = this._bounds; var model = this.dataItem; if (model) { diagram._suspendModelRefresh(); if (defined(model.x) && bounds.x !== model.x) { model.set("x", bounds.x); } if (defined(model.y) && bounds.y !== model.y) { model.set("y", bounds.y); } if (defined(model.width) && bounds.width !== model.width) { model.set("width", bounds.width); } if (defined(model.height) && bounds.height !== model.height) { model.set("height", bounds.height); } this.dataItem = model; diagram._resumeModelRefresh(); if (syncChanges) { diagram._syncShapeChanges(); } } } }, updateBounds: function() { var bounds = this.visual._measure(true); var options = this.options; this.bounds(new Rect(options.x, options.y, bounds.width, bounds.height)); this._rotate(); this._alignContent(); }, content: function(content) { var result = this._content(content); this._alignContent(); return result; }, _alignContent: function() { var contentOptions = this.options.content || {}; var contentVisual = this._contentVisual; if (contentVisual && contentOptions.align) { var containerRect = this.visual._measure(); var aligner = new diagram.RectAlign(containerRect); var contentBounds = contentVisual.drawingElement.bbox(null); var contentRect = new Rect(0, 0, contentBounds.width(), contentBounds.height()); var alignedBounds = aligner.align(contentRect, contentOptions.align); contentVisual.position(alignedBounds.topLeft()); } }, _createConnectors: function() { var options = this.options, length = options.connectors.length, connectorDefaults = options.connectorDefaults, connector, i; for (i = 0; i < length; i++) { connector = new Connector( this, deepExtend({}, connectorDefaults, options.connectors[i] ) ); this.connectors.push(connector); } }, bounds: function (value) { var bounds; if (value) { if (isString(value)) { switch (value) { case TRANSFORMED : bounds = this._transformedBounds(); break; case ABSOLUTE : bounds = this._transformedBounds(); var pan = this.diagram._pan; bounds.x += pan.x; bounds.y += pan.y; break; case ROTATED : bounds = this._rotatedBounds(); break; default: bounds = this._bounds; } } else { this._setBounds(value); this._triggerBoundsChange(); if (!(this.diagram && this.diagram._layouting)) { this.refreshConnections(); } } } else { bounds = this._bounds; } return bounds; }, _setBounds: function(rect) { var options = this.options; var topLeft = rect.topLeft(); var x = options.x = topLeft.x; var y = options.y = topLeft.y; var width = options.width = math.max(rect.width, options.minWidth); var height = options.height = math.max(rect.height, options.minHeight); this._bounds = new Rect(x, y, width, height); this.visual.redraw({ x: x, y: y, width: width, height: height }); }, position: function (point) { if (point) { this.bounds(new Rect(point.x, point.y, this._bounds.width, this._bounds.height)); } else { return this._bounds.topLeft(); } }, /** * Returns a clone of this shape. * @returns {Shape} */ clone: function () { var json = this.serialize(); json.options.id = diagram.randomId(); if (this.diagram && this.diagram._isEditable && defined(this.dataItem)) { json.options.dataItem = cloneDataItem(this.dataItem); } return new Shape(json.options); }, select: function (value) { var diagram = this.diagram, selected, deselected; if (isUndefined(value)) { value = true; } if (this._canSelect()) { if (this.isSelected != value) { selected = []; deselected = []; this.isSelected = value; if (this.isSelected) { diagram._selectedItems.push(this); selected.push(this); } else { Utils.remove(diagram._selectedItems, this); deselected.push(this); } if (!diagram._internalSelection) { diagram._selectionChanged(selected, deselected); } return true; } } }, rotate: function (angle, center, undoable) { // we assume the center is always the center of the shape. var rotate = this.visual.rotate(); if (angle !== undefined) { if (undoable !== false && this.diagram && this.diagram.undoRedoService && angle !== rotate.angle) { this.diagram.undoRedoService.add( new diagram.RotateUnit(this.diagram._resizingAdorner, [this], [rotate.angle]), false); } var b = this.bounds(), sc = new Point(b.width / 2, b.height / 2), deltaAngle, newPosition; if (center) { deltaAngle = angle - rotate.angle; newPosition = b.center().rotate(center, 360 - deltaAngle).minus(sc); this._rotationOffset = this._rotationOffset.plus(newPosition.minus(b.topLeft())); this.position(newPosition); } this.visual.rotate(angle, sc); this.options.rotation.angle = angle; if (this.diagram && this.diagram._connectorsAdorner) { this.diagram._connectorsAdorner.refresh(); } this.refreshConnections(); if (this.diagram) { this.diagram.trigger(ITEMROTATE, { item: this }); } } return rotate; }, connections: function (type) { // in, out, undefined = both var result = [], i, j, con, cons, ctr; for (i = 0; i < this.connectors.length; i++) { ctr = this.connectors[i]; cons = ctr.connections; for (j = 0, cons; j < cons.length; j++) { con = cons[j]; if (type == "out") { var source = con.source(); if (source.shape && source.shape == this) { result.push(con); } } else if (type == "in") { var target = con.target(); if (target.shape && target.shape == this) { result.push(con); } } else { result.push(con); } } } return result; }, refreshConnections: function () { $.each(this.connections(), function () { this.refresh(); }); }, /** * Gets a connector of this shape either by the connector's supposed name or * via a Point in which case the closest connector will be returned. * @param nameOrPoint The name of a Connector or a Point. * @returns {Connector} */ getConnector: function (nameOrPoint) { var i, ctr; if (isString(nameOrPoint)) { nameOrPoint = nameOrPoint.toLocaleLowerCase(); for (i = 0; i < this.connectors.length; i++) { ctr = this.connectors[i]; if (ctr.options.name.toLocaleLowerCase() == nameOrPoint) { return ctr; } } } else if (nameOrPoint instanceof Point) { return closestConnector(nameOrPoint, this.connectors); } else { return this.connectors.length ? this.connectors[0] : null; } }, getPosition: function (side) { var b = this.bounds(), fnName = side.charAt(0).toLowerCase() + side.slice(1); if (isFunction(b[fnName])) { return this._transformPoint(b[fnName]()); } return b.center(); }, redraw: function (options) { if (options) { var shapeOptions = this.options; var boundsChange; this.shapeVisual.redraw(this._visualOptions(options)); if (this._diffNumericOptions(options, [WIDTH, HEIGHT, X, Y])) { this.bounds(new Rect(shapeOptions.x, shapeOptions.y, shapeOptions.width, shapeOptions.height)); boundsChange = true; } if (options.connectors) { shapeOptions.connectors = options.connectors; this._updateConnectors(); } shapeOptions = deepExtend(shapeOptions, options); if (options.rotation || boundsChange) { this._rotate(); } if (shapeOptions.content) { this.content(shapeOptions.content); } } }, _updateConnectors: function() { var connections = this.connections(); this.connectors = []; this._createConnectors(); var connection; var source; var target; for (var idx = 0; idx < connections.length; idx++) { connection = connections[idx]; source = connection.source(); target = connection.target(); if (source.shape && source.shape === this) { connection.source(this.getConnector(source.options.name) || null); } else if (target.shape && target.shape === this) { connection.target(this.getConnector(target.options.name) || null); } connection.updateModel(); } }, _diffNumericOptions: diagram.diffNumericOptions, _visualOptions: function(options) { return { data: options.path, source: options.source, hover: options.hover, fill: options.fill, stroke: options.stroke }; }, _triggerBoundsChange: function () { if (this.diagram) { this.diagram.trigger(ITEMBOUNDSCHANGE, {item: this, bounds: this._bounds.clone()}); // the trigger modifies the arguments internally. } }, _transformPoint: function (point) { var rotate = this.rotate(), bounds = this.bounds(), tl = bounds.topLeft(); if (rotate.angle) { point.rotate(rotate.center().plus(tl), 360 - rotate.angle); } return point; }, _transformedBounds: function () { var bounds = this.bounds(), tl = bounds.topLeft(), br = bounds.bottomRight(); return Rect.fromPoints(this.diagram.modelToView(tl), this.diagram.modelToView(br)); }, _rotatedBounds: function () { var bounds = this.bounds().rotatedBounds(this.rotate().angle), tl = bounds.topLeft(), br = bounds.bottomRight(); return Rect.fromPoints(tl, br); }, _rotate: function () { var rotation = this.options.rotation; if (rotation && rotation.angle) { this.rotate(rotation.angle); } this._rotationOffset = new Point(); }, _hover: function (value) { var options = this.options, hover = options.hover, stroke = options.stroke, fill = options.fill; if (value && isDefined(hover.stroke)) { stroke = deepExtend({}, stroke, hover.stroke); } if (value && isDefined(hover.fill)) { fill = hover.fill; } this.shapeVisual.redraw({ stroke: stroke, fill: fill }); if (options.editable && options.editable.connect) { this.diagram._showConnectors(this, value); } }, _hitTest: function (value) { if (this.visible()) { var bounds = this.bounds(), rotatedPoint, angle = this.rotate().angle; if (value.isEmpty && !value.isEmpty()) { // rect selection return Intersect.rects(value, bounds, angle ? angle : 0); } else { // point rotatedPoint = value.clone().rotate(bounds.center(), angle); // cloning is important because rotate modifies the point inline. if (bounds.contains(rotatedPoint)) { return this; } } } }, toJSON: function() { return { shapeId: this.options.id }; }, createShapeVisual: function() { var options = this.options; var visualOptions = this._visualOptions(options); var visualTemplate = options.visual; var type = (options.type + "").toLocaleLowerCase(); var shapeVisual; visualOptions.width = options.width; visualOptions.height = options.height; if (isFunction(visualTemplate)) { // custom template shapeVisual = visualTemplate.call(this, options); } else if (visualOptions.data) { shapeVisual = new Path(visualOptions); translateToOrigin(shapeVisual); } else if (type == "rectangle"){ shapeVisual = new Rectangle(visualOptions); } else if (type == "circle") { shapeVisual = new Circle(visualOptions); } else if (type == "text") { shapeVisual = new TextBlock(visualOptions); } else if (type == "image") { shapeVisual = new Image(visualOptions); } else { shapeVisual = new Path(visualOptions); } this.shapeVisual = shapeVisual; this.visual.append(this.shapeVisual); } }); /** * The visual link between two Shapes through the intermediate of Connectors. */ var Connection = DiagramElement.extend({ init: function (from, to, options) { var that = this; DiagramElement.fn.init.call(that, options); this.updateOptionsFromModel(); this._initRouter(); that.path = new diagram.Polyline(that.options); that.path.fill(TRANSPARENT); that.visual.append(that.path); that._sourcePoint = that._targetPoint = new Point(); that._setSource(from); that._setTarget(to); that.content(that.options.content); that.definers = []; if (defined(options) && options.points) { that.points(options.points); } }, options: { hover: { stroke: {} }, startCap: NONE, endCap: NONE, points: [], selectable: true, fromConnector: AUTO, toConnector: AUTO }, _setOptionsFromModel: function(model) { this.updateOptionsFromModel(model || this.dataItem); }, updateOptionsFromModel: function(model) { if (this.diagram && this.diagram._isEditable) { var dataMap = this.diagram._dataMap; var options = filterConnectionDataItem(model || this.dataItem); if (model) { if (defined(options.from)) { var from = dataMap[options.from]; if (from && defined(options.fromConnector)) { from = from.getConnector(options.fromConnector); } this.source(from); } else if (defined(options.fromX) && defined(options.fromY)) { this.source(new Point(options.fromX, options.fromY)); } if (defined(options.to)) { var to = dataMap[options.to]; if (to && defined(options.toConnector)) { to = to.getConnector(options.toConnector); } this.target(to); } else if (defined(options.toX) && defined(options.toY)) { this.target(new Point(options.toX, options.toY)); } if (defined(options.type) && this.type() !== options.type) { this.points([]); this.type(options.type); } this.dataItem = model; this._template(); this.redraw(this.options); } else { this.options = deepExtend({}, options, this.options); } } }, updateModel: function(syncChanges) { if (this.diagram && this.diagram._isEditable) { if (this.diagram.connectionsDataSource) { var model = this.diagram.connectionsDataSource.getByUid(this.dataItem.uid); if (model) { this.diagram._suspendModelRefresh(); if (defined(this.options.fromX) && this.options.fromX !== null) { clearField("from", model); clearField("fromConnector", model); model.set("fromX", this.options.fromX); model.set("fromY", this.options.fromY); } else { model.set("from", this.options.from); if (defined(model.fromConnector)) { model.set("fromConnector", this.sourceConnector ? this.sourceConnector.options.name : null); } clearField("fromX", model); clearField("fromY", model); } if (defined(this.options.toX) && this.options.toX !== null) { clearField("to", model); clearField("toConnector", model); model.set("toX", this.options.toX); model.set("toY", this.options.toY); } else { model.set("to", this.options.to); if (defined(model.toConnector)) { model.set("toConnector", this.targetConnector ? this.targetConnector.options.name : null); } clearField("toX", model); clearField("toY", model); } if (defined(this.options.type) && defined(model.type)) { model.set("type", this.options.type); } this.dataItem = model; this.diagram._resumeModelRefresh(); if (syncChanges) { this.diagram._syncConnectionChanges(); } } } } }, /** * Gets the Point where the source of the connection resides. * If the endpoint in Auto-connector the location of the resolved connector will be returned. * If the endpoint is floating the location of the endpoint is returned. */ sourcePoint: function () { return this._resolvedSourceConnector ? this._resolvedSourceConnector.position() : this._sourcePoint; }, _setSource: function(source) { var shapeSource = source instanceof Shape; var defaultConnector = this.options.fromConnector || AUTO; var dataItem; if (shapeSource && !source.getConnector(defaultConnector)) { return; } if (source !== undefined) { this.from = source; } this._removeFromSourceConnector(); if (source === null) { // detach if (this.sourceConnector) { this._sourcePoint = (this._resolvedSourceConnector || this.sourceConnector).position(); this._clearSourceConnector(); this._setFromOptions(null, this._sourcePoint); } } else if (source instanceof Connector) { dataItem = source.shape.dataItem; if (dataItem) { this._setFromOptions(dataItem.id); } this.sourceConnector = source; this.sourceConnector.connections.push(this); } else if (source instanceof Point) { this._setFromOptions(null, source); this._sourcePoint = source; if (this.sourceConnector) { this._clearSourceConnector(); } } else if (shapeSource) { dataItem = source.dataItem; if (dataItem) { this._setFromOptions(dataItem.id); } this.sourceConnector = source.getConnector(defaultConnector); this.sourceConnector.connections.push(this); } }, source: function (source, undoable) { if (isDefined(source)) { if (undoable && this.diagram) { this.diagram.undoRedoService.addCompositeItem(new diagram.ConnectionEditUnit(this, source)); } this._setSource(source); this.refresh(); } return this.sourceConnector ? this.sourceConnector : this._sourcePoint; }, _setFromOptions: function(from, fromPoint) { this.options.from = from; if (fromPoint) { this.options.fromX = fromPoint.x; this.options.fromY = fromPoint.y; } else { this.options.fromX = null; this.options.fromY = null; } }, /** * Gets or sets the PathDefiner of the sourcePoint. * The left part of this definer is always null since it defines the source tangent. * @param value * @returns {*} */ sourceDefiner: function (value) { if (value) { if (value instanceof diagram.PathDefiner) { value.left = null; this._sourceDefiner = value; this.source(value.point); // refresh implicit here } else { throw "The sourceDefiner needs to be a PathDefiner."; } } else { if (!this._sourceDefiner) { this._sourceDefiner = new diagram.PathDefiner(this.sourcePoint(), null, null); } return this._sourceDefiner; } }, /** * Gets the Point where the target of the connection resides. */ targetPoint: function () { return this._resolvedTargetConnector ? this._resolvedTargetConnector.position() : this._targetPoint; }, _setTarget: function(target) { var shapeTarget = target instanceof Shape; var defaultConnector = this.options.toConnector || AUTO; var dataItem; if (shapeTarget && !target.getConnector(defaultConnector)) { return; } if (target !== undefined) { this.to = target; } this._removeFromTargetConnector(); if (target === null) { // detach if (this.targetConnector) { this._targetPoint = (this._resolvedTargetConnector || this.targetConnector).position(); this._clearTargetConnector(); this._setToOptions(null, this._targetPoint); } } else if (target instanceof Connector) { dataItem = target.shape.dataItem; if (dataItem) { this._setToOptions(dataItem.id); } this.targetConnector = target; this.targetConnector.connections.push(this); } else if (target instanceof Point) { this._setToOptions(null, target); this._targetPoint = target; if (this.targetConnector) { this._clearTargetConnector(); } } else if (shapeTarget) { dataItem = target.dataItem; if (dataItem) { this._setToOptions(dataItem.id); } this.targetConnector = target.getConnector(defaultConnector); this.targetConnector.connections.push(this); } }, target: function (target, undoable) { if (isDefined(target)) { if (undoable && this.diagram) { this.diagram.undoRedoService.addCompositeItem(new diagram.ConnectionEd