처리가 필요한 클릭 이벤트는 크게 두 가지다.
1. 창이 여러 개 열려 있을 때, 가장 최근에 클릭한 창을 가장 위에 띄워줘야 한다.
2. 창 닫기 버튼(x)을 눌렀을 때 창이 꺼져야 한다.
click-event.js
const clickWindowEl = (elem) => {
elem.addEventListener('click', () => {
OPEN_EL_LIST.forEach((elem) => {
elem.style.zIndex = '0';
});
elem.style.zIndex = '1';
});
};
로직 자체는 단순하다. 창 요소에 클릭이 일어나면 먼저 열려 있는 모든 창(OPEN_EL_LIST
)의 zIndex
를 0으로 초기화하고, 마지막으로 해당 창 요소의 zIndex
를 1로 줘서 가장 위에 올 수 있게 만든다.
main.js
OPEN_EL_LIST
는 set을 사용했다. 이 자료구조에는 별다른 정보 없이 단일 요소 노드를 바로 넣으려 했는데, 배열을 사용하면 인덱스로 접근하거나 그 요소를 따로 검색하는 코드가 필요해서 검색이 쉬운 set을 선택했다.add
, 닫기 버튼을 누를 때 delete
한다....
// 전역 스코프
const OPEN_EL_LIST = new Set();
...
// 요소 생성 함수
const clickClockLabel = () => {
// Make sure only one window is open
if (desktop.contains(clockEl)) return;
clockEl = createClockEl();
...
OPEN_EL_LIST.add(clockEl); // 먼저 set에 넣어주고
clickWindowEl(clockEl); // 클릭 이벤트 달아줌
};
요소를 생성하는 함수에서 clickWindowEl
을 호출해 이벤트 리스너를 달아준다.
위 함수보다 더 간단하다. x 버튼의 클릭 이벤트에서 창을 제거하고 OPEN_EL_LIST
에서도 지워 준다.
const clickCloseBtn = (elem, timerId) => {
elem.querySelector('#close-btn').addEventListener('click', () => {
if (!!timerId) clearInterval(timerId);
OPEN_EL_LIST.delete(elem);
elem.remove();
});
};
이때 시계 창에서는 등록했던 타이머도 지워줘야 하므로 timerId
가 넘어오면 clearInverval
도 호출하게끔 했다.