mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 04:34:06 -08:00
refactor to simplify
This commit is contained in:
parent
6a080a1ac5
commit
2db0ed504c
|
@ -1,277 +1,29 @@
|
||||||
(function () {
|
(function () {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
var root = this, _jp = root.jsPlumb, _ju = root.jsPlumbUtil, _jg = root.Biltong;
|
const root = this, _jp = root.jsPlumb, _ju = root.jsPlumbUtil, _jg = root.Biltong;
|
||||||
var STRAIGHT = "Straight";
|
const STRAIGHT = "Straight";
|
||||||
var ARC = "Arc";
|
const ARC = "Arc";
|
||||||
|
|
||||||
const _findControlPoint = function (point, sourceAnchorPosition, targetAnchorPosition, sourceEndpoint, targetEndpoint, soo, too, majorAnchor, minorAnchor) {
|
const _prepareCompute = function (params, overrideTargetEndpoint) {
|
||||||
// determine if the two anchors are perpendicular to each other in their orientation. we swap the control
|
let { targetPos, targetEndpoint, getEndpointOffset } = params;
|
||||||
// points around if so (code could be tightened up)
|
const gap = params.gap || 0;
|
||||||
var perpendicular = soo[0] !== too[0] || soo[1] === too[1],
|
const sourceGap = _ju.isArray(gap) ? gap[0] : gap;
|
||||||
p = [];
|
const targetGap = _ju.isArray(gap) ? gap[1] : gap;
|
||||||
|
const stub = params.stub || 0;
|
||||||
if (!perpendicular) {
|
const sourceStub = _ju.isArray(stub) ? stub[0] : stub;
|
||||||
if (soo[0] === 0) {
|
const targetStub = _ju.isArray(stub) ? stub[1] : stub;
|
||||||
p.push(sourceAnchorPosition[0] < targetAnchorPosition[0] ? point[0] + minorAnchor : point[0] - minorAnchor);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
p.push(point[0] - (majorAnchor * soo[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (soo[1] === 0) {
|
|
||||||
p.push(sourceAnchorPosition[1] < targetAnchorPosition[1] ? point[1] + minorAnchor : point[1] - minorAnchor);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
p.push(point[1] + (majorAnchor * too[1]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (too[0] === 0) {
|
|
||||||
p.push(targetAnchorPosition[0] < sourceAnchorPosition[0] ? point[0] + minorAnchor : point[0] - minorAnchor);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
p.push(point[0] + (majorAnchor * too[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (too[1] === 0) {
|
|
||||||
p.push(targetAnchorPosition[1] < sourceAnchorPosition[1] ? point[1] + minorAnchor : point[1] - minorAnchor);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
p.push(point[1] + (majorAnchor * soo[1]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return p;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Class: UIComponent
|
|
||||||
Superclass for Connector and AbstractEndpoint.
|
|
||||||
*/
|
|
||||||
const AbstractComponent = function () {
|
|
||||||
this.resetBounds = function () {
|
|
||||||
this.bounds = { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity };
|
|
||||||
};
|
|
||||||
this.resetBounds();
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: Connector
|
|
||||||
* Superclass for all Connectors; here is where Segments are managed. This is exposed on jsPlumb just so it
|
|
||||||
* can be accessed from other files. You should not try to instantiate one of these directly.
|
|
||||||
*
|
|
||||||
* When this class is asked for a pointOnPath, or gradient etc, it must first figure out which segment to dispatch
|
|
||||||
* that request to. This is done by keeping track of the total connector length as segments are added, and also
|
|
||||||
* their cumulative ratios to the total length. Then when the right segment is found it is a simple case of dispatching
|
|
||||||
* the request to it (and adjusting 'location' so that it is relative to the beginning of that segment.)
|
|
||||||
*/
|
|
||||||
_jp.Connectors.N8nAbstractConnector = function (params) {
|
|
||||||
|
|
||||||
AbstractComponent.apply(this, arguments);
|
|
||||||
|
|
||||||
var segments = [],
|
|
||||||
totalLength = 0,
|
|
||||||
segmentProportions = [],
|
|
||||||
segmentProportionalLengths = [],
|
|
||||||
getEndpointOffset = params.getEndpointOffset,
|
|
||||||
stub = params.stub || 0,
|
|
||||||
sourceStub = _ju.isArray(stub) ? stub[0] : stub,
|
|
||||||
targetStub = _ju.isArray(stub) ? stub[1] : stub,
|
|
||||||
gap = params.gap || 0,
|
|
||||||
sourceGap = _ju.isArray(gap) ? gap[0] : gap,
|
|
||||||
targetGap = _ju.isArray(gap) ? gap[1] : gap,
|
|
||||||
userProvidedSegments = null,
|
|
||||||
paintInfo = null;
|
|
||||||
|
|
||||||
this.getPathData = function() {
|
|
||||||
var p = "";
|
|
||||||
for (var i = 0; i < segments.length; i++) {
|
|
||||||
p += _jp.SegmentRenderer.getPath(segments[i], i === 0);
|
|
||||||
p += " ";
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function: findSegmentForPoint
|
|
||||||
* Returns the segment that is closest to the given [x,y],
|
|
||||||
* null if nothing found. This function returns a JS
|
|
||||||
* object with:
|
|
||||||
*
|
|
||||||
* d - distance from segment
|
|
||||||
* l - proportional location in segment
|
|
||||||
* x - x point on the segment
|
|
||||||
* y - y point on the segment
|
|
||||||
* s - the segment itself.
|
|
||||||
* connectorLocation - the location on the connector of the point, expressed as a decimal between 0 and 1 inclusive.
|
|
||||||
*/
|
|
||||||
this.findSegmentForPoint = function (x, y) {
|
|
||||||
var out = { d: Infinity, s: null, x: null, y: null, l: null };
|
|
||||||
for (var i = 0; i < segments.length; i++) {
|
|
||||||
var _s = segments[i].findClosestPointOnPath(x, y);
|
|
||||||
if (_s.d < out.d) {
|
|
||||||
out.d = _s.d;
|
|
||||||
out.l = _s.l;
|
|
||||||
out.x = _s.x;
|
|
||||||
out.y = _s.y;
|
|
||||||
out.s = segments[i];
|
|
||||||
out.x1 = _s.x1;
|
|
||||||
out.x2 = _s.x2;
|
|
||||||
out.y1 = _s.y1;
|
|
||||||
out.y2 = _s.y2;
|
|
||||||
out.index = i;
|
|
||||||
out.connectorLocation = segmentProportions[i][0] + (_s.l * (segmentProportions[i][1] - segmentProportions[i][0]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.lineIntersection = function(x1, y1, x2, y2) {
|
|
||||||
var out = [];
|
|
||||||
for (var i = 0; i < segments.length; i++) {
|
|
||||||
out.push.apply(out, segments[i].lineIntersection(x1, y1, x2, y2));
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.boxIntersection = function(x, y, w, h) {
|
|
||||||
var out = [];
|
|
||||||
for (var i = 0; i < segments.length; i++) {
|
|
||||||
out.push.apply(out, segments[i].boxIntersection(x, y, w, h));
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.boundingBoxIntersection = function(box) {
|
|
||||||
var out = [];
|
|
||||||
for (var i = 0; i < segments.length; i++) {
|
|
||||||
out.push.apply(out, segments[i].boundingBoxIntersection(box));
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _updateSegmentProportions = function () {
|
|
||||||
var curLoc = 0;
|
|
||||||
for (var i = 0; i < segments.length; i++) {
|
|
||||||
var sl = segments[i].getLength();
|
|
||||||
segmentProportionalLengths[i] = sl / totalLength;
|
|
||||||
segmentProportions[i] = [curLoc, (curLoc += (sl / totalLength)) ];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns [segment, proportion of travel in segment, segment index] for the segment
|
|
||||||
* that contains the point which is 'location' distance along the entire path, where
|
|
||||||
* 'location' is a decimal between 0 and 1 inclusive. in this connector type, paths
|
|
||||||
* are made up of a list of segments, each of which contributes some fraction to
|
|
||||||
* the total length.
|
|
||||||
* From 1.3.10 this also supports the 'absolute' property, which lets us specify a location
|
|
||||||
* as the absolute distance in pixels, rather than a proportion of the total path.
|
|
||||||
*/
|
|
||||||
_findSegmentForLocation = function (location, absolute) {
|
|
||||||
|
|
||||||
var idx, i, inSegmentProportion;
|
|
||||||
|
|
||||||
if (absolute) {
|
|
||||||
location = location > 0 ? location / totalLength : (totalLength + location) / totalLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if location 1 we know its the last segment
|
|
||||||
if (location === 1) {
|
|
||||||
idx = segments.length - 1;
|
|
||||||
inSegmentProportion = 1;
|
|
||||||
} else if (location === 0) {
|
|
||||||
// if location 0 we know its the first segment
|
|
||||||
inSegmentProportion = 0;
|
|
||||||
idx = 0;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// if location >= 0.5, traverse backwards (of course not exact, who knows the segment proportions. but
|
|
||||||
// an educated guess at least)
|
|
||||||
if (location >= 0.5) {
|
|
||||||
|
|
||||||
idx = 0;
|
|
||||||
inSegmentProportion = 0;
|
|
||||||
for (i = segmentProportions.length - 1; i > -1; i--) {
|
|
||||||
if (segmentProportions[i][1] >= location && segmentProportions[i][0] <= location) {
|
|
||||||
idx = i;
|
|
||||||
inSegmentProportion = (location - segmentProportions[i][0]) / segmentProportionalLengths[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
idx = segmentProportions.length - 1;
|
|
||||||
inSegmentProportion = 1;
|
|
||||||
for (i = 0; i < segmentProportions.length; i++) {
|
|
||||||
if (segmentProportions[i][1] >= location) {
|
|
||||||
idx = i;
|
|
||||||
inSegmentProportion = (location - segmentProportions[i][0]) / segmentProportionalLengths[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { segment: segments[idx], proportion: inSegmentProportion, index: idx };
|
|
||||||
},
|
|
||||||
_addSegment = function (conn, type, params) {
|
|
||||||
if (params.x1 === params.x2 && params.y1 === params.y2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var s = new _jp.Segments[type](params);
|
|
||||||
segments.push(s);
|
|
||||||
totalLength += s.getLength();
|
|
||||||
conn.updateBounds(s);
|
|
||||||
},
|
|
||||||
_clearSegments = function () {
|
|
||||||
totalLength = segments.length = segmentProportions.length = segmentProportionalLengths.length = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setSegments = function (_segs) {
|
|
||||||
userProvidedSegments = [];
|
|
||||||
totalLength = 0;
|
|
||||||
for (var i = 0; i < _segs.length; i++) {
|
|
||||||
userProvidedSegments.push(_segs[i]);
|
|
||||||
totalLength += _segs[i].getLength();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.getLength = function() {
|
|
||||||
return totalLength;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set target endpoint
|
|
||||||
* (to override default behavior tracking mouse when dragging mouse)
|
|
||||||
* @param {Endpoint} endpoint
|
|
||||||
*/
|
|
||||||
this.setTargetEndpoint = function (endpoint) {
|
|
||||||
this.overrideTargetEndpoint = endpoint;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* reset target endpoint overriding default behavior
|
|
||||||
*/
|
|
||||||
this.resetTargetEndpoint = function () {
|
|
||||||
this.overrideTargetEndpoint = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _prepareCompute = function (params) {
|
|
||||||
let { targetPos, targetEndpoint } = params;
|
|
||||||
|
|
||||||
// if has override, use override
|
// if has override, use override
|
||||||
if (
|
if (
|
||||||
this.overrideTargetEndpoint
|
overrideTargetEndpoint
|
||||||
) {
|
) {
|
||||||
const target = this.overrideTargetEndpoint.anchor.lastReturnValue;
|
const target = overrideTargetEndpoint.anchor.lastReturnValue;
|
||||||
targetPos = [target[0], target[1]];
|
targetPos = [target[0], target[1]];
|
||||||
targetEndpoint = this.overrideTargetEndpoint;
|
targetEndpoint = overrideTargetEndpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.strokeWidth = params.strokeWidth;
|
// this.strokeWidth = params.strokeWidth;
|
||||||
var segment = _jg.quadrant(params.sourcePos, targetPos),
|
var segment = _jg.quadrant(params.sourcePos, targetPos),
|
||||||
swapX = targetPos[0] < params.sourcePos[0],
|
swapX = targetPos[0] < params.sourcePos[0],
|
||||||
swapY = targetPos[1] < params.sourcePos[1],
|
swapY = targetPos[1] < params.sourcePos[1],
|
||||||
|
@ -334,76 +86,72 @@
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getSegments = function () {
|
const _findControlPoint = function (point, sourceAnchorPosition, targetAnchorPosition, sourceEndpoint, targetEndpoint, soo, too, majorAnchor, minorAnchor) {
|
||||||
return segments;
|
// determine if the two anchors are perpendicular to each other in their orientation. we swap the control
|
||||||
|
// points around if so (code could be tightened up)
|
||||||
|
var perpendicular = soo[0] !== too[0] || soo[1] === too[1],
|
||||||
|
p = [];
|
||||||
|
|
||||||
|
if (!perpendicular) {
|
||||||
|
if (soo[0] === 0) {
|
||||||
|
p.push(sourceAnchorPosition[0] < targetAnchorPosition[0] ? point[0] + minorAnchor : point[0] - minorAnchor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p.push(point[0] - (majorAnchor * soo[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (soo[1] === 0) {
|
||||||
|
p.push(sourceAnchorPosition[1] < targetAnchorPosition[1] ? point[1] + minorAnchor : point[1] - minorAnchor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p.push(point[1] + (majorAnchor * too[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (too[0] === 0) {
|
||||||
|
p.push(targetAnchorPosition[0] < sourceAnchorPosition[0] ? point[0] + minorAnchor : point[0] - minorAnchor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p.push(point[0] + (majorAnchor * too[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (too[1] === 0) {
|
||||||
|
p.push(targetAnchorPosition[1] < sourceAnchorPosition[1] ? point[1] + minorAnchor : point[1] - minorAnchor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p.push(point[1] + (majorAnchor * soo[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updateBounds = function (segment) {
|
const N8nCustom = function (params) {
|
||||||
var segBounds = segment.getBounds();
|
|
||||||
this.bounds.minX = Math.min(this.bounds.minX, segBounds.minX);
|
|
||||||
this.bounds.maxX = Math.max(this.bounds.maxX, segBounds.maxX);
|
|
||||||
this.bounds.minY = Math.min(this.bounds.minY, segBounds.minY);
|
|
||||||
this.bounds.maxY = Math.max(this.bounds.maxY, segBounds.maxY);
|
|
||||||
};
|
|
||||||
|
|
||||||
// var dumpSegmentsToConsole = function () {
|
|
||||||
// console.log("SEGMENTS:");
|
|
||||||
// for (var i = 0; i < segments.length; i++) {
|
|
||||||
// console.log(segments[i].type, segments[i].getLength(), segmentProportions[i]);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
this.pointOnPath = function (location, absolute) {
|
|
||||||
var seg = _findSegmentForLocation(location, absolute);
|
|
||||||
return seg.segment && seg.segment.pointOnPath(seg.proportion, false) || [0, 0];
|
|
||||||
};
|
|
||||||
|
|
||||||
this.gradientAtPoint = function (location, absolute) {
|
|
||||||
var seg = _findSegmentForLocation(location, absolute);
|
|
||||||
return seg.segment && seg.segment.gradientAtPoint(seg.proportion, false) || 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.pointAlongPathFrom = function (location, distance, absolute) {
|
|
||||||
var seg = _findSegmentForLocation(location, absolute);
|
|
||||||
// TODO what happens if this crosses to the next segment?
|
|
||||||
return seg.segment && seg.segment.pointAlongPathFrom(seg.proportion, distance, false) || [0, 0];
|
|
||||||
};
|
|
||||||
|
|
||||||
this.compute = function (params) {
|
|
||||||
paintInfo = _prepareCompute.call(this, params);
|
|
||||||
|
|
||||||
_clearSegments();
|
|
||||||
this._compute(paintInfo);
|
|
||||||
this.x = paintInfo.points[0];
|
|
||||||
this.y = paintInfo.points[1];
|
|
||||||
this.w = paintInfo.points[2];
|
|
||||||
this.h = paintInfo.points[3];
|
|
||||||
this.segment = paintInfo.segment;
|
|
||||||
_updateSegmentProportions();
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
addSegment: _addSegment,
|
|
||||||
prepareCompute: _prepareCompute,
|
|
||||||
sourceStub: sourceStub,
|
|
||||||
targetStub: targetStub,
|
|
||||||
maxStub: Math.max(sourceStub, targetStub),
|
|
||||||
sourceGap: sourceGap,
|
|
||||||
targetGap: targetGap,
|
|
||||||
maxGap: Math.max(sourceGap, targetGap),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
_ju.extend(_jp.Connectors.N8nAbstractConnector, AbstractComponent);
|
|
||||||
|
|
||||||
var N8nCustom = function (params) {
|
|
||||||
params = params || {};
|
params = params || {};
|
||||||
this.type = "N8nCustom";
|
this.type = "N8nCustom";
|
||||||
|
|
||||||
var _super = _jp.Connectors.N8nAbstractConnector.apply(this, arguments),
|
var _super = _jp.Connectors.AbstractConnector.apply(this, arguments),
|
||||||
majorAnchor = params.curviness || 150,
|
majorAnchor = params.curviness || 150,
|
||||||
minorAnchor = 10;
|
minorAnchor = 10;
|
||||||
|
|
||||||
this._compute = function (paintInfo) {
|
/**
|
||||||
|
* Set target endpoint
|
||||||
|
* (to override default behavior tracking mouse when dragging mouse)
|
||||||
|
* @param {Endpoint} endpoint
|
||||||
|
*/
|
||||||
|
this.setTargetEndpoint = function (endpoint) {
|
||||||
|
this.overrideTargetEndpoint = endpoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reset target endpoint overriding default behavior
|
||||||
|
*/
|
||||||
|
this.resetTargetEndpoint = function () {
|
||||||
|
this.overrideTargetEndpoint = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
this._compute = function (_, params) {
|
||||||
|
const paintInfo = _prepareCompute(params, this.overrideTargetEndpoint);
|
||||||
var sp = paintInfo.sourcePos,
|
var sp = paintInfo.sourcePos,
|
||||||
tp = paintInfo.targetPos,
|
tp = paintInfo.targetPos,
|
||||||
_w = Math.abs(sp[0] - tp[0]),
|
_w = Math.abs(sp[0] - tp[0]),
|
||||||
|
@ -429,8 +177,8 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
_jp.Connectors.N8nCustom= N8nCustom;
|
_jp.Connectors.N8nCustom = N8nCustom;
|
||||||
_ju.extend(_jp.Connectors.N8nCustom, _jp.Connectors.N8nAbstractConnector);
|
_ju.extend(_jp.Connectors.N8nCustom, _jp.Connectors.AbstractConnector);
|
||||||
|
|
||||||
}).call(typeof window !== 'undefined' ? window : this);
|
}).call(typeof window !== 'undefined' ? window : this);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue