하위 메뉴가 세로형 GNB

n-u·2022년 10월 17일
1

웹 접근성

목록 보기
2/3
post-thumbnail

이번에는 하위메뉴가 가로로 나타는 메뉴를 jQuery로 마우스 호버, 초점진입 코드를 Vanilla Javascript로 변경하는 작업을 하였다.

jQuery로는 fadeIn()와 fadeOut()메서드를 이용해 display:none인 요소를 부드럽게 나타나지만, 같은 css를 이용해야 하는 전제조건(css까지 하기에는 귀찮다.)으로 javascript에는 약간의 나타나는 효과는 다를 수 있으나, 마우스 호버와 초점진입에 대한 동작이 같도록 하는 것을 목표로 하였다.

jQuery

$(document).ready(function () {
  //gnb의 li에 마우스오버, 포커싱 했을때 동작
  $(".gnb li").on("mouseover focusin", function () {
    $(this).children("ul").stop().fadeIn(300);
  });
  //마우스가 떠나갈떄 동작
  $(".gnb li").on("mouseleave", function () {
    $(this).children("ul").stop().fadeOut(200);
  });
  //배경색이 나타나도록 하는 동작
  $(".gnb").on("mouseover focusin", function () {
    $(".bg_gnb").stop().fadeIn(300);
  });
  $(".gnb").on("mouseleave focusout", function () {
    $(".bg_gnb").stop().fadeOut(200);
  });
  //1뎁스 메뉴에서 키보드 초점이 벗어나면 ul이 없어지는 작용을 한다.
  $(".gnb > li").on("focusout", function () {
    $(this).children("ul").stop().fadeOut(200);
  });
});

Javascript

1. map()을 이용해 각 요소에 이벤트 지정

전개연산자map()을 이용해 Nodelist에 접근해 각 요소에 이벤트들이 실행되면 지정된 함수가 실행되도록 작성해 보았다.

1뎁스의 li에 초점 진입시 이벤트

[...depth1].map((li)=>{
  li.addEventListener("mouseenter",function(e){
    const target = e.target;
    notShowMenu();  
    showMenu(target);
  });

  li.addEventListener("mouseleave",function(e){
    const target = e.target;
    notShowMenu();  
  });
});

1뎁스의 a에 초점 진입시 이벤트

[...depth1TagA].map((a)=>{
  const lastLi = a.nextElementSibling.lastElementChild;
  a.addEventListener("focusin",function(e){
    const target = e.target.parentElement;
    notShowMenu();
    showMenu(target);
  });
  lastLi.addEventListener("focusout",function(e){
    notShowMenu();
  });
})
  • focusout 이벤트 경우
    lastLi(하위메뉴의 마지막 li)에 초점이 나갈때 하위메뉴가 사라지도록 했다.
    • 초점 같은 경우에는 순차적 탐색이 가능해야 하는데 a태그에 focusout 이벤트를 지정해주면 하위메뉴가 나타나지만 다음 tab동작에서 초점이 a태그를 벗어나기 때문에 하위메뉴로 초점이 가지 않는 상황이 발생했다.
    • 따라서 focusout이벤트는 하위메뉴를 다 탐색하고 난 후 마지막 li에 초점이 떠날때 하위메뉴가 사라지는 함수인 notShowMenu()를 불러 동작하게 했다.

하위메뉴에 동작 대한 함수

//메뉴 나타남(a 호버시 형제 노드인 ul의 style을 지정)
function showMenu(elem){
  elem.querySelector('ul').style.display = 'block';
  bg.style.display = 'block';
}
//사라짐(a호버, 초점 진입시 -> 모든 ul의 style을 지정해 다 안보이게 만든다. )
function notShowMenu(){  
  [...depth2].map((ul)=> ul.style.display = 'none');
  bg.style.display = 'none';
}
매개변수로 받지 않고 querySelectorAll을 이용해 Nodelist형태로 받은 이유

다른 li에 호버 및 초점 진입시 다른(형제) li들의 하위메뉴 인 ul이 보이지 않아야 하기 떄문이다.
인수로 받을 경우 해당 타켓된 ul의 메뉴만 사라지기 때문에 Nodelist형태에 map()을 이용해 모든 ul에 display = none을 지정해주어 하위메뉴가 보이지 않도록 해주었다.

2. 위의 코드를 정리(...예정)






마치며

저번 하위메뉴가 세로형 GNB에서는 nodeElement를 이용해 코드를 작성하려고 했으나 class를 이용해 해결했다면 이번에는 매개변수로 element를 받고 그 element의 자식, 형제 node를 찾아 스타일을 지정하는 방법으로 해결하였다.

솔직히 이 방법이 좋은 방법인지는 잘 모르겠지만, 일단은 화면상에서 jQuery에서 의도한 동작을 Javascript를 통해 동작하고 있다는 것에 의의를 둔다.

글을 적으면서 2개의 함수(나타나는 함수와 사라지는 함수)로 코드를 정리하면 어떨까 하는 생각이 들었다. 시간이 된다면 차차 2개의 함수 안에 코드를 넣어 함수를 호출해 동작하도록 해봐야겠다.

profile
기록하며 발전하는 삶

0개의 댓글