구글 캘린더에 기능 중 일정 만들기를 구현하였다. 기능은 다음과 같다.
구글 캘린더 일정만들기 특징
1. 마우스 클릭 이벤트가 발생하면 일정(1시간) 영역이 생성되고 모달창이 뜬다.
2. 일정(1시간) 영역은 30분 아니면 정각이다.
=> 만약 2시간 20분 쯤 위치를 클릭하면 일정 영역은 2시 30분에 생긴다.
마찬가지로 2시 50분 쯤 위치를 클릭하면 일정 영역은 3시에 생긴다.
3. 일정 영역에는 일정 텍스트와 시간이 표시된다.
offsetX : 이벤트 대상 객체에서의 상대적 마우스 x좌표 위치를 반환한다.
offsetY : 이벤트 대상 객체에서의 상대적 마우스 y좌표 위치를 반환한다.
왜 clientX,Y 아니면 PageX,Y를 사용하지 않았나?
그 이유는 scroll이 있기 때문이다. 만약 clientX, Y(브라우저 기준 scroll x)사용하면 브라우저 좌표값이 나오고 pageX, Y(브라우저 기준 scroll o)도 브라우저 좌표값이 나오기 때문이다.
반면에 offsetX, Y는 스크롤을 포함한 div가 이벤트 대상 객체이므로 스크롤을 포함한 x,y좌표를 반환한다.
그림으로 설명하자면 빨간색은 클릭한 좌표이고 offset을 할 경우 일정표 div 영역내에서 좌표를 설정하게 된다. 만약 offset을 하지 않을 경우 브라우저 기준으로 설정을 할 것이다. 그렇게 될 경우 스크롤 하위는 포함하지 않는다.
본 프로젝트에서는 시간 사이간격은 100px로 정하였다.
그리고 구글 캘린더는 30분 간격이지만 본 프로젝트에서는 15분마다 일정이 생기도록 하였다.
1시간 100px이니 15분이면 25px이다.
예를 들어 좌표가 (100, 200)이라고 가정해보자
200/25 => 8 이고 이 말은 15분 간격이 8번 온다는 의미이다.
좌표가 (100, 220)이라고 가정해보자
220/25 => 8.8이고 이말은 15분 간격이 8.8번 온다는 의미이다. 하지만 8번보다 9번에 가까우므로 9번으로 하자
이것을 코드로 나타내보면 다음과 같다.
_left는 단순히 offsetX값을 넣어주면 된다.
cnt는 15분 간격 갯수라고 생각하면 된다. offsetY / 25 값의 반올림을 하여 15분 간격 갯수를 구하고 15분 간격은 25px이니 곱한값을 top으로 설정한다.
반면에 cnt갯수가 2이하면 오전 8시 이전 값이므로 return (일정을 만들지 않는다.)한다.
이로서 0분, 15분, 30분 45분 으로만 일정을 만들 수가 있다.
cnt란 15분 간격을 나타내는 25px 갯수
오전 8시는 50px 떨어져 있기 때문에 cnt는 2가 된다.
오전 9시는 (50 + 100)px 떨어져 있기 때문에 cnt는 6이 된다.
만약 cnt = 13이면 어떻게 될까
(13-2) / 4 = 2
(13-2) % 4 = 3이 된다.
즉 8시 기준으로 2시간 떨어져 있고 45분 떨어져 있다는 의미이다. (10시 45분)
이것을 코드로 나타내보자
이로서 오전 오후, 시간을 나타낼 수 있다.
앞서 설명한 cnt값으로 top, left(left는 그냥 offsetX 사용하면 됨), start, end, width, height 등등을 newDiv값에 object 형식으로 저장하고 이 좌표를 DB에 넣어준다.
그 이유는 새로고침을 하여도 DB에서 값을 불러와 똑같이 렌더링하기 위해서이다.
성공적으로 insert되면 State를 변경하여 재렌더링 한다.
일정표 하위에 일정div가 있다. 일정 div에서 onMouseDown()이벤트를 발생시켰더니 부모인 일정표 div에 onMouseDown()이벤트도 발생되는 것이였다.
자식 div에서 e.stopPropagation을 사용하면 부모로 이벤트가 전파되지 않는다.
이벤트 버블링, 캡처링에 대해 자세히 나온 블로그이다.
이벤트 버블링과 캡처링에 대한 정리