1

I've got three interconnected methods inside an object:

    dragStartHandler: function(e) {
        console.log(e.type, 'dragstart', e.pageX, e.pageY);
        document.addEventListener('mousemove', this.dragMoveHandler, false);
        document.addEventListener('mouseup', this.dragEndHandler.bind(this), false);
    },

    dragMoveHandler: function(e) {
        console.log(e.type, 'dragmove', e.pageX, e.pageY);
        this.updateRotation();
    },

    dragEndHandler: function(e) {
        console.log(e.type, 'dragend', e.pageX, e.pageY);
        document.removeEventListener('mousemove', this.dragMoveHandler, false);
    },

They handle rotation based on mouse pointer position. I can't figure out what to do to have access to original this inside dragMoveHandler and be able to remove the element listener at the same time. I tried using .bind(this) but it returns anonymous function which I can't remove inside dragEndHandler.

Is there a technique I'm not aware of?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • Create an event tracker, and add the reference to the binded function to the tracker. – Teemu Jan 15 '15 at 16:18
  • Could you elaborate further? – Richard the Lionheart Jan 15 '15 at 19:10
  • Create an object which has a method for attaching events. Call this method instead of direct `addEventListener`. Then in the method you can push an element, event etc. to a tracker, and use also `bind` in a way you can remove an event later. [Here's an example](http://jsfiddle.net/pnb46b4m/) how you can create such an object. (There's only a property definition at the fiddle, the code is not working as it is, it will need some more context.) – Teemu Jan 15 '15 at 19:24
  • This is a great aproach - easy to understand, controll and reuse. Post it as an answer so I can accept this and let others learn. – Richard the Lionheart Jan 19 '15 at 11:40
  • Well, the fiddle snippet is just a demo, it's not deeply tested, and it might have some flaws I haven't noticed (yet). It works well in simple add/remove cases though. If you'll play with it, you'll soon find out, that you can easily extend the prototype with methods like `triggerEvent`, `removeByTypes`, `removeByElements`, `removeAll` etc. [Here's](http://jsfiddle.net/16uvpxhb/) a live demo with a small use-case. – Teemu Jan 19 '15 at 19:08

1 Answers1

0

In the surrounding class you have to remember your class pointer, since this in javascript always points to the current execution/event context.

First of all I would suggest to rewrite your class definition to not use object-literal-syntax if possible.

Because then you could take advantage of a common pattern where you "remember" the original this reference in a variable (named self in this example):

var MyClass = function(){
  var self = this; // this line is important, since `this` can change you have to save it
  var dragStartHandler = function(e) {
        console.log(e.type, 'dragstart', e.pageX, e.pageY);
        document.addEventListener('mousemove', self.dragMoveHandler, false);
        document.addEventListener('mouseup', self.dragEndHandler.bind(self), false);
    }
  var dragMoveHandler = function(e) {
        console.log(e.type, 'dragmove', e.pageX, e.pageY);
        self.updateRotation();
    }

  var dragEndHandler = function(e) {
        console.log(e.type, 'dragend', e.pageX, e.pageY);
        document.removeEventListener('mousemove', self.dragMoveHandler, false);
    }
}
ovm
  • 2,452
  • 3
  • 28
  • 51
  • If OP has built the object using an object literal? – Teemu Jan 15 '15 at 16:22
  • @Teemu you are right, I added some notes concerning this. – ovm Jan 15 '15 at 16:30
  • @ovm I'm using Polymer, it's all inside a web component so I'd rather stick to the object literals for consistency. But I'm all about learning best practice, is sometning wrong with obj literals in general or is it this case? I've heard about something called object proxy patern - is it applicable? – Richard the Lionheart Jan 15 '15 at 19:20