Javascript | 우클릭 다루기 + 커스텀 컨텍스트 메뉴 만들기

이동욱·2024년 1월 25일

사내 관리자 페이지의 기획 회의 중, 회원 카드를 우클릭하면 현재 연결된 프린터기 목록이 표시되고 해당 버튼을 누르면 선택한 프린터에서 출력되는 기능에 대한 아이디어가 나왔다.

그러나 이 아이디어는 JavaScript에서가 아닌 JavaScript로 실행된 프린트 다이얼로그를 통해 작동해야 하는 작업이었기 때문에 구현이 불가했고, 기획적인 문제로 인해 이 아이디어는 반려되었다.

하지만 컨텍스트 메뉴를 커스텀해서 만들어 본 적이 없어 구현해보고 싶었다.기획에서 제시된 작업을 수정하여, 유저 카드를 우클릭하면 툴팁과 같이 더 디테일한 정보가 나오도록 가볍게 만들어봤다.


1. 우클릭 이벤트 막기

우선 우클릭을 했을때 이벤트를 막는 작업부터 진행했다.

js에서 우클릭 이벤트를 제어하기 위해서는 addEventListener의 contextmenu이벤트를 감지하면 된다.

userCardList.forEach((userCard) => {
  userCard.addEventListener("contextmenu", function (e) {
    e.preventDefault();
  });
});

모든 userCard의 DOM에 이벤트 리스너를 연결하고, e.preventDefault()를 사용하여 이벤트 동작을 중단시켰다.

2. 커스텀 컨텍스트 생성

이제 클릭할때 커스컴 컨텍스트 메뉴를 만들어보자

<div id="customMenu"></div>
#customMenu {
  display: none;
  position: absolute;
  background-color: #d1d1d1;
  border: 1px solid #d4d4d4;
  padding: 10px;
  z-index: 1;
}

위 코드에서는 display: none과 position: absolute로 설정된 태그를 이용하여 커스텀 컨텍스트 메뉴 역할을 할 공간을 미리 생성했다.

그리고 우클릭 시 해당 이벤트의 clientX와 clientY 값을 이용하여 left와 top 위치를 설정하고, display를 block으로 변경하여 클릭한 위치에 컨텍스트가 보이게했다.

const myContext = document.getElementById("myContext");

userCardList.forEach((userCard) => {
  userCard.addEventListener("contextmenu", function (e) {
    e.preventDefault();   
    // 컨텍스트 위치 조정
    myContext.style.left = e.clientX + "px";
    myContext.style.top = e.clientY + "px";
    // 컨텍스트 보이게
    myContext.style.display = "block";
  });
});

3. 컨텍스트 메뉴 채우기

이후, 클릭이 발생하면 클릭된 태그의 정보를 확인하고 해당 정보를 이용하여 커스텀 컨텍스트에 내용을 채웠다. 또한, 다른 곳을 클릭할 때 해당 컨텍스트가 다시 숨겨지도록 click이벤트를 추가했다.

// 클릭시 컨텍스트 없애기
document.addEventListener("click", function () {
  myContext.style.display = "none";
});

userCardList.forEach((userCard) => {
  userCard.addEventListener("contextmenu", function (e) {
    e.preventDefault();
    
    // 메뉴를 표시할 위치 조정
    myContext.style.left = e.clientX + "px";
    myContext.style.top = e.clientY + "px";
    // 메뉴를 보이게 함
    myContext.style.display = "block";

    // 컨텍스트에 추가할 내용
    const userIdx = +this.dataset.idx;
    const selectedUser = userList[userIdx];
    
    //내용 추가
    myContext.innerHTML = "";
    myContext.insertAdjacentHTML("beforeend", `<p>${selectedUser.name}</p><p>${selectedUser.job}</p>`);
  });
});

완성!


하고 나니 이런 작업을 프로젝트에서 구현할 일이 있을까? 하는 생각은 들었다. 근데 지금까지 한 일들 다 알고 한거 아니니까 언젠가 또 요긴하게 쓰일 경험이 되겠지

근래 프로젝트가 React가 아닌 순수 자바스크립트로 작업하는 중인데 너무 오랜만이어서 처음에는 팔과 다리를 다 떼고 작업하는 느낌이었다. 그러나 계속 하다 보니 은근히 재미있고 어떤 면에선 또 좀 낭만적인것 같기도 하고... 이왕 하는거 이것저것 좀 더 다양하게 해보고싶다.

근데 낭만도 좋지만 리액트 쓰고싶다🥲

profile
프론트엔드

0개의 댓글