1

I have an element that need to drag in window, code with function work well, but when i use classes i cant understand why it doesnt.

Can you help me with manipulate_this_element() method in codepen below?

https://codepen.io/igor-sushko/pen/oNNBvQX?editors=1011

class View {
  create_staff() {
    console.log("staff work!");
    this.listener();
  };

  listener() {
    console.log("listener work!");
    let a = document.getElementById("AAA");
    a.addEventListener("mousedown", this.mouse_down)
    // .onmousedown = this.mouse_down();
  };

  mouse_down(e) {
    let that = this;
    console.log("mouse_down work!");
    e.preventDefault();
    document.addEventListener("mousemove",  that.manipulate_this_element)
    // document.onmousemove = this.manipulate_this_element();
  };

  manipulate_this_element() {
    console.log("manipulate_this_element work!");
  };
}

let a = new View();
a.create_staff();

I want to see "manipulate_this_element work!" in console when i moving mouse

2 Answers2

0

It is too late for :

    mouse_down(e) {

      let that = this;
      ...

    }

In mouse event callback 'this' is undefined.

Most simply but not the best way is to use global scope access.


listener() {
    var root = this;
    console.log("listener work!");
    let a = document.getElementById("AAA");
    a.addEventListener("mousedown", this.mouse_down)

    // Global access 
    document.addEventListener("mousemove",  a.manipulate_this_element, false);

   // simple this
    document.addEventListener("mousemove",  root.manipulate_this_element, false);

  };


 mouse_down(e) {
    let that = this;
    console.log("mouse_down work!");
    e.preventDefault();
    // You can't attach event infinity , just one time.
  };
Nikola Lukic
  • 4,001
  • 6
  • 44
  • 75
0

The problem is that with a.addEventListener("mousedown", this.mouse_down) the mouse_down would not be called on the view object when the event occurs, so the this within that mouse_down does not refer to the view instance anymore.

To solve the problem you have various ways to bind the this to the function.

Given that you already use class then you are probably already able to use this syntax:

 mouse_down = (e) => {
 }

Using the arrow function that way will bind the this of that arrow function to the instance of View.

The big advantage of this method is, that this also allows you to remove the event listener easily using a.removeEventListener("mousedown", this.mouse_down)

Here the full code:

class View {
  create_staff() {
    console.log("staff work!");
    this.listener();
  }

  listener() {
    console.log("listener work!");
    let a = document.getElementById("AAA");
    a.addEventListener("mousedown", this.mouse_down)
    // .onmousedown = this.mouse_down();
  }

  mouse_down = (e) => {
    let that = this;
    console.log("mouse_down work!");
    e.preventDefault();
    document.addEventListener("mousemove",  that.manipulate_this_element)
    // document.onmousemove = this.manipulate_this_element();
  }

  manipulate_this_element = () => {
    console.log("manipulate_this_element work!");
  }
}

let a = new View();
a.create_staff();
t.niese
  • 39,256
  • 9
  • 74
  • 101