Rob
Rob

Reputation: 8195

Mootools - how to destroy a class instance

What I'm trying to do is create a class that I can quickly attach to links, that will fetch and display a thumbnail preview of the document being linked to. Now, I am focusing on ease of use and portability here, I want to simply add a mouseover event to links like this:

<a href="some-document.pdf" onmouseover="new TestClass(this)">Testing</a>

I realize there are other ways I can go about this that would solve my issue here, and I may end up having to do that, but right now my goal is to implement this as above. I don't want to manually add a mouseout event to each link, and I don't want code anywhere other than within the class (and the mouseover event creating the class instance).

The code:

TestClass = new Class({
    initialize: function(anchor) {
        this.anchor = $(anchor);
        if(!this.anchor) return;

        if(!window.zzz) window.zzz = 0;
        this.id = ++window.zzz;

        this.anchor.addEvent('mouseout', function() {
            // i need to get a reference to this function
            this.hide();
        }.bind(this));

        this.show();

    },
    show: function() {
        // TODO: cool web 2.0 stuff here!
    },
    hide: function() {
        alert(this.id);

        //this.removeEvent('mouseout', ?);  // need reference to the function to remove

        /*** this works, but what if there are unrelated mouseout events? and the class instance still exists! ***/
        //this.anchor.removeEvents('mouseout');

        //delete(this);  // does not work !
        //this = null; // invalid assignment!
        //this = undefined; // invalid assignment!

    }
});

What currently happens with the above code:

Desired behavior:

The problem is, each time I mouse over the link, I'm creating a new class instance and appending a new mouseout event for that instance. The class instance also remains in memory indefinitely.

On mouseout I need to remove the mouseout event and destroy the class instance, so on subsequent mouseovers we are starting fresh.

I could create a helper function for this to make sure that the class is only created once for each link, something like this:

function TestClassHelper(anchor) {
    anchor = $(anchor);
    if(!anchor) return;

    if(!anchor.retrieve('TestClass')) anchor.store('TestClass', new TestClass(anchor));
    anchor.retrieve('TestClass').show();
}

<a href="some-document.pdf" onmouseover="TestClassHelper(this)">Testing</a>

I may end up implementing it this way if I have to, but I'm curious as to how I can fix the other method.

Upvotes: 2

Views: 2022

Answers (1)

Anurag
Anurag

Reputation: 141889

This looks a lot more complex than it should be. But if you want to fix this, you need to save a reference to the bound function somewhere and later pass that to removeEvent.

For example:

// inside initialize
this.boundHandler = function() {
    this.hide();
}.bind(this)
this.anchor.addEvent('mouseout', this.boundHandler);

// inside hide    
this.removeEvent('mouseout', this.boundHandler);

See the removeEvent docs for examples of this very issue.

I wouldn't recommend event delegation here either for performance reasons. The best approach is to attach the handler in code rather than inline and only do it once, so unnecessary objects are not being created each time the user mouses over.

Upvotes: 3

Related Questions