What was preventing me from eliminating the Listeners?

Hello, I have developed a Whiteboard application in vue where users can draw. The drawing is done using SVG paths. Currently, the EventHandlers are being used to enable drawing when the mouse is clicked. However, I want to remove these handlers once the mouse is released. The desired functionality is that clicking on the Whiteboard enables drawing and not clicking stops the drawing process. Currently, it creates an endless line with just one click.

I hope this explanation makes sense :)

Thank you


main() {
    let whiteboard = document.getElementById("whiteboard");
    const color = "black";

    let test2 = event => {
        this.createSvgElement(whiteboard, color);
        this.setup(event);
    }

    whiteboard.addEventListener("mousedown", test2);

},
createSvgElement(w, c){
    this.whiteboard.removeEventListener("mousedown", this);
    this.whiteboard = w;
    this.segments = [];
    this.points = [];

    this.path = document.createElementNS("http://www.w3.org/2000/svg", "path");

    this.path.setAttributeNS(null, "stroke", c);
    this.path.setAttributeNS(null, "stroke-width", "2");
    this.path.setAttributeNS(null, "fill", "transparent");

},
setup(event){
    this.whiteboard.addEventListener("mousemove", e => {
        const [x, y] = this.pos(e);
        this.points.push({ x, y });
        const test = this.path.getAttributeNS(null, "d");
        this.path.setAttributeNS(null, "d", test + ` L${x},${y}`);
    });

    this.whiteboard.addEventListener("mouseleave", e =>{
        this.whiteboard.removeEventListener("mousemove", this);
        this.whiteboard.removeEventListener("mouseup", this);
        this.whiteboard.removeEventListener("mouseleave", this);
    });

    this.whiteboard.addEventListener("mouseup", e =>{
        this.whiteboard.removeEventListener("mousemove", this);
        this.whiteboard.removeEventListener("mouseup", this);
        this.whiteboard.removeEventListener("mouseleave", this);
    });

}, 
pos(e){
    const rect = this.whiteboard.getBoundingClientRect();
    return [e.clientX - rect.left, e.clientY - rect.top];
}, 

Answer №1

When dealing with the mousedown event on a specific element, there is no guarantee that you will receive the corresponding mouseup event on the same element. This is because the mouse button might be released while the pointer hovers over another element or even outside of the window entirely.

The only API that allows for this behavior is setCapture, but it is not considered standard practice.

A recommended approach to handling mouse events like this is by attaching the mousemove and mouseup events to the document element when the mouse is pressed down on the target element. Because mouse events bubble up, the mouseup event will still trigger on the document even if the pointer is outside of the browser window.

Summarized:

const onMouseDown = e => {
  document.addEventListener('mousemove', onMouseMove)
  document.addEventListener('mouseup', onMouseUp)
}

const onMouseUp = e => {
  document.removeEventListener('mousemove', onMouseMove)
  document.removeEventListener('mouseup', onMouseUp)
}

const onMouseMove = e => {
  // Handle move event
}

this.whiteboard.addEventListener('mousedown', onMouseDown)

You seem to have an error in the way you are calling removeEventListener:

this.whiteboard.removeEventListener("mousemove", this)
                                                 ^^^^

The second argument should be the event listener function that you want to remove; this refers to the component object instance.

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

Incorporate a single file into the source code using React just once

I am looking to add a JavaScript script to the body when a React Component renders, but I only want it to happen once. Here is the current code I have: const MyComponent: React.FC = () => { const script = document.createElement('script'); ...

Basic setup of an embedded database in MongoDB

I am currently facing a dilemma as I try to establish the database structure for my Mongodb application using Mongoose/Node.js. I have two main entities, namely Users and Books, and due to the lack of joins in MongoDB, I need to decide on an embedded syste ...

Error: Undefined state in a React class component has not been defined

I seem to be facing an issue with my code and I could use some assistance! When running npm install, I encounter an error if I use it with a file generated from create-react-app. It works perfectly fine in that scenario. However, I am unsure about the miss ...

Variety of properties determined by a "type" prop, expanding variations based on a value from the interface

I am trying to enhance a type based on a value from the main interface. If the type == multiline, it will have a specific interface, and if the type == icon, it will have a different type. import React, { memo, useCallback, ReactNode } from 'react&apo ...

Become a Vue Js pro by simulating the $http request with the help of sinon modules

In my VueJs project, I have a list of API request methods stored in the apiList.ts file. I am currently attempting to add unit test cases for the getUsers, addUser, and updateUser methods, but I am facing difficulties in mocking the HTTP methods (get/post/ ...

Modifying the font style within an ePub document can affect the page count displayed in a UIWebView

Currently in the development phase of my epubReader app. Utilizing CSS to customize the font style within UIWebView, however encountering a challenge with the fixed font size causing fluctuations in the number of pages when changing the font style. Seeki ...

Generating a dynamic sitemap with Next.js

I have been working on a project where I need to create a sitemap, and I am currently using next-sitemap for generation. However, I've encountered an issue with this method, as well as other solutions I've come across, because the sitemap is only ...

How can I retrieve the line number of a code during runtime in JavaScript?

Is there a way to add a console.log statement that would indicate the line number it is on in JavaScript? For example: console.log ('Line:', [code to get the line]). The output in the console would be Line: [line number], helping me identify wher ...

Vue Router with a Dynamic Twist

In my exploration, I am delving into whether utilizing a vue router would be the most effective method for the specific situation outlined below: The challenge I am facing involves a page that contains an unknown number of div elements, each with unique c ...

Utilizing ReactJS to fetch data from Material-UI's <TableRow/> component upon selection - a comprehensive guide

I've integrated Material-UI's <Table/> (http://www.material-ui.com/#/components/table) component with <TableRow/> containing checkboxes in a ReactJS project. While I can successfully select rows by checking the boxes, I am struggling ...

When an event is triggered in Angular Component, the object is not properly defined in the handler causing errors

While experimenting with createjs and angular, I encountered an issue when trying to update my stage after an image loads. It seems like there might be a problem related to Angular in this situation. Upon completion of the load event on the Bitmap object a ...

How can I eliminate the Origin header that jQuery adds to my Ajax requests?

As an example, consider the following Ajax request: $.post( 'http://example.com/script.pl', formdata, function ( data ) { // ... }); However, despite not being a cross-domain request, this request also contains an "Origin" header. What is ...

JavaScript has the ability to sort tables using tags

I am currently working on a Vue project where I am attempting to filter my table based on the tags that users click. I have created a method that outputs all the rows containing the tag clicked by the user. <el-table-column prop="Keyword" labe ...

Revamping tree organization with Accelerando

I recently made the switch from XML to JSON data structures in a small web project. As I was looking for ways to transform the data, similar to how XSLT is used with XML, I came across an interesting library called . However, I encountered a challenge whe ...

Is there a way for TypeScript to recognize that the potential data types in a union type align with the valid prototypes for a function? Any solutions available?

There seems to be an issue with this (playground link) code snippet: type ReplaceAll2ndArgType = string | ((substring: string, ...args: unknown[]) => string) export async function renderHTMLTemplate( args: Record<string, ReplaceAll2ndArgType> ...

Programmatically setting a value in MUI Tree Select

Hey there, I've been using this package and everything is working smoothly. However, I'm having trouble programmatically selecting a value that the user has already chosen using the same component. Check it out on CodeSandbox The developer reco ...

In Pure JavaScript, an HTML element is added every time the click event is triggered

Hey everyone, I'm facing a small issue and I could use some help fixing it. I need to implement an onclick event that adds HTML code every time it's clicked. I am hesitant to use innerHTML due to its potential risks. Here is the code snippet: bu ...

Limiting the textfield to 100 characters while allowing special characters in React.js

I am working with a text field that can accept the following types of values: >35% <=60% =55% =100% My goal is to set the maximum limit of the numbers to 100. How can this be achieved? Below is the code for the textfield in question: <TextField ...

Unable to retrieve information from compact JSON files

It's been 2 hours and I still can't figure this out I need help with reading my Json Data in my JavaScript File, saving it to a variable, and then printing it out. I've tried multiple solutions but nothing seems to work (I'm new to ...

Is it secure to transmit Tenant ID's as GET parameters to the API in a Multi-Tenant database environment?

When working with a Multi-Tenant database, is it secure to pass Tenant ID's as query string parameters to the API while using popular JavaScript-based UI platforms like Angular or Vue and ensuring both the site and the API are HTTPS? For example, let ...