diff --git a/packages/joint-core/demo/links/src/links.js b/packages/joint-core/demo/links/src/links.js index c0500f274..b294545f2 100644 --- a/packages/joint-core/demo/links/src/links.js +++ b/packages/joint-core/demo/links/src/links.js @@ -782,7 +782,7 @@ paper.on('link:mouseenter', function(linkView) { break; case link6: tools = [ - new joint.linkTools.Vertices(), + new joint.linkTools.Vertices({ vertexAdding: { interactiveLinkNode: 'outline' }}), new CustomBoundary({ padding: 25 }) ]; break; diff --git a/packages/joint-core/src/linkTools/Vertices.mjs b/packages/joint-core/src/linkTools/Vertices.mjs index 862e03512..56f69df41 100644 --- a/packages/joint-core/src/linkTools/Vertices.mjs +++ b/packages/joint-core/src/linkTools/Vertices.mjs @@ -65,6 +65,8 @@ export const Vertices = ToolView.extend({ snapRadius: 20, redundancyRemoval: true, vertexAdding: true, + // vertexRemoving: true, + // vertexMoving: true, stopPropagation: true, scale: null }, @@ -80,19 +82,48 @@ export const Vertices = ToolView.extend({ } }], handles: null, + interactiveLinkNode: null, events: { 'mousedown .joint-vertices-path': 'onPathPointerDown', 'touchstart .joint-vertices-path': 'onPathPointerDown' }, + linkEvents: { + mousedown: 'onLinkPointerDown', + touchstart: 'onLinkPointerDown' + }, onRender: function() { - if (this.options.vertexAdding) { - this.renderChildren(); - this.updatePath(); + const { vertexAdding } = this.options; + if (vertexAdding) { + const { interactiveLinkNode = null } = vertexAdding; + if (interactiveLinkNode) { + this.delegateLinkEvents(interactiveLinkNode); + } else { + this.renderChildren(); + this.updatePath(); + } } this.resetHandles(); this.renderHandles(); return this; }, + delegateLinkEvents: function(selector) { + this.undelegateLinkEvents(); + const el = this.relatedView.findNode(selector); + if (!el) { + console.warn(`Interactive link node "${selector}" not found.`); + return; + } + el.classList.add('joint-vertices-path'); + this.interactiveLinkNode = el; + this.delegateElementEvents(el, this.linkEvents); + }, + undelegateLinkEvents: function() { + const el = this.interactiveLinkNode; + if (!el) return; + this.undelegateElementEvents(el); + el.classList.remove('joint-vertices-path'); + this.interactiveLinkNode = null; + }, update: function() { var relatedView = this.relatedView; var vertices = relatedView.model.vertices(); @@ -146,7 +177,8 @@ export const Vertices = ToolView.extend({ } }, updatePath: function() { - var connection = this.childNodes.connection; + if (this.interactiveLinkNode) return; + const connection = this.childNodes.connection; if (connection) connection.setAttribute('d', this.relatedView.getSerializedConnection()); }, startHandleListening: function(handle) { @@ -245,8 +277,13 @@ export const Vertices = ToolView.extend({ this.eventData(normalizedEvent, { vertexAdded: true }); handle.onPointerDown(normalizedEvent); }, + onLinkPointerDown: function(evt) { + this.relatedView.preventDefaultInteraction(evt); + this.onPathPointerDown(evt); + }, onRemove: function() { this.resetHandles(); + this.undelegateLinkEvents(); } }, { VertexHandle: VertexHandle // keep as class property diff --git a/packages/joint-core/test/jointjs/dia/linkTools.js b/packages/joint-core/test/jointjs/dia/linkTools.js index be5f2775e..416403130 100644 --- a/packages/joint-core/test/jointjs/dia/linkTools.js +++ b/packages/joint-core/test/jointjs/dia/linkTools.js @@ -343,4 +343,39 @@ QUnit.module('linkTools', function(hooks) { }); }); + QUnit.module('Vertices', function() { + QUnit.test('vertexAdding', function(assert) { + // vertexAdding = true + const vertices1 = new joint.linkTools.Vertices({ + vertexAdding: true + }); + linkView.addTools(new joint.dia.ToolsView({ tools: [vertices1] })); + assert.ok(vertices1.el.querySelector('.joint-vertices-path')); + assert.notOk(linkView.el.querySelector('.joint-vertices-path')); + linkView.removeTools(); + // vertexAdding = false + const vertices2 = new joint.linkTools.Vertices({ + vertexAdding: false + }); + linkView.addTools(new joint.dia.ToolsView({ tools: [vertices2] })); + assert.notOk(vertices2.el.querySelector('.joint-vertices-path')); + assert.notOk(linkView.el.querySelector('.joint-vertices-path')); + linkView.removeTools(); + // interactiveLinkNode selector + const selector = 'wrapper'; + const vertices3 = new joint.linkTools.Vertices({ + vertexAdding: { interactiveLinkNode: selector } + }); + linkView.addTools(new joint.dia.ToolsView({ tools: [vertices3] })); + assert.notOk(vertices3.el.querySelector('.joint-vertices-path')); + assert.ok(linkView.el.querySelector('.joint-vertices-path')); + assert.ok(joint.mvc.$.event.has(linkView.findNode(selector))); + assert.ok(linkView.findNode(selector).classList.contains('joint-vertices-path')); + linkView.removeTools(); + assert.notOk(linkView.el.querySelector('.joint-vertices-path')); + assert.notOk(linkView.findNode(selector).classList.contains('joint-vertices-path')); + assert.notOk(joint.mvc.$.event.has(linkView.findNode(selector))); + }); + }); + }); diff --git a/packages/joint-core/types/joint.d.ts b/packages/joint-core/types/joint.d.ts index 2ef0c9547..12a92a7f0 100644 --- a/packages/joint-core/types/joint.d.ts +++ b/packages/joint-core/types/joint.d.ts @@ -4214,11 +4214,15 @@ export namespace linkTools { protected onPointerClick(evt: dia.Event): void; } + interface VertexAddingOptions { + interactiveLineNode: string; + } + interface Options extends dia.ToolView.Options { handleClass?: typeof VertexHandle; snapRadius?: number; redundancyRemoval?: boolean; - vertexAdding?: boolean; + vertexAdding?: boolean | Partial; vertexRemoving?: boolean; vertexMoving?: boolean; stopPropagation?: boolean;