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

이동욱·2024년 1월 25일
0

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

그러나 이 아이디어는 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개의 댓글