The Sigma.js nodes are causing the click event to unexpectedly trigger during dragging

Within my sigma.js web application, I am dealing with two main types of events. The first type involves handling click events to open a node's URL, while the second type involves managing drag events to allow nodes to be moved around in the space.

  const renderer = new Sigma(graph, container);

  renderer.on("clickNode", ({ node }) => {
    if (!graph.getNodeAttribute(node, "hidden")) {
      window.open(graph.getNodeAttribute(node, "pageURL"), "_blank");
    }
  });

The code snippet above is responsible for triggering the click event. When we click on nodes, it opens the corresponding page URL:

  let draggedNode: string | null = null;
  let isDragging = false;

  /* On mouse down on a node
    - we enable the drag mode
    - save the dragged node in the state
    - highlight the node
    - disable the camera to prevent updates */

  renderer.on("downNode", (e) => {
    isDragging = true;
    draggedNode = e.node;
    graph.setNodeAttribute(draggedNode, "highlighted", true);
  });

  // On mouse move, change the position of the draggedNode if drag mode is enabled
  renderer.getMouseCaptor().on("mousemovebody", (e) => {
    if (!isDragging || !draggedNode) return;

    // Get new position of node
    const pos = renderer.viewportToGraph(e);

    graph.setNodeAttribute(draggedNode, "x", pos.x);
    graph.setNodeAttribute(draggedNode, "y", pos.y);

    // Prevent sigma from moving the camera:
    e.preventSigmaDefault();
    e.original.preventDefault();
    e.original.stopPropagation();
  });

  // Disable autoscale at the initial interaction
  renderer.getMouseCaptor().on("mousedown", () => {
    if (!renderer.getCustomBBox()) renderer.setCustomBBox(renderer.getBBox());
  });

  // Reset autoscaling and dragging mode on mouse up
  renderer.getMouseCaptor().on("mouseup", () => {
    if (draggedNode) {
      graph.removeNodeAttribute(draggedNode, "highlighted");
    }
    isDragging = false;
    draggedNode = null;
  });
}

A specific issue arises when dragging nodes and releasing the mouse button triggers the click event, causing the pageURL to open unintentionally. This behavior should only occur when clicking on a node, not during dragging.

Is there a way to prevent the click event from being triggered while dragging? Despite attempting methods from Stack Overflow, none have been successful. You can experiment with the problem yourself by visiting this CodeSandbox link.

Answer №1

Credit for solving this issue goes to my mentor, Sarah Johnson. Many thanks for the assistance :)

  const threshold = 15;
  let xStart;
  let yStart;
  let canClick = true;

  // Prevent autoscaling on initial mouse click
  renderer.getMouseTracker().on("mousedown", (event) => {
    xStart = event.original.pageX;
    yStart = event.original.pageY;
    if (!renderer.getCustomBounds()) renderer.setCustomBounds(renderer.getBounds());
  });

  // Reset autoscale and dragging on mouse release
  renderer.getMouseTracker().on("mouseup", (event) => {
    if (draggedElement) {
      graph.removeElementAttribute(draggedElement, "highlighted");
      const diffX = Math.abs(event.original.pageX - xStart);
      const diffY = Math.abs(event.original.pageY - yStart);
      canClick = diffX < threshold && diffY < threshold;
      isDragging = false;
      draggedElement = null;
    }
  });

  renderer.on("clickElement", ({ element }) => {
    if (!graph.getElementAttribute(element, "hidden") && canClick) {
      window.open(graph.getElementAttribute(element, "linkURL"), "_blank");
    }
  });

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the method to extract a value from the $emit payload using Vue.js?

I have a situation where I am sending an event with different values from my ConversationList component (child) to the ConversationModel component (parent). Conversation List getConversation(conversation_id, receiver_id, username, avatar){ this.$emit(& ...

Adding a Timepicker to a Datepicker on a jsp webpage with javascript

I am working on a JSP page that includes a date picker. I want to enhance this datepicker by adding a start time and end time within the calendar itself. How can I achieve this? Additionally, I need to implement validation ensuring that the start time is a ...

Attempting to dispatch data from Vue.js event bus

I am attempting to increase the count of quotes by one and also add the text from a textarea to an array. While the text is successfully added to the array, the number of quotes always remains zero. I have tried combining the two actions in one method as w ...

The expect.objectContaining() function in Jest does not work properly when used in expect.toHaveBeenCalled()

Currently, I am working on writing a test to validate code that interacts with AWS DynamoDB using aws-sdk. Despite following a similar scenario outlined in the official documentation (https://jestjs.io/docs/en/expect#expectobjectcontainingobject), my asser ...

Help setting up Angular ng-class is needed

Hey there, I'm currently attempting to change the background color of my CSS based on the value of ng-class (true or false). Can someone help me out with this? <div id="home"> Summoner <div id="in ...

Are there alternative methods for handling routes in React, other than using the react-router-dom@latest library?

Currently, I am focused on a frontend project. One of the tasks at hand is to configure the network of routes. During my research, I came across react-router-dom@latest as a potential solution. However, I am curious to explore alternative options availa ...

Is there a way to verify duplicate email addresses without the need to click any button?

As I work on developing a web application, I am faced with the challenge of checking for duplicate email addresses in real-time without the need to press a button. This check must be done by comparing the data with information stored in the database. Since ...

Delay Export of React Component Until After Request in Shopify App Development

Being a newbie in Shopify App Development, React, and Next.js, I may have a silly question. Currently, I am making a request to a website and using the response in the React component that I want to export/render. To avoid it being undefined, I need to wai ...

How to position items at specific coordinates in a dropdown using JavaScript

I have five images in my code and I would like to arrange them in a circular pattern when they are dropped into the designated area. For example, instead of lining up the five images in a straight line, I want them to form a circle shape once dropped. Ho ...

howler.js resumes playing sprite sound after being paused

I have been working on setting up an audio sprite using Howler.js. The basic functionality of the sprite is working well, but I am facing an issue when trying to resume playback after pausing a sprite. When I call play(), it does not work as expected. sou ...

Access real-time information via JSON

I am facing a logical thinking challenge. Successfully retrieving data from a PHP file via JSON, but now encountering a slight issue. My goal is to retrieve various headlines - main and sub headlines. Each main headline may contain an unknown number of su ...

Verifying the accessibility of a website using JQuery/Javascript

I am attempting to use JavaScript to ping a website and display the result. Unfortunately, I have not had any success with this JSFiddle: https://jsfiddle.net/yyjowtru/ Although I believe I am close to achieving the desired outcome, changing the URL in t ...

Using Selenium Webdriver with C# to dynamically expand a RadMenu Webelement in Javascript

I am currently working with Selenium WebDriver in C# and facing an issue with a RadMenu. My goal is to hover over the menu so that it expands a sub menu, where I can find a specific webelement to click. I have tried using JavaScript for this purpose, but u ...

Why does Vue continuously insert undefined values when adding non-consecutive indexes to an array?

In my application, users can select values from a dropdown list and add them to an array by clicking the "add" button. The goal is to use the selected value's id as the index in the array. For example: List of Values 1 - Apple 3 - Bananas 8 - P ...

Optimal approach for integrating an ionic mobile app with Django to streamline form processing

Currently in the process of developing a mobile application with ionic technology. In the case of a traditional django website, we typically create context within the view and pass it to the template, where the HTML is displayed using various methods such ...

Displaying data from an array using jQuery or JavaScript loop

I have a scenario where I have multiple links on a webpage that have been converted into an array using jQuery. The idea is that when a user clicks on a "load more" button, I want to create a <ul> element with 4 images inside it (or fewer if there ar ...

Display the designated element upon clicking the designated link exclusively

I'm working with this specific HTML setup: <a href="#" class="dp">Click me</a> <div class="dp_div" style="display: none;"> this is the content within the div </div> My goal is to display the hidden div with a class of "dp_ ...

Rails - removing list item upon deletion of parent object

Currently working on a project app as part of a full stack developer bootcamp program. One of the features I'm implementing is a destroy method to remove an item from a list. Using AJAX requests, the goal is to dynamically remove the li element repres ...

Trouble initiating Jquery on a dynamically generated table

I am currently working on a project in ASP.Net where I need to dynamically build an HTML Table. I have implemented the ability for users to resequence rows in the table, but I'm facing issues with the delegate events I've written. Sometimes they ...

Can you explain the distinction between using call and apply?

Can you explain the distinction between utilizing Function.prototype.apply() and Function.prototype.call() to execute a function? const func = function() { alert("Hello world!"); }; func.apply() compared to func.call() Do performance dispar ...