utilize jQuery contextMenu with D3.js forced graph

37
January 12, 2022, at 5:50 PM

I am trying to combine jQuery contextMenu (2.x) with a simple D3.js forced graph. The contextmenu should appear if a node is right-clicked. So far I created the simple graph and the contextmenu function to trigger the event. Unfortunately it does not work.

Obvously I understand the documentation above wrong. Regarding the documentation it should be possible to utilize jQuery contextMenu on DOM elements. I assume the problem might be line 93 $(d3.selectAll(".node")).contextMenu({ where I try to define the trigger. I tested several code snippets to point to each node, like "this" or selectAll("circles") unfortunately none of my attempts worked out.

<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>jQuery Context Menu</title>
    <!-- call external d3.js framework -->
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <!-- jQuery contextmenu Import -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.1/jquery.contextMenu.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.1/jquery.contextMenu.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.1/jquery.ui.position.js"></script>
</head>
<style>
    body {
        overflow: hidden;
        background: #e6e7ee;
        margin: 0;
    }
    circle {
        fill: whitesmoke;
        stroke: white;
        stroke-width: 2px
    }
    line {
        stroke: black;
    }
    line:hover {
        stroke: yellow;
    }
</style>
<body>
    <span class="context-menu"></span>
    <script>
        var svg = d3.select("body").append("svg")
            .attr("width", window.innerWidth)
            .attr("height", window.innerHeight)
            .call(d3.zoom().on("zoom", function (event) {
                svg.attr("transform", event.transform)
            }))
            .append("g")
        var nodes = [
            { "id": 1 }, 
            { "id": 2 }, 
            { "id": 3 }, 
        ]
        var links = [
            { "source": 1, "target": 2 },
            { "source": 2, "target": 3 },
            { "source": 3, "target": 1 }
        ]
        var simulation = d3.forceSimulation()
            .force("link", d3.forceLink().id(function (d) { return d.id; }).distance(100))
            .force('charge', d3.forceManyBody().strength(-400))
            .force('center', d3.forceCenter(window.innerWidth / 2, window.innerHeight / 2))
        var linksContainer = svg.append("g").attr("class", "linksContainer")
        var nodesContainer = svg.append("g").attr("class", "nodesContainer")
        initialize()
        function initialize() {
            link = linksContainer.selectAll("line")
                .data(links)
                .join("line")
                .attr("class", "link")
            node = nodesContainer.selectAll(".node")
                .data(nodes)
                .join("g")
                .attr("class", "node")
                .call(d3.drag()
                    .on("start", dragStarted)
                    .on("drag", dragged)
                    .on("end", dragEnded)
                )
                .on("contextmenu", function(event, d) {
                    event.preventDefault()
                    console.log("contextmenu clicked")
                    $(d3.selectAll(".node")).contextMenu({
                        selector: '.context-menu',
                        callback: function(key, options) {
                            var m = "clicked: " + key;
                            console.log(m);
                        },
                        items: {
                            "edit": {name: "Edit", icon: "edit"},
                            "delete": {name: "Delete", icon: "delete"}
                        }
                    })
                    $('.context-menu').on('click', function(e) {
                        console.log('clicked', this)
                    })
                })
            node.selectAll("circle")
                .data(d => [d])
                .join("circle")
                .attr("r", 20)
            node.selectAll("text")
                .data(d => [d])
                .join("text")
                .style("class", "icon")
                .attr("font-family", "FontAwesome")
                .attr("dominant-baseline", "central")
                .attr("text-anchor", "middle")
                .attr("font-size", 10)
                .attr("fill", "black")
                .attr("pointer-events", "none")
                .text(function (d) {
                    return d.id
                })
            simulation
                .nodes(nodes)
                .on("tick", ticked);
            simulation
                .force("link")
                .links(links)
        }
  
        function ticked() {
            link
                .attr("x1", function (d) { return d.source.x; })
                .attr("y1", function (d) { return d.source.y; })
                .attr("x2", function (d) { return d.target.x; })
                .attr("y2", function (d) { return d.target.y; });
            
            node
                .attr("transform", function (d) { return "translate(" + d.x + ", " + d.y + ")"; });
        }
        function dragStarted(event, d) {
            if (!event.active) simulation.alphaTarget(0.3).restart();
            d.fx = d.x;
            d.fy = d.y;
        }
        function dragged (event, d) {
            d.fx = event.x;
            d.fy = event.y;
        }
        function dragEnded(event, d) {
            if (!event.active) simulation.alphaTarget(0);
            d.fx = undefined;
            d.fy = undefined;
        }
    </script>
</body>
</html>

READ ALSO
AssertionError: Must have equivalent tags in image_2, label_2 and velodyne dirs, check those files what is the meaning of it and how to solve?

AssertionError: Must have equivalent tags in image_2, label_2 and velodyne dirs, check those files what is the meaning of it and how to solve?

I was following the official Voxelnet repo on [Voxelnet][1] [1]: https://githubcom/gkadusumilli/Voxelnet/ As per the instructions, I preprocessed the data

62
babel command converts when run in terminal but running the script ends in error

babel command converts when run in terminal but running the script ends in error

I've been trying to get babel core and cli to convert modern JavaScript from indexjs into bundle

27
codeigniter 4 / how to select emoji from mysql db and display in view

codeigniter 4 / how to select emoji from mysql db and display in view

I have a table called mh_countryHere is one row from phpmyadmin

54
How to prevent visitors or bots submitting a certain message that contain a certain string?

How to prevent visitors or bots submitting a certain message that contain a certain string?

I have a message box at the bottom of my siteI don't know how these messages manage to slip through my validations

23