The event listener cannot be unbound

As a newcomer to javascript, I'm facing an issue that I couldn't find answers to despite searching extensively. Here is my problem: I have a module or class where I am attempting to create a draggable component on the screen. The objective is to listen for mousemove events when the user first clicks on it and then remove these event listeners once the user releases the mouse.

The code appears simple and straightforward, and it works fine when not inside an IIFE (Immediately-Invoked Function Expression). However, the removeEventListener doesn't seem to work as expected. I suspect it has something to do with closures, scope, or some other concept that I am missing. Your help will be greatly appreciated. Below is the code:

MyClass.js

 var myNamespace = myNamespace || {};
 (function(myNamespace){

     var onMouseDragDown = function(e){
          window.addEventListener("mousemove", onMouseDragMove,true);
          window.addEventListener("mouseup", onMouseDragUp,false);
       };

      var onMouseDragUp = function(e){
         // This code executes, but the events CONTINUE to be triggered after removing the event listener

        //The following lines do not seem to have any effect whatsoever even though they are executed when the user releases the mouse button
      window.removeEventListener("mousemove", onMouseDragMove, true);
      window.removeEventListener("mouseup", onMouseDragUp,false);
  };

  var onMouseDragMove = function(e){
      console.log('moving');
   };

   myNamespace.MyClass = function(param){
      this._param = param;
      this._div = document.createElement('div');  
      this._div = ....

      this._div.addEventListener('mousedown', onMouseDragDown.bind(this), false);
   }

   myNameSpace.MyClass.prototype.getDiv = function (){
      return this._div;
   }
)(myNameSpace);

Index.html

...

function onCreateNewDocumentClicked(event){
    var myObject = new myNamepace.MyClass(someParams);
    document.body.appendChild(mdi.getDiv());
}

Answer №1

If you want to remove an event listener, make sure to provide the exact function that was used when adding it originally.
The issue arises from the fact that bind() generates a new function each time it is called, resulting in :

someFunc.bind(someObj) !== someFunc.bind(someObj)

In order to effectively remove an event listener, it is necessary to retain the initial function provided during addition.

Therefore, store the listener upon addition for future removal purposes :

var someListener = someFunc.bind(someObj);
element.addEventListener("--", someListener ) ;

// later on :
element.removeEventListener('--', someListener);

I have created a brief demonstration here; clicking the first button will trigger an alert saying 'hello'.
By attempting to remove the listener with a fresh bind call, it remains unchanged.
However, removing the stored function accomplishes the task successfully.

http://jsbin.com/EjevIQA/2/edit

Edit : It is unnecessary to add or remove a listener on each draggable div individually. Instead, you can listen for click events within the window and utilize the 'target' property to determine which specific div was clicked.
You may need to halt propagation or prevent default actions if a handled div gets clicked, depending on your requirements.

The event handler would appear as follows:

 function handleMouseDown(e) {
     // Check which mouse button was clicked (0=left, 2=right)
     var button = e.button;
     // Get the target element
     var target = e.target ;
     // Verify if the target is a draggable object
     ...
     ... otherwise return.
     // Perform necessary actions to initiate dragging.
     ...
     // To prevent the click from triggering default behavior or bubbling:
     e.stopPropagation();
     e.preventDefault();
 } 

Add this event listener once on the window or document object:

document.addEventListener("mousedown", handleMouseDown)

Check out my simple demo where clicking on a div displays its identification:
http://jsbin.com/ilavikI/2/edit

Answer №2

Is it possible that when you use

 .bind(this) 

within

  this._div.addEventListener('mousedown', onMouseDragDown.bind(this), false);

it doesn't actually return the exact function you intend to remove?

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

Authenticate with Google using the Javascript API without causing a pop-up to appear

Here is the code I'm using to allow users to log in with their Google account via the Javascript API. HTML <a id="gp_login" href="javascript:void(0)" onclick="javascript:googleAuth()">Login using Google</a> Javascript function gPOnLoad ...

AWS Amplify-hosted Nuxt applications are resilient to errors during the build process

My website is built using Nuxt js and hosted on AWS Amplify. I've encountered a major issue where the website still gets generated successfully even when there's a failure in the nuxt generate command (like a JavaScript error in my code). Below i ...

Upcoming verification with JSON Web Token

I am looking to incorporate JWT auth into my Next app. Currently, I have mapped out the flow as such: User enters email and password to log in Server responds with status 200 and a jwt access token in httpOnly cookies My main dilemma lies in deciding on ...

navigation menu 'selective emphasis' feature

I have created a JQuery script that will highlight the 'About', 'My Projects', or 'Contact Me' text on the navigation bar when the corresponding section of the page is in view. To achieve this, I am using a scroll() event list ...

Discovering nested routes in Ember.js through search functionality

I am currently working on implementing a search functionality within a nested route that shares a model. Below is an example of my code: The "Products" and "Search" functionalities return a JSON response. Router Market.Router.map -> @resource &a ...

What Causes the Undefined Value of "this" in Vue 3 Functions?

Here is a basic example of a component in Vue 3: <script> import { defineComponent } from 'vue' export default defineComponent({ name: 'Test', setup(){ return{ one, two } } }) function one(){ console. ...

A comprehensive guide on retrieving data from API across several pages

Struggling with pulling data from an API using React and facing the challenge of retrieving more than one page of data. "info": { "count": 493, "pages": 25, "next": "https://rickandmortyapi.com/api/character/?pa ...

The PHP file on the server is missing the mandatory "event" parameter for the EventSource

Explaining this issue was a bit of a challenge. I've set up a Javascript EventSource object with some customized event handlers like so: var source = new EventSource('updates.php'); source.addEventListener('add', addHandler, fals ...

Possible solution to address the issue: xhr.js:178 encountered a 403 error when attempting to access https://www.googleapis.com/youtube/v3/search?q=Tesla

Encountering this console error: xhr.js:178 GET https://www.googleapis.com/youtube/v3/search?q=river 403 A specific component was designed to utilize the API at a later point: const KEY = "mykeyas23d2sdffa12sasd12dfasdfasdfasdf"; export default ...

How do I select the first element with class "cell" in D3, similar to jQuery's $(".cell:first")?

I have attempted this: d3.select(".cell:first") d3.selectAll(".cell").filter(":first") d3.selectAll(".cell").select(":first") but unfortunately, none of these methods are effective. ...

Comment sections that refresh automatically after being posted

I am determined to provide a clear explanation. Despite having some code, I am uncertain about how to make it clone comments and add new ones with user inputted text. Below is the snippet of code I am struggling with: <!DOCTYPE html> <!-- this i ...

The Input element's onChange event is not functioning as expected

I am experiencing some issues with my code. I am trying to dynamically change the background color based on user input, but I am struggling to make it work. It seems like a simple task, so I must be missing something. Below is my HTML markup and jQuery: ...

Utilizing JavaScript or jQuery in MVC4 to showcase information for the primary record

I'm currently working on constructing a page that displays a list of users. My aim is to have a "Details" link in each row that, when clicked, will render a partial view on the same page without having to reload it using either javascript or jQuery. D ...

What is the process for creating a React Component with partially applied props?

I am struggling with a function that takes a React component and partially applies its props. This approach is commonly used to provide components with themes from consumers. Essentially, it transforms <FancyComponent theme="black" text="blah"/> int ...

Utilize Jquery to easily interact with RadComboBoxes

Is there a way to capture all RadComboBoxes change events in JQUERY for ASP.NET? $("input[type='text']").Change(function() { alert('changed'); }); In this example, I am specifying the input type as "text" because RadComboBoxes hav ...

Is it possible for me to design a unique path without relying on redux?

I am working on a Loginscreen.js component import React, { Component } from 'react'; import Login from './Login'; class Loginscreen extends Component { constructor(props){ super(props); this.state={ username:'&apo ...

Caution when using a React form: Value of `true` has been detected for a non-boolean attribute `validate`

I am trying to address a warning message that I have received index.js:1 Warning: Received true for a non-boolean attribute validate. If you want to write it to the DOM, pass a string instead: validate="true" or validate={value.toString()}. I ...

What is the most effective method for transmitting a zip file as a response in Azure functions with node.js?

With the Azure function app, my goal is to download images from various URLs and store them in a specific folder. I then need to zip these images and send the zip file back as a response. I have successfully achieved this by following these steps: Send ...

Unable to click on the icon when modifying Mui Text Field

Utilizing the MUI Text Field component, I have successfully added a select prop to transform it into a dropdown list with values and an icon. However, I encountered an issue while attempting to change the default dropdown icon to a custom one from Figma. D ...

"Encountered an error: File or directory not found while attempting to export a function

src/test.js module.exports.test = function() { const { readFileSync } = require('fs'); console.log(readFileSync('test.txt', 'utf8').toString()) } index.js const { test } = require('./src/test.js'); test(); ...