Home > database >  Javascript - Remove event listener at resize
Javascript - Remove event listener at resize

Time:12-04

I'm doing some work to make navigation fully accessible by mouse over, keyboard and click, depending on the resolution.

I am looking for that in mobile, only the click works. And hover, click, keyboard for higher resolutions.

Important edit : It only works perfectly when I load the page at the correct resolution (low or high). BUT, if I resize live, the removeEventListener doesn't work.

Plus : I don't know if my stopImmediatePropagation is the better solution to avoid multiple functions.

Here is the idea of the code.

JS

window.addEventListener("DOMContentLoaded", onl oadFunction);

function onLoadFunction(e) {
  menu_burger();
  onResizeFunction(); //trigger resize function immediately

  window.addEventListener("resize", onResizeFunction);
}

function onResizeFunction(e) {
  if (window.innerWidth > 770) {
    window.removeEventListener('resize', menu_onClick);
    menu_onClick();
    menu_mouseOver();
    menu_onFocus();
    menu_onFocusDetection();
  } else {
    window.removeEventListener('resize', menu_onClick);
    window.removeEventListener('resize', menu_mouseOver);
    window.removeEventListener('resize', menu_onFocusDetection);
    window.removeEventListener('resize', menu_onFocus);
    menu_onClick();
  }
}

// FONCTIONS MENU
const focusDetectionEntry = document.querySelectorAll('.nav-list--focus-detection > li[aria-expanded] > button');
const focusEntry = document.querySelectorAll('.nav-list--focus > li[aria-expanded] > button');
const overEntry = document.querySelectorAll('.nav-list--over > li[aria-expanded] > button');
const clickEntry = document.querySelectorAll('.nav-list--click > li[aria-expanded] > button');

function menu_burger() {
  document.querySelector('.menu-burger').addEventListener('click', function () {
    this.classList.toggle('menu--open');
    document.querySelector('.main-nav-list').classList.toggle('main-nav-list--open');
  });
}

function menu_mouseOver() {
  overEntry.forEach(sub => {
    var subParent = sub.parentElement;
    subParent.addEventListener('mouseover', function(e) {
      subParent.setAttribute('aria-expanded', 'true');
      console.log('OVER IN');
      e.stopImmediatePropagation();
    });

    subParent.addEventListener('mouseout', function(e) {
      subParent.setAttribute('aria-expanded', 'false');
      console.log('OVER OUT');
      e.stopImmediatePropagation();
    });
  })
}

function menu_onClick() {
  clickEntry.forEach(sub => {
    var subParent = sub.parentElement;
    sub.addEventListener('click', function(e) {
      let attrState = subParent.getAttribute('aria-expanded');

      if (attrState === 'false') {
        subParent.setAttribute('aria-expanded', 'true')
      } else if (attrState === 'true') {
        subParent.setAttribute('aria-expanded', 'false');
      }

      console.log('CLICK');
      e.stopImmediatePropagation();
    });
  })
}

function menu_onFocus() {
  focusEntry.forEach(sub => {
    var subParent = sub.parentElement;
    sub.addEventListener('keyup', (e) => {
      console.log('TOUCHE');
      if (e.keyCode === 27) {
        console.log('ECHAP');
        subParent.setAttribute('aria-expanded', 'false');
      }
      e.stopImmediatePropagation();
    });
  })
}

function menu_onFocusDetection() {
  focusDetectionEntry.forEach(sub => {
    var subParent = sub.parentElement;
    sub.addEventListener('focus', function (e) {
      subParent.setAttribute('aria-expanded', 'true');
      console.log('FOCUS');
      e.stopImmediatePropagation();
    });

    subParent.addEventListener('focusout', function (e) {
      console.log('FOCUS OUT');
      //console.log(e.relatedTarget); //target actuel
      if (!subParent.contains(e.relatedTarget)) {
        subParent.setAttribute('aria-expanded', 'false');
      }
      e.stopImmediatePropagation();
    });
  })
}

I tried something like that, but not successfull :

function menu_onFocusDetection() {
  focusDetectionEntry.forEach(sub => {
    var subParent = sub.parentElement;
    // si focus sur le bouton, on modifie sont parent
    function test(ev) {
      subParent.setAttribute('aria-expanded', 'true');
      console.log('FOCUS');
      ev.stopImmediatePropagation();
    }


    // si le focus sort du li
    function test2(ev2) {
      // console.log(ev2.relatedTarget); //target actuel
      console.log('FOCUS OUT');
      if (!subParent.contains(ev2.relatedTarget)) {
        subParent.setAttribute('aria-expanded', 'false');
      }
      ev2.stopImmediatePropagation();
    }

    if (window.innerWidth > 770) {
      sub.addEventListener('focus', test);
      sub.addEventListener('focusout', test2);
    } else {
      sub.removeEventListener('focus', test);
      sub.removeEventListener('focusout', test2);
    }
  })

}

CodePudding user response:

Ok, so here it is the answer :

I had to split my function and do the condition in each.

window.addEventListener("DOMContentLoaded", onl oadFunction);
function onLoadFunction(e) {
  onResizeFunction(); //trigger resize function immediately
  window.addEventListener("resize", onResizeFunction);
}

function onResizeFunction(e) {
  menu_onFocusDetection();
}

function initEntries() {
  focusDetectionEntry = document.querySelectorAll('.nav-list--focus-detection > li[aria-expanded] > button');
}

function focus(e) {
  this.parentElement.setAttribute('aria-expanded', 'true');
  e.stopImmediatePropagation();
}

function menu_onFocusDetection() {
  focusDetectionEntry.forEach(sub => {
    var subParent = sub.parentElement;
    if (window.innerWidth > 770) {
      sub.addEventListener('focus', focus);
      subParent.addEventListener('focusout', focusOut);
    } else {
      sub.removeEventListener('focus', focus);
      subParent.removeEventListener('focusout', focusOut);
    }
  });
}

CodePudding user response:

Event handlers are executed every time an event occurs, not just the first time. They need to be registered only once.

Move the click and mouseover handlers to standalone function declarations, and register those handlers in the outer block. So basically:

window.addEventListener("load", onl oadFunction);

function onLoadFunction(e) {
  onResizeFunction();// trigger resize function immediately

  window.addEventListener("resize", onResizeFunction);
}

function onResizeFunction(e) {
  if (window.innerWidth > 770) {
    //over   click
    over();
    click();
  } else {
    //only click
    click();
  }

}

function click() {
  console.log('CLICK');
}
  
function over() {
  console.log('OVER');
}

document.querySelector('.test').addEventListener('click', click);
document.querySelector('.test').addEventListener('mouseover', over);
  • Related