본문 바로가기
바닐라코딩 사전학습/코드연습, 퀴즈, 과제

Calendar

by 꼬마보노 2021. 12. 28.

** 자세한 코드는 GitHub kkomabono/vanilla_practice: Practice for vanilla_prep. (github.com) 에 업로드

 

아이디어

  1. 오늘의 요일, 날짜, 월, 연도 표기 
    - Date()메서드를 이용해서 현재시간을 받아온 후 textContent로 할당, 요일과 월은 해당 요일과 월이 숫자로 나오므로 함수를 작성해서 숫자로 나올 수 있도록 변환해서 출력하였다.
  2. 일~토 요일 라벨링 표기 
    - 태그를 새로 만들고 부모요소에 추가시켜준다. 이를 for문으로 반복
  3. 현재 월의 1일 판단 
    - 달력은 7일을 한 행으로 만드는 점에 착안해서 오늘 날짜를 받아서 7로 나눈 값과 오늘의 요일을 비교해서 1일을 판단했다.
    -> 그러나 이후에 좀 더 쉬운 방법을 찾아내어 작성한 코드는 더 이상 사용하지 않음.
  4. 현재 월의 마지막 날짜까지 달력에 표기 
    - 1일을 판단 후 이후에 해당 월은 몇일까지 있는지 판단 후 표기
    -> 달력은 1일 전과 마지막 날짜 이후에 빈 칸이 있는데, 몇칸이 생기는지 판단하는 코드를 작성후 채워넣었다.
    -> 빈칸은 요소를 하나 만들고 해당 요소에 visibility: hidden 스타일을 사용하였다.
  5. 우측 화살표 클릭했을 때 다음 달의 요일 및 날짜 표기
    - 1~12월까지 순서대로 나오게 하는 건 금방 작성하였지만 1->12, 12->1로 년도가 바뀔때 헷갈리는 부분이 있었다.월과 요일이 0부터 시작되는 점이 헷갈려서 undefined가 나타나는 경우가 있었지만 종이에 적으면서 값의 증감을 판단하고 작성하였다
  6. 특정 날짜를 클릭했을때, 상단의 요일 및 날짜 반영하기 
    - 클릭한 요소가 몇번째 요소인지 판단하여 날짜를 판단하게 하였다.

 

어려웠던 점

  1. 함수를 작성하고 함수를 호출하면 에러메세지가 자꾸 출력되었다. 
    -> 찾아본 결과 내가 작성한 함수는 전부 표현식으로 작성하였다.(var a = function() {})
    이를 해결하려면 선언식(a(); function a() {})으로 함수를 작성하면 되는데, 이는 JS의 호이스팅때문에 일어나는 문제이다!

  2. 달의 마지막날짜 이후에 칸을 채워주지 않으면 마지막 줄은 정렬이 되지 않았다.
    -> 달력의 한 행은 요소가 7개이다(일~월). 이를 아이디어로 해서 마지막 요소까지 모두 채워진다면 요소들의 갯수는 7의 배수가 나올것이다.  element.childElementCount;를 사용해서 div태그에 자식요소가 몇개있는지 검사한다. 마지막 줄에 몇개의 빈칸을 더 추가할 지 수식을 만든다. (k<7-div_element_count%7)

  3. 달의 첫번째 날짜 알아내기
    일일이 코딩으로 이번달의 1일의 요일, 이 함수를 이용해서 마지막 날짜까지 라벨링 등을 만드느라 코드가 매우 길어지고 물리고 물리는 함수가 많아져서 알아보고 사용하기가 어려워졌다.
    이번 달의 날짜, 요일찾기는 규칙찾고 계산해가며 코딩으로 작성했는데, 작성하는 와중에 작성한 여러 함수들을 다시 활용해서 전 달이나 다음 달의 1일의 요일찾기 등을 만드는건 또 다른 문제였다.
    결국 구글링을 통해 해법을 얻었는데, 만약 생일의 요일을 알고싶다면 아래의 코드를 쓰면 된다.
    var birthday = new Date(Year, 11, 17);
    전 달 1일의 요일을 알고싶다면
    var now = new Date();
    var pre_month = new Date(now.getFullYear(), now.getMonth(), 1);​
    위와같은 코드를 사용하면 얻을 수 있다.
    Date()메서드는 3가지의 파라미터를 받을 수 있는데 아무것도 입력하지 않으면 현재 날짜를 반환해준다.
    Date(Year, Month, Date); 파라미터를 입력해주면 입력한 날짜에 따라서 알아서 값을 리턴해준다..

    앞으로는 구글링 잘 하자... 그리고 MDN 예제부분까지 자세히 보자... 

  4. 달력을 출력 후 화살표를 눌렀을 때 새로운 달력이 나오도록 할때 문제발생
    문제점 1) remove() is not a function이라는 에러가 발생하였다. 
    -> 달력 내부의 태그들에 클래스를 부여해서 x = document.getElementsByClassName()으로 가져온 뒤 for문을 돌려서 해결
    문제점 2) 문제점1에서 for문으로 돌리면 홀수의 숫자들만 지워지는 문제 발생
    -> 간단히 요약하자면 getElementsByClassNAme()으로 가져온 x는 엄밀히 따지면 배열이 아니다. ""노드리스트"" 이다. 따라서 첫번째 요소가 지워지고 두번째 요소를 지우려고 하면 3번째 요소가 선택되어서 지워지는 것이다
    노드리스트는 하나가 삭제되면 그 다음에 있던 노드가 앞으로 자리를 채우기 때문이다.
    -> for문이 아닌 while 문으로 작성하였더니 해결..
    //removedate() 화면에 나타나 있는 날짜들을 지움
    function removedate(){
        // for(var i=0; i<$class_labeling.length; i++){
        //     console.log($class_labeling.length);
        //     $class_labeling[i].remove();
        // };
        
        while($class_labeling.length>0){
            $class_labeling[0].remove();
        };​
  5. 변수와 매개변수의 구분
    next_month() 함수에서 날짜와 연도를 재할당하는 구문이 있다.
    $month_year.textContent = `${number_to_Month(month+1)}` + " " + `${year}`;
    month++;​

    처음에는 number_to_Month(month+1) 첫번째 줄만 썼는데 왜 month값이 한번만 바뀌지? 라고 생각했었다.
    이 문제는 변수와 매개변수의 차이인데, 매개변수는 변수를 직접 바꾸지 않는다는 것이다. 매개변수로 들어가는 변수는 값을 복사해서 전달해주는 것이다. 따라서 첫번째 줄의 동작을 수행 후 month++를 적어줘야 비로소 month의 값이 바뀌는 것이다.

  6. 바닐라 JS에는 부모노드 내에서 몇번째 요소인지 가져오는 parentemelent.index() 메서드가 없다. 따라서 직접 가져오는 코드를 작성하였다.
    for (var i = 0; i < $realdates.length; i++) {
        (function(idx) {
            $realdates[idx].onclick = function() {
                alert(idx);
            }
        })(i);
    }​
  7. addEventListner() is not a function 오류발생
    -> 코드실행순서때문에 발생한 오류이다.
    HTML요소를 사용할 수 있기 전에 addEventListner() 메서드가 실행되서 발생하는 문제이다.
    나의 경우에는 $realdates[i].addEventListner()에서 $realdates에 요소가 할당되기 전에 addEventListner()가 실행된것이다.
    이를 해결하기 위해서 JS코드(스크립트)를 $realdates가 할당된 후에 사용될 수 있도록 위치를 옮겼더니 해결되었다.
    또한 getElementsByClassName은 html컬렉션을 리턴하는데 만약 요소에 addEventListner()를 추가하고자 한다면 아래와 같은 코드를 작성하면 된다.
    comment[0].addEventListener('click' , showComment , false ) ;
    getElementsByClassName로 불러온 모든 Class요소에 addEventListner()를 추가하고자 한다면
    for (var i = 0 ; i < comment.length; i++) {
       comment[i].addEventListener('click' , showComment , false ) ; 
    }
    위와같이 반복문을 돌려서 요소에 모두 붙여주면 가능하다.

 

노드의 특성떄문에 나타난 문제

 

참조)

https://stackoverflow.com/questions/28316289/javascript-remove-not-removing-all-elements
https://stackoverflow.com/questions/32027935/addeventlistener-is-not-a-function-why-does-this-error-occur/47941240

 

".addEventListener is not a function" why does this error occur?

I’m getting an ".addEventListener is not a function" error. I am stuck on this: var comment = document.getElementsByClassName("button"); function showComment() { var place = document.getElementB...

stackoverflow.com

 

 

Javascript remove not removing all elements

Please refer fiddle - http://jsfiddle.net/fkwwyvz8/ x = document.getElementsByClassName("buddy_blocks"); for(i=0;i<x.length;i++) x[i].remove(); Click on the last button, and it had to remo...

stackoverflow.com

 

'바닐라코딩 사전학습 > 코드연습, 퀴즈, 과제' 카테고리의 다른 글

Number Baseball  (0) 2021.12.28
JavaScript Koans-master  (0) 2021.12.28
Primitive / Reference 퀴즈  (0) 2021.12.27
Scope Quiz  (0) 2021.12.27
Craousel  (0) 2021.12.24