From 3f72fd099dc8dc6659a03469e6b097b358cef37b Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Mon, 13 Apr 2026 13:37:28 -0400 Subject: [PATCH 1/7] initial attempt to delete an edge --- inst/htmlwidgets/cytoscapeNetwork.js | 41 +++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/inst/htmlwidgets/cytoscapeNetwork.js b/inst/htmlwidgets/cytoscapeNetwork.js index 9c1fed6..1bc0900 100644 --- a/inst/htmlwidgets/cytoscapeNetwork.js +++ b/inst/htmlwidgets/cytoscapeNetwork.js @@ -436,11 +436,50 @@ HTMLWidgets.widget({ tooltip.style.display = "none"; }); - /* ── Evidence link on edge click ─────────────────────────────── */ + /* ── Right-click on edge → delete it ────────────────────────── */ + + /* Record which mouse button started the current click so the tap + handler can tell left from right without relying on Cytoscape's + originalEvent (which is unreliable for button detection). */ + var lastMouseButton = 0; + cyContainer.addEventListener("mousedown", function (evt) { + lastMouseButton = evt.button; + }); + + /* Track whichever non-PTM edge the cursor is currently over */ + var hoveredEdge = null; + cy.on("mouseover", "edge", function (evt) { + var e = evt.target; + if (e.data("edge_type") !== "ptm_attachment") hoveredEdge = e; + }); + cy.on("mouseout", "edge", function () { + hoveredEdge = null; + }); + + /* contextmenu fires reliably on right-click before the browser + can show its native menu; preventDefault stops the native menu */ + cyContainer.addEventListener("contextmenu", function (evt) { + evt.preventDefault(); + if (!hoveredEdge || !hoveredEdge.inside()) return; + var deleted = { + source: hoveredEdge.data("source"), + target: hoveredEdge.data("target"), + interaction: hoveredEdge.data("interaction") + }; + hoveredEdge.remove(); + hoveredEdge = null; + if (window.Shiny) { + Shiny.setInputValue(el.id + "_edge_deleted", deleted, { priority: "event" }); + } + }); + + /* ── Evidence link on left-click ────────────────────────────── */ cy.on("tap", "edge", function (evt) { var edge = evt.target; // skip compound/ptm attachment edges if (edge.data("edge_type") === "ptm_attachment") return; + // skip right-click — handled by the contextmenu listener above + if (lastMouseButton === 2) return; openSafe(edge.data("evidenceLink")); if (window.Shiny) { Shiny.setInputValue(el.id + "_edge_clicked", { From 4b3dc6a31217000c57813e42e72b2e861daa40b6 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Tue, 14 Apr 2026 22:56:20 -0400 Subject: [PATCH 2/7] additinal atempts to delet edge --- inst/htmlwidgets/cytoscapeNetwork.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/inst/htmlwidgets/cytoscapeNetwork.js b/inst/htmlwidgets/cytoscapeNetwork.js index 1bc0900..51e1a8a 100644 --- a/inst/htmlwidgets/cytoscapeNetwork.js +++ b/inst/htmlwidgets/cytoscapeNetwork.js @@ -438,13 +438,14 @@ HTMLWidgets.widget({ /* ── Right-click on edge → delete it ────────────────────────── */ - /* Record which mouse button started the current click so the tap - handler can tell left from right without relying on Cytoscape's - originalEvent (which is unreliable for button detection). */ - var lastMouseButton = 0; + /* Block right-click mousedown from reaching Cytoscape by intercepting + it in the capture phase (runs before any element-level listener). + This prevents Cytoscape from ever starting a tap cycle on right-click, + stopping the evidence link from opening. The contextmenu event is + fired by the OS independently and is unaffected by this. */ cyContainer.addEventListener("mousedown", function (evt) { - lastMouseButton = evt.button; - }); + if (evt.button === 2) evt.stopImmediatePropagation(); + }, true); /* Track whichever non-PTM edge the cursor is currently over */ var hoveredEdge = null; @@ -478,8 +479,6 @@ HTMLWidgets.widget({ var edge = evt.target; // skip compound/ptm attachment edges if (edge.data("edge_type") === "ptm_attachment") return; - // skip right-click — handled by the contextmenu listener above - if (lastMouseButton === 2) return; openSafe(edge.data("evidenceLink")); if (window.Shiny) { Shiny.setInputValue(el.id + "_edge_clicked", { From cfbcce78db4740e9e9c6de638879862ece1b8680 Mon Sep 17 00:00:00 2001 From: tonywu1999 Date: Wed, 15 Apr 2026 13:13:37 -0400 Subject: [PATCH 3/7] properly delete edge --- inst/htmlwidgets/cytoscapeNetwork.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/inst/htmlwidgets/cytoscapeNetwork.js b/inst/htmlwidgets/cytoscapeNetwork.js index 51e1a8a..d7ec85c 100644 --- a/inst/htmlwidgets/cytoscapeNetwork.js +++ b/inst/htmlwidgets/cytoscapeNetwork.js @@ -474,11 +474,27 @@ HTMLWidgets.widget({ } }); - /* ── Evidence link on left-click ────────────────────────────── */ + /* ── Edge tap: Ctrl+Click → delete; plain click → evidence link ── */ cy.on("tap", "edge", function (evt) { var edge = evt.target; - // skip compound/ptm attachment edges + // skip ptm attachment edges if (edge.data("edge_type") === "ptm_attachment") return; + + // Ctrl+Click → delete edge + if (evt.originalEvent && evt.originalEvent.ctrlKey) { + var deleted = { + source: edge.data("source"), + target: edge.data("target"), + interaction: edge.data("interaction") + }; + edge.remove(); + if (window.Shiny) { + Shiny.setInputValue(el.id + "_edge_deleted", deleted, { priority: "event" }); + } + return; + } + + // Plain click → open evidence link openSafe(edge.data("evidenceLink")); if (window.Shiny) { Shiny.setInputValue(el.id + "_edge_clicked", { From d0befc727febb7b94a95dc49713b2f5dc3c056c4 Mon Sep 17 00:00:00 2001 From: tonywu1999 Date: Wed, 15 Apr 2026 13:16:49 -0400 Subject: [PATCH 4/7] add note on deleting edges --- inst/htmlwidgets/cytoscapeNetwork.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/inst/htmlwidgets/cytoscapeNetwork.js b/inst/htmlwidgets/cytoscapeNetwork.js index d7ec85c..2381f5b 100644 --- a/inst/htmlwidgets/cytoscapeNetwork.js +++ b/inst/htmlwidgets/cytoscapeNetwork.js @@ -243,7 +243,9 @@ HTMLWidgets.widget({ ' ' + (edgeItems ? '
Edge types
' + edgeItems : '') + '
' + - 'PTM info: Hover over edges to see overlapping PTM sites.
'; + 'PTM info: Hover over edges to see overlapping PTM sites.' + + '
' + + 'Delete edge: Right-click or Ctrl+Click an edge to remove it from the network.
'; } /* ── renderValue ──────────────────────────────────────────────────── */ From f78e8fb8cd01ed9b2cd17151fd7726c5c2c98874 Mon Sep 17 00:00:00 2001 From: tonywu1999 Date: Thu, 16 Apr 2026 10:01:28 -0400 Subject: [PATCH 5/7] feat delete refactored --- inst/htmlwidgets/cytoscapeNetwork.js | 67 ++++++++-------------------- 1 file changed, 18 insertions(+), 49 deletions(-) diff --git a/inst/htmlwidgets/cytoscapeNetwork.js b/inst/htmlwidgets/cytoscapeNetwork.js index 2381f5b..05ef65c 100644 --- a/inst/htmlwidgets/cytoscapeNetwork.js +++ b/inst/htmlwidgets/cytoscapeNetwork.js @@ -247,6 +247,18 @@ HTMLWidgets.widget({ '
' + 'Delete edge: Right-click or Ctrl+Click an edge to remove it from the network.
'; } + + // Helper to delete an edge and notify Shiny + function deleteEdge(edge) { + if (window.Shiny) { + Shiny.setInputValue(el.id + "_edge_deleted", { + source: edge.data("source"), + target: edge.data("target"), + interaction: edge.data("interaction") + }, { priority: "event" }); + } + edge.remove(); + } /* ── renderValue ──────────────────────────────────────────────────── */ return { @@ -438,61 +450,18 @@ HTMLWidgets.widget({ tooltip.style.display = "none"; }); - /* ── Right-click on edge → delete it ────────────────────────── */ - - /* Block right-click mousedown from reaching Cytoscape by intercepting - it in the capture phase (runs before any element-level listener). - This prevents Cytoscape from ever starting a tap cycle on right-click, - stopping the evidence link from opening. The contextmenu event is - fired by the OS independently and is unaffected by this. */ - cyContainer.addEventListener("mousedown", function (evt) { - if (evt.button === 2) evt.stopImmediatePropagation(); - }, true); - - /* Track whichever non-PTM edge the cursor is currently over */ - var hoveredEdge = null; - cy.on("mouseover", "edge", function (evt) { - var e = evt.target; - if (e.data("edge_type") !== "ptm_attachment") hoveredEdge = e; - }); - cy.on("mouseout", "edge", function () { - hoveredEdge = null; - }); - - /* contextmenu fires reliably on right-click before the browser - can show its native menu; preventDefault stops the native menu */ - cyContainer.addEventListener("contextmenu", function (evt) { - evt.preventDefault(); - if (!hoveredEdge || !hoveredEdge.inside()) return; - var deleted = { - source: hoveredEdge.data("source"), - target: hoveredEdge.data("target"), - interaction: hoveredEdge.data("interaction") - }; - hoveredEdge.remove(); - hoveredEdge = null; - if (window.Shiny) { - Shiny.setInputValue(el.id + "_edge_deleted", deleted, { priority: "event" }); - } - }); + // Suppress the native context menu + cyContainer.addEventListener("contextmenu", e => e.preventDefault()); /* ── Edge tap: Ctrl+Click → delete; plain click → evidence link ── */ - cy.on("tap", "edge", function (evt) { + cy.on("cxttap tap", "edge", function (evt) { var edge = evt.target; // skip ptm attachment edges if (edge.data("edge_type") === "ptm_attachment") return; - // Ctrl+Click → delete edge - if (evt.originalEvent && evt.originalEvent.ctrlKey) { - var deleted = { - source: edge.data("source"), - target: edge.data("target"), - interaction: edge.data("interaction") - }; - edge.remove(); - if (window.Shiny) { - Shiny.setInputValue(el.id + "_edge_deleted", deleted, { priority: "event" }); - } + // Ctrl+Click or Right Click → delete edge + if (evt.type === "cxttap" || (evt.originalEvent && evt.originalEvent.ctrlKey)) { + deleteEdge(edge); return; } From baae9d08a1d9aa6616fa7676e33736e2c85b9471 Mon Sep 17 00:00:00 2001 From: tonywu1999 Date: Thu, 16 Apr 2026 10:08:45 -0400 Subject: [PATCH 6/7] get rid of prevent default --- inst/htmlwidgets/cytoscapeNetwork.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/inst/htmlwidgets/cytoscapeNetwork.js b/inst/htmlwidgets/cytoscapeNetwork.js index 05ef65c..bf440e0 100644 --- a/inst/htmlwidgets/cytoscapeNetwork.js +++ b/inst/htmlwidgets/cytoscapeNetwork.js @@ -450,9 +450,6 @@ HTMLWidgets.widget({ tooltip.style.display = "none"; }); - // Suppress the native context menu - cyContainer.addEventListener("contextmenu", e => e.preventDefault()); - /* ── Edge tap: Ctrl+Click → delete; plain click → evidence link ── */ cy.on("cxttap tap", "edge", function (evt) { var edge = evt.target; From ca1f975ffe40bd70db02e0e7a02e188dcafaf916 Mon Sep 17 00:00:00 2001 From: tonywu1999 Date: Thu, 16 Apr 2026 10:26:36 -0400 Subject: [PATCH 7/7] coderabbit comment --- inst/htmlwidgets/cytoscapeNetwork.js | 1 + 1 file changed, 1 insertion(+) diff --git a/inst/htmlwidgets/cytoscapeNetwork.js b/inst/htmlwidgets/cytoscapeNetwork.js index bf440e0..5dfc3ac 100644 --- a/inst/htmlwidgets/cytoscapeNetwork.js +++ b/inst/htmlwidgets/cytoscapeNetwork.js @@ -459,6 +459,7 @@ HTMLWidgets.widget({ // Ctrl+Click or Right Click → delete edge if (evt.type === "cxttap" || (evt.originalEvent && evt.originalEvent.ctrlKey)) { deleteEdge(edge); + buildLegend(cy, legendPanel); return; }