--- /dev/null
+;(function() {
+
+ var makeConnector = function(_jsPlumb, renderMode, connectorName, connectorArgs) {
+ if (!_jsPlumb.Defaults.DoNotThrowErrors && jsPlumb.Connectors[renderMode][connectorName] == null)
+ throw { msg:"jsPlumb: unknown connector type '" + connectorName + "'" };
+
+ return new jsPlumb.Connectors[renderMode][connectorName](connectorArgs);
+ },
+ _makeAnchor = function(anchorParams, elementId, _jsPlumb) {
+ return (anchorParams) ? _jsPlumb.makeAnchor(anchorParams, elementId, _jsPlumb) : null;
+ },
+ prepareEndpoint = function(_jsPlumb, _newEndpoint, conn, existing, index, params, element, elementId, connectorPaintStyle, connectorHoverPaintStyle) {
+ var e;
+ if (existing) {
+ conn.endpoints[index] = existing;
+ existing.addConnection(conn);
+ } else {
+ if (!params.endpoints) params.endpoints = [ null, null ];
+ var ep = params.endpoints[index] || params.endpoint || _jsPlumb.Defaults.Endpoints[index] || jsPlumb.Defaults.Endpoints[index] || _jsPlumb.Defaults.Endpoint || jsPlumb.Defaults.Endpoint;
+ if (!params.endpointStyles) params.endpointStyles = [ null, null ];
+ if (!params.endpointHoverStyles) params.endpointHoverStyles = [ null, null ];
+ var es = params.endpointStyles[index] || params.endpointStyle || _jsPlumb.Defaults.EndpointStyles[index] || jsPlumb.Defaults.EndpointStyles[index] || _jsPlumb.Defaults.EndpointStyle || jsPlumb.Defaults.EndpointStyle;
+ // Endpoints derive their fillStyle from the connector's strokeStyle, if no fillStyle was specified.
+ if (es.fillStyle == null && connectorPaintStyle != null)
+ es.fillStyle = connectorPaintStyle.strokeStyle;
+
+ // TODO: decide if the endpoint should derive the connection's outline width and color. currently it does:
+ //*
+ if (es.outlineColor == null && connectorPaintStyle != null)
+ es.outlineColor = connectorPaintStyle.outlineColor;
+ if (es.outlineWidth == null && connectorPaintStyle != null)
+ es.outlineWidth = connectorPaintStyle.outlineWidth;
+ //*/
+
+ var ehs = params.endpointHoverStyles[index] || params.endpointHoverStyle || _jsPlumb.Defaults.EndpointHoverStyles[index] || jsPlumb.Defaults.EndpointHoverStyles[index] || _jsPlumb.Defaults.EndpointHoverStyle || jsPlumb.Defaults.EndpointHoverStyle;
+ // endpoint hover fill style is derived from connector's hover stroke style. TODO: do we want to do this by default? for sure?
+ if (connectorHoverPaintStyle != null) {
+ if (ehs == null) ehs = {};
+ if (ehs.fillStyle == null) {
+ ehs.fillStyle = connectorHoverPaintStyle.strokeStyle;
+ }
+ }
+ var a = params.anchors ? params.anchors[index] :
+ params.anchor ? params.anchor :
+ _makeAnchor(_jsPlumb.Defaults.Anchors[index], elementId, _jsPlumb) ||
+ _makeAnchor(jsPlumb.Defaults.Anchors[index], elementId,_jsPlumb) ||
+ _makeAnchor(_jsPlumb.Defaults.Anchor, elementId,_jsPlumb) ||
+ _makeAnchor(jsPlumb.Defaults.Anchor, elementId, _jsPlumb),
+ u = params.uuids ? params.uuids[index] : null;
+ e = _newEndpoint({
+ paintStyle : es, hoverPaintStyle:ehs, endpoint : ep, connections : [ conn ],
+ uuid : u, anchor : a, source : element, scope : params.scope, container:params.container,
+ reattach:params.reattach || _jsPlumb.Defaults.ReattachConnections,
+ detachable:params.detachable || _jsPlumb.Defaults.ConnectionsDetachable
+ });
+ conn.endpoints[index] = e;
+
+ if (params.drawEndpoints === false) e.setVisible(false, true, true);
+
+ }
+ return e;
+ };
+
+ jsPlumb.Connection = function(params) {
+ var _newConnection = params.newConnection,
+ _newEndpoint = params.newEndpoint,
+ jpcl = jsPlumb.CurrentLibrary,
+ _att = jpcl.getAttribute,
+ _gel = jpcl.getElementObject,
+ _dom = jpcl.getDOMElement,
+ _ju = jsPlumbUtil,
+ _getOffset = jpcl.getOffset;
+
+ this.connector = null;
+ this.idPrefix = "_jsplumb_c_";
+ this.defaultLabelLocation = 0.5;
+ this.defaultOverlayKeys = ["Overlays", "ConnectionOverlays"];
+ this.parent = params.parent;
+ // if a new connection is the result of moving some existing connection, params.previousConnection
+ // will have that Connection in it. listeners for the jsPlumbConnection event can look for that
+ // member and take action if they need to.
+ this.previousConnection = params.previousConnection;
+ this.source = _dom(params.source);
+ this.target = _dom(params.target);
+ // sourceEndpoint and targetEndpoint override source/target, if they are present. but
+ // source is not overridden if the Endpoint has declared it is not the final target of a connection;
+ // instead we use the source that the Endpoint declares will be the final source element.
+ if (params.sourceEndpoint) this.source = params.sourceEndpoint.endpointWillMoveTo || params.sourceEndpoint.getElement();
+ if (params.targetEndpoint) this.target = params.targetEndpoint.getElement();
+
+ OverlayCapableJsPlumbUIComponent.apply(this, arguments);
+
+ this.sourceId = this._jsPlumb.instance.getId(this.source);
+ this.targetId = this._jsPlumb.instance.getId(this.target);
+ this.scope = params.scope; // scope may have been passed in to the connect call. if it wasn't, we will pull it from the source endpoint, after having initialised the endpoints.
+ this.endpoints = [];
+ this.endpointStyles = [];
+
+ var _jsPlumb = this._jsPlumb.instance;
+ this._jsPlumb.visible = true;
+ this._jsPlumb.editable = params.editable === true;
+ this._jsPlumb.params = {
+ parent:params.parent,
+ cssClass:params.cssClass,
+ container:params.container,
+ "pointer-events":params["pointer-events"],
+ editorParams:params.editorParams
+ };
+ this._jsPlumb.lastPaintedAt = null;
+ this.getDefaultType = function() {
+ return {
+ parameters:{},
+ scope:null,
+ detachable:this._jsPlumb.instance.Defaults.ConnectionsDetachable,
+ rettach:this._jsPlumb.instance.Defaults.ReattachConnections,
+ paintStyle:this._jsPlumb.instance.Defaults.PaintStyle || jsPlumb.Defaults.PaintStyle,
+ connector:this._jsPlumb.instance.Defaults.Connector || jsPlumb.Defaults.Connector,
+ hoverPaintStyle:this._jsPlumb.instance.Defaults.HoverPaintStyle || jsPlumb.Defaults.HoverPaintStyle,
+ overlays:this._jsPlumb.instance.Defaults.ConnectorOverlays || jsPlumb.Defaults.ConnectorOverlays
+ };
+ };
+
+// INITIALISATION CODE
+
+ // wrapped the main function to return null if no input given. this lets us cascade defaults properly.
+
+ var eS = prepareEndpoint(_jsPlumb, _newEndpoint, this, params.sourceEndpoint, 0, params, this.source, this.sourceId, params.paintStyle, params.hoverPaintStyle);
+ if (eS) _ju.addToList(params.endpointsByElement, this.sourceId, eS);
+ var eT = prepareEndpoint(_jsPlumb, _newEndpoint, this, params.targetEndpoint, 1, params, this.target, this.targetId, params.paintStyle, params.hoverPaintStyle);
+ if (eT) _ju.addToList(params.endpointsByElement, this.targetId, eT);
+ // if scope not set, set it to be the scope for the source endpoint.
+ if (!this.scope) this.scope = this.endpoints[0].scope;
+
+ // if explicitly told to (or not to) delete endpoints on detach, override endpoint's preferences
+ if (params.deleteEndpointsOnDetach != null) {
+ this.endpoints[0]._deleteOnDetach = params.deleteEndpointsOnDetach;
+ this.endpoints[1]._deleteOnDetach = params.deleteEndpointsOnDetach;
+ }
+ else {
+ // otherwise, unless the endpoints say otherwise, mark them for deletion.
+ if (!this.endpoints[0]._doNotDeleteOnDetach) this.endpoints[0]._deleteOnDetach = true;
+ if (!this.endpoints[1]._doNotDeleteOnDetach) this.endpoints[1]._deleteOnDetach = true;
+ }
+
+ // TODO these could surely be refactored into some method that tries them one at a time until something exists
+ this.setConnector(this.endpoints[0].connector ||
+ this.endpoints[1].connector ||
+ params.connector ||
+ _jsPlumb.Defaults.Connector ||
+ jsPlumb.Defaults.Connector, true);
+
+ if (params.path)
+ this.connector.setPath(params.path);
+
+ this.setPaintStyle(this.endpoints[0].connectorStyle ||
+ this.endpoints[1].connectorStyle ||
+ params.paintStyle ||
+ _jsPlumb.Defaults.PaintStyle ||
+ jsPlumb.Defaults.PaintStyle, true);
+
+ this.setHoverPaintStyle(this.endpoints[0].connectorHoverStyle ||
+ this.endpoints[1].connectorHoverStyle ||
+ params.hoverPaintStyle ||
+ _jsPlumb.Defaults.HoverPaintStyle ||
+ jsPlumb.Defaults.HoverPaintStyle, true);
+
+ this._jsPlumb.paintStyleInUse = this.getPaintStyle();
+
+ var _suspendedAt = _jsPlumb.getSuspendedAt();
+ _jsPlumb.updateOffset( { elId : this.sourceId, timestamp:_suspendedAt });
+ _jsPlumb.updateOffset( { elId : this.targetId, timestamp:_suspendedAt });
+
+//*
+ if(!_jsPlumb.isSuspendDrawing()) {
+ // paint the endpoints
+ var myInfo = _jsPlumb.getCachedData(this.sourceId),
+ myOffset = myInfo.o, myWH = myInfo.s,
+ otherInfo = _jsPlumb.getCachedData(this.targetId),
+ otherOffset = otherInfo.o,
+ otherWH = otherInfo.s,
+ initialTimestamp = _suspendedAt || _jsPlumb.timestamp(),
+ anchorLoc = this.endpoints[0].anchor.compute( {
+ xy : [ myOffset.left, myOffset.top ], wh : myWH, element : this.endpoints[0],
+ elementId:this.endpoints[0].elementId,
+ txy : [ otherOffset.left, otherOffset.top ], twh : otherWH, tElement : this.endpoints[1],
+ timestamp:initialTimestamp
+ });
+
+ this.endpoints[0].paint( { anchorLoc : anchorLoc, timestamp:initialTimestamp });
+
+ anchorLoc = this.endpoints[1].anchor.compute( {
+ xy : [ otherOffset.left, otherOffset.top ], wh : otherWH, element : this.endpoints[1],
+ elementId:this.endpoints[1].elementId,
+ txy : [ myOffset.left, myOffset.top ], twh : myWH, tElement : this.endpoints[0],
+ timestamp:initialTimestamp
+ });
+ this.endpoints[1].paint({ anchorLoc : anchorLoc, timestamp:initialTimestamp });
+ }
+ //*/
+
+// END INITIALISATION CODE
+
+// DETACHABLE
+ this._jsPlumb.detachable = _jsPlumb.Defaults.ConnectionsDetachable;
+ if (params.detachable === false) this._jsPlumb.detachable = false;
+ if(this.endpoints[0].connectionsDetachable === false) this._jsPlumb.detachable = false;
+ if(this.endpoints[1].connectionsDetachable === false) this._jsPlumb.detachable = false;
+// REATTACH
+ this._jsPlumb.reattach = params.reattach || this.endpoints[0].reattachConnections || this.endpoints[1].reattachConnections || _jsPlumb.Defaults.ReattachConnections;
+// COST + DIRECTIONALITY
+ // if cost not supplied, try to inherit from source endpoint
+ this._jsPlumb.cost = params.cost || this.endpoints[0].getConnectionCost();
+ this._jsPlumb.directed = params.directed;
+ // inherit directed flag if set no source endpoint
+ if (params.directed == null) this._jsPlumb.directed = this.endpoints[0].areConnectionsDirected();
+// END COST + DIRECTIONALITY
+
+// PARAMETERS
+ // merge all the parameters objects into the connection. parameters set
+ // on the connection take precedence; then source endpoint params, then
+ // finally target endpoint params.
+ // TODO jsPlumb.extend could be made to take more than two args, and it would
+ // apply the second through nth args in order.
+ var _p = jsPlumb.extend({}, this.endpoints[1].getParameters());
+ jsPlumb.extend(_p, this.endpoints[0].getParameters());
+ jsPlumb.extend(_p, this.getParameters());
+ this.setParameters(_p);
+// END PARAMETERS
+
+// PAINTING
+
+ // the very last thing we do is apply types, if there are any.
+ var _types = [params.type, this.endpoints[0].connectionType, this.endpoints[1].connectionType ].join(" ");
+ if (/[a-zA-Z]/.test(_types))
+ this.addType(_types, params.data, true);
+
+
+// END PAINTING
+ };
+
+ jsPlumbUtil.extend(jsPlumb.Connection, OverlayCapableJsPlumbUIComponent, {
+ applyType : function(t, doNotRepaint) {
+ if (t.detachable != null) this.setDetachable(t.detachable);
+ if (t.reattach != null) this.setReattach(t.reattach);
+ if (t.scope) this.scope = t.scope;
+ //editable = t.editable; // TODO
+ this.setConnector(t.connector, doNotRepaint);
+ },
+ getTypeDescriptor : function() { return "connection"; },
+ getAttachedElements : function() {
+ return this.endpoints;
+ },
+ addClass : function(c, informEndpoints) {
+ if (informEndpoints) {
+ this.endpoints[0].addClass(c);
+ this.endpoints[1].addClass(c);
+ if (this.suspendedEndpoint) this.suspendedEndpoint.addClass(c);
+ }
+ if (this.connector) {
+ this.connector.addClass(c);
+ }
+ },
+ removeClass : function(c, informEndpoints) {
+ if (informEndpoints) {
+ this.endpoints[0].removeClass(c);
+ this.endpoints[1].removeClass(c);
+ if (this.suspendedEndpoint) this.suspendedEndpoint.removeClass(c);
+ }
+ if (this.connector) {
+ this.connector.removeClass(c);
+ }
+ },
+ isVisible : function() { return this._jsPlumb.visible; },
+ setVisible : function(v) {
+ this._jsPlumb.visible = v;
+ //this[v ? "showOverlays" : "hideOverlays"]();
+ if (this.connector)
+ this.connector.setVisible(v);
+ this.repaint();
+ },
+
+ /* TODO move to connecto editors; it should put these on the prototype.
+
+ setEditable : function(e) {
+ if (this.connector && this.connector.isEditable())
+ this._jsPlumb.editable = e;
+
+ return this._jsPlumb.editable;
+ },
+ isEditable : function() { return this._jsPlumb.editable; },
+ editStarted : function() {
+ this.setSuspendEvents(true);
+ this.fire("editStarted", {
+ path:this.connector.getPath()
+ });
+ this._jsPlumb.instance.setHoverSuspended(true);
+ },
+ editCompleted : function() {
+ this.fire("editCompleted", {
+ path:this.connector.getPath()
+ });
+ this.setSuspendEvents(false);
+ this.setHover(false);
+ this._jsPlumb.instance.setHoverSuspended(false);
+ },
+ editCanceled : function() {
+ this.fire("editCanceled", {
+ path:this.connector.getPath()
+ });
+ this.setHover(false);
+ this._jsPlumb.instance.setHoverSuspended(false);
+ },
+
+*/
+
+ cleanup:function() {
+ //this.endpointsToDeleteOnDetach = null;
+ this.endpoints = null;
+ this.source = null;
+ this.target = null;
+ if (this.connector != null) {
+ this.connector.cleanup();
+ this.connector.destroy();
+ }
+ this.connector = null;
+ },
+ isDetachable : function() {
+ return this._jsPlumb.detachable === true;
+ },
+ setDetachable : function(detachable) {
+ this._jsPlumb.detachable = detachable === true;
+ },
+ isReattach : function() {
+ return this._jsPlumb.reattach === true;
+ },
+ setReattach : function(reattach) {
+ this._jsPlumb.reattach = reattach === true;
+ },
+ setHover : function(state) {
+ if (this.connector && this._jsPlumb && !this._jsPlumb.instance.isConnectionBeingDragged()) {
+ this.connector.setHover(state);
+ jsPlumb.CurrentLibrary[state ? "addClass" : "removeClass"](this.source, this._jsPlumb.instance.hoverSourceClass);
+ jsPlumb.CurrentLibrary[state ? "addClass" : "removeClass"](this.target, this._jsPlumb.instance.hoverTargetClass);
+ }
+ },
+ getCost : function() { return this._jsPlumb.cost; },
+ setCost : function(c) { this._jsPlumb.cost = c; },
+ isDirected : function() { return this._jsPlumb.directed === true; },
+ //
+ // changes the parent element of this connection to newParent. not exposed for the public API.
+ //
+ // TODO ensure moveParent method still works (the overlay stuff in particular)
+ moveParent : function(newParent) {
+ var jpcl = jsPlumb.CurrentLibrary, curParent = jpcl.getParent(this.connector.canvas);
+ if (this.connector.bgCanvas) {
+ jpcl.removeElement(this.connector.bgCanvas);
+ jpcl.appendElement(this.connector.bgCanvas, newParent);
+ }
+ jpcl.removeElement(this.connector.canvas);
+ jpcl.appendElement(this.connector.canvas, newParent);
+ // this only applies for DOMOverlays
+ for (var i = 0; i < this._jsPlumb.overlays.length; i++) {
+ if (this._jsPlumb.overlays[i].isAppendedAtTopLevel) {
+ jpcl.removeElement(this._jsPlumb.overlays[i].canvas);
+ jpcl.appendElement(this._jsPlumb.overlays[i].canvas, newParent);
+ if (this._jsPlumb.overlays[i].reattachListeners)
+ this._jsPlumb.overlays[i].reattachListeners(this.connector);
+ }
+ }
+ if (this.connector.reattachListeners) // this is for SVG/VML; change an element's parent and you have to reinit its listeners.
+ this.connector.reattachListeners(); // the Canvas implementation doesn't have to care about this
+ },
+ getConnector : function() { return this.connector; },
+ setConnector : function(connectorSpec, doNotRepaint) {
+ var _ju = jsPlumbUtil;
+ if (this.connector != null) {
+ this.connector.cleanup();
+ this.connector.destroy();
+ }
+
+ var connectorArgs = {
+ _jsPlumb:this._jsPlumb.instance,
+ parent:this._jsPlumb.params.parent,
+ cssClass:this._jsPlumb.params.cssClass,
+ container:this._jsPlumb.params.container,
+ "pointer-events":this._jsPlumb.params["pointer-events"]
+ },
+ renderMode = this._jsPlumb.instance.getRenderMode();
+
+ if (_ju.isString(connectorSpec))
+ this.connector = makeConnector(this._jsPlumb.instance, renderMode, connectorSpec, connectorArgs); // lets you use a string as shorthand.
+ else if (_ju.isArray(connectorSpec)) {
+ if (connectorSpec.length == 1)
+ this.connector = makeConnector(this._jsPlumb.instance, renderMode, connectorSpec[0], connectorArgs);
+ else
+ this.connector = makeConnector(this._jsPlumb.instance, renderMode, connectorSpec[0], _ju.merge(connectorSpec[1], connectorArgs));
+ }
+ // binds mouse listeners to the current connector.
+ this.bindListeners(this.connector, this, function(state) {
+ this.setHover(state, false);
+ }.bind(this));
+
+ this.canvas = this.connector.canvas;
+
+ if (this._jsPlumb.editable && jsPlumb.ConnectorEditors != null && jsPlumb.ConnectorEditors[this.connector.type] && this.connector.isEditable()) {
+ new jsPlumb.ConnectorEditors[this.connector.type]({
+ connector:this.connector,
+ connection:this,
+ params:this._jsPlumb.params.editorParams || { }
+ });
+ }
+ else {
+ this._jsPlumb.editable = false;
+ }
+
+ if (!doNotRepaint) this.repaint();
+ },
+ paint : function(params) {
+
+ if (!this._jsPlumb.instance.isSuspendDrawing() && this._jsPlumb.visible) {
+
+ params = params || {};
+ var elId = params.elId, ui = params.ui, recalc = params.recalc, timestamp = params.timestamp,
+ // if the moving object is not the source we must transpose the two references.
+ swap = false,
+ tId = swap ? this.sourceId : this.targetId, sId = swap ? this.targetId : this.sourceId,
+ tIdx = swap ? 0 : 1, sIdx = swap ? 1 : 0;
+
+ if (timestamp == null || timestamp != this._jsPlumb.lastPaintedAt) {
+ var sourceInfo = this._jsPlumb.instance.updateOffset( { elId : sId, offset : ui, recalc : recalc, timestamp : timestamp }).o,
+ targetInfo = this._jsPlumb.instance.updateOffset( { elId : tId, timestamp : timestamp }).o, // update the target if this is a forced repaint. otherwise, only the source has been moved.
+ sE = this.endpoints[sIdx], tE = this.endpoints[tIdx];
+
+ if (params.clearEdits) {
+ this._jsPlumb.overlayPositions = null;
+ sE.anchor.clearUserDefinedLocation();
+ tE.anchor.clearUserDefinedLocation();
+ this.connector.setEdited(false);
+ }
+
+ var sAnchorP = sE.anchor.getCurrentLocation({xy:[sourceInfo.left,sourceInfo.top], wh:[sourceInfo.width, sourceInfo.height], element:sE, timestamp:timestamp}),
+ tAnchorP = tE.anchor.getCurrentLocation({xy:[targetInfo.left,targetInfo.top], wh:[targetInfo.width, targetInfo.height], element:tE, timestamp:timestamp});
+
+ this.connector.resetBounds();
+
+ this.connector.compute({
+ sourcePos:sAnchorP,
+ targetPos:tAnchorP,
+ sourceEndpoint:this.endpoints[sIdx],
+ targetEndpoint:this.endpoints[tIdx],
+ lineWidth:this._jsPlumb.paintStyleInUse.lineWidth,
+ sourceInfo:sourceInfo,
+ targetInfo:targetInfo,
+ clearEdits:params.clearEdits === true
+ });
+
+ var overlayExtents = { minX:Infinity, minY:Infinity, maxX:-Infinity, maxY:-Infinity };
+
+ // compute overlays. we do this first so we can get their placements, and adjust the
+ // container if needs be (if an overlay would be clipped)
+ for ( var i = 0; i < this._jsPlumb.overlays.length; i++) {
+ var o = this._jsPlumb.overlays[i];
+ if (o.isVisible()) {
+ this._jsPlumb.overlayPlacements[i] = o.draw(this.connector, this._jsPlumb.paintStyleInUse, this.getAbsoluteOverlayPosition(o));
+ overlayExtents.minX = Math.min(overlayExtents.minX, this._jsPlumb.overlayPlacements[i].minX);
+ overlayExtents.maxX = Math.max(overlayExtents.maxX, this._jsPlumb.overlayPlacements[i].maxX);
+ overlayExtents.minY = Math.min(overlayExtents.minY, this._jsPlumb.overlayPlacements[i].minY);
+ overlayExtents.maxY = Math.max(overlayExtents.maxY, this._jsPlumb.overlayPlacements[i].maxY);
+ }
+ }
+
+ var lineWidth = parseFloat(this._jsPlumb.paintStyleInUse.lineWidth || 1) / 2,
+ outlineWidth = parseFloat(this._jsPlumb.paintStyleInUse.lineWidth || 0),
+ extents = {
+ xmin : Math.min(this.connector.bounds.minX - (lineWidth + outlineWidth), overlayExtents.minX),
+ ymin : Math.min(this.connector.bounds.minY - (lineWidth + outlineWidth), overlayExtents.minY),
+ xmax : Math.max(this.connector.bounds.maxX + (lineWidth + outlineWidth), overlayExtents.maxX),
+ ymax : Math.max(this.connector.bounds.maxY + (lineWidth + outlineWidth), overlayExtents.maxY)
+ };
+
+ // paint the connector.
+ this.connector.paint(this._jsPlumb.paintStyleInUse, null, extents);
+ // and then the overlays
+ for ( var j = 0; j < this._jsPlumb.overlays.length; j++) {
+ var p = this._jsPlumb.overlays[j];
+ if (p.isVisible()) {
+ p.paint(this._jsPlumb.overlayPlacements[j], extents);
+ }
+ }
+ }
+ this._jsPlumb.lastPaintedAt = timestamp;
+ }
+ },
+ /*
+ * Function: repaint
+ * Repaints the Connection. No parameters exposed to public API.
+ */
+ repaint : function(params) {
+ params = params || {};
+ this.paint({ elId : this.sourceId, recalc : !(params.recalc === false), timestamp:params.timestamp, clearEdits:params.clearEdits });
+ }
+
+ }); // END Connection class
+})();
\ No newline at end of file