diff --git a/packages/joint-core/src/dia/CellView.mjs b/packages/joint-core/src/dia/CellView.mjs index 621fad69b..5d3ad6f4a 100644 --- a/packages/joint-core/src/dia/CellView.mjs +++ b/packages/joint-core/src/dia/CellView.mjs @@ -433,15 +433,20 @@ export const CellView = View.extend({ getLinkEnd: function(magnet, ...args) { - var model = this.model; - var id = model.id; - var port = this.findAttribute('port', magnet); + const model = this.model; + const id = model.id; + // Find a node with the `port` attribute set on it. + const portNode = this.findAttributeNode('port', magnet); // Find a unique `selector` of the element under pointer that is a magnet. - var selector = magnet.getAttribute('joint-selector'); + const selector = magnet.getAttribute('joint-selector'); - var end = { id: id }; + const end = { id: id }; if (selector != null) end.magnet = selector; - if (port != null) { + if (portNode != null) { + let port = portNode.getAttribute('port'); + if (portNode.getAttribute('port-id-type') === 'number') { + port = parseInt(port, 10); + } end.port = port; if (!model.hasPort(port) && !selector) { // port created via the `port` attribute (not API) diff --git a/packages/joint-core/src/dia/ports.mjs b/packages/joint-core/src/dia/ports.mjs index d3186f0ca..a9ef05527 100644 --- a/packages/joint-core/src/dia/ports.mjs +++ b/packages/joint-core/src/dia/ports.mjs @@ -731,6 +731,13 @@ export const elementViewPortPrototype = { 'port-group': port.group }); + // If the port ID is a number, we need to add + // extra information to the port element to distinguish + // between ports with the same ID but different types. + if (util.isNumber(port.id)) { + portElement.attr('port-id-type', 'number'); + } + const labelMarkupDef = this._getPortLabelMarkup(port.label); if (Array.isArray(labelMarkupDef)) { // JSON Markup diff --git a/packages/joint-core/src/mvc/View.mjs b/packages/joint-core/src/mvc/View.mjs index 196461e1b..02ce8dcc9 100644 --- a/packages/joint-core/src/mvc/View.mjs +++ b/packages/joint-core/src/mvc/View.mjs @@ -63,23 +63,25 @@ export const View = ViewBase.extend({ return this; }, - findAttribute: function(attributeName, node) { - - var currentNode = node; - + findAttributeNode: function(attributeName, node) { + let currentNode = node; while (currentNode && currentNode.nodeType === 1) { - var attributeValue = currentNode.getAttribute(attributeName); // attribute found - if (attributeValue) return attributeValue; + // (empty value does not count as attribute found) + if (currentNode.getAttribute(attributeName)) return currentNode; // do not climb up the DOM if (currentNode === this.el) return null; // try parent node currentNode = currentNode.parentNode; } - return null; }, + findAttribute: function(attributeName, node) { + const matchedNode = this.findAttributeNode(attributeName, node); + return matchedNode && matchedNode.getAttribute(attributeName); + }, + // Override the mvc ViewBase `_ensureElement()` method in order to create an // svg element (e.g., ``) node that wraps all the nodes of the Cell view. // Expose class name setter as a separate method. diff --git a/packages/joint-core/test/jointjs/cellView.js b/packages/joint-core/test/jointjs/cellView.js index 526a3c823..b7bcd8229 100644 --- a/packages/joint-core/test/jointjs/cellView.js +++ b/packages/joint-core/test/jointjs/cellView.js @@ -666,4 +666,23 @@ QUnit.module('cellView', function(hooks) { }); }); + + QUnit.module('getLinkEnd()', function (hooks) { + ['port1', 13].forEach(function (portId) { + QUnit.test('port id: ' + typeof portId, function (assert) { + const cell = cellView.model; + cell.addPort({ + id: portId, + }); + const portNode = cellView.findPortNode(portId); + assert.equal(portNode.getAttribute('port'), portId); + const end = cellView.getLinkEnd(portNode); + assert.deepEqual(end, { + id: cell.id, + magnet: 'circle', + port: portId, + }); + }); + }); + }); }); diff --git a/packages/joint-core/types/joint.d.ts b/packages/joint-core/types/joint.d.ts index 61731ca7b..786f39f8b 100644 --- a/packages/joint-core/types/joint.d.ts +++ b/packages/joint-core/types/joint.d.ts @@ -3302,6 +3302,8 @@ export namespace mvc { isMounted(): boolean; + protected findAttributeNode(attributeName: string, node: Element): Element | null; + protected init(): void; protected onRender(): void;