Sir
Sir

Reputation: 8280

Can't remove the event Listener, not understanding my mistake

I have a event listener which is assigned to a div using the click listener.

The problem is it does not remove the listener it just keeps adding to it.

This is the script where it is happening:

var resourceCheckout = function (quantity,btn){
    //quantity = integer
    // btn = document.getElementByID('the_div');

    var calculate = function (e) {
        var allowed = false;
        for(var i in test){
            var total = quantity * test[i].q;                        
            if(total > 200){ //if total > 200 remove eventListener
                allowed = false; break;
            } else {
                allowed = true;
            }
        };    
        if(allowed){
            btn.addEventListener('click',assign,false);
        } else {
            btn.removeEventListener('click', assign ,false);
        }
    };
    var assign = function (e) {
        do_it(quantity); //this gets called more than once when it should be
        // a maximum of one
    };
    calculate();
};

I decided to make a working jsfiddle to show you it in action, simply move the slider then hit the button, it will then call the function the listener is assigned to and count how many times it was called.

JSFIDDLE LINK

I hope someone can explain my mistake as its getting confusing to understand as my script gets more complicated!

Upvotes: 4

Views: 165

Answers (2)

6502
6502

Reputation: 114461

This code potentially adds a new listener for the event each time it is called.

Also note that every time you call ResourceCheckout a new different function object is created for variable assign and therefore the removeEventListener will never succeed because that specific function object passed has just been created and was never registered for the event (what was registered was a different function object, created in a previous call).

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074048

The problem is that the function you try to remove has never been added, and so nothing is removed.

Every call to your resourceCheckout function creates a new assign function, which is then used by your calculate function. Since it's a new assign function, it cannot have ever been added to the button, so calling removeEventListener and passing it in has no effect.

If a previous call to resourceCheckout put an assign on a button, you have to use that same function reference to remove it.

This may be clearer with a simpler example:

function foo() {
    function bar() {
    }

    return bar;
}

foo creates a new bar function every time it's called. So:

var b1 = foo();
var b2 = foo();
console.log(b1 === b2); // false

b1 and b2 are different functions.

To make your resourceCheckout work, you'd need to remember the previous assign and use that to remove the handler.

You asked in a comment why this doesn't apply to the slider code in the fiddle, which looks like this (since it's not in the question):

// The OP's slider code
var initSlider = function (el,func,data) {
    var clickX = null;
    var startSlider = function (e) {
        clickX = e.pageX;
        document.body.addEventListener('mousemove', calc, false);
        document.body.addEventListener('mouseup', endSlider, false);
    };
    var endSlider = function (e) {
        document.body.removeEventListener('mousemove', calc, false);
        document.body.removeEventListener('mouseup', endSlider, false);
    };

    var calc = function (e) {
        var dif = e.pageX - clickX;
        clickX = e.pageX;
        var parentWidth = parseInt(window.getComputedStyle(el.parentNode).width);
        var childWidth = parseInt(window.getComputedStyle(el).width);
        var childLeft = parseInt(window.getComputedStyle(el).left);
        var left = childLeft + dif;

        if (left < 0) { left = 0; }
        else if (left > (parentWidth-childWidth)) { left = (parentWidth-childWidth); }

        el.style.left = left + 'px';
        func(data,left,parentWidth-childWidth);
    };
    el.addEventListener("mousedown", startSlider, false);
};

There, the startSlider code successfully removes a handler from the body element. It works because the startSlider code has a reference to the endSlider function that was created at the same time startSlider was created (the same call to initSlider). So since startSlider has a reference to the same function that was used with addEventListener, removeEventListener works.

Upvotes: 4

Related Questions