javascriptaddeventlistener

Remove event listener if screen is smaller than


I have an issue with my code if the screen is bigger than 960px the event listeners added the functions dropopen and dropclose if I scale to a screen less 960px the event listeners are not removed.

If I have a window less 960px and I refresh the page the event listeners are removed and if I resized the page bigger than 960px the event listeners are added.

Why are the event listeners not removed if I resize down the window?

window.addEventListener("load", function() {
  bindIt();
});

window.addEventListener("resize", function() {
  bindIt();
});


function bindIt() {
  var elements = document.getElementsByClassName("DropMenu");
  if (window.innerWidth > 960) {
    for (var i = 0; i < elements.length; i++) {
      elements[i].addEventListener('mouseover', dropopen, false);
    }

    for (var i = 0; i < elements.length; i++) {
      elements[i].addEventListener('mouseout', dropclose, false);
    }
  } else {
    for (var i = 0; i < elements.length; i++) {
      elements[i].removeEventListener('mouseover', dropopen);
    }

    for (var i = 0; i < elements.length; i++) {
      elements[i].removeEventListener('mouseout', dropclose);
    }
  }

  function dropopen() {
    var attribute = this.getAttribute("group");
    if (this.querySelector('#' + attribute) != null) {
      document.getElementById(attribute).style.display = 'block';
    }
  }

  function dropclose() {
    var attribute = this.getAttribute("group");
    if (this.querySelector('#' + attribute) != null) {
      document.getElementById(attribute).style.display = 'none';
    }
  }
}

Solution

  • Each time bindIt is called, it will create a new copy of dropopen and dropclose, since those functions were defined within another function. In order for removeEventListener to work, it needs to know exactly which function to remove. Since there are multiple copies, it tries to remove one that didn't exist.

    If you move the definitions of dropopen and dropclose to be outside of bindIt, your code will work as intended.

    window.addEventListener("load", function() {
        bindIt();
    });
    
    window.addEventListener("resize", function() {
        bindIt();
    });
    
    
    function bindIt() {
        var elements = document.getElementsByClassName("DropMenu");
        if (window.innerWidth > 960) {
            for (var i = 0; i < elements.length; i++) {
                elements[i].addEventListener('mouseover', dropopen, false);
            }
    
            for (var i = 0; i < elements.length; i++) {
                elements[i].addEventListener('mouseout', dropclose, false);
            }
        } else {
            for (var i = 0; i < elements.length; i++) {
                elements[i].removeEventListener('mouseover', dropopen);
            }
    
            for (var i = 0; i < elements.length; i++) {
                elements[i].removeEventListener('mouseout', dropclose);
            }
        }
    }
    
    
    function dropopen() {
        var attribute = this.getAttribute("group");
        if (this.querySelector('#' + attribute) != null) {
            document.getElementById(attribute).style.display = 'block';
        }
    }
    
    function dropclose() {
        var attribute = this.getAttribute("group");
        if (this.querySelector('#' + attribute) != null) {
            document.getElementById(attribute).style.display = 'none';
        }
    }